loading up the forgejo repo on tangled to test page performance
fork

Configure Feed

Select the types of activity you want to include in your feed.

at forgejo 817 lines 30 kB view raw
1// Copyright 2021 The Gitea Authors. All rights reserved. 2// SPDX-License-Identifier: MIT 3 4package integration 5 6import ( 7 "archive/zip" 8 "bytes" 9 "encoding/base64" 10 "encoding/xml" 11 "fmt" 12 "io" 13 "net/http" 14 "net/http/httptest" 15 neturl "net/url" 16 "strconv" 17 "testing" 18 "time" 19 20 auth_model "forgejo.org/models/auth" 21 "forgejo.org/models/db" 22 "forgejo.org/models/packages" 23 "forgejo.org/models/unittest" 24 user_model "forgejo.org/models/user" 25 nuget_module "forgejo.org/modules/packages/nuget" 26 "forgejo.org/modules/setting" 27 "forgejo.org/modules/structs" 28 "forgejo.org/routers/api/packages/nuget" 29 "forgejo.org/tests" 30 31 "github.com/stretchr/testify/assert" 32 "github.com/stretchr/testify/require" 33) 34 35func addNuGetAPIKeyHeader(req *RequestWrapper, token string) { 36 req.SetHeader("X-NuGet-ApiKey", token) 37} 38 39func decodeXML(t testing.TB, resp *httptest.ResponseRecorder, v any) { 40 t.Helper() 41 42 require.NoError(t, xml.NewDecoder(resp.Body).Decode(v)) 43} 44 45func TestPackageNuGet(t *testing.T) { 46 defer tests.PrepareTestEnv(t)() 47 48 type FeedEntryProperties struct { 49 Version string `xml:"Version"` 50 NormalizedVersion string `xml:"NormalizedVersion"` 51 Authors string `xml:"Authors"` 52 Owners string `xml:"Owners,omitempty"` 53 Copyright string `xml:"Copyright,omitempty"` 54 Language string `xml:"Language,omitempty"` 55 Dependencies string `xml:"Dependencies"` 56 Description string `xml:"Description"` 57 VersionDownloadCount nuget.TypedValue[int64] `xml:"VersionDownloadCount"` 58 DownloadCount nuget.TypedValue[int64] `xml:"DownloadCount"` 59 PackageSize nuget.TypedValue[int64] `xml:"PackageSize"` 60 Created nuget.TypedValue[time.Time] `xml:"Created"` 61 LastUpdated nuget.TypedValue[time.Time] `xml:"LastUpdated"` 62 Published nuget.TypedValue[time.Time] `xml:"Published"` 63 ProjectURL string `xml:"ProjectUrl,omitempty"` 64 LicenseURL string `xml:"LicenseUrl,omitempty"` 65 IconURL string `xml:"IconUrl,omitempty"` 66 ReleaseNotes string `xml:"ReleaseNotes,omitempty"` 67 RequireLicenseAcceptance nuget.TypedValue[bool] `xml:"RequireLicenseAcceptance"` 68 DevelopmentDependency nuget.TypedValue[bool] `xml:"DevelopmentDependency"` 69 Title string `xml:"Title"` 70 MinClientVersion string `xml:"MinClientVersion,omitempty"` 71 Tags string `xml:"Tags,omitempty"` 72 ID string `xml:"Id,omitempty"` 73 } 74 75 type FeedEntry struct { 76 XMLName xml.Name `xml:"entry"` 77 Properties *FeedEntryProperties `xml:"properties"` 78 Content string `xml:",innerxml"` 79 } 80 81 type FeedEntryLink struct { 82 Rel string `xml:"rel,attr"` 83 Href string `xml:"href,attr"` 84 } 85 86 type FeedResponse struct { 87 XMLName xml.Name `xml:"feed"` 88 Links []FeedEntryLink `xml:"link"` 89 Entries []*FeedEntry `xml:"entry"` 90 Count int64 `xml:"count"` 91 } 92 93 user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 94 token := getUserToken(t, user.Name, auth_model.AccessTokenScopeWritePackage) 95 96 packageName := "test.package" 97 packageVersion := "1.0.3" 98 packageAuthors := "KN4CK3R" 99 packageDescription := "Forgejo Test Package" 100 symbolFilename := "test.pdb" 101 symbolID := "d910bb6948bd4c6cb40155bcf52c3c94" 102 103 packageTitle := "Package Title" 104 packageLanguage := "Package Language" 105 packageOwners := "Package Owners" 106 packageCopyright := "Package Copyright" 107 packageProjectURL := "https://forgejo.org" 108 packageLicenseURL := "https://forgejo.org/docs/latest/license/" 109 packageIconURL := "https://codeberg.org/forgejo/governance/raw/branch/main/branding/logo/forgejo.png" 110 packageReleaseNotes := "Package Release Notes" 111 packageTags := "tag_1 tag_2 tag_3" 112 packageMinClientVersion := "1.0.0.0" 113 114 createPackage := func(id, version string) io.Reader { 115 var buf bytes.Buffer 116 archive := zip.NewWriter(&buf) 117 w, _ := archive.Create("package.nuspec") 118 w.Write([]byte(`<?xml version="1.0" encoding="utf-8"?> 119 <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> 120 <metadata minClientVersion="` + packageMinClientVersion + `"> 121 <id>` + id + `</id> 122 <title>` + packageTitle + `</title> 123 <language>` + packageLanguage + `</language> 124 <version>` + version + `</version> 125 <authors>` + packageAuthors + `</authors> 126 <owners>` + packageOwners + `</owners> 127 <copyright>` + packageCopyright + `</copyright> 128 <developmentDependency>true</developmentDependency> 129 <requireLicenseAcceptance>true</requireLicenseAcceptance> 130 <projectUrl>` + packageProjectURL + `</projectUrl> 131 <licenseUrl>` + packageLicenseURL + `</licenseUrl> 132 <iconUrl>` + packageIconURL + `</iconUrl> 133 <description>` + packageDescription + `</description> 134 <releaseNotes>` + packageReleaseNotes + `</releaseNotes> 135 <tags>` + packageTags + `</tags> 136 <dependencies> 137 <group targetFramework=".NETStandard2.0"> 138 <dependency id="Microsoft.CSharp" version="4.5.0" /> 139 </group> 140 </dependencies> 141 </metadata> 142 </package>`)) 143 archive.Close() 144 return &buf 145 } 146 147 nuspec := `<?xml version="1.0" encoding="utf-8"?> 148 <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> 149 <metadata minClientVersion="` + packageMinClientVersion + `"> 150 <id>` + packageName + `</id> 151 <title>` + packageTitle + `</title> 152 <language>` + packageLanguage + `</language> 153 <version>` + packageVersion + `</version> 154 <authors>` + packageAuthors + `</authors> 155 <owners>` + packageOwners + `</owners> 156 <copyright>` + packageCopyright + `</copyright> 157 <developmentDependency>true</developmentDependency> 158 <requireLicenseAcceptance>true</requireLicenseAcceptance> 159 <projectUrl>` + packageProjectURL + `</projectUrl> 160 <licenseUrl>` + packageLicenseURL + `</licenseUrl> 161 <iconUrl>` + packageIconURL + `</iconUrl> 162 <description>` + packageDescription + `</description> 163 <releaseNotes>` + packageReleaseNotes + `</releaseNotes> 164 <tags>` + packageTags + `</tags> 165 <dependencies> 166 <group targetFramework=".NETStandard2.0"> 167 <dependency id="Microsoft.CSharp" version="4.5.0" /> 168 </group> 169 </dependencies> 170 </metadata> 171 </package>` 172 content, _ := io.ReadAll(createPackage(packageName, packageVersion)) 173 174 url := fmt.Sprintf("/api/packages/%s/nuget", user.Name) 175 176 t.Run("ServiceIndex", func(t *testing.T) { 177 t.Run("v2", func(t *testing.T) { 178 defer tests.PrintCurrentTest(t)() 179 180 privateUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{Visibility: structs.VisibleTypePrivate}) 181 182 cases := []struct { 183 Owner string 184 UseBasicAuth bool 185 UseTokenAuth bool 186 }{ 187 {privateUser.Name, false, false}, 188 {privateUser.Name, true, false}, 189 {privateUser.Name, false, true}, 190 {user.Name, false, false}, 191 {user.Name, true, false}, 192 {user.Name, false, true}, 193 } 194 195 for _, c := range cases { 196 url := fmt.Sprintf("/api/packages/%s/nuget", c.Owner) 197 198 req := NewRequest(t, "GET", url) 199 if c.UseBasicAuth { 200 req.AddBasicAuth(user.Name) 201 } else if c.UseTokenAuth { 202 addNuGetAPIKeyHeader(req, token) 203 } 204 resp := MakeRequest(t, req, http.StatusOK) 205 206 var result nuget.ServiceIndexResponseV2 207 decodeXML(t, resp, &result) 208 209 assert.Equal(t, setting.AppURL+url[1:], result.Base) 210 assert.Equal(t, "Packages", result.Workspace.Collection.Href) 211 } 212 }) 213 214 t.Run("v3", func(t *testing.T) { 215 defer tests.PrintCurrentTest(t)() 216 217 privateUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{Visibility: structs.VisibleTypePrivate}) 218 219 cases := []struct { 220 Owner string 221 UseBasicAuth bool 222 UseTokenAuth bool 223 }{ 224 {privateUser.Name, false, false}, 225 {privateUser.Name, true, false}, 226 {privateUser.Name, false, true}, 227 {user.Name, false, false}, 228 {user.Name, true, false}, 229 {user.Name, false, true}, 230 } 231 232 for _, c := range cases { 233 url := fmt.Sprintf("/api/packages/%s/nuget", c.Owner) 234 235 req := NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url)) 236 if c.UseBasicAuth { 237 req.AddBasicAuth(user.Name) 238 } else if c.UseTokenAuth { 239 addNuGetAPIKeyHeader(req, token) 240 } 241 resp := MakeRequest(t, req, http.StatusOK) 242 243 var result nuget.ServiceIndexResponseV3 244 DecodeJSON(t, resp, &result) 245 246 assert.Equal(t, "3.0.0", result.Version) 247 assert.NotEmpty(t, result.Resources) 248 249 root := setting.AppURL + url[1:] 250 for _, r := range result.Resources { 251 switch r.Type { 252 case "SearchQueryService": 253 fallthrough 254 case "SearchQueryService/3.0.0-beta": 255 fallthrough 256 case "SearchQueryService/3.0.0-rc": 257 assert.Equal(t, root+"/query", r.ID) 258 case "RegistrationsBaseUrl": 259 fallthrough 260 case "RegistrationsBaseUrl/3.0.0-beta": 261 fallthrough 262 case "RegistrationsBaseUrl/3.0.0-rc": 263 assert.Equal(t, root+"/registration", r.ID) 264 case "PackageBaseAddress/3.0.0": 265 assert.Equal(t, root+"/package", r.ID) 266 case "PackagePublish/2.0.0": 267 assert.Equal(t, root, r.ID) 268 } 269 } 270 } 271 }) 272 }) 273 274 t.Run("Upload", func(t *testing.T) { 275 t.Run("DependencyPackage", func(t *testing.T) { 276 defer tests.PrintCurrentTest(t)() 277 278 req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)). 279 AddBasicAuth(user.Name) 280 MakeRequest(t, req, http.StatusCreated) 281 282 pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeNuGet) 283 require.NoError(t, err) 284 assert.Len(t, pvs, 1, "Should have one version") 285 286 pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) 287 require.NoError(t, err) 288 assert.NotNil(t, pd.SemVer) 289 assert.IsType(t, &nuget_module.Metadata{}, pd.Metadata) 290 assert.Equal(t, packageName, pd.Package.Name) 291 assert.Equal(t, packageVersion, pd.Version.Version) 292 293 pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID) 294 require.NoError(t, err) 295 assert.Len(t, pfs, 2, "Should have 2 files: nuget and nuspec") 296 assert.Equal(t, fmt.Sprintf("%s.%s.nupkg", packageName, packageVersion), pfs[0].Name) 297 assert.True(t, pfs[0].IsLead) 298 299 pb, err := packages.GetBlobByID(db.DefaultContext, pfs[0].BlobID) 300 require.NoError(t, err) 301 assert.Equal(t, int64(len(content)), pb.Size) 302 303 req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)). 304 AddBasicAuth(user.Name) 305 MakeRequest(t, req, http.StatusConflict) 306 }) 307 308 t.Run("SymbolPackage", func(t *testing.T) { 309 defer tests.PrintCurrentTest(t)() 310 311 createSymbolPackage := func(id, packageType string) io.Reader { 312 var buf bytes.Buffer 313 archive := zip.NewWriter(&buf) 314 315 w, _ := archive.Create("package.nuspec") 316 w.Write([]byte(`<?xml version="1.0" encoding="utf-8"?> 317 <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> 318 <metadata> 319 <id>` + id + `</id> 320 <version>` + packageVersion + `</version> 321 <authors>` + packageAuthors + `</authors> 322 <description>` + packageDescription + `</description> 323 <packageTypes><packageType name="` + packageType + `" /></packageTypes> 324 </metadata> 325 </package>`)) 326 327 w, _ = archive.Create(symbolFilename) 328 b, _ := base64.StdEncoding.DecodeString(`QlNKQgEAAQAAAAAADAAAAFBEQiB2MS4wAAAAAAAABgB8AAAAWAAAACNQZGIAAAAA1AAAAAgBAAAj 329fgAA3AEAAAQAAAAjU3RyaW5ncwAAAADgAQAABAAAACNVUwDkAQAAMAAAACNHVUlEAAAAFAIAACgB 330AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) 331 w.Write(b) 332 333 archive.Close() 334 return &buf 335 } 336 337 req := NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage("unknown-package", "SymbolsPackage")). 338 AddBasicAuth(user.Name) 339 MakeRequest(t, req, http.StatusNotFound) 340 341 req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage(packageName, "DummyPackage")). 342 AddBasicAuth(user.Name) 343 MakeRequest(t, req, http.StatusBadRequest) 344 345 req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage(packageName, "SymbolsPackage")). 346 AddBasicAuth(user.Name) 347 MakeRequest(t, req, http.StatusCreated) 348 349 pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeNuGet) 350 require.NoError(t, err) 351 assert.Len(t, pvs, 1) 352 353 pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) 354 require.NoError(t, err) 355 assert.NotNil(t, pd.SemVer) 356 assert.IsType(t, &nuget_module.Metadata{}, pd.Metadata) 357 assert.Equal(t, packageName, pd.Package.Name) 358 assert.Equal(t, packageVersion, pd.Version.Version) 359 360 pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID) 361 require.NoError(t, err) 362 assert.Len(t, pfs, 4, "Should have 4 files: nupkg, snupkg, nuspec and pdb") 363 for _, pf := range pfs { 364 switch pf.Name { 365 case fmt.Sprintf("%s.%s.nupkg", packageName, packageVersion): 366 assert.True(t, pf.IsLead) 367 368 pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID) 369 require.NoError(t, err) 370 assert.Equal(t, int64(len(content)), pb.Size) 371 case fmt.Sprintf("%s.%s.snupkg", packageName, packageVersion): 372 assert.False(t, pf.IsLead) 373 374 pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID) 375 require.NoError(t, err) 376 assert.Equal(t, int64(616), pb.Size) 377 case fmt.Sprintf("%s.nuspec", packageName): 378 assert.False(t, pf.IsLead) 379 380 pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID) 381 require.NoError(t, err) 382 assert.Equal(t, int64(len([]byte(nuspec))), pb.Size) 383 case symbolFilename: 384 assert.False(t, pf.IsLead) 385 386 pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID) 387 require.NoError(t, err) 388 assert.Equal(t, int64(160), pb.Size) 389 390 pps, err := packages.GetProperties(db.DefaultContext, packages.PropertyTypeFile, pf.ID) 391 require.NoError(t, err) 392 assert.Len(t, pps, 1) 393 assert.Equal(t, nuget_module.PropertySymbolID, pps[0].Name) 394 assert.Equal(t, symbolID, pps[0].Value) 395 default: 396 assert.FailNow(t, "unexpected file", "name: %s", pf.Name) 397 } 398 } 399 400 req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage(packageName, "SymbolsPackage")). 401 AddBasicAuth(user.Name) 402 MakeRequest(t, req, http.StatusConflict) 403 }) 404 }) 405 406 t.Run("Download", func(t *testing.T) { 407 defer tests.PrintCurrentTest(t)() 408 409 checkDownloadCount := func(count int64) { 410 pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeNuGet) 411 require.NoError(t, err) 412 assert.Len(t, pvs, 1) 413 assert.Equal(t, count, pvs[0].DownloadCount) 414 } 415 416 checkDownloadCount(0) 417 418 req := NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s.%s.nupkg", url, packageName, packageVersion, packageName, packageVersion)). 419 AddBasicAuth(user.Name) 420 resp := MakeRequest(t, req, http.StatusOK) 421 422 assert.Equal(t, content, resp.Body.Bytes()) 423 424 req = NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s.nuspec", url, packageName, packageVersion, packageName)). 425 AddBasicAuth(user.Name) 426 resp = MakeRequest(t, req, http.StatusOK) 427 428 assert.Equal(t, nuspec, resp.Body.String()) 429 430 checkDownloadCount(1) 431 432 req = NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s.%s.snupkg", url, packageName, packageVersion, packageName, packageVersion)). 433 AddBasicAuth(user.Name) 434 MakeRequest(t, req, http.StatusOK) 435 436 checkDownloadCount(1) 437 438 t.Run("Symbol", func(t *testing.T) { 439 defer tests.PrintCurrentTest(t)() 440 441 req := NewRequest(t, "GET", fmt.Sprintf("%s/symbols/%s/%sFFFFFFFF/gitea.pdb", url, symbolFilename, symbolID)) 442 MakeRequest(t, req, http.StatusBadRequest) 443 444 req = NewRequest(t, "GET", fmt.Sprintf("%s/symbols/%s/%sFFFFFFFF/%s", url, symbolFilename, "00000000000000000000000000000000", symbolFilename)). 445 AddBasicAuth(user.Name) 446 MakeRequest(t, req, http.StatusNotFound) 447 448 req = NewRequest(t, "GET", fmt.Sprintf("%s/symbols/%s/%sFFFFffff/%s", url, symbolFilename, symbolID, symbolFilename)). 449 AddBasicAuth(user.Name) 450 MakeRequest(t, req, http.StatusOK) 451 452 checkDownloadCount(1) 453 }) 454 }) 455 456 containsOneNextLink := func(t *testing.T, links []FeedEntryLink) func() bool { 457 return func() bool { 458 found := 0 459 for _, l := range links { 460 if l.Rel == "next" { 461 found++ 462 u, err := neturl.Parse(l.Href) 463 require.NoError(t, err) 464 q := u.Query() 465 assert.Contains(t, q, "$skip") 466 assert.Contains(t, q, "$top") 467 assert.Equal(t, "1", q.Get("$skip")) 468 assert.Equal(t, "1", q.Get("$top")) 469 } 470 } 471 return found == 1 472 } 473 } 474 475 t.Run("SearchService", func(t *testing.T) { 476 cases := []struct { 477 Query string 478 Skip int 479 Take int 480 ExpectedTotal int64 481 ExpectedResults int 482 ExpectedExactMatch bool 483 }{ 484 {"", 0, 0, 4, 4, false}, 485 {"", 0, 10, 4, 4, false}, 486 {"gitea", 0, 10, 0, 0, false}, 487 {"test", 0, 10, 1, 1, false}, 488 {"test", 1, 10, 1, 0, false}, 489 {"almost.similar", 0, 0, 3, 3, true}, 490 } 491 492 fakePackages := []string{ 493 packageName, 494 "almost.similar.dependency", 495 "almost.similar", 496 "almost.similar.dependent", 497 } 498 499 for _, fakePackageName := range fakePackages { 500 req := NewRequestWithBody(t, "PUT", url, createPackage(fakePackageName, "1.0.99")). 501 AddBasicAuth(user.Name) 502 MakeRequest(t, req, http.StatusCreated) 503 } 504 505 t.Run("v2", func(t *testing.T) { 506 t.Run("Search()", func(t *testing.T) { 507 defer tests.PrintCurrentTest(t)() 508 509 for i, c := range cases { 510 req := NewRequest(t, "GET", fmt.Sprintf("%s/Search()?searchTerm='%s'&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). 511 AddBasicAuth(user.Name) 512 resp := MakeRequest(t, req, http.StatusOK) 513 514 var result FeedResponse 515 decodeXML(t, resp, &result) 516 517 assert.Equal(t, c.ExpectedTotal, result.Count, "case %d: unexpected total hits", i) 518 assert.Len(t, result.Entries, c.ExpectedResults, "case %d: unexpected result count", i) 519 520 req = NewRequest(t, "GET", fmt.Sprintf("%s/Search()/$count?searchTerm='%s'&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). 521 AddBasicAuth(user.Name) 522 resp = MakeRequest(t, req, http.StatusOK) 523 524 assert.Equal(t, strconv.FormatInt(c.ExpectedTotal, 10), resp.Body.String(), "case %d: unexpected total hits", i) 525 } 526 }) 527 528 t.Run("Packages()", func(t *testing.T) { 529 defer tests.PrintCurrentTest(t)() 530 531 for i, c := range cases { 532 req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages()?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). 533 AddBasicAuth(user.Name) 534 resp := MakeRequest(t, req, http.StatusOK) 535 536 var result FeedResponse 537 decodeXML(t, resp, &result) 538 539 assert.Equal(t, c.ExpectedTotal, result.Count, "case %d: unexpected total hits", i) 540 assert.Len(t, result.Entries, c.ExpectedResults, "case %d: unexpected result count", i) 541 542 req = NewRequest(t, "GET", fmt.Sprintf("%s/Packages()/$count?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). 543 AddBasicAuth(user.Name) 544 resp = MakeRequest(t, req, http.StatusOK) 545 546 assert.Equal(t, strconv.FormatInt(c.ExpectedTotal, 10), resp.Body.String(), "case %d: unexpected total hits", i) 547 } 548 }) 549 550 t.Run("Packages()", func(t *testing.T) { 551 defer tests.PrintCurrentTest(t)() 552 553 t.Run("substringof", func(t *testing.T) { 554 defer tests.PrintCurrentTest(t)() 555 556 for i, c := range cases { 557 req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages()?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). 558 AddBasicAuth(user.Name) 559 resp := MakeRequest(t, req, http.StatusOK) 560 561 var result FeedResponse 562 decodeXML(t, resp, &result) 563 564 assert.Equal(t, c.ExpectedTotal, result.Count, "case %d: unexpected total hits", i) 565 assert.Len(t, result.Entries, c.ExpectedResults, "case %d: unexpected result count", i) 566 567 req = NewRequest(t, "GET", fmt.Sprintf("%s/Packages()/$count?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). 568 AddBasicAuth(user.Name) 569 resp = MakeRequest(t, req, http.StatusOK) 570 571 assert.Equal(t, strconv.FormatInt(c.ExpectedTotal, 10), resp.Body.String(), "case %d: unexpected total hits", i) 572 } 573 }) 574 575 t.Run("IdEq", func(t *testing.T) { 576 defer tests.PrintCurrentTest(t)() 577 578 for i, c := range cases { 579 if c.Query == "" { 580 // Ignore the `tolower(Id) eq ''` as it's unlikely to happen 581 continue 582 } 583 req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages()?$filter=(tolower(Id) eq '%s')&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). 584 AddBasicAuth(user.Name) 585 resp := MakeRequest(t, req, http.StatusOK) 586 587 var result FeedResponse 588 decodeXML(t, resp, &result) 589 590 expectedCount := 0 591 if c.ExpectedExactMatch { 592 expectedCount = 1 593 } 594 595 assert.Equal(t, int64(expectedCount), result.Count, "case %d: unexpected total hits", i) 596 assert.Len(t, result.Entries, expectedCount, "case %d: unexpected result count", i) 597 598 req = NewRequest(t, "GET", fmt.Sprintf("%s/Packages()/$count?$filter=(tolower(Id) eq '%s')&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). 599 AddBasicAuth(user.Name) 600 resp = MakeRequest(t, req, http.StatusOK) 601 602 assert.Equal(t, strconv.FormatInt(int64(expectedCount), 10), resp.Body.String(), "case %d: unexpected total hits", i) 603 } 604 }) 605 }) 606 607 t.Run("Next", func(t *testing.T) { 608 req := NewRequest(t, "GET", fmt.Sprintf("%s/Search()?searchTerm='test'&$skip=0&$top=1", url)). 609 AddBasicAuth(user.Name) 610 resp := MakeRequest(t, req, http.StatusOK) 611 612 var result FeedResponse 613 decodeXML(t, resp, &result) 614 615 assert.Condition(t, containsOneNextLink(t, result.Links)) 616 }) 617 }) 618 619 t.Run("v3", func(t *testing.T) { 620 defer tests.PrintCurrentTest(t)() 621 622 for i, c := range cases { 623 req := NewRequest(t, "GET", fmt.Sprintf("%s/query?q=%s&skip=%d&take=%d", url, c.Query, c.Skip, c.Take)). 624 AddBasicAuth(user.Name) 625 resp := MakeRequest(t, req, http.StatusOK) 626 627 var result nuget.SearchResultResponse 628 DecodeJSON(t, resp, &result) 629 630 assert.Equal(t, c.ExpectedTotal, result.TotalHits, "case %d: unexpected total hits", i) 631 assert.Len(t, result.Data, c.ExpectedResults, "case %d: unexpected result count", i) 632 } 633 634 t.Run("EnforceGrouped", func(t *testing.T) { 635 defer tests.PrintCurrentTest(t)() 636 637 req := NewRequestWithBody(t, "PUT", url, createPackage(packageName+".dummy", "1.0.0")). 638 AddBasicAuth(user.Name) 639 MakeRequest(t, req, http.StatusCreated) 640 641 req = NewRequest(t, "GET", fmt.Sprintf("%s/query?q=%s", url, packageName)). 642 AddBasicAuth(user.Name) 643 resp := MakeRequest(t, req, http.StatusOK) 644 645 var result nuget.SearchResultResponse 646 DecodeJSON(t, resp, &result) 647 648 assert.EqualValues(t, 2, result.TotalHits) 649 assert.Len(t, result.Data, 2) 650 for _, sr := range result.Data { 651 if sr.ID == packageName { 652 assert.Len(t, sr.Versions, 2) 653 } else { 654 assert.Len(t, sr.Versions, 1) 655 } 656 } 657 658 req = NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName+".dummy", "1.0.0")). 659 AddBasicAuth(user.Name) 660 MakeRequest(t, req, http.StatusNoContent) 661 }) 662 }) 663 664 for _, fakePackageName := range fakePackages { 665 req := NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, fakePackageName, "1.0.99")). 666 AddBasicAuth(user.Name) 667 MakeRequest(t, req, http.StatusNoContent) 668 } 669 }) 670 671 t.Run("RegistrationService", func(t *testing.T) { 672 indexURL := fmt.Sprintf("%s%s/registration/%s/index.json", setting.AppURL, url[1:], packageName) 673 leafURL := fmt.Sprintf("%s%s/registration/%s/%s.json", setting.AppURL, url[1:], packageName, packageVersion) 674 contentURL := fmt.Sprintf("%s%s/package/%s/%s/%s.%s.nupkg", setting.AppURL, url[1:], packageName, packageVersion, packageName, packageVersion) 675 676 t.Run("RegistrationIndex", func(t *testing.T) { 677 defer tests.PrintCurrentTest(t)() 678 679 req := NewRequest(t, "GET", fmt.Sprintf("%s/registration/%s/index.json", url, packageName)). 680 AddBasicAuth(user.Name) 681 resp := MakeRequest(t, req, http.StatusOK) 682 683 var result nuget.RegistrationIndexResponse 684 DecodeJSON(t, resp, &result) 685 686 assert.Equal(t, indexURL, result.RegistrationIndexURL) 687 assert.Equal(t, 1, result.Count) 688 assert.Len(t, result.Pages, 1) 689 assert.Equal(t, indexURL, result.Pages[0].RegistrationPageURL) 690 assert.Equal(t, packageVersion, result.Pages[0].Lower) 691 assert.Equal(t, packageVersion, result.Pages[0].Upper) 692 assert.Equal(t, 1, result.Pages[0].Count) 693 assert.Len(t, result.Pages[0].Items, 1) 694 assert.Equal(t, packageName, result.Pages[0].Items[0].CatalogEntry.ID) 695 assert.Equal(t, packageVersion, result.Pages[0].Items[0].CatalogEntry.Version) 696 assert.Equal(t, packageAuthors, result.Pages[0].Items[0].CatalogEntry.Authors) 697 assert.Equal(t, packageDescription, result.Pages[0].Items[0].CatalogEntry.Description) 698 assert.Equal(t, leafURL, result.Pages[0].Items[0].CatalogEntry.CatalogLeafURL) 699 assert.Equal(t, contentURL, result.Pages[0].Items[0].CatalogEntry.PackageContentURL) 700 }) 701 702 t.Run("RegistrationLeaf", func(t *testing.T) { 703 t.Run("v2", func(t *testing.T) { 704 defer tests.PrintCurrentTest(t)() 705 706 req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages(Id='%s',Version='%s')", url, packageName, packageVersion)). 707 AddBasicAuth(user.Name) 708 resp := MakeRequest(t, req, http.StatusOK) 709 710 var result FeedEntry 711 decodeXML(t, resp, &result) 712 713 assert.Equal(t, packageName, result.Properties.ID) 714 assert.Equal(t, packageVersion, result.Properties.Version) 715 assert.Equal(t, packageAuthors, result.Properties.Authors) 716 assert.Equal(t, packageDescription, result.Properties.Description) 717 assert.Equal(t, packageTitle, result.Properties.Title) 718 assert.Equal(t, packageLanguage, result.Properties.Language) 719 assert.Equal(t, packageOwners, result.Properties.Owners) 720 assert.Equal(t, packageCopyright, result.Properties.Copyright) 721 assert.Equal(t, packageProjectURL, result.Properties.ProjectURL) 722 assert.Equal(t, packageLicenseURL, result.Properties.LicenseURL) 723 assert.Equal(t, packageIconURL, result.Properties.IconURL) 724 assert.Equal(t, packageReleaseNotes, result.Properties.ReleaseNotes) 725 assert.Equal(t, packageTags, result.Properties.Tags) 726 assert.Equal(t, packageMinClientVersion, result.Properties.MinClientVersion) 727 assert.True(t, result.Properties.DevelopmentDependency.Value) 728 assert.True(t, result.Properties.RequireLicenseAcceptance.Value) 729 assert.Equal(t, "Microsoft.CSharp:4.5.0:.NETStandard2.0", result.Properties.Dependencies) 730 }) 731 732 t.Run("v3", func(t *testing.T) { 733 defer tests.PrintCurrentTest(t)() 734 735 req := NewRequest(t, "GET", fmt.Sprintf("%s/registration/%s/%s.json", url, packageName, packageVersion)). 736 AddBasicAuth(user.Name) 737 resp := MakeRequest(t, req, http.StatusOK) 738 739 var result nuget.RegistrationLeafResponse 740 DecodeJSON(t, resp, &result) 741 742 assert.Equal(t, leafURL, result.RegistrationLeafURL) 743 assert.Equal(t, contentURL, result.PackageContentURL) 744 assert.Equal(t, indexURL, result.RegistrationIndexURL) 745 }) 746 }) 747 }) 748 749 t.Run("PackageService", func(t *testing.T) { 750 t.Run("v2", func(t *testing.T) { 751 defer tests.PrintCurrentTest(t)() 752 753 req := NewRequest(t, "GET", fmt.Sprintf("%s/FindPackagesById()?id='%s'&$top=1", url, packageName)). 754 AddBasicAuth(user.Name) 755 resp := MakeRequest(t, req, http.StatusOK) 756 757 var result FeedResponse 758 decodeXML(t, resp, &result) 759 760 assert.Len(t, result.Entries, 1) 761 assert.Equal(t, packageVersion, result.Entries[0].Properties.Version) 762 assert.Condition(t, containsOneNextLink(t, result.Links)) 763 764 req = NewRequest(t, "GET", fmt.Sprintf("%s/FindPackagesById()/$count?id='%s'", url, packageName)). 765 AddBasicAuth(user.Name) 766 resp = MakeRequest(t, req, http.StatusOK) 767 768 assert.Equal(t, "1", resp.Body.String()) 769 }) 770 771 t.Run("v3", func(t *testing.T) { 772 defer tests.PrintCurrentTest(t)() 773 774 req := NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/index.json", url, packageName)). 775 AddBasicAuth(user.Name) 776 resp := MakeRequest(t, req, http.StatusOK) 777 778 var result nuget.PackageVersionsResponse 779 DecodeJSON(t, resp, &result) 780 781 assert.Len(t, result.Versions, 1) 782 assert.Equal(t, packageVersion, result.Versions[0]) 783 }) 784 }) 785 786 t.Run("Delete", func(t *testing.T) { 787 defer tests.PrintCurrentTest(t)() 788 789 req := NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName, packageVersion)). 790 AddBasicAuth(user.Name) 791 MakeRequest(t, req, http.StatusNoContent) 792 793 pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeNuGet) 794 require.NoError(t, err) 795 assert.Empty(t, pvs) 796 }) 797 798 t.Run("DownloadNotExists", func(t *testing.T) { 799 defer tests.PrintCurrentTest(t)() 800 801 req := NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s.%s.nupkg", url, packageName, packageVersion, packageName, packageVersion)). 802 AddBasicAuth(user.Name) 803 MakeRequest(t, req, http.StatusNotFound) 804 805 req = NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s.%s.snupkg", url, packageName, packageVersion, packageName, packageVersion)). 806 AddBasicAuth(user.Name) 807 MakeRequest(t, req, http.StatusNotFound) 808 }) 809 810 t.Run("DeleteNotExists", func(t *testing.T) { 811 defer tests.PrintCurrentTest(t)() 812 813 req := NewRequest(t, "DELETE", fmt.Sprintf("%s/package/%s/%s", url, packageName, packageVersion)). 814 AddBasicAuth(user.Name) 815 MakeRequest(t, req, http.StatusNotFound) 816 }) 817}