code.gitea.io/gitea@v1.22.3/tests/integration/api_packages_cargo_test.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package integration 5 6 import ( 7 "bytes" 8 "encoding/binary" 9 "fmt" 10 "io" 11 "net/http" 12 neturl "net/url" 13 "testing" 14 15 "code.gitea.io/gitea/models/db" 16 "code.gitea.io/gitea/models/packages" 17 repo_model "code.gitea.io/gitea/models/repo" 18 "code.gitea.io/gitea/models/unittest" 19 user_model "code.gitea.io/gitea/models/user" 20 "code.gitea.io/gitea/modules/gitrepo" 21 "code.gitea.io/gitea/modules/json" 22 cargo_module "code.gitea.io/gitea/modules/packages/cargo" 23 "code.gitea.io/gitea/modules/setting" 24 cargo_router "code.gitea.io/gitea/routers/api/packages/cargo" 25 cargo_service "code.gitea.io/gitea/services/packages/cargo" 26 "code.gitea.io/gitea/tests" 27 28 "github.com/stretchr/testify/assert" 29 ) 30 31 func TestPackageCargo(t *testing.T) { 32 onGiteaRun(t, testPackageCargo) 33 } 34 35 func testPackageCargo(t *testing.T, _ *neturl.URL) { 36 user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 37 38 packageName := "cargo-package" 39 packageVersion := "1.0.3" 40 packageDescription := "Package Description" 41 packageAuthor := "KN4CK3R" 42 packageHomepage := "https://gitea.io/" 43 packageLicense := "MIT" 44 45 createPackage := func(name, version string) io.Reader { 46 metadata := `{ 47 "name":"` + name + `", 48 "vers":"` + version + `", 49 "description":"` + packageDescription + `", 50 "authors": ["` + packageAuthor + `"], 51 "deps":[ 52 { 53 "name":"dep", 54 "version_req":"1.0", 55 "registry": "https://gitea.io/user/_cargo-index", 56 "kind": "normal", 57 "default_features": true 58 } 59 ], 60 "homepage":"` + packageHomepage + `", 61 "license":"` + packageLicense + `" 62 }` 63 64 var buf bytes.Buffer 65 binary.Write(&buf, binary.LittleEndian, uint32(len(metadata))) 66 buf.WriteString(metadata) 67 binary.Write(&buf, binary.LittleEndian, uint32(4)) 68 buf.WriteString("test") 69 return &buf 70 } 71 72 err := cargo_service.InitializeIndexRepository(db.DefaultContext, user, user) 73 assert.NoError(t, err) 74 75 repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, user.Name, cargo_service.IndexRepositoryName) 76 assert.NotNil(t, repo) 77 assert.NoError(t, err) 78 79 readGitContent := func(t *testing.T, path string) string { 80 gitRepo, err := gitrepo.OpenRepository(db.DefaultContext, repo) 81 assert.NoError(t, err) 82 defer gitRepo.Close() 83 84 commit, err := gitRepo.GetBranchCommit(repo.DefaultBranch) 85 assert.NoError(t, err) 86 87 blob, err := commit.GetBlobByPath(path) 88 assert.NoError(t, err) 89 90 content, err := blob.GetBlobContent(1024) 91 assert.NoError(t, err) 92 93 return content 94 } 95 96 root := fmt.Sprintf("%sapi/packages/%s/cargo", setting.AppURL, user.Name) 97 url := fmt.Sprintf("%s/api/v1/crates", root) 98 99 t.Run("Index", func(t *testing.T) { 100 t.Run("Git/Config", func(t *testing.T) { 101 defer tests.PrintCurrentTest(t)() 102 103 content := readGitContent(t, cargo_service.ConfigFileName) 104 105 var config cargo_service.Config 106 err := json.Unmarshal([]byte(content), &config) 107 assert.NoError(t, err) 108 109 assert.Equal(t, url, config.DownloadURL) 110 assert.Equal(t, root, config.APIURL) 111 }) 112 113 t.Run("HTTP/Config", func(t *testing.T) { 114 defer tests.PrintCurrentTest(t)() 115 116 req := NewRequest(t, "GET", root+"/"+cargo_service.ConfigFileName) 117 resp := MakeRequest(t, req, http.StatusOK) 118 119 var config cargo_service.Config 120 err := json.Unmarshal(resp.Body.Bytes(), &config) 121 assert.NoError(t, err) 122 123 assert.Equal(t, url, config.DownloadURL) 124 assert.Equal(t, root, config.APIURL) 125 }) 126 }) 127 128 t.Run("Upload", func(t *testing.T) { 129 t.Run("InvalidNameOrVersion", func(t *testing.T) { 130 defer tests.PrintCurrentTest(t)() 131 132 content := createPackage("0test", "1.0.0") 133 134 req := NewRequestWithBody(t, "PUT", url+"/new", content). 135 AddBasicAuth(user.Name) 136 resp := MakeRequest(t, req, http.StatusBadRequest) 137 138 var status cargo_router.StatusResponse 139 DecodeJSON(t, resp, &status) 140 assert.False(t, status.OK) 141 142 content = createPackage("test", "-1.0.0") 143 144 req = NewRequestWithBody(t, "PUT", url+"/new", content). 145 AddBasicAuth(user.Name) 146 resp = MakeRequest(t, req, http.StatusBadRequest) 147 148 DecodeJSON(t, resp, &status) 149 assert.False(t, status.OK) 150 }) 151 152 t.Run("InvalidContent", func(t *testing.T) { 153 defer tests.PrintCurrentTest(t)() 154 155 metadata := `{"name":"test","vers":"1.0.0"}` 156 157 var buf bytes.Buffer 158 binary.Write(&buf, binary.LittleEndian, uint32(len(metadata))) 159 buf.WriteString(metadata) 160 binary.Write(&buf, binary.LittleEndian, uint32(4)) 161 buf.WriteString("te") 162 163 req := NewRequestWithBody(t, "PUT", url+"/new", &buf). 164 AddBasicAuth(user.Name) 165 MakeRequest(t, req, http.StatusBadRequest) 166 }) 167 168 t.Run("Valid", func(t *testing.T) { 169 defer tests.PrintCurrentTest(t)() 170 171 req := NewRequestWithBody(t, "PUT", url+"/new", createPackage(packageName, packageVersion)) 172 MakeRequest(t, req, http.StatusUnauthorized) 173 174 req = NewRequestWithBody(t, "PUT", url+"/new", createPackage(packageName, packageVersion)). 175 AddBasicAuth(user.Name) 176 resp := MakeRequest(t, req, http.StatusOK) 177 178 var status cargo_router.StatusResponse 179 DecodeJSON(t, resp, &status) 180 assert.True(t, status.OK) 181 182 pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeCargo) 183 assert.NoError(t, err) 184 assert.Len(t, pvs, 1) 185 186 pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) 187 assert.NoError(t, err) 188 assert.NotNil(t, pd.SemVer) 189 assert.IsType(t, &cargo_module.Metadata{}, pd.Metadata) 190 assert.Equal(t, packageName, pd.Package.Name) 191 assert.Equal(t, packageVersion, pd.Version.Version) 192 193 pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID) 194 assert.NoError(t, err) 195 assert.Len(t, pfs, 1) 196 assert.Equal(t, fmt.Sprintf("%s-%s.crate", packageName, packageVersion), pfs[0].Name) 197 assert.True(t, pfs[0].IsLead) 198 199 pb, err := packages.GetBlobByID(db.DefaultContext, pfs[0].BlobID) 200 assert.NoError(t, err) 201 assert.EqualValues(t, 4, pb.Size) 202 203 req = NewRequestWithBody(t, "PUT", url+"/new", createPackage(packageName, packageVersion)). 204 AddBasicAuth(user.Name) 205 MakeRequest(t, req, http.StatusConflict) 206 207 t.Run("Index", func(t *testing.T) { 208 t.Run("Git", func(t *testing.T) { 209 t.Run("Entry", func(t *testing.T) { 210 defer tests.PrintCurrentTest(t)() 211 212 content := readGitContent(t, cargo_service.BuildPackagePath(packageName)) 213 214 var entry cargo_service.IndexVersionEntry 215 err := json.Unmarshal([]byte(content), &entry) 216 assert.NoError(t, err) 217 218 assert.Equal(t, packageName, entry.Name) 219 assert.Equal(t, packageVersion, entry.Version) 220 assert.Equal(t, pb.HashSHA256, entry.FileChecksum) 221 assert.False(t, entry.Yanked) 222 assert.Len(t, entry.Dependencies, 1) 223 dep := entry.Dependencies[0] 224 assert.Equal(t, "dep", dep.Name) 225 assert.Equal(t, "1.0", dep.Req) 226 assert.Equal(t, "normal", dep.Kind) 227 assert.True(t, dep.DefaultFeatures) 228 assert.Empty(t, dep.Features) 229 assert.False(t, dep.Optional) 230 assert.Nil(t, dep.Target) 231 assert.NotNil(t, dep.Registry) 232 assert.Equal(t, "https://gitea.io/user/_cargo-index", *dep.Registry) 233 assert.Nil(t, dep.Package) 234 }) 235 236 t.Run("Rebuild", func(t *testing.T) { 237 defer tests.PrintCurrentTest(t)() 238 239 err := cargo_service.RebuildIndex(db.DefaultContext, user, user) 240 assert.NoError(t, err) 241 242 _ = readGitContent(t, cargo_service.BuildPackagePath(packageName)) 243 }) 244 }) 245 246 t.Run("HTTP", func(t *testing.T) { 247 t.Run("Entry", func(t *testing.T) { 248 defer tests.PrintCurrentTest(t)() 249 250 req := NewRequest(t, "GET", root+"/"+cargo_service.BuildPackagePath(packageName)) 251 resp := MakeRequest(t, req, http.StatusOK) 252 253 var entry cargo_service.IndexVersionEntry 254 err := json.Unmarshal(resp.Body.Bytes(), &entry) 255 assert.NoError(t, err) 256 257 assert.Equal(t, packageName, entry.Name) 258 assert.Equal(t, packageVersion, entry.Version) 259 assert.Equal(t, pb.HashSHA256, entry.FileChecksum) 260 assert.False(t, entry.Yanked) 261 assert.Len(t, entry.Dependencies, 1) 262 dep := entry.Dependencies[0] 263 assert.Equal(t, "dep", dep.Name) 264 assert.Equal(t, "1.0", dep.Req) 265 assert.Equal(t, "normal", dep.Kind) 266 assert.True(t, dep.DefaultFeatures) 267 assert.Empty(t, dep.Features) 268 assert.False(t, dep.Optional) 269 assert.Nil(t, dep.Target) 270 assert.NotNil(t, dep.Registry) 271 assert.Equal(t, "https://gitea.io/user/_cargo-index", *dep.Registry) 272 assert.Nil(t, dep.Package) 273 }) 274 }) 275 }) 276 }) 277 }) 278 279 t.Run("Download", func(t *testing.T) { 280 defer tests.PrintCurrentTest(t)() 281 282 pv, err := packages.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages.TypeCargo, packageName, packageVersion) 283 assert.NoError(t, err) 284 assert.EqualValues(t, 0, pv.DownloadCount) 285 286 pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pv.ID) 287 assert.NoError(t, err) 288 assert.Len(t, pfs, 1) 289 290 req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s/download", url, neturl.PathEscape(packageName), neturl.PathEscape(pv.Version))). 291 AddBasicAuth(user.Name) 292 resp := MakeRequest(t, req, http.StatusOK) 293 294 assert.Equal(t, "test", resp.Body.String()) 295 296 pv, err = packages.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages.TypeCargo, packageName, packageVersion) 297 assert.NoError(t, err) 298 assert.EqualValues(t, 1, pv.DownloadCount) 299 }) 300 301 t.Run("Search", func(t *testing.T) { 302 defer tests.PrintCurrentTest(t)() 303 304 cases := []struct { 305 Query string 306 Page int 307 PerPage int 308 ExpectedTotal int64 309 ExpectedResults int 310 }{ 311 {"", 0, 0, 1, 1}, 312 {"", 1, 10, 1, 1}, 313 {"cargo", 1, 0, 1, 1}, 314 {"cargo", 1, 10, 1, 1}, 315 {"cargo", 2, 10, 1, 0}, 316 {"test", 0, 10, 0, 0}, 317 } 318 319 for i, c := range cases { 320 req := NewRequest(t, "GET", fmt.Sprintf("%s?q=%s&page=%d&per_page=%d", url, c.Query, c.Page, c.PerPage)). 321 AddBasicAuth(user.Name) 322 resp := MakeRequest(t, req, http.StatusOK) 323 324 var result cargo_router.SearchResult 325 DecodeJSON(t, resp, &result) 326 327 assert.Equal(t, c.ExpectedTotal, result.Meta.Total, "case %d: unexpected total hits", i) 328 assert.Len(t, result.Crates, c.ExpectedResults, "case %d: unexpected result count", i) 329 } 330 }) 331 332 t.Run("Yank", func(t *testing.T) { 333 defer tests.PrintCurrentTest(t)() 334 335 req := NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s/yank", url, neturl.PathEscape(packageName), neturl.PathEscape(packageVersion))). 336 AddBasicAuth(user.Name) 337 resp := MakeRequest(t, req, http.StatusOK) 338 339 var status cargo_router.StatusResponse 340 DecodeJSON(t, resp, &status) 341 assert.True(t, status.OK) 342 343 content := readGitContent(t, cargo_service.BuildPackagePath(packageName)) 344 345 var entry cargo_service.IndexVersionEntry 346 err := json.Unmarshal([]byte(content), &entry) 347 assert.NoError(t, err) 348 349 assert.True(t, entry.Yanked) 350 }) 351 352 t.Run("Unyank", func(t *testing.T) { 353 defer tests.PrintCurrentTest(t)() 354 355 req := NewRequest(t, "PUT", fmt.Sprintf("%s/%s/%s/unyank", url, neturl.PathEscape(packageName), neturl.PathEscape(packageVersion))). 356 AddBasicAuth(user.Name) 357 resp := MakeRequest(t, req, http.StatusOK) 358 359 var status cargo_router.StatusResponse 360 DecodeJSON(t, resp, &status) 361 assert.True(t, status.OK) 362 363 content := readGitContent(t, cargo_service.BuildPackagePath(packageName)) 364 365 var entry cargo_service.IndexVersionEntry 366 err := json.Unmarshal([]byte(content), &entry) 367 assert.NoError(t, err) 368 369 assert.False(t, entry.Yanked) 370 }) 371 372 t.Run("ListOwners", func(t *testing.T) { 373 defer tests.PrintCurrentTest(t)() 374 375 req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/owners", url, neturl.PathEscape(packageName))) 376 resp := MakeRequest(t, req, http.StatusOK) 377 378 var owners cargo_router.Owners 379 DecodeJSON(t, resp, &owners) 380 381 assert.Len(t, owners.Users, 1) 382 assert.Equal(t, user.ID, owners.Users[0].ID) 383 assert.Equal(t, user.Name, owners.Users[0].Login) 384 assert.Equal(t, user.DisplayName(), owners.Users[0].Name) 385 }) 386 }