blob: 69329857c627a77c989ab05247150b2e3851c8d9 [file] [log] [blame]
package registry // import "github.com/docker/docker/registry"
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/errdefs"
"gotest.tools/v3/assert"
)
func TestSearchErrors(t *testing.T) {
errorCases := []struct {
filtersArgs filters.Args
shouldReturnError bool
expectedError string
}{
{
expectedError: "Unexpected status code 500",
shouldReturnError: true,
},
{
filtersArgs: filters.NewArgs(filters.Arg("type", "custom")),
expectedError: "invalid filter 'type'",
},
{
filtersArgs: filters.NewArgs(filters.Arg("is-automated", "invalid")),
expectedError: "invalid filter 'is-automated=[invalid]'",
},
{
filtersArgs: filters.NewArgs(
filters.Arg("is-automated", "true"),
filters.Arg("is-automated", "false"),
),
expectedError: "invalid filter 'is-automated",
},
{
filtersArgs: filters.NewArgs(filters.Arg("is-official", "invalid")),
expectedError: "invalid filter 'is-official=[invalid]'",
},
{
filtersArgs: filters.NewArgs(
filters.Arg("is-official", "true"),
filters.Arg("is-official", "false"),
),
expectedError: "invalid filter 'is-official",
},
{
filtersArgs: filters.NewArgs(filters.Arg("stars", "invalid")),
expectedError: "invalid filter 'stars=invalid'",
},
{
filtersArgs: filters.NewArgs(
filters.Arg("stars", "1"),
filters.Arg("stars", "invalid"),
),
expectedError: "invalid filter 'stars=invalid'",
},
}
for _, tc := range errorCases {
tc := tc
t.Run(tc.expectedError, func(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !tc.shouldReturnError {
t.Errorf("unexpected HTTP request")
}
http.Error(w, "no search for you", http.StatusInternalServerError)
}))
defer srv.Close()
// Construct the search term by cutting the 'http://' prefix off srv.URL.
term := srv.URL[7:] + "/term"
reg, err := NewService(ServiceOptions{})
assert.NilError(t, err)
_, err = reg.Search(context.Background(), tc.filtersArgs, term, 0, nil, map[string][]string{})
assert.ErrorContains(t, err, tc.expectedError)
if tc.shouldReturnError {
assert.Check(t, errdefs.IsUnknown(err), "got: %T: %v", err, err)
return
}
assert.Check(t, errdefs.IsInvalidParameter(err), "got: %T: %v", err, err)
})
}
}
func TestSearch(t *testing.T) {
const term = "term"
successCases := []struct {
name string
filtersArgs filters.Args
registryResults []registry.SearchResult
expectedResults []registry.SearchResult
}{
{
name: "empty results",
registryResults: []registry.SearchResult{},
expectedResults: []registry.SearchResult{},
},
{
name: "no filter",
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
},
},
expectedResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
},
},
},
{
name: "is-automated=true, no results",
filtersArgs: filters.NewArgs(filters.Arg("is-automated", "true")),
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
},
},
expectedResults: []registry.SearchResult{},
},
{
name: "is-automated=true",
filtersArgs: filters.NewArgs(filters.Arg("is-automated", "true")),
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
IsAutomated: true,
},
},
expectedResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
IsAutomated: true,
},
},
},
{
name: "is-automated=false, no results",
filtersArgs: filters.NewArgs(filters.Arg("is-automated", "false")),
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
IsAutomated: true,
},
},
expectedResults: []registry.SearchResult{},
},
{
name: "is-automated=false",
filtersArgs: filters.NewArgs(filters.Arg("is-automated", "false")),
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
IsAutomated: false,
},
},
expectedResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
IsAutomated: false,
},
},
},
{
name: "is-official=true, no results",
filtersArgs: filters.NewArgs(filters.Arg("is-official", "true")),
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
},
},
expectedResults: []registry.SearchResult{},
},
{
name: "is-official=true",
filtersArgs: filters.NewArgs(filters.Arg("is-official", "true")),
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
IsOfficial: true,
},
},
expectedResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
IsOfficial: true,
},
},
},
{
name: "is-official=false, no results",
filtersArgs: filters.NewArgs(filters.Arg("is-official", "false")),
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
IsOfficial: true,
},
},
expectedResults: []registry.SearchResult{},
},
{
name: "is-official=false",
filtersArgs: filters.NewArgs(filters.Arg("is-official", "false")),
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
IsOfficial: false,
},
},
expectedResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
IsOfficial: false,
},
},
},
{
name: "stars=0",
filtersArgs: filters.NewArgs(filters.Arg("stars", "0")),
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
StarCount: 0,
},
},
expectedResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
StarCount: 0,
},
},
},
{
name: "stars=0, no results",
filtersArgs: filters.NewArgs(filters.Arg("stars", "1")),
registryResults: []registry.SearchResult{
{
Name: "name",
Description: "description",
StarCount: 0,
},
},
expectedResults: []registry.SearchResult{},
},
{
name: "stars=1",
filtersArgs: filters.NewArgs(filters.Arg("stars", "1")),
registryResults: []registry.SearchResult{
{
Name: "name0",
Description: "description0",
StarCount: 0,
},
{
Name: "name1",
Description: "description1",
StarCount: 1,
},
},
expectedResults: []registry.SearchResult{
{
Name: "name1",
Description: "description1",
StarCount: 1,
},
},
},
{
name: "stars=1, is-official=true, is-automated=true",
filtersArgs: filters.NewArgs(
filters.Arg("stars", "1"),
filters.Arg("is-official", "true"),
filters.Arg("is-automated", "true"),
),
registryResults: []registry.SearchResult{
{
Name: "name0",
Description: "description0",
StarCount: 0,
IsOfficial: true,
IsAutomated: true,
},
{
Name: "name1",
Description: "description1",
StarCount: 1,
IsOfficial: false,
IsAutomated: true,
},
{
Name: "name2",
Description: "description2",
StarCount: 1,
IsOfficial: true,
IsAutomated: false,
},
{
Name: "name3",
Description: "description3",
StarCount: 2,
IsOfficial: true,
IsAutomated: true,
},
},
expectedResults: []registry.SearchResult{
{
Name: "name3",
Description: "description3",
StarCount: 2,
IsOfficial: true,
IsAutomated: true,
},
},
},
}
for _, tc := range successCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type", "application/json")
json.NewEncoder(w).Encode(registry.SearchResults{
Query: term,
NumResults: len(tc.registryResults),
Results: tc.registryResults,
})
}))
defer srv.Close()
// Construct the search term by cutting the 'http://' prefix off srv.URL.
searchTerm := srv.URL[7:] + "/" + term
reg, err := NewService(ServiceOptions{})
assert.NilError(t, err)
results, err := reg.Search(context.Background(), tc.filtersArgs, searchTerm, 0, nil, map[string][]string{})
assert.NilError(t, err)
assert.DeepEqual(t, results, tc.expectedResults)
})
}
}