github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/daemon/images/image_search_test.go (about)

     1  package images // import "github.com/docker/docker/daemon/images"
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"testing"
     7  
     8  	"github.com/docker/docker/api/types/filters"
     9  	"github.com/docker/docker/api/types/registry"
    10  	"github.com/docker/docker/errdefs"
    11  	registrypkg "github.com/docker/docker/registry"
    12  	"gotest.tools/v3/assert"
    13  )
    14  
    15  type fakeService struct {
    16  	registrypkg.Service
    17  	shouldReturnError bool
    18  
    19  	term    string
    20  	results []registry.SearchResult
    21  }
    22  
    23  func (s *fakeService) Search(ctx context.Context, term string, limit int, authConfig *registry.AuthConfig, userAgent string, headers map[string][]string) (*registry.SearchResults, error) {
    24  	if s.shouldReturnError {
    25  		return nil, errdefs.Unknown(errors.New("search unknown error"))
    26  	}
    27  	return &registry.SearchResults{
    28  		Query:      s.term,
    29  		NumResults: len(s.results),
    30  		Results:    s.results,
    31  	}, nil
    32  }
    33  
    34  func TestSearchRegistryForImagesErrors(t *testing.T) {
    35  	errorCases := []struct {
    36  		filtersArgs       filters.Args
    37  		shouldReturnError bool
    38  		expectedError     string
    39  	}{
    40  		{
    41  			expectedError:     "search unknown error",
    42  			shouldReturnError: true,
    43  		},
    44  		{
    45  			filtersArgs:   filters.NewArgs(filters.Arg("type", "custom")),
    46  			expectedError: "invalid filter 'type'",
    47  		},
    48  		{
    49  			filtersArgs:   filters.NewArgs(filters.Arg("is-automated", "invalid")),
    50  			expectedError: "invalid filter 'is-automated=[invalid]'",
    51  		},
    52  		{
    53  			filtersArgs: filters.NewArgs(
    54  				filters.Arg("is-automated", "true"),
    55  				filters.Arg("is-automated", "false"),
    56  			),
    57  			expectedError: "invalid filter 'is-automated",
    58  		},
    59  		{
    60  			filtersArgs:   filters.NewArgs(filters.Arg("is-official", "invalid")),
    61  			expectedError: "invalid filter 'is-official=[invalid]'",
    62  		},
    63  		{
    64  			filtersArgs: filters.NewArgs(
    65  				filters.Arg("is-official", "true"),
    66  				filters.Arg("is-official", "false"),
    67  			),
    68  			expectedError: "invalid filter 'is-official",
    69  		},
    70  		{
    71  			filtersArgs:   filters.NewArgs(filters.Arg("stars", "invalid")),
    72  			expectedError: "invalid filter 'stars=invalid'",
    73  		},
    74  		{
    75  			filtersArgs: filters.NewArgs(
    76  				filters.Arg("stars", "1"),
    77  				filters.Arg("stars", "invalid"),
    78  			),
    79  			expectedError: "invalid filter 'stars=invalid'",
    80  		},
    81  	}
    82  	for _, tc := range errorCases {
    83  		tc := tc
    84  		t.Run(tc.expectedError, func(t *testing.T) {
    85  			daemon := &ImageService{
    86  				registryService: &fakeService{
    87  					shouldReturnError: tc.shouldReturnError,
    88  				},
    89  			}
    90  			_, err := daemon.SearchRegistryForImages(context.Background(), tc.filtersArgs, "term", 0, nil, map[string][]string{})
    91  			assert.ErrorContains(t, err, tc.expectedError)
    92  			if tc.shouldReturnError {
    93  				assert.Check(t, errdefs.IsUnknown(err), "got: %T: %v", err, err)
    94  				return
    95  			}
    96  			assert.Check(t, errdefs.IsInvalidParameter(err), "got: %T: %v", err, err)
    97  		})
    98  	}
    99  }
   100  
   101  func TestSearchRegistryForImages(t *testing.T) {
   102  	term := "term"
   103  	successCases := []struct {
   104  		name            string
   105  		filtersArgs     filters.Args
   106  		registryResults []registry.SearchResult
   107  		expectedResults []registry.SearchResult
   108  	}{
   109  		{
   110  			name:            "empty results",
   111  			registryResults: []registry.SearchResult{},
   112  			expectedResults: []registry.SearchResult{},
   113  		},
   114  		{
   115  			name: "no filter",
   116  			registryResults: []registry.SearchResult{
   117  				{
   118  					Name:        "name",
   119  					Description: "description",
   120  				},
   121  			},
   122  			expectedResults: []registry.SearchResult{
   123  				{
   124  					Name:        "name",
   125  					Description: "description",
   126  				},
   127  			},
   128  		},
   129  		{
   130  			name:        "is-automated=true, no results",
   131  			filtersArgs: filters.NewArgs(filters.Arg("is-automated", "true")),
   132  			registryResults: []registry.SearchResult{
   133  				{
   134  					Name:        "name",
   135  					Description: "description",
   136  				},
   137  			},
   138  			expectedResults: []registry.SearchResult{},
   139  		},
   140  		{
   141  			name:        "is-automated=true",
   142  			filtersArgs: filters.NewArgs(filters.Arg("is-automated", "true")),
   143  			registryResults: []registry.SearchResult{
   144  				{
   145  					Name:        "name",
   146  					Description: "description",
   147  					IsAutomated: true,
   148  				},
   149  			},
   150  			expectedResults: []registry.SearchResult{
   151  				{
   152  					Name:        "name",
   153  					Description: "description",
   154  					IsAutomated: true,
   155  				},
   156  			},
   157  		},
   158  		{
   159  			name:        "is-automated=false, no results",
   160  			filtersArgs: filters.NewArgs(filters.Arg("is-automated", "false")),
   161  			registryResults: []registry.SearchResult{
   162  				{
   163  					Name:        "name",
   164  					Description: "description",
   165  					IsAutomated: true,
   166  				},
   167  			},
   168  			expectedResults: []registry.SearchResult{},
   169  		},
   170  		{
   171  			name:        "is-automated=false",
   172  			filtersArgs: filters.NewArgs(filters.Arg("is-automated", "false")),
   173  			registryResults: []registry.SearchResult{
   174  				{
   175  					Name:        "name",
   176  					Description: "description",
   177  					IsAutomated: false,
   178  				},
   179  			},
   180  			expectedResults: []registry.SearchResult{
   181  				{
   182  					Name:        "name",
   183  					Description: "description",
   184  					IsAutomated: false,
   185  				},
   186  			},
   187  		},
   188  		{
   189  			name:        "is-official=true, no results",
   190  			filtersArgs: filters.NewArgs(filters.Arg("is-official", "true")),
   191  			registryResults: []registry.SearchResult{
   192  				{
   193  					Name:        "name",
   194  					Description: "description",
   195  				},
   196  			},
   197  			expectedResults: []registry.SearchResult{},
   198  		},
   199  		{
   200  			name:        "is-official=true",
   201  			filtersArgs: filters.NewArgs(filters.Arg("is-official", "true")),
   202  			registryResults: []registry.SearchResult{
   203  				{
   204  					Name:        "name",
   205  					Description: "description",
   206  					IsOfficial:  true,
   207  				},
   208  			},
   209  			expectedResults: []registry.SearchResult{
   210  				{
   211  					Name:        "name",
   212  					Description: "description",
   213  					IsOfficial:  true,
   214  				},
   215  			},
   216  		},
   217  		{
   218  			name:        "is-official=false, no results",
   219  			filtersArgs: filters.NewArgs(filters.Arg("is-official", "false")),
   220  			registryResults: []registry.SearchResult{
   221  				{
   222  					Name:        "name",
   223  					Description: "description",
   224  					IsOfficial:  true,
   225  				},
   226  			},
   227  			expectedResults: []registry.SearchResult{},
   228  		},
   229  		{
   230  			name:        "is-official=false",
   231  			filtersArgs: filters.NewArgs(filters.Arg("is-official", "false")),
   232  			registryResults: []registry.SearchResult{
   233  				{
   234  					Name:        "name",
   235  					Description: "description",
   236  					IsOfficial:  false,
   237  				},
   238  			},
   239  			expectedResults: []registry.SearchResult{
   240  				{
   241  					Name:        "name",
   242  					Description: "description",
   243  					IsOfficial:  false,
   244  				},
   245  			},
   246  		},
   247  		{
   248  			name:        "stars=0",
   249  			filtersArgs: filters.NewArgs(filters.Arg("stars", "0")),
   250  			registryResults: []registry.SearchResult{
   251  				{
   252  					Name:        "name",
   253  					Description: "description",
   254  					StarCount:   0,
   255  				},
   256  			},
   257  			expectedResults: []registry.SearchResult{
   258  				{
   259  					Name:        "name",
   260  					Description: "description",
   261  					StarCount:   0,
   262  				},
   263  			},
   264  		},
   265  		{
   266  			name:        "stars=0, no results",
   267  			filtersArgs: filters.NewArgs(filters.Arg("stars", "1")),
   268  			registryResults: []registry.SearchResult{
   269  				{
   270  					Name:        "name",
   271  					Description: "description",
   272  					StarCount:   0,
   273  				},
   274  			},
   275  			expectedResults: []registry.SearchResult{},
   276  		},
   277  		{
   278  			name:        "stars=1",
   279  			filtersArgs: filters.NewArgs(filters.Arg("stars", "1")),
   280  			registryResults: []registry.SearchResult{
   281  				{
   282  					Name:        "name0",
   283  					Description: "description0",
   284  					StarCount:   0,
   285  				},
   286  				{
   287  					Name:        "name1",
   288  					Description: "description1",
   289  					StarCount:   1,
   290  				},
   291  			},
   292  			expectedResults: []registry.SearchResult{
   293  				{
   294  					Name:        "name1",
   295  					Description: "description1",
   296  					StarCount:   1,
   297  				},
   298  			},
   299  		},
   300  		{
   301  			name: "stars=1, is-official=true, is-automated=true",
   302  			filtersArgs: filters.NewArgs(
   303  				filters.Arg("stars", "1"),
   304  				filters.Arg("is-official", "true"),
   305  				filters.Arg("is-automated", "true"),
   306  			),
   307  			registryResults: []registry.SearchResult{
   308  				{
   309  					Name:        "name0",
   310  					Description: "description0",
   311  					StarCount:   0,
   312  					IsOfficial:  true,
   313  					IsAutomated: true,
   314  				},
   315  				{
   316  					Name:        "name1",
   317  					Description: "description1",
   318  					StarCount:   1,
   319  					IsOfficial:  false,
   320  					IsAutomated: true,
   321  				},
   322  				{
   323  					Name:        "name2",
   324  					Description: "description2",
   325  					StarCount:   1,
   326  					IsOfficial:  true,
   327  					IsAutomated: false,
   328  				},
   329  				{
   330  					Name:        "name3",
   331  					Description: "description3",
   332  					StarCount:   2,
   333  					IsOfficial:  true,
   334  					IsAutomated: true,
   335  				},
   336  			},
   337  			expectedResults: []registry.SearchResult{
   338  				{
   339  					Name:        "name3",
   340  					Description: "description3",
   341  					StarCount:   2,
   342  					IsOfficial:  true,
   343  					IsAutomated: true,
   344  				},
   345  			},
   346  		},
   347  	}
   348  	for _, tc := range successCases {
   349  		tc := tc
   350  		t.Run(tc.name, func(t *testing.T) {
   351  			daemon := &ImageService{
   352  				registryService: &fakeService{
   353  					term:    term,
   354  					results: tc.registryResults,
   355  				},
   356  			}
   357  			results, err := daemon.SearchRegistryForImages(context.Background(), tc.filtersArgs, term, 0, nil, map[string][]string{})
   358  			assert.NilError(t, err)
   359  			assert.Equal(t, results.Query, term)
   360  			assert.Equal(t, results.NumResults, len(tc.expectedResults))
   361  			assert.DeepEqual(t, results.Results, tc.expectedResults)
   362  		})
   363  	}
   364  }