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