1
16
17 package merge_test
18
19 import (
20 "testing"
21
22 "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
23 . "sigs.k8s.io/structured-merge-diff/v4/internal/fixture"
24 "sigs.k8s.io/structured-merge-diff/v4/merge"
25 "sigs.k8s.io/structured-merge-diff/v4/typed"
26 )
27
28 var duplicatesParser = func() Parser {
29 parser, err := typed.NewParser(`types:
30 - name: type
31 map:
32 fields:
33 - name: list
34 type:
35 namedType: associativeList
36 - name: unrelated
37 type:
38 scalar: numeric
39 - name: set
40 type:
41 namedType: set
42 - name: associativeList
43 list:
44 elementType:
45 namedType: myElement
46 elementRelationship: associative
47 keys:
48 - name
49 - name: myElement
50 map:
51 fields:
52 - name: name
53 type:
54 scalar: string
55 - name: value1
56 type:
57 scalar: numeric
58 - name: value2
59 type:
60 scalar: numeric
61 - name: set
62 list:
63 elementType:
64 scalar: numeric
65 elementRelationship: associative
66 `)
67 if err != nil {
68 panic(err)
69 }
70 return SameVersionParser{T: parser.Type("type")}
71 }()
72
73 func TestDuplicates(t *testing.T) {
74 tests := map[string]TestCase{
75 "sets/ownership/duplicates": {
76 Ops: []Operation{
77 Update{
78 Manager: "updater-one",
79 Object: `
80 set: [1, 1, 3, 4]
81 `,
82 APIVersion: "v1",
83 },
84 },
85 Managed: fieldpath.ManagedFields{
86 "updater-one": fieldpath.NewVersionedSet(
87 _NS(
88 _P("set"),
89 _P("set", _V(1)),
90 _P("set", _V(3)),
91 _P("set", _V(4)),
92 ),
93 "v1",
94 false,
95 ),
96 },
97 },
98 "sets/ownership/add_duplicate": {
99 Ops: []Operation{
100 Update{
101 Manager: "updater-one",
102 Object: `
103 set: [1, 3, 4]
104 `,
105 APIVersion: "v1",
106 },
107 Update{
108 Manager: "updater-two",
109 Object: `
110 set: [1, 1, 3, 4]
111 `,
112 APIVersion: "v1",
113 },
114 },
115 Managed: fieldpath.ManagedFields{
116 "updater-one": fieldpath.NewVersionedSet(
117 _NS(
118 _P("set"),
119 _P("set", _V(3)),
120 _P("set", _V(4)),
121 ),
122 "v1",
123 false,
124 ),
125 "updater-two": fieldpath.NewVersionedSet(
126 _NS(
127 _P("set", _V(1)),
128 ),
129 "v1",
130 false,
131 ),
132 },
133 },
134 "sets/ownership/remove_duplicate": {
135 Ops: []Operation{
136 Update{
137 Manager: "updater-one",
138 Object: `
139 set: [1, 1, 3, 4]
140 `,
141 APIVersion: "v1",
142 },
143 Update{
144 Manager: "updater-two",
145 Object: `
146 set: [1, 3, 4]
147 `,
148 APIVersion: "v1",
149 },
150 },
151 Managed: fieldpath.ManagedFields{
152 "updater-one": fieldpath.NewVersionedSet(
153 _NS(
154 _P("set"),
155 _P("set", _V(3)),
156 _P("set", _V(4)),
157 ),
158 "v1",
159 false,
160 ),
161 "updater-two": fieldpath.NewVersionedSet(
162 _NS(
163 _P("set", _V(1)),
164 ),
165 "v1",
166 false,
167 ),
168 },
169 },
170 "sets/merging/remove_duplicate": {
171 Ops: []Operation{
172 Update{
173 Manager: "updater",
174 Object: `
175 set: [1, 1, 3, 4]
176 `,
177 APIVersion: "v1",
178 },
179 Apply{
180 Manager: "applier",
181 Object: `
182 set: [1]
183 `,
184 APIVersion: "v1",
185 Conflicts: merge.Conflicts{
186 {Manager: "updater", Path: _P("set", _V(1))},
187 },
188 },
189 ForceApply{
190 Manager: "applier",
191 Object: `
192 set: [1]
193 `,
194 APIVersion: "v1",
195 },
196 },
197 Object: `
198 set: [1, 3, 4]
199 `,
200 APIVersion: "v1",
201 Managed: fieldpath.ManagedFields{
202 "updater": fieldpath.NewVersionedSet(
203 _NS(
204 _P("set"),
205 _P("set", _V(3)),
206 _P("set", _V(4)),
207 ),
208 "v1",
209 false,
210 ),
211 "applier": fieldpath.NewVersionedSet(
212 _NS(
213 _P("set", _V(1)),
214 ),
215 "v1",
216 true,
217 ),
218 },
219 },
220 "sets/merging/ignore_duplicate": {
221 Ops: []Operation{
222 Update{
223 Manager: "updater",
224 Object: `
225 set: [1, 1, 3, 4]
226 `,
227 APIVersion: "v1",
228 },
229 Apply{
230 Manager: "applier",
231 Object: `
232 set: [5]
233 `,
234 APIVersion: "v1",
235 },
236 },
237 Object: `
238 set: [1, 1, 3, 4, 5]
239 `,
240 APIVersion: "v1",
241 Managed: fieldpath.ManagedFields{
242 "updater": fieldpath.NewVersionedSet(
243 _NS(
244 _P("set"),
245 _P("set", _V(1)),
246 _P("set", _V(3)),
247 _P("set", _V(4)),
248 ),
249 "v1",
250 false,
251 ),
252 "applier": fieldpath.NewVersionedSet(
253 _NS(
254 _P("set", _V(5)),
255 ),
256 "v1",
257 true,
258 ),
259 },
260 },
261 "list/ownership/duplicated_items": {
262 Ops: []Operation{
263 Update{
264 Manager: "updater",
265 Object: `
266 list:
267 - name: a
268 value1: 1
269 - name: a
270 value1: 2
271 - name: b
272 value1: 3
273 `,
274 APIVersion: "v1",
275 },
276 },
277
278 Managed: fieldpath.ManagedFields{
279 "updater": fieldpath.NewVersionedSet(
280 _NS(
281 _P("list"),
282 _P("list", _KBF("name", "a")),
283 _P("list", _KBF("name", "b")),
284 _P("list", _KBF("name", "b"), "name"),
285 _P("list", _KBF("name", "b"), "value1"),
286 ),
287 "v1",
288 false,
289 ),
290 },
291 },
292 "list/ownership/change_duplicated_items": {
293 Ops: []Operation{
294 Update{
295 Manager: "updater-one",
296 Object: `
297 list:
298 - name: a
299 value1: 1
300 - name: a
301 value1: 2
302 - name: b
303 value1: 3
304 `,
305 APIVersion: "v1",
306 },
307 Update{
308 Manager: "updater-two",
309 Object: `
310 list:
311 - name: a
312 value1: 1
313 - name: a
314 value1: 3
315 - name: b
316 value1: 3
317 `,
318 APIVersion: "v1",
319 },
320 },
321
322 Managed: fieldpath.ManagedFields{
323 "updater-one": fieldpath.NewVersionedSet(
324 _NS(
325 _P("list"),
326 _P("list", _KBF("name", "b")),
327 _P("list", _KBF("name", "b"), "name"),
328 _P("list", _KBF("name", "b"), "value1"),
329 ),
330 "v1",
331 false,
332 ),
333 "updater-two": fieldpath.NewVersionedSet(
334 _NS(
335 _P("list", _KBF("name", "a")),
336 ),
337 "v1",
338 false,
339 ),
340 },
341 },
342 "list/ownership/change_fields_duplicated_items": {
343 Ops: []Operation{
344 Update{
345 Manager: "updater-one",
346 Object: `
347 list:
348 - name: a
349 value1: 1
350 - name: a
351 value1: 2
352 - name: b
353 value1: 3
354 `,
355 APIVersion: "v1",
356 },
357 Update{
358 Manager: "updater-two",
359 Object: `
360 list:
361 - name: a
362 value1: 1
363 - name: a
364 value1: 2
365 value2: 3 # New field
366 - name: b
367 value1: 3
368 `,
369 APIVersion: "v1",
370 },
371 },
372 Managed: fieldpath.ManagedFields{
373 "updater-one": fieldpath.NewVersionedSet(
374 _NS(
375 _P("list"),
376 _P("list", _KBF("name", "b")),
377 _P("list", _KBF("name", "b"), "name"),
378 _P("list", _KBF("name", "b"), "value1"),
379 ),
380 "v1",
381 false,
382 ),
383 "updater-two": fieldpath.NewVersionedSet(
384 _NS(
385 _P("list", _KBF("name", "a")),
386 ),
387 "v1",
388 false,
389 ),
390 },
391 },
392 "list/ownership/add_duplicated_items_different_field": {
393 Ops: []Operation{
394 Update{
395 Manager: "updater-one",
396 Object: `
397 list:
398 - name: a
399 value1: 1
400 - name: b
401 value1: 3
402 `,
403 APIVersion: "v1",
404 },
405 Update{
406 Manager: "updater-two",
407 Object: `
408 list:
409 - name: a
410 value1: 1
411 - name: a
412 value2: 3 # New field
413 - name: b
414 value1: 3
415 `,
416 APIVersion: "v1",
417 },
418 },
419 Managed: fieldpath.ManagedFields{
420 "updater-one": fieldpath.NewVersionedSet(
421 _NS(
422 _P("list"),
423 _P("list", _KBF("name", "b")),
424 _P("list", _KBF("name", "b"), "name"),
425 _P("list", _KBF("name", "b"), "value1"),
426 ),
427 "v1",
428 false,
429 ),
430 "updater-two": fieldpath.NewVersionedSet(
431 _NS(
432 _P("list", _KBF("name", "a")),
433 ),
434 "v1",
435 false,
436 ),
437 },
438 },
439 "list/ownership/add_unrelated_to_list_with_duplicates": {
440 Ops: []Operation{
441 Update{
442 Manager: "updater-one",
443 Object: `
444 list:
445 - name: a
446 value1: 1
447 - name: a
448 value1: 2
449 `,
450 APIVersion: "v1",
451 },
452 Update{
453 Manager: "updater-two",
454 Object: `
455 list:
456 - name: a
457 value1: 1
458 - name: a
459 value1: 2
460 - name: b
461 value1: 3
462 `,
463 APIVersion: "v1",
464 },
465 },
466 Managed: fieldpath.ManagedFields{
467 "updater-one": fieldpath.NewVersionedSet(
468 _NS(
469 _P("list"),
470 _P("list", _KBF("name", "a")),
471 ),
472 "v1",
473 false,
474 ),
475 "updater-two": fieldpath.NewVersionedSet(
476 _NS(
477 _P("list", _KBF("name", "b")),
478 _P("list", _KBF("name", "b"), "name"),
479 _P("list", _KBF("name", "b"), "value1"),
480 ),
481 "v1",
482 false,
483 ),
484 },
485 },
486 "list/merge/unrelated_with_duplicated_items": {
487 Ops: []Operation{
488 Update{
489 Manager: "updater",
490 Object: `
491 list:
492 - name: a
493 value1: 1
494 - name: a
495 value1: 2
496 - name: b
497 value1: 3
498 `,
499 APIVersion: "v1",
500 },
501 ForceApply{
502 Manager: "applier",
503 Object: `
504 unrelated: 5
505 `,
506 APIVersion: "v1",
507 },
508 },
509 Object: `
510 list:
511 - name: a
512 value1: 1
513 - name: a
514 value1: 2
515 - name: b
516 value1: 3
517 unrelated: 5
518 `,
519 APIVersion: "v1",
520 Managed: fieldpath.ManagedFields{
521 "updater": fieldpath.NewVersionedSet(
522 _NS(
523 _P("list"),
524 _P("list", _KBF("name", "a")),
525 _P("list", _KBF("name", "b")),
526 _P("list", _KBF("name", "b"), "name"),
527 _P("list", _KBF("name", "b"), "value1"),
528 ),
529 "v1",
530 false,
531 ),
532 "applier": fieldpath.NewVersionedSet(
533 _NS(
534 _P("unrelated"),
535 ),
536 "v1",
537 true,
538 ),
539 },
540 },
541
542 "list/merge/change_duplicated_item": {
543 Ops: []Operation{
544 Update{
545 Manager: "updater",
546 Object: `
547 list:
548 - name: a
549 value1: 1
550 - name: a
551 value1: 2
552 - name: b
553 value1: 3
554 `,
555 APIVersion: "v1",
556 },
557 Apply{
558 Manager: "applier",
559 Object: `
560 list:
561 - name: a
562 value1: 3
563 `,
564 APIVersion: "v1",
565 Conflicts: merge.Conflicts{
566 {Manager: "updater", Path: _P("list", _KBF("name", "a"))},
567 },
568 },
569 ForceApply{
570 Manager: "applier",
571 Object: `
572 list:
573 - name: a
574 value1: 3
575 `,
576 APIVersion: "v1",
577 },
578 },
579 Object: `
580 list:
581 - name: a
582 value1: 3
583 - name: b
584 value1: 3
585 `,
586 APIVersion: "v1",
587 Managed: fieldpath.ManagedFields{
588 "updater": fieldpath.NewVersionedSet(
589 _NS(
590 _P("list"),
591 _P("list", _KBF("name", "b")),
592 _P("list", _KBF("name", "b"), "name"),
593 _P("list", _KBF("name", "b"), "value1"),
594 ),
595 "v1",
596 false,
597 ),
598 "applier": fieldpath.NewVersionedSet(
599 _NS(
600 _P("list", _KBF("name", "a")),
601 _P("list", _KBF("name", "a"), "name"),
602 _P("list", _KBF("name", "a"), "value1"),
603 ),
604 "v1",
605 true,
606 ),
607 },
608 },
609
610 "list/merge/unchanged_duplicated_item": {
611 Ops: []Operation{
612 Update{
613 Manager: "updater",
614 Object: `
615 list:
616 - name: a
617 value1: 1
618 - name: a
619 value1: 2
620 - name: b
621 value1: 3
622 `,
623 APIVersion: "v1",
624 },
625 Apply{
626 Manager: "applier",
627 Object: `
628 list:
629 - name: a
630 value1: 2
631 `,
632 APIVersion: "v1",
633 Conflicts: merge.Conflicts{
634 {Manager: "updater", Path: _P("list", _KBF("name", "a"))},
635 },
636 },
637 ForceApply{
638 Manager: "applier",
639 Object: `
640 list:
641 - name: a
642 value1: 3
643 `,
644 APIVersion: "v1",
645 },
646 },
647 Object: `
648 list:
649 - name: a
650 value1: 3
651 - name: b
652 value1: 3
653 `,
654 APIVersion: "v1",
655 Managed: fieldpath.ManagedFields{
656 "updater": fieldpath.NewVersionedSet(
657 _NS(
658 _P("list"),
659 _P("list", _KBF("name", "b")),
660 _P("list", _KBF("name", "b"), "name"),
661 _P("list", _KBF("name", "b"), "value1"),
662 ),
663 "v1",
664 false,
665 ),
666 "applier": fieldpath.NewVersionedSet(
667 _NS(
668 _P("list", _KBF("name", "a")),
669 _P("list", _KBF("name", "a"), "name"),
670 _P("list", _KBF("name", "a"), "value1"),
671 ),
672 "v1",
673 true,
674 ),
675 },
676 },
677 "list/merge/change_non_duplicated_item": {
678 Ops: []Operation{
679 Update{
680 Manager: "updater",
681 Object: `
682 list:
683 - name: a
684 value1: 1
685 - name: a
686 value1: 2
687 - name: b
688 value1: 3
689 `,
690 APIVersion: "v1",
691 },
692 ForceApply{
693 Manager: "applier",
694 Object: `
695 list:
696 - name: b
697 value1: 4
698 `,
699 APIVersion: "v1",
700 },
701 },
702 Object: `
703 list:
704 - name: a
705 value1: 1
706 - name: a
707 value1: 2
708 - name: b
709 value1: 4
710 `,
711 APIVersion: "v1",
712 Managed: fieldpath.ManagedFields{
713 "updater": fieldpath.NewVersionedSet(
714 _NS(
715 _P("list"),
716 _P("list", _KBF("name", "a")),
717 _P("list", _KBF("name", "b")),
718 _P("list", _KBF("name", "b"), "name"),
719 ),
720 "v1",
721 false,
722 ),
723 "applier": fieldpath.NewVersionedSet(
724 _NS(
725 _P("list", _KBF("name", "b")),
726 _P("list", _KBF("name", "b"), "name"),
727 _P("list", _KBF("name", "b"), "value1"),
728 ),
729 "v1",
730 true,
731 ),
732 },
733 },
734 "list/merge/apply_update_duplicates_apply_without": {
735 Ops: []Operation{
736 Apply{
737 Manager: "applier",
738 Object: `
739 list:
740 - name: a
741 value1: 1
742 - name: b
743 value1: 3
744 `,
745 APIVersion: "v1",
746 },
747 Update{
748 Manager: "updater",
749 Object: `
750 list:
751 - name: a
752 value1: 1
753 - name: a
754 value1: 2
755 - name: b
756 value1: 3
757 `,
758 APIVersion: "v1",
759 },
760 Apply{
761 Manager: "applier",
762 Object: `
763 list:
764 - name: b
765 value1: 3
766 `,
767 APIVersion: "v1",
768 },
769 },
770 Object: `
771 list:
772 - name: a
773 value1: 1
774 - name: a
775 value1: 2
776 - name: b
777 value1: 3
778 `,
779 APIVersion: "v1",
780 Managed: fieldpath.ManagedFields{
781 "applier": fieldpath.NewVersionedSet(
782 _NS(
783 _P("list", _KBF("name", "b")),
784 _P("list", _KBF("name", "b"), "name"),
785 _P("list", _KBF("name", "b"), "value1"),
786 ),
787 "v1",
788 true,
789 ),
790 "updater": fieldpath.NewVersionedSet(
791 _NS(
792 _P("list", _KBF("name", "a")),
793 ),
794 "v1",
795 false,
796 ),
797 },
798 },
799 }
800
801 for name, test := range tests {
802 t.Run(name, func(t *testing.T) {
803 if err := test.Test(duplicatesParser); err != nil {
804 t.Fatal(err)
805 }
806 })
807 }
808 }
809
View as plain text