diff --git a/routers/api/packages/nuget/api_v3.go b/routers/api/packages/nuget/api_v3.go index 552054f26b2e3..bb3e447bd647f 100644 --- a/routers/api/packages/nuget/api_v3.go +++ b/routers/api/packages/nuget/api_v3.go @@ -207,20 +207,13 @@ type SearchResultVersion struct { } func createSearchResultResponse(l *linkBuilder, totalHits int64, pds []*packages_model.PackageDescriptor) *SearchResultResponse { - data := make([]*SearchResult, 0, len(pds)) + grouped := make(map[string][]*packages_model.PackageDescriptor) + for _, pd := range pds { + grouped[pd.Package.Name] = append(grouped[pd.Package.Name], pd) + } - if len(pds) > 0 { - groupID := pds[0].Package.Name - group := make([]*packages_model.PackageDescriptor, 0, 10) - - for i := 0; i < len(pds); i++ { - if groupID != pds[i].Package.Name { - data = append(data, createSearchResult(l, group)) - groupID = pds[i].Package.Name - group = group[:0] - } - group = append(group, pds[i]) - } + data := make([]*SearchResult, 0, len(pds)) + for _, group := range grouped { data = append(data, createSearchResult(l, group)) } diff --git a/tests/integration/api_packages_nuget_test.go b/tests/integration/api_packages_nuget_test.go index f1f8a950c605d..bf4217ef26217 100644 --- a/tests/integration/api_packages_nuget_test.go +++ b/tests/integration/api_packages_nuget_test.go @@ -11,6 +11,7 @@ import ( "encoding/xml" "fmt" "io" + "io/ioutil" "net/http" "net/http/httptest" "testing" @@ -83,25 +84,29 @@ func TestPackageNuGet(t *testing.T) { symbolFilename := "test.pdb" symbolID := "d910bb6948bd4c6cb40155bcf52c3c94" - var buf bytes.Buffer - archive := zip.NewWriter(&buf) - w, _ := archive.Create("package.nuspec") - w.Write([]byte(` - - - ` + packageName + ` - ` + packageVersion + ` - ` + packageAuthors + ` - ` + packageDescription + ` - - - - - - - `)) - archive.Close() - content := buf.Bytes() + createPackage := func(id, version string) io.Reader { + var buf bytes.Buffer + archive := zip.NewWriter(&buf) + w, _ := archive.Create("package.nuspec") + w.Write([]byte(` + + + ` + id + ` + ` + version + ` + ` + packageAuthors + ` + ` + packageDescription + ` + + + + + + + `)) + archive.Close() + return &buf + } + + content, _ := ioutil.ReadAll(createPackage(packageName, packageVersion)) url := fmt.Sprintf("/api/packages/%s/nuget", user.Name) @@ -242,7 +247,7 @@ func TestPackageNuGet(t *testing.T) { t.Run("SymbolPackage", func(t *testing.T) { defer tests.PrintCurrentTest(t)() - createPackage := func(id, packageType string) io.Reader { + createSymbolPackage := func(id, packageType string) io.Reader { var buf bytes.Buffer archive := zip.NewWriter(&buf) @@ -268,15 +273,15 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) return &buf } - req := NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createPackage("unknown-package", "SymbolsPackage")) + req := NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage("unknown-package", "SymbolsPackage")) req = AddBasicAuthHeader(req, user.Name) MakeRequest(t, req, http.StatusNotFound) - req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createPackage(packageName, "DummyPackage")) + req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage(packageName, "DummyPackage")) req = AddBasicAuthHeader(req, user.Name) MakeRequest(t, req, http.StatusBadRequest) - req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createPackage(packageName, "SymbolsPackage")) + req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage(packageName, "SymbolsPackage")) req = AddBasicAuthHeader(req, user.Name) MakeRequest(t, req, http.StatusCreated) @@ -320,7 +325,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) } } - req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createPackage(packageName, "SymbolsPackage")) + req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/symbolpackage", url), createSymbolPackage(packageName, "SymbolsPackage")) req = AddBasicAuthHeader(req, user.Name) MakeRequest(t, req, http.StatusConflict) }) @@ -437,6 +442,43 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) assert.Equal(t, c.ExpectedTotal, result.TotalHits, "case %d: unexpected total hits", i) assert.Len(t, result.Data, c.ExpectedResults, "case %d: unexpected result count", i) } + + t.Run("EnforceGrouped", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequestWithBody(t, "PUT", url, createPackage(packageName+".dummy", "1.0.0")) + req = AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, http.StatusCreated) + + req = NewRequestWithBody(t, "PUT", url, createPackage(packageName, "1.0.99")) + req = AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, http.StatusCreated) + + req = NewRequest(t, "GET", fmt.Sprintf("%s/query?q=%s", url, packageName)) + req = AddBasicAuthHeader(req, user.Name) + resp := MakeRequest(t, req, http.StatusOK) + + var result nuget.SearchResultResponse + DecodeJSON(t, resp, &result) + + assert.EqualValues(t, 3, result.TotalHits) + assert.Len(t, result.Data, 2) + for _, sr := range result.Data { + if sr.ID == packageName { + assert.Len(t, sr.Versions, 2) + } else { + assert.Len(t, sr.Versions, 1) + } + } + + req = NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName+".dummy", "1.0.0")) + req = AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, http.StatusNoContent) + + req = NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName, "1.0.99")) + req = AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, http.StatusNoContent) + }) }) })