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