Enforce grouped NuGet search results (#21442)
Fixes #21434 Added tests to enforce this behaviour. Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		
							parent
							
								
									cad9adeff4
								
							
						
					
					
						commit
						11d3677818
					
				| @ -207,20 +207,13 @@ type SearchResultVersion struct { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func createSearchResultResponse(l *linkBuilder, totalHits int64, pds []*packages_model.PackageDescriptor) *SearchResultResponse { | func createSearchResultResponse(l *linkBuilder, totalHits int64, pds []*packages_model.PackageDescriptor) *SearchResultResponse { | ||||||
|  | 	grouped := make(map[string][]*packages_model.PackageDescriptor) | ||||||
|  | 	for _, pd := range pds { | ||||||
|  | 		grouped[pd.Package.Name] = append(grouped[pd.Package.Name], pd) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	data := make([]*SearchResult, 0, len(pds)) | 	data := make([]*SearchResult, 0, len(pds)) | ||||||
| 
 | 	for _, group := range grouped { | ||||||
| 	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 = append(data, createSearchResult(l, group)) | 		data = append(data, createSearchResult(l, group)) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ import ( | |||||||
| 	"encoding/xml" | 	"encoding/xml" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"io/ioutil" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"net/http/httptest" | 	"net/http/httptest" | ||||||
| 	"testing" | 	"testing" | ||||||
| @ -83,25 +84,29 @@ func TestPackageNuGet(t *testing.T) { | |||||||
| 	symbolFilename := "test.pdb" | 	symbolFilename := "test.pdb" | ||||||
| 	symbolID := "d910bb6948bd4c6cb40155bcf52c3c94" | 	symbolID := "d910bb6948bd4c6cb40155bcf52c3c94" | ||||||
| 
 | 
 | ||||||
| 	var buf bytes.Buffer | 	createPackage := func(id, version string) io.Reader { | ||||||
| 	archive := zip.NewWriter(&buf) | 		var buf bytes.Buffer | ||||||
| 	w, _ := archive.Create("package.nuspec") | 		archive := zip.NewWriter(&buf) | ||||||
| 	w.Write([]byte(`<?xml version="1.0" encoding="utf-8"?> | 		w, _ := archive.Create("package.nuspec") | ||||||
| 	<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> | 		w.Write([]byte(`<?xml version="1.0" encoding="utf-8"?> | ||||||
| 	  <metadata> | 		<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> | ||||||
| 		<id>` + packageName + `</id> | 			<metadata> | ||||||
| 		<version>` + packageVersion + `</version> | 				<id>` + id + `</id> | ||||||
| 		<authors>` + packageAuthors + `</authors> | 				<version>` + version + `</version> | ||||||
| 		<description>` + packageDescription + `</description> | 				<authors>` + packageAuthors + `</authors> | ||||||
| 		<dependencies> | 				<description>` + packageDescription + `</description> | ||||||
| 			<group targetFramework=".NETStandard2.0"> | 				<dependencies> | ||||||
| 				<dependency id="Microsoft.CSharp" version="4.5.0" /> | 					<group targetFramework=".NETStandard2.0"> | ||||||
| 			</group> | 						<dependency id="Microsoft.CSharp" version="4.5.0" /> | ||||||
| 		</dependencies> | 					</group> | ||||||
| 	  </metadata> | 				</dependencies> | ||||||
| 	</package>`)) | 			</metadata> | ||||||
| 	archive.Close() | 		</package>`)) | ||||||
| 	content := buf.Bytes() | 		archive.Close() | ||||||
|  | 		return &buf | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	content, _ := ioutil.ReadAll(createPackage(packageName, packageVersion)) | ||||||
| 
 | 
 | ||||||
| 	url := fmt.Sprintf("/api/packages/%s/nuget", user.Name) | 	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) { | 		t.Run("SymbolPackage", func(t *testing.T) { | ||||||
| 			defer tests.PrintCurrentTest(t)() | 			defer tests.PrintCurrentTest(t)() | ||||||
| 
 | 
 | ||||||
| 			createPackage := func(id, packageType string) io.Reader { | 			createSymbolPackage := func(id, packageType string) io.Reader { | ||||||
| 				var buf bytes.Buffer | 				var buf bytes.Buffer | ||||||
| 				archive := zip.NewWriter(&buf) | 				archive := zip.NewWriter(&buf) | ||||||
| 
 | 
 | ||||||
| @ -268,15 +273,15 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) | |||||||
| 				return &buf | 				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) | 			req = AddBasicAuthHeader(req, user.Name) | ||||||
| 			MakeRequest(t, req, http.StatusNotFound) | 			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) | 			req = AddBasicAuthHeader(req, user.Name) | ||||||
| 			MakeRequest(t, req, http.StatusBadRequest) | 			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) | 			req = AddBasicAuthHeader(req, user.Name) | ||||||
| 			MakeRequest(t, req, http.StatusCreated) | 			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) | 			req = AddBasicAuthHeader(req, user.Name) | ||||||
| 			MakeRequest(t, req, http.StatusConflict) | 			MakeRequest(t, req, http.StatusConflict) | ||||||
| 		}) | 		}) | ||||||
| @ -437,6 +442,43 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) | |||||||
| 				assert.Equal(t, c.ExpectedTotal, result.TotalHits, "case %d: unexpected total hits", i) | 				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) | 				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) | ||||||
|  | 			}) | ||||||
| 		}) | 		}) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user