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 ®istrytypes.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 }