1
16
17 package fieldpath
18
19 import (
20 "bytes"
21 "fmt"
22 "math/rand"
23 "testing"
24
25 "gopkg.in/yaml.v2"
26 "sigs.k8s.io/structured-merge-diff/v4/schema"
27 )
28
29 type randomPathAlphabet []PathElement
30
31 func (a randomPathAlphabet) makePath(minLen, maxLen int) Path {
32 n := minLen
33 if minLen < maxLen {
34 n += rand.Intn(maxLen - minLen)
35 }
36 var p Path
37 for i := 0; i < n; i++ {
38 p = append(p, a[rand.Intn(len(a))])
39 }
40 return p
41 }
42
43 var randomPathMaker = randomPathAlphabet(MakePathOrDie(
44 "aaa",
45 "aab",
46 "aac",
47 "aad",
48 "aae",
49 "aaf",
50 KeyByFields("name", "first"),
51 KeyByFields("name", "second"),
52 KeyByFields("port", 443, "protocol", "tcp"),
53 KeyByFields("port", 443, "protocol", "udp"),
54 _V(1),
55 _V(2),
56 _V(3),
57 _V("aa"),
58 _V("ab"),
59 _V(true),
60 1, 2, 3, 4,
61 ))
62
63 func BenchmarkFieldSet(b *testing.B) {
64 cases := []struct {
65 size int
66 minPathLen int
67 maxPathLen int
68 }{
69
70 {20, 2, 3},
71 {50, 2, 4},
72 {100, 3, 6},
73 {500, 3, 7},
74 {1000, 3, 8},
75 }
76 for i := range cases {
77 here := cases[i]
78 makeSet := func() *Set {
79 x := NewSet()
80 for j := 0; j < here.size; j++ {
81 x.Insert(randomPathMaker.makePath(here.minPathLen, here.maxPathLen))
82 }
83 return x
84 }
85 operands := make([]*Set, 500)
86 serialized := make([][]byte, len(operands))
87 for i := range operands {
88 operands[i] = makeSet()
89 serialized[i], _ = operands[i].ToJSON()
90 }
91 randOperand := func() *Set { return operands[rand.Intn(len(operands))] }
92
93 b.Run(fmt.Sprintf("insert-%v", here.size), func(b *testing.B) {
94 b.ReportAllocs()
95 for i := 0; i < b.N; i++ {
96 makeSet()
97 }
98 })
99 b.Run(fmt.Sprintf("has-%v", here.size), func(b *testing.B) {
100 b.ReportAllocs()
101 for i := 0; i < b.N; i++ {
102 randOperand().Has(randomPathMaker.makePath(here.minPathLen, here.maxPathLen))
103 }
104 })
105 b.Run(fmt.Sprintf("serialize-%v", here.size), func(b *testing.B) {
106 b.ReportAllocs()
107 for i := 0; i < b.N; i++ {
108 randOperand().ToJSON()
109 }
110 })
111 b.Run(fmt.Sprintf("deserialize-%v", here.size), func(b *testing.B) {
112 b.ReportAllocs()
113 s := NewSet()
114 for i := 0; i < b.N; i++ {
115 s.FromJSON(bytes.NewReader(serialized[rand.Intn(len(serialized))]))
116 }
117 })
118
119 b.Run(fmt.Sprintf("union-%v", here.size), func(b *testing.B) {
120 b.ReportAllocs()
121 for i := 0; i < b.N; i++ {
122 randOperand().Union(randOperand())
123 }
124 })
125 b.Run(fmt.Sprintf("intersection-%v", here.size), func(b *testing.B) {
126 b.ReportAllocs()
127 for i := 0; i < b.N; i++ {
128 randOperand().Intersection(randOperand())
129 }
130 })
131 b.Run(fmt.Sprintf("difference-%v", here.size), func(b *testing.B) {
132 b.ReportAllocs()
133 for i := 0; i < b.N; i++ {
134 randOperand().Difference(randOperand())
135 }
136 })
137 b.Run(fmt.Sprintf("recursive-difference-%v", here.size), func(b *testing.B) {
138 b.ReportAllocs()
139 for i := 0; i < b.N; i++ {
140 randOperand().RecursiveDifference(randOperand())
141 }
142 })
143 b.Run(fmt.Sprintf("leaves-%v", here.size), func(b *testing.B) {
144 b.ReportAllocs()
145 for i := 0; i < b.N; i++ {
146 randOperand().Leaves()
147 }
148 })
149 }
150 }
151
152 func TestSetInsertHas(t *testing.T) {
153 s1 := NewSet(
154 MakePathOrDie("foo", 0, "bar", "baz"),
155 MakePathOrDie("foo", 0, "bar"),
156 MakePathOrDie("foo", 0),
157 MakePathOrDie("foo", 1, "bar", "baz"),
158 MakePathOrDie("foo", 1, "bar"),
159 MakePathOrDie("qux", KeyByFields("name", "first")),
160 MakePathOrDie("qux", KeyByFields("name", "first"), "bar"),
161 MakePathOrDie("qux", KeyByFields("name", "second"), "bar"),
162 MakePathOrDie("canonicalOrder", KeyByFields(
163 "a", "a",
164 "b", "a",
165 "c", "a",
166 "d", "a",
167 "e", "a",
168 "f", "a",
169 )),
170 )
171
172 table := []struct {
173 set *Set
174 check Path
175 expectMembership bool
176 }{
177 {s1, MakePathOrDie("qux", KeyByFields("name", "second")), false},
178 {s1, MakePathOrDie("qux", KeyByFields("name", "second"), "bar"), true},
179 {s1, MakePathOrDie("qux", KeyByFields("name", "first")), true},
180 {s1, MakePathOrDie("xuq", KeyByFields("name", "first")), false},
181 {s1, MakePathOrDie("foo", 0), true},
182 {s1, MakePathOrDie("foo", 0, "bar"), true},
183 {s1, MakePathOrDie("foo", 0, "bar", "baz"), true},
184 {s1, MakePathOrDie("foo", 1), false},
185 {s1, MakePathOrDie("foo", 1, "bar"), true},
186 {s1, MakePathOrDie("foo", 1, "bar", "baz"), true},
187 {s1, MakePathOrDie("canonicalOrder", KeyByFields(
188 "f", "a",
189 "e", "a",
190 "d", "a",
191 "c", "a",
192 "b", "a",
193 "a", "a",
194 )), true}}
195
196 for _, tt := range table {
197 got := tt.set.Has(tt.check)
198 if e, a := tt.expectMembership, got; e != a {
199 t.Errorf("%v: wanted %v, got %v", tt.check.String(), e, a)
200 }
201 }
202
203 if NewSet().Has(Path{}) {
204 t.Errorf("empty set should not include the empty path")
205 }
206 if NewSet(Path{}).Has(Path{}) {
207 t.Errorf("empty set should not include the empty path")
208 }
209 }
210
211 func TestSetString(t *testing.T) {
212 p := MakePathOrDie("foo", KeyByFields("name", "first"))
213 s1 := NewSet(p)
214
215 if p.String() != s1.String() {
216 t.Errorf("expected single entry set to just call the path's string, but got %s %s", p, s1)
217 }
218 }
219
220 func TestSetIterSize(t *testing.T) {
221 s1 := NewSet(
222 MakePathOrDie("foo", 0, "bar", "baz"),
223 MakePathOrDie("foo", 0, "bar", "zot"),
224 MakePathOrDie("foo", 0, "bar"),
225 MakePathOrDie("foo", 0),
226 MakePathOrDie("foo", 1, "bar", "baz"),
227 MakePathOrDie("foo", 1, "bar"),
228 MakePathOrDie("qux", KeyByFields("name", "first")),
229 MakePathOrDie("qux", KeyByFields("name", "first"), "bar"),
230 MakePathOrDie("qux", KeyByFields("name", "second"), "bar"),
231 )
232
233 s2 := NewSet()
234
235 addedCount := 0
236 s1.Iterate(func(p Path) {
237 if s2.Size() != addedCount {
238 t.Errorf("added %v items to set, but size is %v", addedCount, s2.Size())
239 }
240 if addedCount > 0 == s2.Empty() {
241 t.Errorf("added %v items to set, but s2.Empty() is %v", addedCount, s2.Empty())
242 }
243 s2.Insert(p)
244 addedCount++
245 })
246
247 if !s1.Equals(s2) {
248
249 t.Errorf("Iterate missed something?\n%#v\n%#v", s1, s2)
250 }
251 }
252
253 func TestSetEquals(t *testing.T) {
254 table := []struct {
255 a *Set
256 b *Set
257 equal bool
258 }{
259 {
260 a: NewSet(MakePathOrDie("foo")),
261 b: NewSet(MakePathOrDie("bar")),
262 equal: false,
263 },
264 {
265 a: NewSet(MakePathOrDie("foo")),
266 b: NewSet(MakePathOrDie("foo")),
267 equal: true,
268 },
269 {
270 a: NewSet(),
271 b: NewSet(MakePathOrDie(0, "foo")),
272 equal: false,
273 },
274 {
275 a: NewSet(MakePathOrDie(1, "foo")),
276 b: NewSet(MakePathOrDie(0, "foo")),
277 equal: false,
278 },
279 {
280 a: NewSet(MakePathOrDie(1, "foo")),
281 b: NewSet(MakePathOrDie(1, "foo", "bar")),
282 equal: false,
283 },
284 {
285 a: NewSet(
286 MakePathOrDie(0),
287 MakePathOrDie(1),
288 ),
289 b: NewSet(
290 MakePathOrDie(1),
291 MakePathOrDie(0),
292 ),
293 equal: true,
294 },
295 {
296 a: NewSet(
297 MakePathOrDie("foo", 0),
298 MakePathOrDie("foo", 1),
299 ),
300 b: NewSet(
301 MakePathOrDie("foo", 1),
302 MakePathOrDie("foo", 0),
303 ),
304 equal: true,
305 },
306 {
307 a: NewSet(
308 MakePathOrDie("foo", 0),
309 MakePathOrDie("foo"),
310 MakePathOrDie("bar", "baz"),
311 MakePathOrDie("qux", KeyByFields("name", "first")),
312 ),
313 b: NewSet(
314 MakePathOrDie("foo", 1),
315 MakePathOrDie("bar", "baz"),
316 MakePathOrDie("bar"),
317 MakePathOrDie("qux", KeyByFields("name", "second")),
318 ),
319 equal: false,
320 },
321 }
322
323 for _, tt := range table {
324 if e, a := tt.equal, tt.a.Equals(tt.b); e != a {
325 t.Errorf("expected %v, got %v for:\na=\n%v\nb=\n%v", e, a, tt.a, tt.b)
326 }
327 }
328 }
329
330 func TestSetUnion(t *testing.T) {
331
332
333
334
335 s1 := NewSet(
336 MakePathOrDie("foo", 0),
337 MakePathOrDie("foo"),
338 MakePathOrDie("bar", "baz"),
339 MakePathOrDie("qux", KeyByFields("name", "first")),
340 MakePathOrDie("parent", "child", "grandchild"),
341 )
342
343 s2 := NewSet(
344 MakePathOrDie("foo", 1),
345 MakePathOrDie("bar", "baz"),
346 MakePathOrDie("bar"),
347 MakePathOrDie("qux", KeyByFields("name", "second")),
348 MakePathOrDie("parent", "child"),
349 )
350
351 u := NewSet(
352 MakePathOrDie("foo", 0),
353 MakePathOrDie("foo", 1),
354 MakePathOrDie("foo"),
355 MakePathOrDie("bar", "baz"),
356 MakePathOrDie("bar"),
357 MakePathOrDie("qux", KeyByFields("name", "first")),
358 MakePathOrDie("qux", KeyByFields("name", "second")),
359 MakePathOrDie("parent", "child"),
360 MakePathOrDie("parent", "child", "grandchild"),
361 )
362
363 got := s1.Union(s2)
364
365 if !got.Equals(u) {
366 t.Errorf("union: expected: \n%v\n, got \n%v\n", u, got)
367 }
368 }
369
370 func TestSetIntersectionDifference(t *testing.T) {
371
372
373
374
375 nameFirst := KeyByFields("name", "first")
376 s1 := NewSet(
377 MakePathOrDie("a0"),
378 MakePathOrDie("a1"),
379 MakePathOrDie("foo", 0),
380 MakePathOrDie("foo", 1),
381 MakePathOrDie("b0", nameFirst),
382 MakePathOrDie("b1", nameFirst),
383 MakePathOrDie("bar", "c0"),
384
385 MakePathOrDie("cp", nameFirst, "child"),
386 )
387
388 s2 := NewSet(
389 MakePathOrDie("a1"),
390 MakePathOrDie("a2"),
391 MakePathOrDie("foo", 1),
392 MakePathOrDie("foo", 2),
393 MakePathOrDie("b1", nameFirst),
394 MakePathOrDie("b2", nameFirst),
395 MakePathOrDie("bar", "c2"),
396
397 MakePathOrDie("cp", nameFirst),
398 )
399 t.Logf("s1:\n%v\n", s1)
400 t.Logf("s2:\n%v\n", s2)
401
402 t.Run("intersection", func(t *testing.T) {
403 i := NewSet(
404 MakePathOrDie("a1"),
405 MakePathOrDie("foo", 1),
406 MakePathOrDie("b1", nameFirst),
407 )
408
409 got := s1.Intersection(s2)
410 if !got.Equals(i) {
411 t.Errorf("expected: \n%v\n, got \n%v\n", i, got)
412 }
413 })
414
415 t.Run("s1 - s2", func(t *testing.T) {
416 sDiffS2 := NewSet(
417 MakePathOrDie("a0"),
418 MakePathOrDie("foo", 0),
419 MakePathOrDie("b0", nameFirst),
420 MakePathOrDie("bar", "c0"),
421 MakePathOrDie("cp", nameFirst, "child"),
422 )
423
424 got := s1.Difference(s2)
425 if !got.Equals(sDiffS2) {
426 t.Errorf("expected: \n%v\n, got \n%v\n", sDiffS2, got)
427 }
428 })
429
430 t.Run("s2 - s1", func(t *testing.T) {
431 s2DiffS := NewSet(
432 MakePathOrDie("a2"),
433 MakePathOrDie("foo", 2),
434 MakePathOrDie("b2", nameFirst),
435 MakePathOrDie("bar", "c2"),
436 MakePathOrDie("cp", nameFirst),
437 )
438
439 got := s2.Difference(s1)
440 if !got.Equals(s2DiffS) {
441 t.Errorf("expected: \n%v\n, got \n%v\n", s2DiffS, got)
442 }
443 })
444
445 t.Run("intersection (the hard way)", func(t *testing.T) {
446 i := NewSet(
447 MakePathOrDie("a1"),
448 MakePathOrDie("foo", 1),
449 MakePathOrDie("b1", nameFirst),
450 )
451
452
453
454 u := s1.Union(s2)
455 t.Logf("s1 u s2:\n%v\n", u)
456 notIntersection := s2.Difference(s1).Union(s1.Difference(s2))
457 t.Logf("s1 !i s2:\n%v\n", notIntersection)
458 got := u.Difference(notIntersection)
459 if !got.Equals(i) {
460 t.Errorf("expected: \n%v\n, got \n%v\n", i, got)
461 }
462 })
463 }
464
465 func TestSetLeaves(t *testing.T) {
466 table := []struct {
467 name string
468 input *Set
469 expected *Set
470 }{
471 {
472 name: "empty set",
473 input: NewSet(),
474 expected: NewSet(),
475 }, {
476 name: "all leaves",
477 input: NewSet(
478 _P("path1"),
479 _P("path2"),
480 _P("path3"),
481 ),
482 expected: NewSet(
483 _P("path1"),
484 _P("path2"),
485 _P("path3"),
486 ),
487 }, {
488 name: "only one leaf",
489 input: NewSet(
490 _P("root"),
491 _P("root", "l1"),
492 _P("root", "l1", "l2"),
493 _P("root", "l1", "l2", "l3"),
494 ),
495 expected: NewSet(
496 _P("root", "l1", "l2", "l3"),
497 ),
498 }, {
499 name: "multiple values, check for overwrite",
500 input: NewSet(
501 _P("root", KeyByFields("name", "a")),
502 _P("root", KeyByFields("name", "a"), "name"),
503 _P("root", KeyByFields("name", "a"), "value", "b"),
504 _P("root", KeyByFields("name", "a"), "value", "c"),
505 ),
506 expected: NewSet(
507 _P("root", KeyByFields("name", "a"), "name"),
508 _P("root", KeyByFields("name", "a"), "value", "b"),
509 _P("root", KeyByFields("name", "a"), "value", "c"),
510 ),
511 }, {
512 name: "multiple values and nested",
513 input: NewSet(
514 _P("root", KeyByFields("name", "a")),
515 _P("root", KeyByFields("name", "a"), "name"),
516 _P("root", KeyByFields("name", "a"), "value", "b"),
517 _P("root", KeyByFields("name", "a"), "value", "b", "d"),
518 _P("root", KeyByFields("name", "a"), "value", "c"),
519 ),
520 expected: NewSet(
521 _P("root", KeyByFields("name", "a"), "name"),
522 _P("root", KeyByFields("name", "a"), "value", "b", "d"),
523 _P("root", KeyByFields("name", "a"), "value", "c"),
524 ),
525 }, {
526 name: "all-in-one",
527 input: NewSet(
528 _P("root"),
529 _P("root", KeyByFields("name", "a")),
530 _P("root", KeyByFields("name", "a"), "name"),
531 _P("root", KeyByFields("name", "a"), "value", "b"),
532 _P("root", KeyByFields("name", "a"), "value", "b", "c"),
533 _P("root", KeyByFields("name", "a"), "value", "d"),
534 _P("root", KeyByFields("name", "a"), "value", "e"),
535 _P("root", "x"),
536 _P("root", "x", "y"),
537 _P("root", "x", "z"),
538 _P("root", KeyByFields("name", "p")),
539 _P("root", KeyByFields("name", "p"), "name"),
540 _P("root", KeyByFields("name", "p"), "value", "q"),
541 ),
542 expected: NewSet(
543 _P("root", KeyByFields("name", "a"), "name"),
544 _P("root", KeyByFields("name", "a"), "value", "b", "c"),
545 _P("root", KeyByFields("name", "a"), "value", "d"),
546 _P("root", KeyByFields("name", "a"), "value", "e"),
547 _P("root", "x", "y"),
548 _P("root", "x", "z"),
549 _P("root", KeyByFields("name", "p"), "name"),
550 _P("root", KeyByFields("name", "p"), "value", "q"),
551 ),
552 },
553 }
554
555 for _, tt := range table {
556 t.Run(tt.name, func(t *testing.T) {
557 if got := tt.input.Leaves(); !tt.expected.Equals(got) {
558 t.Errorf("expected %v, got %v for input %v", tt.expected, got, tt.input)
559 }
560 })
561 }
562
563 }
564
565 func TestSetDifference(t *testing.T) {
566 table := []struct {
567 name string
568 a *Set
569 b *Set
570 expectDifference *Set
571 expectRecursiveDifference *Set
572 }{
573 {
574 name: "removes simple path",
575 a: NewSet(MakePathOrDie("a")),
576 b: NewSet(MakePathOrDie("a")),
577 expectDifference: NewSet(),
578 expectRecursiveDifference: NewSet(),
579 },
580 {
581 name: "removes direct path",
582 a: NewSet(MakePathOrDie("a", "b", "c")),
583 b: NewSet(MakePathOrDie("a", "b", "c")),
584 expectDifference: NewSet(),
585 expectRecursiveDifference: NewSet(),
586 },
587 {
588 name: "only removes matching child",
589 a: NewSet(
590 MakePathOrDie("a", "b", "c"),
591 MakePathOrDie("b", "b", "c"),
592 ),
593 b: NewSet(MakePathOrDie("a", "b", "c")),
594 expectDifference: NewSet(MakePathOrDie("b", "b", "c")),
595 expectRecursiveDifference: NewSet(MakePathOrDie("b", "b", "c")),
596 },
597 {
598 name: "does not remove parent of specific path",
599 a: NewSet(
600 MakePathOrDie("a"),
601 ),
602 b: NewSet(MakePathOrDie("a", "aa")),
603 expectDifference: NewSet(MakePathOrDie("a")),
604 expectRecursiveDifference: NewSet(MakePathOrDie("a")),
605 },
606 {
607 name: "RecursiveDifference removes nested path",
608 a: NewSet(MakePathOrDie("a", "b", "c")),
609 b: NewSet(MakePathOrDie("a")),
610 expectDifference: NewSet(MakePathOrDie("a", "b", "c")),
611 expectRecursiveDifference: NewSet(),
612 },
613 {
614 name: "RecursiveDifference only removes nested path for matching children",
615 a: NewSet(
616 MakePathOrDie("a", "aa", "aab"),
617 MakePathOrDie("a", "ab", "aba"),
618 ),
619 b: NewSet(MakePathOrDie("a", "aa")),
620 expectDifference: NewSet(
621 MakePathOrDie("a", "aa", "aab"),
622 MakePathOrDie("a", "ab", "aba"),
623 ),
624 expectRecursiveDifference: NewSet(MakePathOrDie("a", "ab", "aba")),
625 },
626 {
627 name: "RecursiveDifference removes all matching children",
628 a: NewSet(
629 MakePathOrDie("a", "aa", "aab"),
630 MakePathOrDie("a", "ab", "aba"),
631 ),
632 b: NewSet(MakePathOrDie("a")),
633 expectDifference: NewSet(
634 MakePathOrDie("a", "aa", "aab"),
635 MakePathOrDie("a", "ab", "aba"),
636 ),
637 expectRecursiveDifference: NewSet(),
638 },
639 }
640
641 for _, c := range table {
642 t.Run(c.name, func(t *testing.T) {
643 if result := c.a.Difference(c.b); !result.Equals(c.expectDifference) {
644 t.Fatalf("Difference expected: \n%v\n, got: \n%v\n", c.expectDifference, result)
645 }
646 if result := c.a.RecursiveDifference(c.b); !result.Equals(c.expectRecursiveDifference) {
647 t.Fatalf("RecursiveDifference expected: \n%v\n, got: \n%v\n", c.expectRecursiveDifference, result)
648 }
649 })
650 }
651 }
652
653 var nestedSchema = func() (*schema.Schema, schema.TypeRef) {
654 sc := &schema.Schema{}
655 name := "type"
656 err := yaml.Unmarshal([]byte(`types:
657 - name: type
658 map:
659 elementType:
660 namedType: type
661 fields:
662 - name: named
663 type:
664 namedType: type
665 - name: list
666 type:
667 list:
668 elementRelationShip: associative
669 keys: ["name"]
670 elementType:
671 namedType: type
672 - name: value
673 type:
674 scalar: numeric
675 `), &sc)
676 if err != nil {
677 panic(err)
678 }
679 return sc, schema.TypeRef{NamedType: &name}
680 }
681
682 var _P = MakePathOrDie
683
684 func TestEnsureNamedFieldsAreMembers(t *testing.T) {
685 table := []struct {
686 set, expected *Set
687 }{
688 {
689 set: NewSet(_P("named", "named", "value")),
690 expected: NewSet(
691 _P("named", "named", "value"),
692 _P("named", "named"),
693 _P("named"),
694 ),
695 },
696 {
697 set: NewSet(_P("named", "a", "named", "value"), _P("a", "named", "value"), _P("a", "b", "value")),
698 expected: NewSet(
699 _P("named", "a", "named", "value"),
700 _P("named", "a", "named"),
701 _P("named"),
702 _P("a", "named", "value"),
703 _P("a", "named"),
704 _P("a", "b", "value"),
705 ),
706 },
707 {
708 set: NewSet(_P("named", "list", KeyByFields("name", "a"), "named", "a", "value")),
709 expected: NewSet(
710 _P("named", "list", KeyByFields("name", "a"), "named", "a", "value"),
711 _P("named", "list", KeyByFields("name", "a"), "named"),
712 _P("named", "list"),
713 _P("named"),
714 ),
715 },
716 }
717
718 for _, test := range table {
719 t.Run(fmt.Sprintf("%v", test.set), func(t *testing.T) {
720 got := test.set.EnsureNamedFieldsAreMembers(nestedSchema())
721 if !got.Equals(test.expected) {
722 t.Errorf("expected %v, got %v (missing: %v/superfluous: %v)",
723 test.expected,
724 got,
725 test.expected.Difference(got),
726 got.Difference(test.expected),
727 )
728 }
729 })
730 }
731 }
732
733 func TestSetNodeMapIterate(t *testing.T) {
734 set := &SetNodeMap{}
735 toAdd := 5
736 addedElements := make([]string, toAdd)
737 for i := 0; i < toAdd; i++ {
738 p := i
739 pe := PathElement{Index: &p}
740 addedElements[i] = pe.String()
741 _ = set.Descend(pe)
742 }
743
744 iteratedElements := make(map[string]bool, toAdd)
745 set.Iterate(func(pe PathElement) {
746 iteratedElements[pe.String()] = true
747 })
748
749 if len(iteratedElements) != toAdd {
750 t.Errorf("expected %v elements to be iterated over, got %v", toAdd, len(iteratedElements))
751 }
752 for _, pe := range addedElements {
753 if _, ok := iteratedElements[pe]; !ok {
754 t.Errorf("expected to have iterated over %v, but never did", pe)
755 }
756 }
757 }
758
View as plain text