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