github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/api/types/filters/parse_test.go (about) 1 package filters // import "github.com/docker/docker/api/types/filters" 2 3 import ( 4 "errors" 5 "testing" 6 7 "gotest.tools/v3/assert" 8 is "gotest.tools/v3/assert/cmp" 9 ) 10 11 func TestToJSON(t *testing.T) { 12 fields := map[string]map[string]bool{ 13 "created": {"today": true}, 14 "image.name": {"ubuntu*": true, "*untu": true}, 15 } 16 a := Args{fields: fields} 17 18 _, err := ToJSON(a) 19 if err != nil { 20 t.Errorf("failed to marshal the filters: %s", err) 21 } 22 } 23 24 func TestToParamWithVersion(t *testing.T) { 25 fields := map[string]map[string]bool{ 26 "created": {"today": true}, 27 "image.name": {"ubuntu*": true, "*untu": true}, 28 } 29 a := Args{fields: fields} 30 31 str1, err := ToParamWithVersion("1.21", a) 32 if err != nil { 33 t.Errorf("failed to marshal the filters with version < 1.22: %s", err) 34 } 35 str2, err := ToParamWithVersion("1.22", a) 36 if err != nil { 37 t.Errorf("failed to marshal the filters with version >= 1.22: %s", err) 38 } 39 if str1 != `{"created":["today"],"image.name":["*untu","ubuntu*"]}` && 40 str1 != `{"created":["today"],"image.name":["ubuntu*","*untu"]}` { 41 t.Errorf("incorrectly marshaled the filters: %s", str1) 42 } 43 if str2 != `{"created":{"today":true},"image.name":{"*untu":true,"ubuntu*":true}}` && 44 str2 != `{"created":{"today":true},"image.name":{"ubuntu*":true,"*untu":true}}` { 45 t.Errorf("incorrectly marshaled the filters: %s", str2) 46 } 47 } 48 49 func TestFromJSON(t *testing.T) { 50 invalids := []string{ 51 "anything", 52 "['a','list']", 53 "{'key': 'value'}", 54 `{"key": "value"}`, 55 } 56 valid := map[*Args][]string{ 57 {fields: map[string]map[string]bool{"key": {"value": true}}}: { 58 `{"key": ["value"]}`, 59 `{"key": {"value": true}}`, 60 }, 61 {fields: map[string]map[string]bool{"key": {"value1": true, "value2": true}}}: { 62 `{"key": ["value1", "value2"]}`, 63 `{"key": {"value1": true, "value2": true}}`, 64 }, 65 {fields: map[string]map[string]bool{"key1": {"value1": true}, "key2": {"value2": true}}}: { 66 `{"key1": ["value1"], "key2": ["value2"]}`, 67 `{"key1": {"value1": true}, "key2": {"value2": true}}`, 68 }, 69 } 70 71 for _, invalid := range invalids { 72 _, err := FromJSON(invalid) 73 if err == nil { 74 t.Fatalf("Expected an error with %v, got nothing", invalid) 75 } 76 var invalidFilterError invalidFilter 77 if !errors.As(err, &invalidFilterError) { 78 t.Fatalf("Expected an invalidFilter error, got %T", err) 79 } 80 } 81 82 for expectedArgs, matchers := range valid { 83 for _, json := range matchers { 84 args, err := FromJSON(json) 85 if err != nil { 86 t.Fatal(err) 87 } 88 if args.Len() != expectedArgs.Len() { 89 t.Fatalf("Expected %v, go %v", expectedArgs, args) 90 } 91 for key, expectedValues := range expectedArgs.fields { 92 values := args.Get(key) 93 94 if len(values) != len(expectedValues) { 95 t.Fatalf("Expected %v, go %v", expectedArgs, args) 96 } 97 98 for _, v := range values { 99 if !expectedValues[v] { 100 t.Fatalf("Expected %v, go %v", expectedArgs, args) 101 } 102 } 103 } 104 } 105 } 106 } 107 108 func TestEmpty(t *testing.T) { 109 a := Args{} 110 v, err := ToJSON(a) 111 if err != nil { 112 t.Errorf("failed to marshal the filters: %s", err) 113 } 114 v1, err := FromJSON(v) 115 if err != nil { 116 t.Errorf("%s", err) 117 } 118 if a.Len() != v1.Len() { 119 t.Error("these should both be empty sets") 120 } 121 } 122 123 func TestArgsMatchKVListEmptySources(t *testing.T) { 124 args := NewArgs() 125 if !args.MatchKVList("created", map[string]string{}) { 126 t.Fatalf("Expected true for (%v,created), got true", args) 127 } 128 129 args = Args{map[string]map[string]bool{"created": {"today": true}}} 130 if args.MatchKVList("created", map[string]string{}) { 131 t.Fatalf("Expected false for (%v,created), got true", args) 132 } 133 } 134 135 func TestArgsMatchKVList(t *testing.T) { 136 // Not empty sources 137 sources := map[string]string{ 138 "key1": "value1", 139 "key2": "value2", 140 "key3": "value3", 141 } 142 143 matches := map[*Args]string{ 144 {}: "field", 145 {map[string]map[string]bool{ 146 "created": {"today": true}, 147 "labels": {"key1": true}}, 148 }: "labels", 149 {map[string]map[string]bool{ 150 "created": {"today": true}, 151 "labels": {"key1=value1": true}}, 152 }: "labels", 153 } 154 155 for args, field := range matches { 156 if !args.MatchKVList(field, sources) { 157 t.Fatalf("Expected true for %v on %v, got false", sources, args) 158 } 159 } 160 161 differs := map[*Args]string{ 162 {map[string]map[string]bool{ 163 "created": {"today": true}}, 164 }: "created", 165 {map[string]map[string]bool{ 166 "created": {"today": true}, 167 "labels": {"key4": true}}, 168 }: "labels", 169 {map[string]map[string]bool{ 170 "created": {"today": true}, 171 "labels": {"key1=value3": true}}, 172 }: "labels", 173 } 174 175 for args, field := range differs { 176 if args.MatchKVList(field, sources) { 177 t.Fatalf("Expected false for %v on %v, got true", sources, args) 178 } 179 } 180 } 181 182 func TestArgsMatch(t *testing.T) { 183 source := "today" 184 185 matches := map[*Args]string{ 186 {}: "field", 187 {map[string]map[string]bool{ 188 "created": {"today": true}}, 189 }: "today", 190 {map[string]map[string]bool{ 191 "created": {"to*": true}}, 192 }: "created", 193 {map[string]map[string]bool{ 194 "created": {"to(.*)": true}}, 195 }: "created", 196 {map[string]map[string]bool{ 197 "created": {"tod": true}}, 198 }: "created", 199 {map[string]map[string]bool{ 200 "created": {"anything": true, "to*": true}}, 201 }: "created", 202 } 203 204 for args, field := range matches { 205 assert.Check(t, args.Match(field, source), 206 "Expected field %s to match %s", field, source) 207 } 208 209 differs := map[*Args]string{ 210 {map[string]map[string]bool{ 211 "created": {"tomorrow": true}}, 212 }: "created", 213 {map[string]map[string]bool{ 214 "created": {"to(day": true}}, 215 }: "created", 216 {map[string]map[string]bool{ 217 "created": {"tom(.*)": true}}, 218 }: "created", 219 {map[string]map[string]bool{ 220 "created": {"tom": true}}, 221 }: "created", 222 {map[string]map[string]bool{ 223 "created": {"today1": true}, 224 "labels": {"today": true}}, 225 }: "created", 226 } 227 228 for args, field := range differs { 229 assert.Check(t, !args.Match(field, source), "Expected field %s to not match %s", field, source) 230 } 231 } 232 233 func TestAdd(t *testing.T) { 234 f := NewArgs() 235 f.Add("status", "running") 236 v := f.fields["status"] 237 if len(v) != 1 || !v["running"] { 238 t.Fatalf("Expected to include a running status, got %v", v) 239 } 240 241 f.Add("status", "paused") 242 if len(v) != 2 || !v["paused"] { 243 t.Fatalf("Expected to include a paused status, got %v", v) 244 } 245 } 246 247 func TestDel(t *testing.T) { 248 f := NewArgs() 249 f.Add("status", "running") 250 f.Del("status", "running") 251 v := f.fields["status"] 252 if v["running"] { 253 t.Fatal("Expected to not include a running status filter, got true") 254 } 255 } 256 257 func TestLen(t *testing.T) { 258 f := NewArgs() 259 if f.Len() != 0 { 260 t.Fatal("Expected to not include any field") 261 } 262 f.Add("status", "running") 263 if f.Len() != 1 { 264 t.Fatal("Expected to include one field") 265 } 266 } 267 268 func TestExactMatch(t *testing.T) { 269 f := NewArgs() 270 271 if !f.ExactMatch("status", "running") { 272 t.Fatal("Expected to match `running` when there are no filters, got false") 273 } 274 275 f.Add("status", "running") 276 f.Add("status", "pause*") 277 278 if !f.ExactMatch("status", "running") { 279 t.Fatal("Expected to match `running` with one of the filters, got false") 280 } 281 282 if f.ExactMatch("status", "paused") { 283 t.Fatal("Expected to not match `paused` with one of the filters, got true") 284 } 285 } 286 287 func TestOnlyOneExactMatch(t *testing.T) { 288 f := NewArgs() 289 290 if !f.UniqueExactMatch("status", "running") { 291 t.Fatal("Expected to match `running` when there are no filters, got false") 292 } 293 294 f.Add("status", "running") 295 296 if !f.UniqueExactMatch("status", "running") { 297 t.Fatal("Expected to match `running` with one of the filters, got false") 298 } 299 300 if f.UniqueExactMatch("status", "paused") { 301 t.Fatal("Expected to not match `paused` with one of the filters, got true") 302 } 303 304 f.Add("status", "pause") 305 if f.UniqueExactMatch("status", "running") { 306 t.Fatal("Expected to not match only `running` with two filters, got true") 307 } 308 } 309 310 func TestContains(t *testing.T) { 311 f := NewArgs() 312 if f.Contains("status") { 313 t.Fatal("Expected to not contain a status key, got true") 314 } 315 f.Add("status", "running") 316 if !f.Contains("status") { 317 t.Fatal("Expected to contain a status key, got false") 318 } 319 } 320 321 func TestValidate(t *testing.T) { 322 f := NewArgs() 323 f.Add("status", "running") 324 325 valid := map[string]bool{ 326 "status": true, 327 "dangling": true, 328 } 329 330 if err := f.Validate(valid); err != nil { 331 t.Fatal(err) 332 } 333 334 f.Add("bogus", "running") 335 err := f.Validate(valid) 336 if err == nil { 337 t.Fatal("Expected to return an error, got nil") 338 } 339 var invalidFilterError invalidFilter 340 if !errors.As(err, &invalidFilterError) { 341 t.Fatalf("Expected an invalidFilter error, got %T", err) 342 } 343 } 344 345 func TestWalkValues(t *testing.T) { 346 f := NewArgs() 347 f.Add("status", "running") 348 f.Add("status", "paused") 349 350 err := f.WalkValues("status", func(value string) error { 351 if value != "running" && value != "paused" { 352 t.Fatalf("Unexpected value %s", value) 353 } 354 return nil 355 }) 356 if err != nil { 357 t.Fatalf("Expected no error, got %v", err) 358 } 359 360 err = f.WalkValues("status", func(value string) error { 361 return errors.New("return") 362 }) 363 if err == nil { 364 t.Fatal("Expected to get an error, got nil") 365 } 366 367 err = f.WalkValues("foo", func(value string) error { 368 return errors.New("return") 369 }) 370 if err != nil { 371 t.Fatalf("Expected to not iterate when the field doesn't exist, got %v", err) 372 } 373 } 374 375 func TestFuzzyMatch(t *testing.T) { 376 f := NewArgs() 377 f.Add("container", "foo") 378 379 cases := map[string]bool{ 380 "foo": true, 381 "foobar": true, 382 "barfoo": false, 383 "bar": false, 384 } 385 for source, match := range cases { 386 got := f.FuzzyMatch("container", source) 387 if got != match { 388 t.Fatalf("Expected %v, got %v: %s", match, got, source) 389 } 390 } 391 } 392 393 func TestClone(t *testing.T) { 394 f := NewArgs() 395 f.Add("foo", "bar") 396 f2 := f.Clone() 397 f2.Add("baz", "qux") 398 assert.Check(t, is.Len(f.Get("baz"), 0)) 399 }