1/*
2Copyright 2014 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package strategicpatch
18
19import (
20	"fmt"
21	"path/filepath"
22	"reflect"
23	"strings"
24	"testing"
25
26	"github.com/davecgh/go-spew/spew"
27	"sigs.k8s.io/yaml"
28
29	"k8s.io/apimachinery/pkg/runtime"
30	"k8s.io/apimachinery/pkg/util/json"
31	"k8s.io/apimachinery/pkg/util/mergepatch"
32	"k8s.io/apimachinery/pkg/util/sets"
33	sptest "k8s.io/apimachinery/pkg/util/strategicpatch/testing"
34)
35
36var (
37	fakeMergeItemSchema     = sptest.Fake{Path: filepath.Join("testdata", "swagger-merge-item.json")}
38	fakePrecisionItemSchema = sptest.Fake{Path: filepath.Join("testdata", "swagger-precision-item.json")}
39)
40
41type SortMergeListTestCases struct {
42	TestCases []SortMergeListTestCase
43}
44
45type SortMergeListTestCase struct {
46	Description string
47	Original    map[string]interface{}
48	Sorted      map[string]interface{}
49}
50
51type StrategicMergePatchTestCases struct {
52	TestCases []StrategicMergePatchTestCase
53}
54
55type StrategicMergePatchTestCase struct {
56	Description string
57	StrategicMergePatchTestCaseData
58}
59
60type StrategicMergePatchRawTestCase struct {
61	Description string
62	StrategicMergePatchRawTestCaseData
63}
64
65type StrategicMergePatchTestCaseData struct {
66	// Original is the original object (last-applied config in annotation)
67	Original map[string]interface{}
68	// Modified is the modified object (new config we want)
69	Modified map[string]interface{}
70	// Current is the current object (live config in the server)
71	Current map[string]interface{}
72	// TwoWay is the expected two-way merge patch diff between original and modified
73	TwoWay map[string]interface{}
74	// ThreeWay is the expected three-way merge patch
75	ThreeWay map[string]interface{}
76	// Result is the expected object after applying the three-way patch on current object.
77	Result map[string]interface{}
78	// TwoWayResult is the expected object after applying the two-way patch on current object.
79	// If nil, Modified is used.
80	TwoWayResult map[string]interface{}
81}
82
83// The meaning of each field is the same as StrategicMergePatchTestCaseData's.
84// The difference is that all the fields in StrategicMergePatchRawTestCaseData are json-encoded data.
85type StrategicMergePatchRawTestCaseData struct {
86	Original      []byte
87	Modified      []byte
88	Current       []byte
89	TwoWay        []byte
90	ThreeWay      []byte
91	Result        []byte
92	TwoWayResult  []byte
93	ExpectedError string
94}
95
96type MergeItem struct {
97	Name                  string               `json:"name,omitempty"`
98	Value                 string               `json:"value,omitempty"`
99	Other                 string               `json:"other,omitempty"`
100	MergingList           []MergeItem          `json:"mergingList,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
101	NonMergingList        []MergeItem          `json:"nonMergingList,omitempty"`
102	MergingIntList        []int                `json:"mergingIntList,omitempty" patchStrategy:"merge"`
103	NonMergingIntList     []int                `json:"nonMergingIntList,omitempty"`
104	MergeItemPtr          *MergeItem           `json:"mergeItemPtr,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
105	SimpleMap             map[string]string    `json:"simpleMap,omitempty"`
106	ReplacingItem         runtime.RawExtension `json:"replacingItem,omitempty" patchStrategy:"replace"`
107	RetainKeysMap         RetainKeysMergeItem  `json:"retainKeysMap,omitempty" patchStrategy:"retainKeys"`
108	RetainKeysMergingList []MergeItem          `json:"retainKeysMergingList,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name"`
109}
110
111type RetainKeysMergeItem struct {
112	Name           string            `json:"name,omitempty"`
113	Value          string            `json:"value,omitempty"`
114	Other          string            `json:"other,omitempty"`
115	SimpleMap      map[string]string `json:"simpleMap,omitempty"`
116	MergingIntList []int             `json:"mergingIntList,omitempty" patchStrategy:"merge"`
117	MergingList    []MergeItem       `json:"mergingList,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
118	NonMergingList []MergeItem       `json:"nonMergingList,omitempty"`
119}
120
121var (
122	mergeItem             MergeItem
123	mergeItemStructSchema = PatchMetaFromStruct{T: GetTagStructTypeOrDie(mergeItem)}
124)
125
126// These are test cases for SortMergeList, used to assert that it (recursively)
127// sorts both merging and non merging lists correctly.
128var sortMergeListTestCaseData = []byte(`
129testCases:
130  - description: sort one list of maps
131    original:
132      mergingList:
133        - name: 1
134        - name: 3
135        - name: 2
136    sorted:
137      mergingList:
138        - name: 1
139        - name: 2
140        - name: 3
141  - description: sort lists of maps but not nested lists of maps
142    original:
143      mergingList:
144        - name: 2
145          nonMergingList:
146            - name: 1
147            - name: 3
148            - name: 2
149        - name: 1
150          nonMergingList:
151            - name: 2
152            - name: 1
153    sorted:
154      mergingList:
155        - name: 1
156          nonMergingList:
157            - name: 2
158            - name: 1
159        - name: 2
160          nonMergingList:
161            - name: 1
162            - name: 3
163            - name: 2
164  - description: sort lists of maps and nested lists of maps
165    original:
166      mergingList:
167        - name: 2
168          mergingList:
169            - name: 1
170            - name: 3
171            - name: 2
172        - name: 1
173          mergingList:
174            - name: 2
175            - name: 1
176    sorted:
177      mergingList:
178        - name: 1
179          mergingList:
180            - name: 1
181            - name: 2
182        - name: 2
183          mergingList:
184            - name: 1
185            - name: 2
186            - name: 3
187  - description: merging list should NOT sort when nested in non merging list
188    original:
189      nonMergingList:
190        - name: 2
191          mergingList:
192            - name: 1
193            - name: 3
194            - name: 2
195        - name: 1
196          mergingList:
197            - name: 2
198            - name: 1
199    sorted:
200      nonMergingList:
201        - name: 2
202          mergingList:
203            - name: 1
204            - name: 3
205            - name: 2
206        - name: 1
207          mergingList:
208            - name: 2
209            - name: 1
210  - description: sort very nested list of maps
211    fieldTypes:
212    original:
213      mergingList:
214        - mergingList:
215            - mergingList:
216                - name: 2
217                - name: 1
218    sorted:
219      mergingList:
220        - mergingList:
221            - mergingList:
222                - name: 1
223                - name: 2
224  - description: sort nested lists of ints
225    original:
226      mergingList:
227        - name: 2
228          mergingIntList:
229            - 1
230            - 3
231            - 2
232        - name: 1
233          mergingIntList:
234            - 2
235            - 1
236    sorted:
237      mergingList:
238        - name: 1
239          mergingIntList:
240            - 1
241            - 2
242        - name: 2
243          mergingIntList:
244            - 1
245            - 2
246            - 3
247  - description: sort nested pointers of ints
248    original:
249      mergeItemPtr:
250        - name: 2
251          mergingIntList:
252            - 1
253            - 3
254            - 2
255        - name: 1
256          mergingIntList:
257            - 2
258            - 1
259    sorted:
260      mergeItemPtr:
261        - name: 1
262          mergingIntList:
263            - 1
264            - 2
265        - name: 2
266          mergingIntList:
267            - 1
268            - 2
269            - 3
270  - description: sort merging list by pointer
271    original:
272      mergeItemPtr:
273        - name: 1
274        - name: 3
275        - name: 2
276    sorted:
277      mergeItemPtr:
278        - name: 1
279        - name: 2
280        - name: 3
281`)
282
283func TestSortMergeLists(t *testing.T) {
284	mergeItemOpenapiSchema := PatchMetaFromOpenAPI{
285		Schema: sptest.GetSchemaOrDie(&fakeMergeItemSchema, "mergeItem"),
286	}
287	schemas := []LookupPatchMeta{
288		mergeItemStructSchema,
289		mergeItemOpenapiSchema,
290	}
291
292	tc := SortMergeListTestCases{}
293	err := yaml.Unmarshal(sortMergeListTestCaseData, &tc)
294	if err != nil {
295		t.Errorf("can't unmarshal test cases: %s\n", err)
296		return
297	}
298
299	for _, schema := range schemas {
300		for _, c := range tc.TestCases {
301			temp := testObjectToJSONOrFail(t, c.Original)
302			got := sortJsonOrFail(t, temp, c.Description, schema)
303			expected := testObjectToJSONOrFail(t, c.Sorted)
304			if !reflect.DeepEqual(got, expected) {
305				t.Errorf("using %s error in test case: %s\ncannot sort object:\n%s\nexpected:\n%s\ngot:\n%s\n",
306					getSchemaType(schema), c.Description, mergepatch.ToYAMLOrError(c.Original), mergepatch.ToYAMLOrError(c.Sorted), jsonToYAMLOrError(got))
307			}
308		}
309	}
310}
311
312// These are test cases for StrategicMergePatch that cannot be generated using
313// CreateTwoWayMergePatch because it may be one of the following cases:
314// - not use the replace directive.
315// - generate duplicate integers for a merging list patch.
316// - generate empty merging lists.
317// - use patch format from an old client.
318var customStrategicMergePatchTestCaseData = []byte(`
319testCases:
320  - description: unique scalars when merging lists
321    original:
322      mergingIntList:
323        - 1
324        - 2
325    twoWay:
326      mergingIntList:
327        - 2
328        - 3
329    modified:
330      mergingIntList:
331        - 1
332        - 2
333        - 3
334  - description: delete map from nested map
335    original:
336      simpleMap:
337        key1: 1
338        key2: 1
339    twoWay:
340      simpleMap:
341        $patch: delete
342    modified:
343      simpleMap:
344        {}
345  - description: delete all items from merging list
346    original:
347      mergingList:
348        - name: 1
349        - name: 2
350    twoWay:
351      mergingList:
352        - $patch: replace
353    modified:
354      mergingList: []
355  - description: merge empty merging lists
356    original:
357      mergingList: []
358    twoWay:
359      mergingList: []
360    modified:
361      mergingList: []
362  - description: delete all keys from map
363    original:
364      name: 1
365      value: 1
366    twoWay:
367      $patch: replace
368    modified: {}
369  - description: add key and delete all keys from map
370    original:
371      name: 1
372      value: 1
373    twoWay:
374      other: a
375      $patch: replace
376    modified:
377      other: a
378  - description: delete all duplicate entries in a merging list
379    original:
380      mergingList:
381        - name: 1
382        - name: 1
383        - name: 2
384          value: a
385        - name: 3
386        - name: 3
387    twoWay:
388      mergingList:
389        - name: 1
390          $patch: delete
391        - name: 3
392          $patch: delete
393    modified:
394      mergingList:
395        - name: 2
396          value: a
397  - description: retainKeys map can add a field when no retainKeys directive present
398    original:
399      retainKeysMap:
400        name: foo
401    twoWay:
402      retainKeysMap:
403        value: bar
404    modified:
405      retainKeysMap:
406        name: foo
407        value: bar
408  - description: retainKeys map can change a field when no retainKeys directive present
409    original:
410      retainKeysMap:
411        name: foo
412        value: a
413    twoWay:
414      retainKeysMap:
415        value: b
416    modified:
417      retainKeysMap:
418        name: foo
419        value: b
420  - description: retainKeys map can delete a field when no retainKeys directive present
421    original:
422      retainKeysMap:
423        name: foo
424        value: a
425    twoWay:
426      retainKeysMap:
427        value: null
428    modified:
429      retainKeysMap:
430        name: foo
431  - description: retainKeys map merge an empty map
432    original:
433      retainKeysMap:
434        name: foo
435        value: a
436    twoWay:
437      retainKeysMap: {}
438    modified:
439      retainKeysMap:
440        name: foo
441        value: a
442  - description: retainKeys list can add a field when no retainKeys directive present
443    original:
444      retainKeysMergingList:
445      - name: bar
446      - name: foo
447    twoWay:
448      retainKeysMergingList:
449      - name: foo
450        value: a
451    modified:
452      retainKeysMergingList:
453      - name: bar
454      - name: foo
455        value: a
456  - description: retainKeys list can change a field when no retainKeys directive present
457    original:
458      retainKeysMergingList:
459      - name: bar
460      - name: foo
461        value: a
462    twoWay:
463      retainKeysMergingList:
464      - name: foo
465        value: b
466    modified:
467      retainKeysMergingList:
468      - name: bar
469      - name: foo
470        value: b
471  - description: retainKeys list can delete a field when no retainKeys directive present
472    original:
473      retainKeysMergingList:
474      - name: bar
475      - name: foo
476        value: a
477    twoWay:
478      retainKeysMergingList:
479      - name: foo
480        value: null
481    modified:
482      retainKeysMergingList:
483      - name: bar
484      - name: foo
485  - description: preserve the order from the patch in a merging list
486    original:
487      mergingList:
488        - name: 1
489        - name: 2
490          value: b
491        - name: 3
492    twoWay:
493      mergingList:
494        - name: 3
495          value: c
496        - name: 1
497          value: a
498        - name: 2
499          other: x
500    modified:
501      mergingList:
502        - name: 3
503          value: c
504        - name: 1
505          value: a
506        - name: 2
507          value: b
508          other: x
509  - description: preserve the order from the patch in a merging list 2
510    original:
511      mergingList:
512        - name: 1
513        - name: 2
514          value: b
515        - name: 3
516    twoWay:
517      mergingList:
518        - name: 3
519          value: c
520        - name: 1
521          value: a
522    modified:
523      mergingList:
524        - name: 2
525          value: b
526        - name: 3
527          value: c
528        - name: 1
529          value: a
530  - description: preserve the order from the patch in a merging int list
531    original:
532      mergingIntList:
533        - 1
534        - 2
535        - 3
536    twoWay:
537      mergingIntList:
538        - 3
539        - 1
540        - 2
541    modified:
542      mergingIntList:
543        - 3
544        - 1
545        - 2
546  - description: preserve the order from the patch in a merging int list
547    original:
548      mergingIntList:
549        - 1
550        - 2
551        - 3
552    twoWay:
553      mergingIntList:
554        - 3
555        - 1
556    modified:
557      mergingIntList:
558        - 2
559        - 3
560        - 1
561`)
562
563var customStrategicMergePatchRawTestCases = []StrategicMergePatchRawTestCase{
564	{
565		Description: "$setElementOrder contains item that is not present in the list to be merged",
566		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
567			Original: []byte(`
568mergingList:
569  - name: 1
570  - name: 3
571`),
572			TwoWay: []byte(`
573$setElementOrder/mergingList:
574  - name: 3
575  - name: 2
576  - name: 1
577mergingList:
578  - name: 3
579    value: 3
580  - name: 1
581    value: 1
582`),
583			Modified: []byte(`
584mergingList:
585  - name: 3
586    value: 3
587  - name: 1
588    value: 1
589`),
590		},
591	},
592	{
593		Description: "$setElementOrder contains item that is not present in the int list to be merged",
594		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
595			Original: []byte(`
596mergingIntList:
597  - 1
598  - 3
599`),
600			TwoWay: []byte(`
601$setElementOrder/mergingIntList:
602  - 3
603  - 2
604  - 1
605`),
606			Modified: []byte(`
607mergingIntList:
608  - 3
609  - 1
610`),
611		},
612	},
613	{
614		Description: "should check if order in $setElementOrder and patch list match",
615		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
616			Original: []byte(`
617mergingList:
618  - name: 1
619  - name: 3
620  - name: 2
621`),
622			TwoWay: []byte(`
623$setElementOrder/mergingList:
624  - name: 1
625  - name: 2
626  - name: 3
627mergingList:
628  - name: 3
629    value: 3
630  - name: 1
631    value: 1
632`),
633			ExpectedError: "doesn't match",
634		},
635	},
636	{
637		Description: "$setElementOrder contains item that is not present in the int list to be merged",
638		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
639			Original: []byte(`
640mergingIntList:
641  - 1
642  - 3
643  - 2
644`),
645			TwoWay: []byte(`
646$setElementOrder/mergingIntList:
647  - 1
648  - 2
649  - 3
650mergingIntList:
651  - 3
652  - 1
653`),
654			ExpectedError: "doesn't match",
655		},
656	},
657	{
658		Description: "missing merge key should error out",
659		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
660			Original: []byte(`
661mergingList:
662  - name: 1
663    value: a
664`),
665			TwoWay: []byte(`
666mergingList:
667  - value: b
668`),
669			ExpectedError: "does not contain declared merge key",
670		},
671	},
672}
673
674func TestCustomStrategicMergePatch(t *testing.T) {
675	mergeItemOpenapiSchema := PatchMetaFromOpenAPI{
676		Schema: sptest.GetSchemaOrDie(&fakeMergeItemSchema, "mergeItem"),
677	}
678	schemas := []LookupPatchMeta{
679		mergeItemStructSchema,
680		mergeItemOpenapiSchema,
681	}
682
683	tc := StrategicMergePatchTestCases{}
684	err := yaml.Unmarshal(customStrategicMergePatchTestCaseData, &tc)
685	if err != nil {
686		t.Errorf("can't unmarshal test cases: %v\n", err)
687		return
688	}
689
690	for _, schema := range schemas {
691		for _, c := range tc.TestCases {
692			original, expectedTwoWayPatch, _, expectedResult := twoWayTestCaseToJSONOrFail(t, c, schema)
693			testPatchApplication(t, original, expectedTwoWayPatch, expectedResult, c.Description, "", schema)
694		}
695
696		for _, c := range customStrategicMergePatchRawTestCases {
697			original, expectedTwoWayPatch, _, expectedResult := twoWayRawTestCaseToJSONOrFail(t, c)
698			testPatchApplication(t, original, expectedTwoWayPatch, expectedResult, c.Description, c.ExpectedError, schema)
699		}
700	}
701}
702
703// These are test cases for StrategicMergePatch, to assert that applying  a patch
704// yields the correct outcome. They are also test cases for CreateTwoWayMergePatch
705// and CreateThreeWayMergePatch, to assert that they both generate the correct patch
706// for the given set of input documents.
707//
708var createStrategicMergePatchTestCaseData = []byte(`
709testCases:
710  - description: nil original
711    twoWay:
712      name: 1
713      value: 1
714    modified:
715      name: 1
716      value: 1
717    current:
718      name: 1
719      other: a
720    threeWay:
721      value: 1
722    result:
723      name: 1
724      value: 1
725      other: a
726  - description: nil patch
727    original:
728      name: 1
729    twoWay:
730      {}
731    modified:
732      name: 1
733    current:
734      name: 1
735    threeWay:
736      {}
737    result:
738      name: 1
739  - description: add field to map
740    original:
741      name: 1
742    twoWay:
743      value: 1
744    modified:
745      name: 1
746      value: 1
747    current:
748      name: 1
749      other: a
750    threeWay:
751      value: 1
752    result:
753      name: 1
754      value: 1
755      other: a
756  - description: add field to map with conflict
757    original:
758      name: 1
759    twoWay:
760      value: 1
761    modified:
762      name: 1
763      value: 1
764    current:
765      name: a
766      other: a
767    threeWay:
768      name: 1
769      value: 1
770    result:
771      name: 1
772      value: 1
773      other: a
774  - description: add field and delete field from map
775    original:
776      name: 1
777    twoWay:
778      name: null
779      value: 1
780    modified:
781      value: 1
782    current:
783      name: 1
784      other: a
785    threeWay:
786      name: null
787      value: 1
788    result:
789      value: 1
790      other: a
791  - description: add field and delete field from map with conflict
792    original:
793      name: 1
794    twoWay:
795      name: null
796      value: 1
797    modified:
798      value: 1
799    current:
800      name: a
801      other: a
802    threeWay:
803      name: null
804      value: 1
805    result:
806      value: 1
807      other: a
808  - description: delete field from nested map
809    original:
810      simpleMap:
811        key1: 1
812        key2: 1
813    twoWay:
814      simpleMap:
815        key2: null
816    modified:
817      simpleMap:
818        key1: 1
819    current:
820      simpleMap:
821        key1: 1
822        key2: 1
823        other: a
824    threeWay:
825      simpleMap:
826        key2: null
827    result:
828      simpleMap:
829        key1: 1
830        other: a
831  - description: delete field from nested map with conflict
832    original:
833      simpleMap:
834        key1: 1
835        key2: 1
836    twoWay:
837      simpleMap:
838        key2: null
839    modified:
840      simpleMap:
841        key1: 1
842    current:
843      simpleMap:
844        key1: a
845        key2: 1
846        other: a
847    threeWay:
848      simpleMap:
849        key1: 1
850        key2: null
851    result:
852      simpleMap:
853        key1: 1
854        other: a
855  - description: delete all fields from map
856    original:
857      name: 1
858      value: 1
859    twoWay:
860      name: null
861      value: null
862    modified: {}
863    current:
864      name: 1
865      value: 1
866      other: a
867    threeWay:
868      name: null
869      value: null
870    result:
871      other: a
872  - description: delete all fields from map with conflict
873    original:
874      name: 1
875      value: 1
876    twoWay:
877      name: null
878      value: null
879    modified: {}
880    current:
881      name: 1
882      value: a
883      other: a
884    threeWay:
885      name: null
886      value: null
887    result:
888      other: a
889  - description: add field and delete all fields from map
890    original:
891      name: 1
892      value: 1
893    twoWay:
894      name: null
895      value: null
896      other: a
897    modified:
898      other: a
899    current:
900      name: 1
901      value: 1
902      other: a
903    threeWay:
904      name: null
905      value: null
906    result:
907      other: a
908  - description: add field and delete all fields from map with conflict
909    original:
910      name: 1
911      value: 1
912    twoWay:
913      name: null
914      value: null
915      other: a
916    modified:
917      other: a
918    current:
919      name: 1
920      value: 1
921      other: b
922    threeWay:
923      name: null
924      value: null
925      other: a
926    result:
927      other: a
928  - description: replace list of scalars
929    original:
930      nonMergingIntList:
931        - 1
932        - 2
933    twoWay:
934      nonMergingIntList:
935        - 2
936        - 3
937    modified:
938      nonMergingIntList:
939        - 2
940        - 3
941    current:
942      nonMergingIntList:
943        - 1
944        - 2
945    threeWay:
946      nonMergingIntList:
947        - 2
948        - 3
949    result:
950      nonMergingIntList:
951        - 2
952        - 3
953  - description: replace list of scalars with conflict
954    original:
955      nonMergingIntList:
956        - 1
957        - 2
958    twoWay:
959      nonMergingIntList:
960        - 2
961        - 3
962    modified:
963      nonMergingIntList:
964        - 2
965        - 3
966    current:
967      nonMergingIntList:
968        - 1
969        - 4
970    threeWay:
971      nonMergingIntList:
972        - 2
973        - 3
974    result:
975      nonMergingIntList:
976        - 2
977        - 3
978  - description: delete all maps from merging list
979    original:
980      mergingList:
981        - name: 1
982        - name: 2
983    twoWay:
984      mergingList:
985        - name: 1
986          $patch: delete
987        - name: 2
988          $patch: delete
989    modified:
990      mergingList: []
991    current:
992      mergingList:
993        - name: 1
994        - name: 2
995    threeWay:
996      mergingList:
997        - name: 1
998          $patch: delete
999        - name: 2
1000          $patch: delete
1001    result:
1002      mergingList: []
1003  - description: delete all maps from merging list with conflict
1004    original:
1005      mergingList:
1006        - name: 1
1007        - name: 2
1008    twoWay:
1009      mergingList:
1010        - name: 1
1011          $patch: delete
1012        - name: 2
1013          $patch: delete
1014    modified:
1015      mergingList: []
1016    current:
1017      mergingList:
1018        - name: 1
1019          other: a
1020        - name: 2
1021          other: b
1022    threeWay:
1023      mergingList:
1024        - name: 1
1025          $patch: delete
1026        - name: 2
1027          $patch: delete
1028    result:
1029      mergingList: []
1030  - description: delete all maps from empty merging list
1031    original:
1032      mergingList:
1033        - name: 1
1034        - name: 2
1035    twoWay:
1036      mergingList:
1037        - name: 1
1038          $patch: delete
1039        - name: 2
1040          $patch: delete
1041    modified:
1042      mergingList: []
1043    current:
1044      mergingList: []
1045    threeWay:
1046      mergingList:
1047        - name: 1
1048          $patch: delete
1049        - name: 2
1050          $patch: delete
1051    result:
1052      mergingList: []
1053  - description: merge empty merging lists
1054    original:
1055      mergingList: []
1056    twoWay:
1057      {}
1058    modified:
1059      mergingList: []
1060    current:
1061      mergingList: []
1062    threeWay:
1063      {}
1064    result:
1065      mergingList: []
1066  - description: defined null values should propagate overwrite current fields (with conflict)
1067    original:
1068      name: 2
1069    twoWay:
1070      name: 1
1071      value: 1
1072      other: null
1073    twoWayResult:
1074      name: 1
1075      value: 1
1076    modified:
1077      name: 1
1078      value: 1
1079      other: null
1080    current:
1081      name: a
1082      other: a
1083    threeWay:
1084      name: 1
1085      value: 1
1086      other: null
1087    result:
1088      name: 1
1089      value: 1
1090  - description: defined null values should propagate removing original fields
1091    original:
1092      name: original-name
1093      value: original-value
1094    current:
1095      name: original-name
1096      value: original-value
1097      other: current-other
1098    modified:
1099      name: modified-name
1100      value: null
1101    twoWay:
1102      name: modified-name
1103      value: null
1104    twoWayResult:
1105      name: modified-name
1106    threeWay:
1107      name: modified-name
1108      value: null
1109    result:
1110      name: modified-name
1111      other: current-other
1112  - description: nil patch with retainKeys map
1113    original:
1114      name: a
1115      retainKeysMap:
1116        name: foo
1117    current:
1118      name: a
1119      value: b
1120      retainKeysMap:
1121        name: foo
1122    modified:
1123      name: a
1124      retainKeysMap:
1125        name: foo
1126    twoWay: {}
1127    threeWay: {}
1128    result:
1129      name: a
1130      value: b
1131      retainKeysMap:
1132        name: foo
1133  - description: retainKeys map with no change should not be present
1134    original:
1135      name: a
1136      retainKeysMap:
1137        name: foo
1138    current:
1139      name: a
1140      other: c
1141      retainKeysMap:
1142        name: foo
1143    modified:
1144      name: a
1145      value: b
1146      retainKeysMap:
1147        name: foo
1148    twoWay:
1149      value: b
1150    threeWay:
1151      value: b
1152    result:
1153      name: a
1154      value: b
1155      other: c
1156      retainKeysMap:
1157        name: foo
1158`)
1159
1160var strategicMergePatchRawTestCases = []StrategicMergePatchRawTestCase{
1161	{
1162		Description: "delete items in lists of scalars",
1163		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1164			Original: []byte(`
1165mergingIntList:
1166  - 1
1167  - 2
1168  - 3
1169`),
1170			TwoWay: []byte(`
1171$setElementOrder/mergingIntList:
1172  - 1
1173  - 2
1174$deleteFromPrimitiveList/mergingIntList:
1175  - 3
1176`),
1177			Modified: []byte(`
1178mergingIntList:
1179  - 1
1180  - 2
1181`),
1182			Current: []byte(`
1183mergingIntList:
1184  - 1
1185  - 2
1186  - 3
1187  - 4
1188`),
1189			ThreeWay: []byte(`
1190$setElementOrder/mergingIntList:
1191  - 1
1192  - 2
1193$deleteFromPrimitiveList/mergingIntList:
1194  - 3
1195`),
1196			Result: []byte(`
1197mergingIntList:
1198  - 1
1199  - 2
1200  - 4
1201`),
1202		},
1203	},
1204	{
1205		Description: "delete all duplicate items in lists of scalars",
1206		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1207			Original: []byte(`
1208mergingIntList:
1209  - 1
1210  - 2
1211  - 3
1212  - 3
1213`),
1214			TwoWay: []byte(`
1215$setElementOrder/mergingIntList:
1216  - 1
1217  - 2
1218$deleteFromPrimitiveList/mergingIntList:
1219  - 3
1220`),
1221			Modified: []byte(`
1222mergingIntList:
1223  - 1
1224  - 2
1225`),
1226			Current: []byte(`
1227mergingIntList:
1228  - 1
1229  - 2
1230  - 3
1231  - 3
1232  - 4
1233`),
1234			ThreeWay: []byte(`
1235$setElementOrder/mergingIntList:
1236  - 1
1237  - 2
1238$deleteFromPrimitiveList/mergingIntList:
1239  - 3
1240`),
1241			Result: []byte(`
1242mergingIntList:
1243  - 1
1244  - 2
1245  - 4
1246`),
1247		},
1248	},
1249	{
1250		Description: "add and delete items in lists of scalars",
1251		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1252			Original: []byte(`
1253mergingIntList:
1254  - 1
1255  - 2
1256  - 3
1257`),
1258			TwoWay: []byte(`
1259$setElementOrder/mergingIntList:
1260  - 1
1261  - 2
1262  - 4
1263$deleteFromPrimitiveList/mergingIntList:
1264  - 3
1265mergingIntList:
1266  - 4
1267`),
1268			Modified: []byte(`
1269mergingIntList:
1270  - 1
1271  - 2
1272  - 4
1273`),
1274			Current: []byte(`
1275mergingIntList:
1276  - 1
1277  - 2
1278  - 3
1279  - 4
1280`),
1281			ThreeWay: []byte(`
1282$setElementOrder/mergingIntList:
1283  - 1
1284  - 2
1285  - 4
1286$deleteFromPrimitiveList/mergingIntList:
1287  - 3
1288`),
1289			Result: []byte(`
1290mergingIntList:
1291  - 1
1292  - 2
1293  - 4
1294`),
1295		},
1296	},
1297	{
1298		Description: "merge lists of maps",
1299		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1300			Original: []byte(`
1301mergingList:
1302  - name: 1
1303  - name: 2
1304    value: 2
1305`),
1306			TwoWay: []byte(`
1307$setElementOrder/mergingList:
1308  - name: 4
1309  - name: 1
1310  - name: 2
1311  - name: 3
1312mergingList:
1313  - name: 4
1314    value: 4
1315  - name: 3
1316    value: 3
1317`),
1318			Modified: []byte(`
1319mergingList:
1320  - name: 4
1321    value: 4
1322  - name: 1
1323  - name: 2
1324    value: 2
1325  - name: 3
1326    value: 3
1327`),
1328			Current: []byte(`
1329mergingList:
1330  - name: 1
1331    other: a
1332  - name: 2
1333    value: 2
1334    other: b
1335`),
1336			ThreeWay: []byte(`
1337$setElementOrder/mergingList:
1338  - name: 4
1339  - name: 1
1340  - name: 2
1341  - name: 3
1342mergingList:
1343  - name: 4
1344    value: 4
1345  - name: 3
1346    value: 3
1347`),
1348			Result: []byte(`
1349mergingList:
1350  - name: 4
1351    value: 4
1352  - name: 1
1353    other: a
1354  - name: 2
1355    value: 2
1356    other: b
1357  - name: 3
1358    value: 3
1359`),
1360		},
1361	},
1362	{
1363		Description: "merge lists of maps with conflict",
1364		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1365			Original: []byte(`
1366mergingList:
1367  - name: 1
1368  - name: 2
1369    value: 2
1370`),
1371			TwoWay: []byte(`
1372$setElementOrder/mergingList:
1373  - name: 1
1374  - name: 2
1375  - name: 3
1376mergingList:
1377  - name: 3
1378    value: 3
1379`),
1380			Modified: []byte(`
1381mergingList:
1382  - name: 1
1383  - name: 2
1384    value: 2
1385  - name: 3
1386    value: 3
1387`),
1388			Current: []byte(`
1389mergingList:
1390  - name: 1
1391    other: a
1392  - name: 2
1393    value: 3
1394    other: b
1395`),
1396			ThreeWay: []byte(`
1397$setElementOrder/mergingList:
1398  - name: 1
1399  - name: 2
1400  - name: 3
1401mergingList:
1402  - name: 2
1403    value: 2
1404  - name: 3
1405    value: 3
1406`),
1407			Result: []byte(`
1408mergingList:
1409  - name: 1
1410    other: a
1411  - name: 2
1412    value: 2
1413    other: b
1414  - name: 3
1415    value: 3
1416`),
1417		},
1418	},
1419	{
1420		Description: "add field to map in merging list",
1421		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1422			Original: []byte(`
1423mergingList:
1424  - name: 1
1425  - name: 2
1426    value: 2
1427`),
1428			TwoWay: []byte(`
1429$setElementOrder/mergingList:
1430  - name: 1
1431  - name: 2
1432mergingList:
1433  - name: 1
1434    value: 1
1435`),
1436			Modified: []byte(`
1437mergingList:
1438  - name: 1
1439    value: 1
1440  - name: 2
1441    value: 2
1442`),
1443			Current: []byte(`
1444mergingList:
1445  - name: 1
1446    other: a
1447  - name: 2
1448    value: 2
1449    other: b
1450`),
1451			ThreeWay: []byte(`
1452$setElementOrder/mergingList:
1453  - name: 1
1454  - name: 2
1455mergingList:
1456  - name: 1
1457    value: 1
1458`),
1459			Result: []byte(`
1460mergingList:
1461  - name: 1
1462    value: 1
1463    other: a
1464  - name: 2
1465    value: 2
1466    other: b
1467`),
1468		},
1469	},
1470	{
1471		Description: "add field to map in merging list",
1472		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1473			Original: []byte(`
1474mergingList:
1475  - name: 1
1476  - name: 2
1477    value: 2
1478`),
1479			TwoWay: []byte(`
1480$setElementOrder/mergingList:
1481  - name: 1
1482  - name: 2
1483mergingList:
1484  - name: 1
1485    value: 1
1486`),
1487			Modified: []byte(`
1488mergingList:
1489  - name: 1
1490    value: 1
1491  - name: 2
1492    value: 2
1493`),
1494			Current: []byte(`
1495mergingList:
1496  - name: 1
1497    other: a
1498  - name: 2
1499    value: 2
1500    other: b
1501`),
1502			ThreeWay: []byte(`
1503$setElementOrder/mergingList:
1504  - name: 1
1505  - name: 2
1506mergingList:
1507  - name: 1
1508    value: 1
1509`),
1510			Result: []byte(`
1511mergingList:
1512  - name: 1
1513    value: 1
1514    other: a
1515  - name: 2
1516    value: 2
1517    other: b
1518`),
1519		},
1520	},
1521	{
1522		Description: "add field to map in merging list with conflict",
1523		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1524			Original: []byte(`
1525mergingList:
1526  - name: 1
1527  - name: 2
1528    value: 2
1529`),
1530			TwoWay: []byte(`
1531$setElementOrder/mergingList:
1532  - name: 1
1533  - name: 2
1534mergingList:
1535  - name: 1
1536    value: 1
1537`),
1538			Modified: []byte(`
1539mergingList:
1540  - name: 1
1541    value: 1
1542  - name: 2
1543    value: 2
1544`),
1545			Current: []byte(`
1546mergingList:
1547  - name: 1
1548    other: a
1549  - name: 3
1550    value: 2
1551    other: b
1552`),
1553			ThreeWay: []byte(`
1554$setElementOrder/mergingList:
1555  - name: 1
1556  - name: 2
1557mergingList:
1558  - name: 1
1559    value: 1
1560  - name: 2
1561    value: 2
1562`),
1563			Result: []byte(`
1564mergingList:
1565  - name: 1
1566    value: 1
1567    other: a
1568  - name: 2
1569    value: 2
1570  - name: 3
1571    value: 2
1572    other: b
1573`),
1574		},
1575	},
1576	{
1577		Description: "add duplicate field to map in merging list",
1578		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1579			Original: []byte(`
1580mergingList:
1581  - name: 1
1582  - name: 2
1583    value: 2
1584`),
1585			TwoWay: []byte(`
1586$setElementOrder/mergingList:
1587  - name: 1
1588  - name: 2
1589mergingList:
1590  - name: 1
1591    value: 1
1592`),
1593			Modified: []byte(`
1594mergingList:
1595  - name: 1
1596    value: 1
1597  - name: 2
1598    value: 2
1599`),
1600			Current: []byte(`
1601mergingList:
1602  - name: 1
1603    value: 1
1604    other: a
1605  - name: 2
1606    value: 2
1607    other: b
1608`),
1609			ThreeWay: []byte(`{}`),
1610			Result: []byte(`
1611mergingList:
1612  - name: 1
1613    value: 1
1614    other: a
1615  - name: 2
1616    value: 2
1617    other: b
1618`),
1619		},
1620	},
1621	{
1622		Description: "add an item that already exists in current object in merging list",
1623		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1624			Original: []byte(`
1625mergingList:
1626  - name: 1
1627    value: a
1628  - name: 2
1629`),
1630			TwoWay: []byte(`
1631$setElementOrder/mergingList:
1632  - name: 1
1633  - name: 2
1634  - name: 3
1635mergingList:
1636  - name: 3
1637`),
1638			Modified: []byte(`
1639mergingList:
1640  - name: 1
1641    value: a
1642  - name: 2
1643  - name: 3
1644`),
1645			Current: []byte(`
1646mergingList:
1647  - name: 1
1648    value: a
1649    other: x
1650  - name: 2
1651  - name: 3
1652`),
1653			ThreeWay: []byte(`{}`),
1654			Result: []byte(`
1655mergingList:
1656  - name: 1
1657    value: a
1658    other: x
1659  - name: 2
1660  - name: 3
1661`),
1662		},
1663	},
1664	{
1665		Description: "add duplicate field to map in merging list with conflict",
1666		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1667			Original: []byte(`
1668mergingList:
1669  - name: 1
1670  - name: 2
1671    value: 2
1672`),
1673			TwoWay: []byte(`
1674$setElementOrder/mergingList:
1675  - name: 1
1676  - name: 2
1677mergingList:
1678  - name: 1
1679    value: 1
1680`),
1681			Modified: []byte(`
1682mergingList:
1683  - name: 1
1684    value: 1
1685  - name: 2
1686    value: 2
1687`),
1688			Current: []byte(`
1689mergingList:
1690  - name: 1
1691    value: 1
1692    other: a
1693  - name: 2
1694    value: 3
1695    other: b
1696`),
1697			ThreeWay: []byte(`
1698$setElementOrder/mergingList:
1699  - name: 1
1700  - name: 2
1701mergingList:
1702  - name: 2
1703    value: 2
1704`),
1705			Result: []byte(`
1706mergingList:
1707  - name: 1
1708    value: 1
1709    other: a
1710  - name: 2
1711    value: 2
1712    other: b
1713`),
1714		},
1715	},
1716	{
1717		Description: "replace map field value in merging list",
1718		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1719			Original: []byte(`
1720mergingList:
1721  - name: 1
1722    value: 1
1723  - name: 2
1724    value: 2
1725`),
1726			TwoWay: []byte(`
1727$setElementOrder/mergingList:
1728  - name: 1
1729  - name: 2
1730mergingList:
1731  - name: 1
1732    value: a
1733`),
1734			Modified: []byte(`
1735mergingList:
1736  - name: 1
1737    value: a
1738  - name: 2
1739    value: 2
1740`),
1741			Current: []byte(`
1742mergingList:
1743  - name: 1
1744    value: 1
1745    other: a
1746  - name: 2
1747    value: 2
1748    other: b
1749`),
1750			ThreeWay: []byte(`
1751$setElementOrder/mergingList:
1752  - name: 1
1753  - name: 2
1754mergingList:
1755  - name: 1
1756    value: a
1757`),
1758			Result: []byte(`
1759mergingList:
1760  - name: 1
1761    value: a
1762    other: a
1763  - name: 2
1764    value: 2
1765    other: b
1766`),
1767		},
1768	},
1769	{
1770		Description: "replace map field value in merging list with conflict",
1771		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1772			Original: []byte(`
1773mergingList:
1774  - name: 1
1775    value: 1
1776  - name: 2
1777    value: 2
1778`),
1779			TwoWay: []byte(`
1780$setElementOrder/mergingList:
1781  - name: 1
1782  - name: 2
1783mergingList:
1784  - name: 1
1785    value: a
1786`),
1787			Modified: []byte(`
1788mergingList:
1789  - name: 1
1790    value: a
1791  - name: 2
1792    value: 2
1793`),
1794			Current: []byte(`
1795mergingList:
1796  - name: 1
1797    value: 3
1798    other: a
1799  - name: 2
1800    value: 2
1801    other: b
1802`),
1803			ThreeWay: []byte(`
1804$setElementOrder/mergingList:
1805  - name: 1
1806  - name: 2
1807mergingList:
1808  - name: 1
1809    value: a
1810`),
1811			Result: []byte(`
1812mergingList:
1813  - name: 1
1814    value: a
1815    other: a
1816  - name: 2
1817    value: 2
1818    other: b
1819`),
1820		},
1821	},
1822	{
1823		Description: "delete map from merging list",
1824		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1825			Original: []byte(`
1826mergingList:
1827  - name: 1
1828  - name: 2
1829`),
1830			TwoWay: []byte(`
1831$setElementOrder/mergingList:
1832  - name: 2
1833mergingList:
1834  - name: 1
1835    $patch: delete
1836`),
1837			Modified: []byte(`
1838mergingList:
1839  - name: 2
1840`),
1841			Current: []byte(`
1842mergingList:
1843  - name: 1
1844  - name: 2
1845    other: b
1846`),
1847			ThreeWay: []byte(`
1848$setElementOrder/mergingList:
1849  - name: 2
1850mergingList:
1851  - name: 1
1852    $patch: delete
1853`),
1854			Result: []byte(`
1855mergingList:
1856  - name: 2
1857    other: b
1858`),
1859		},
1860	},
1861	{
1862		Description: "delete map from merging list with conflict",
1863		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1864			Original: []byte(`
1865mergingList:
1866  - name: 1
1867  - name: 2
1868`),
1869			TwoWay: []byte(`
1870$setElementOrder/mergingList:
1871  - name: 2
1872mergingList:
1873  - name: 1
1874    $patch: delete
1875`),
1876			Modified: []byte(`
1877mergingList:
1878  - name: 2
1879`),
1880			Current: []byte(`
1881mergingList:
1882  - name: 1
1883    other: a
1884  - name: 2
1885    other: b
1886`),
1887			ThreeWay: []byte(`
1888$setElementOrder/mergingList:
1889  - name: 2
1890mergingList:
1891  - name: 1
1892    $patch: delete
1893`),
1894			Result: []byte(`
1895mergingList:
1896  - name: 2
1897    other: b
1898`),
1899		},
1900	},
1901	{
1902		Description: "delete missing map from merging list",
1903		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1904			Original: []byte(`
1905mergingList:
1906  - name: 1
1907  - name: 2
1908`),
1909			TwoWay: []byte(`
1910$setElementOrder/mergingList:
1911  - name: 2
1912mergingList:
1913  - name: 1
1914    $patch: delete
1915`),
1916			Modified: []byte(`
1917mergingList:
1918  - name: 2
1919`),
1920			Current: []byte(`
1921mergingList:
1922  - name: 2
1923    other: b
1924`),
1925			ThreeWay: []byte(`
1926$setElementOrder/mergingList:
1927  - name: 2
1928mergingList:
1929  - name: 1
1930    $patch: delete
1931`),
1932			Result: []byte(`
1933mergingList:
1934  - name: 2
1935    other: b
1936`),
1937		},
1938	},
1939	{
1940		Description: "delete missing map from merging list with conflict",
1941		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1942			Original: []byte(`
1943mergingList:
1944  - name: 1
1945  - name: 2
1946`),
1947			TwoWay: []byte(`
1948$setElementOrder/mergingList:
1949  - name: 2
1950mergingList:
1951  - name: 1
1952    $patch: delete
1953`),
1954			Modified: []byte(`
1955mergingList:
1956  - name: 2
1957`),
1958			Current: []byte(`
1959mergingList:
1960  - name: 3
1961    other: a
1962`),
1963			ThreeWay: []byte(`
1964$setElementOrder/mergingList:
1965  - name: 2
1966mergingList:
1967  - name: 2
1968  - name: 1
1969    $patch: delete
1970`),
1971			Result: []byte(`
1972mergingList:
1973  - name: 2
1974  - name: 3
1975    other: a
1976`),
1977		},
1978	},
1979	{
1980		Description: "add map and delete map from merging list",
1981		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
1982			Original: []byte(`
1983mergingList:
1984  - name: 1
1985  - name: 2
1986`),
1987			TwoWay: []byte(`
1988$setElementOrder/mergingList:
1989  - name: 2
1990  - name: 3
1991mergingList:
1992  - name: 3
1993  - name: 1
1994    $patch: delete
1995`),
1996			Modified: []byte(`
1997mergingList:
1998  - name: 2
1999  - name: 3
2000`),
2001			Current: []byte(`
2002mergingList:
2003  - name: 1
2004  - name: 2
2005    other: b
2006  - name: 4
2007    other: c
2008`),
2009			ThreeWay: []byte(`
2010$setElementOrder/mergingList:
2011  - name: 2
2012  - name: 3
2013mergingList:
2014  - name: 3
2015  - name: 1
2016    $patch: delete
2017`),
2018			Result: []byte(`
2019mergingList:
2020  - name: 2
2021    other: b
2022  - name: 4
2023    other: c
2024  - name: 3
2025`),
2026		},
2027	},
2028	{
2029		Description: "add map and delete map from merging list with conflict",
2030		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2031			Original: []byte(`
2032mergingList:
2033  - name: 1
2034  - name: 2
2035`),
2036			TwoWay: []byte(`
2037$setElementOrder/mergingList:
2038  - name: 2
2039  - name: 3
2040mergingList:
2041  - name: 3
2042  - name: 1
2043    $patch: delete
2044`),
2045			Modified: []byte(`
2046mergingList:
2047  - name: 2
2048  - name: 3
2049`),
2050			Current: []byte(`
2051mergingList:
2052  - name: 1
2053    other: a
2054  - name: 4
2055    other: c
2056`),
2057			ThreeWay: []byte(`
2058$setElementOrder/mergingList:
2059  - name: 2
2060  - name: 3
2061mergingList:
2062  - name: 2
2063  - name: 3
2064  - name: 1
2065    $patch: delete
2066`),
2067			Result: []byte(`
2068mergingList:
2069  - name: 4
2070    other: c
2071  - name: 2
2072  - name: 3
2073`),
2074		},
2075	},
2076	{
2077		Description: "delete field from map in merging list",
2078		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2079			Original: []byte(`
2080mergingList:
2081  - name: 1
2082    value: 1
2083  - name: 2
2084    value: 2
2085`),
2086			TwoWay: []byte(`
2087$setElementOrder/mergingList:
2088  - name: 1
2089  - name: 2
2090mergingList:
2091  - name: 1
2092    value: null
2093`),
2094			Modified: []byte(`
2095mergingList:
2096  - name: 1
2097  - name: 2
2098    value: 2
2099`),
2100			Current: []byte(`
2101mergingList:
2102  - name: 1
2103    value: 1
2104    other: a
2105  - name: 2
2106    value: 2
2107    other: b
2108`),
2109			ThreeWay: []byte(`
2110$setElementOrder/mergingList:
2111  - name: 1
2112  - name: 2
2113mergingList:
2114  - name: 1
2115    value: null
2116`),
2117			Result: []byte(`
2118mergingList:
2119  - name: 1
2120    other: a
2121  - name: 2
2122    value: 2
2123    other: b
2124`),
2125		},
2126	},
2127	{
2128		Description: "delete field from map in merging list with conflict",
2129		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2130			Original: []byte(`
2131mergingList:
2132  - name: 1
2133    value: 1
2134  - name: 2
2135    value: 2
2136`),
2137			TwoWay: []byte(`
2138$setElementOrder/mergingList:
2139  - name: 1
2140  - name: 2
2141mergingList:
2142  - name: 1
2143    value: null
2144`),
2145			Modified: []byte(`
2146mergingList:
2147  - name: 1
2148  - name: 2
2149    value: 2
2150`),
2151			Current: []byte(`
2152mergingList:
2153  - name: 1
2154    value: a
2155    other: a
2156  - name: 2
2157    value: 2
2158`),
2159			ThreeWay: []byte(`
2160$setElementOrder/mergingList:
2161  - name: 1
2162  - name: 2
2163mergingList:
2164  - name: 1
2165    value: null
2166`),
2167			Result: []byte(`
2168mergingList:
2169  - name: 1
2170    other: a
2171  - name: 2
2172    value: 2
2173`),
2174		},
2175	},
2176	{
2177		Description: "delete missing field from map in merging list",
2178		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2179			Original: []byte(`
2180mergingList:
2181  - name: 1
2182    value: 1
2183  - name: 2
2184    value: 2
2185`),
2186			TwoWay: []byte(`
2187$setElementOrder/mergingList:
2188  - name: 1
2189  - name: 2
2190mergingList:
2191  - name: 1
2192    value: null
2193`),
2194			Modified: []byte(`
2195mergingList:
2196  - name: 1
2197  - name: 2
2198    value: 2
2199`),
2200			Current: []byte(`
2201mergingList:
2202  - name: 1
2203    other: a
2204  - name: 2
2205    value: 2
2206    other: b
2207`),
2208			ThreeWay: []byte(`
2209$setElementOrder/mergingList:
2210  - name: 1
2211  - name: 2
2212mergingList:
2213  - name: 1
2214    value: null
2215`),
2216			Result: []byte(`
2217mergingList:
2218  - name: 1
2219    other: a
2220  - name: 2
2221    value: 2
2222    other: b
2223`),
2224		},
2225	},
2226	{
2227		Description: "delete missing field from map in merging list with conflict",
2228		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2229			Original: []byte(`
2230mergingList:
2231  - name: 1
2232    value: 1
2233  - name: 2
2234    value: 2
2235`),
2236			TwoWay: []byte(`
2237$setElementOrder/mergingList:
2238  - name: 1
2239  - name: 2
2240mergingList:
2241  - name: 1
2242    value: null
2243`),
2244			Modified: []byte(`
2245mergingList:
2246  - name: 1
2247  - name: 2
2248    value: 2
2249`),
2250			Current: []byte(`
2251mergingList:
2252  - name: 1
2253    other: a
2254  - name: 2
2255    other: b
2256`),
2257			ThreeWay: []byte(`
2258$setElementOrder/mergingList:
2259  - name: 1
2260  - name: 2
2261mergingList:
2262  - name: 1
2263    value: null
2264  - name: 2
2265    value: 2
2266`),
2267			Result: []byte(`
2268mergingList:
2269  - name: 1
2270    other: a
2271  - name: 2
2272    value: 2
2273    other: b
2274`),
2275		},
2276	},
2277	{
2278		Description: "replace non merging list nested in merging list",
2279		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2280			Original: []byte(`
2281mergingList:
2282  - name: 1
2283    nonMergingList:
2284      - name: 1
2285      - name: 2
2286        value: 2
2287  - name: 2
2288`),
2289			TwoWay: []byte(`
2290$setElementOrder/mergingList:
2291  - name: 1
2292  - name: 2
2293mergingList:
2294  - name: 1
2295    nonMergingList:
2296      - name: 1
2297        value: 1
2298`),
2299			Modified: []byte(`
2300mergingList:
2301  - name: 1
2302    nonMergingList:
2303      - name: 1
2304        value: 1
2305  - name: 2
2306`),
2307			Current: []byte(`
2308mergingList:
2309  - name: 1
2310    other: a
2311    nonMergingList:
2312      - name: 1
2313      - name: 2
2314        value: 2
2315  - name: 2
2316    other: b
2317`),
2318			ThreeWay: []byte(`
2319$setElementOrder/mergingList:
2320  - name: 1
2321  - name: 2
2322mergingList:
2323  - name: 1
2324    nonMergingList:
2325      - name: 1
2326        value: 1
2327`),
2328			Result: []byte(`
2329mergingList:
2330  - name: 1
2331    other: a
2332    nonMergingList:
2333      - name: 1
2334        value: 1
2335  - name: 2
2336    other: b
2337`),
2338		},
2339	},
2340	{
2341		Description: "replace non merging list nested in merging list with value conflict",
2342		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2343			Original: []byte(`
2344mergingList:
2345  - name: 1
2346    nonMergingList:
2347      - name: 1
2348      - name: 2
2349        value: 2
2350  - name: 2
2351`),
2352			TwoWay: []byte(`
2353$setElementOrder/mergingList:
2354  - name: 1
2355  - name: 2
2356mergingList:
2357  - name: 1
2358    nonMergingList:
2359      - name: 1
2360        value: 1
2361`),
2362			Modified: []byte(`
2363mergingList:
2364  - name: 1
2365    nonMergingList:
2366      - name: 1
2367        value: 1
2368  - name: 2
2369`),
2370			Current: []byte(`
2371mergingList:
2372  - name: 1
2373    other: a
2374    nonMergingList:
2375      - name: 1
2376        value: c
2377  - name: 2
2378    other: b
2379`),
2380			ThreeWay: []byte(`
2381$setElementOrder/mergingList:
2382  - name: 1
2383  - name: 2
2384mergingList:
2385  - name: 1
2386    nonMergingList:
2387      - name: 1
2388        value: 1
2389`),
2390			Result: []byte(`
2391mergingList:
2392  - name: 1
2393    other: a
2394    nonMergingList:
2395      - name: 1
2396        value: 1
2397  - name: 2
2398    other: b
2399`),
2400		},
2401	},
2402	{
2403		Description: "replace non merging list nested in merging list with deletion conflict",
2404		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2405			Original: []byte(`
2406mergingList:
2407  - name: 1
2408    nonMergingList:
2409      - name: 1
2410      - name: 2
2411        value: 2
2412  - name: 2
2413`),
2414			TwoWay: []byte(`
2415$setElementOrder/mergingList:
2416  - name: 1
2417  - name: 2
2418mergingList:
2419  - name: 1
2420    nonMergingList:
2421      - name: 1
2422        value: 1
2423`),
2424			Modified: []byte(`
2425mergingList:
2426  - name: 1
2427    nonMergingList:
2428      - name: 1
2429        value: 1
2430  - name: 2
2431`),
2432			Current: []byte(`
2433mergingList:
2434  - name: 1
2435    other: a
2436    nonMergingList:
2437      - name: 2
2438        value: 2
2439  - name: 2
2440    other: b
2441`),
2442			ThreeWay: []byte(`
2443$setElementOrder/mergingList:
2444  - name: 1
2445  - name: 2
2446mergingList:
2447  - name: 1
2448    nonMergingList:
2449      - name: 1
2450        value: 1
2451`),
2452			Result: []byte(`
2453mergingList:
2454  - name: 1
2455    other: a
2456    nonMergingList:
2457      - name: 1
2458        value: 1
2459  - name: 2
2460    other: b
2461`),
2462		},
2463	},
2464	{
2465		Description: "add field to map in merging list nested in merging list",
2466		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2467			Original: []byte(`
2468mergingList:
2469  - name: 1
2470    mergingList:
2471      - name: 1
2472      - name: 2
2473        value: 2
2474  - name: 2
2475`),
2476			TwoWay: []byte(`
2477$setElementOrder/mergingList:
2478  - name: 1
2479  - name: 2
2480mergingList:
2481  - $setElementOrder/mergingList:
2482      - name: 1
2483      - name: 2
2484    name: 1
2485    mergingList:
2486      - name: 1
2487        value: 1
2488`),
2489			Modified: []byte(`
2490mergingList:
2491  - name: 1
2492    mergingList:
2493      - name: 1
2494        value: 1
2495      - name: 2
2496        value: 2
2497  - name: 2
2498`),
2499			Current: []byte(`
2500mergingList:
2501  - name: 1
2502    other: a
2503    mergingList:
2504      - name: 1
2505      - name: 2
2506        value: 2
2507  - name: 2
2508    other: b
2509`),
2510			ThreeWay: []byte(`
2511$setElementOrder/mergingList:
2512  - name: 1
2513  - name: 2
2514mergingList:
2515  - $setElementOrder/mergingList:
2516      - name: 1
2517      - name: 2
2518    name: 1
2519    mergingList:
2520      - name: 1
2521        value: 1
2522`),
2523			Result: []byte(`
2524mergingList:
2525  - name: 1
2526    other: a
2527    mergingList:
2528      - name: 1
2529        value: 1
2530      - name: 2
2531        value: 2
2532  - name: 2
2533    other: b
2534`),
2535		},
2536	},
2537	{
2538		Description: "add field to map in merging list nested in merging list with value conflict",
2539		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2540			Original: []byte(`
2541mergingList:
2542  - name: 1
2543    mergingList:
2544      - name: 1
2545      - name: 2
2546        value: 2
2547  - name: 2
2548`),
2549			TwoWay: []byte(`
2550$setElementOrder/mergingList:
2551  - name: 1
2552  - name: 2
2553mergingList:
2554  - $setElementOrder/mergingList:
2555      - name: 1
2556      - name: 2
2557    name: 1
2558    mergingList:
2559      - name: 1
2560        value: 1
2561`),
2562			Modified: []byte(`
2563mergingList:
2564  - name: 1
2565    mergingList:
2566      - name: 1
2567        value: 1
2568      - name: 2
2569        value: 2
2570  - name: 2
2571`),
2572			Current: []byte(`
2573mergingList:
2574  - name: 1
2575    other: a
2576    mergingList:
2577      - name: 1
2578        value: a
2579        other: c
2580      - name: 2
2581        value: b
2582        other: d
2583  - name: 2
2584    other: b
2585`),
2586			ThreeWay: []byte(`
2587$setElementOrder/mergingList:
2588  - name: 1
2589  - name: 2
2590mergingList:
2591  - $setElementOrder/mergingList:
2592      - name: 1
2593      - name: 2
2594    name: 1
2595    mergingList:
2596      - name: 1
2597        value: 1
2598      - name: 2
2599        value: 2
2600`),
2601			Result: []byte(`
2602mergingList:
2603  - name: 1
2604    other: a
2605    mergingList:
2606      - name: 1
2607        value: 1
2608        other: c
2609      - name: 2
2610        value: 2
2611        other: d
2612  - name: 2
2613    other: b
2614`),
2615		},
2616	},
2617	{
2618		Description: "add field to map in merging list nested in merging list with deletion conflict",
2619		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2620			Original: []byte(`
2621mergingList:
2622  - name: 1
2623    mergingList:
2624      - name: 1
2625      - name: 2
2626        value: 2
2627  - name: 2
2628`),
2629			TwoWay: []byte(`
2630$setElementOrder/mergingList:
2631  - name: 1
2632  - name: 2
2633mergingList:
2634  - $setElementOrder/mergingList:
2635      - name: 1
2636      - name: 2
2637    name: 1
2638    mergingList:
2639      - name: 1
2640        value: 1
2641`),
2642			Modified: []byte(`
2643mergingList:
2644  - name: 1
2645    mergingList:
2646      - name: 1
2647        value: 1
2648      - name: 2
2649        value: 2
2650  - name: 2
2651`),
2652			Current: []byte(`
2653mergingList:
2654  - name: 1
2655    other: a
2656    mergingList:
2657      - name: 2
2658        value: 2
2659        other: d
2660  - name: 2
2661    other: b
2662`),
2663			ThreeWay: []byte(`
2664$setElementOrder/mergingList:
2665  - name: 1
2666  - name: 2
2667mergingList:
2668  - $setElementOrder/mergingList:
2669      - name: 1
2670      - name: 2
2671    name: 1
2672    mergingList:
2673      - name: 1
2674        value: 1
2675`),
2676			Result: []byte(`
2677mergingList:
2678  - name: 1
2679    other: a
2680    mergingList:
2681      - name: 1
2682        value: 1
2683      - name: 2
2684        value: 2
2685        other: d
2686  - name: 2
2687    other: b
2688`),
2689		},
2690	},
2691
2692	{
2693		Description: "add field to map in merging list nested in merging list with deletion conflict",
2694		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2695			Original: []byte(`
2696mergingList:
2697  - name: 1
2698    mergingList:
2699      - name: 1
2700      - name: 2
2701        value: 2
2702  - name: 2
2703`),
2704			TwoWay: []byte(`
2705$setElementOrder/mergingList:
2706  - name: 1
2707  - name: 2
2708mergingList:
2709  - $setElementOrder/mergingList:
2710      - name: 2
2711      - name: 1
2712    name: 1
2713    mergingList:
2714      - name: 1
2715        value: 1
2716`),
2717			Modified: []byte(`
2718mergingList:
2719  - name: 1
2720    mergingList:
2721      - name: 2
2722        value: 2
2723      - name: 1
2724        value: 1
2725  - name: 2
2726`),
2727			Current: []byte(`
2728mergingList:
2729  - name: 1
2730    other: a
2731    mergingList:
2732      - name: 2
2733        value: 2
2734        other: d
2735  - name: 2
2736    other: b
2737`),
2738			ThreeWay: []byte(`
2739$setElementOrder/mergingList:
2740  - name: 1
2741  - name: 2
2742mergingList:
2743  - $setElementOrder/mergingList:
2744      - name: 2
2745      - name: 1
2746    name: 1
2747    mergingList:
2748      - name: 1
2749        value: 1
2750`),
2751			Result: []byte(`
2752mergingList:
2753  - name: 1
2754    other: a
2755    mergingList:
2756      - name: 2
2757        value: 2
2758        other: d
2759      - name: 1
2760        value: 1
2761  - name: 2
2762    other: b
2763`),
2764		},
2765	},
2766	{
2767		Description: "add map to merging list by pointer",
2768		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2769			Original: []byte(`
2770mergeItemPtr:
2771  - name: 1
2772`),
2773			TwoWay: []byte(`
2774$setElementOrder/mergeItemPtr:
2775  - name: 1
2776  - name: 2
2777mergeItemPtr:
2778  - name: 2
2779`),
2780			Modified: []byte(`
2781mergeItemPtr:
2782  - name: 1
2783  - name: 2
2784`),
2785			Current: []byte(`
2786mergeItemPtr:
2787  - name: 1
2788    other: a
2789  - name: 3
2790`),
2791			ThreeWay: []byte(`
2792$setElementOrder/mergeItemPtr:
2793  - name: 1
2794  - name: 2
2795mergeItemPtr:
2796  - name: 2
2797`),
2798			Result: []byte(`
2799mergeItemPtr:
2800  - name: 1
2801    other: a
2802  - name: 2
2803  - name: 3
2804`),
2805		},
2806	},
2807	{
2808		Description: "add map to merging list by pointer with conflict",
2809		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2810			Original: []byte(`
2811mergeItemPtr:
2812  - name: 1
2813`),
2814			TwoWay: []byte(`
2815$setElementOrder/mergeItemPtr:
2816  - name: 1
2817  - name: 2
2818mergeItemPtr:
2819  - name: 2
2820`),
2821			Modified: []byte(`
2822mergeItemPtr:
2823  - name: 1
2824  - name: 2
2825`),
2826			Current: []byte(`
2827mergeItemPtr:
2828  - name: 3
2829`),
2830			ThreeWay: []byte(`
2831$setElementOrder/mergeItemPtr:
2832  - name: 1
2833  - name: 2
2834mergeItemPtr:
2835  - name: 1
2836  - name: 2
2837`),
2838			Result: []byte(`
2839mergeItemPtr:
2840  - name: 1
2841  - name: 2
2842  - name: 3
2843`),
2844		},
2845	},
2846	{
2847		Description: "add field to map in merging list by pointer",
2848		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2849			Original: []byte(`
2850mergeItemPtr:
2851  - name: 1
2852    mergeItemPtr:
2853      - name: 1
2854      - name: 2
2855        value: 2
2856  - name: 2
2857`),
2858			TwoWay: []byte(`
2859$setElementOrder/mergeItemPtr:
2860  - name: 1
2861  - name: 2
2862mergeItemPtr:
2863  - $setElementOrder/mergeItemPtr:
2864      - name: 1
2865      - name: 2
2866    name: 1
2867    mergeItemPtr:
2868      - name: 1
2869        value: 1
2870`),
2871			Modified: []byte(`
2872mergeItemPtr:
2873  - name: 1
2874    mergeItemPtr:
2875      - name: 1
2876        value: 1
2877      - name: 2
2878        value: 2
2879  - name: 2
2880`),
2881			Current: []byte(`
2882mergeItemPtr:
2883  - name: 1
2884    other: a
2885    mergeItemPtr:
2886      - name: 1
2887        other: a
2888      - name: 2
2889        value: 2
2890        other: b
2891  - name: 2
2892    other: b
2893`),
2894			ThreeWay: []byte(`
2895$setElementOrder/mergeItemPtr:
2896  - name: 1
2897  - name: 2
2898mergeItemPtr:
2899  - $setElementOrder/mergeItemPtr:
2900      - name: 1
2901      - name: 2
2902    name: 1
2903    mergeItemPtr:
2904      - name: 1
2905        value: 1
2906`),
2907			Result: []byte(`
2908mergeItemPtr:
2909  - name: 1
2910    other: a
2911    mergeItemPtr:
2912      - name: 1
2913        value: 1
2914        other: a
2915      - name: 2
2916        value: 2
2917        other: b
2918  - name: 2
2919    other: b
2920`),
2921		},
2922	},
2923	{
2924		Description: "add field to map in merging list by pointer with conflict",
2925		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
2926			Original: []byte(`
2927mergeItemPtr:
2928  - name: 1
2929    mergeItemPtr:
2930      - name: 1
2931      - name: 2
2932        value: 2
2933  - name: 2
2934`),
2935			TwoWay: []byte(`
2936$setElementOrder/mergeItemPtr:
2937  - name: 1
2938  - name: 2
2939mergeItemPtr:
2940  - $setElementOrder/mergeItemPtr:
2941      - name: 1
2942      - name: 2
2943    name: 1
2944    mergeItemPtr:
2945      - name: 1
2946        value: 1
2947`),
2948			Modified: []byte(`
2949mergeItemPtr:
2950  - name: 1
2951    mergeItemPtr:
2952      - name: 1
2953        value: 1
2954      - name: 2
2955        value: 2
2956  - name: 2
2957`),
2958			Current: []byte(`
2959mergeItemPtr:
2960  - name: 1
2961    other: a
2962    mergeItemPtr:
2963      - name: 1
2964        value: a
2965      - name: 2
2966        value: 2
2967        other: b
2968  - name: 2
2969    other: b
2970`),
2971			ThreeWay: []byte(`
2972$setElementOrder/mergeItemPtr:
2973  - name: 1
2974  - name: 2
2975mergeItemPtr:
2976  - $setElementOrder/mergeItemPtr:
2977      - name: 1
2978      - name: 2
2979    name: 1
2980    mergeItemPtr:
2981      - name: 1
2982        value: 1
2983`),
2984			Result: []byte(`
2985mergeItemPtr:
2986  - name: 1
2987    other: a
2988    mergeItemPtr:
2989      - name: 1
2990        value: 1
2991      - name: 2
2992        value: 2
2993        other: b
2994  - name: 2
2995    other: b
2996`),
2997		},
2998	},
2999	{
3000		Description: "merge lists of scalars",
3001		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3002			Original: []byte(`
3003mergingIntList:
3004- 1
3005- 2
3006`),
3007			TwoWay: []byte(`
3008$setElementOrder/mergingIntList:
3009- 1
3010- 2
3011- 3
3012mergingIntList:
3013- 3
3014`),
3015			Modified: []byte(`
3016mergingIntList:
3017- 1
3018- 2
3019- 3
3020`),
3021			Current: []byte(`
3022mergingIntList:
3023- 1
3024- 2
3025- 4
3026`),
3027			ThreeWay: []byte(`
3028$setElementOrder/mergingIntList:
3029- 1
3030- 2
3031- 3
3032mergingIntList:
3033- 3
3034`),
3035			Result: []byte(`
3036mergingIntList:
3037- 1
3038- 2
3039- 3
3040- 4
3041`),
3042		},
3043	},
3044	{
3045		Description: "add duplicate field to map in merging int list",
3046		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3047			Original: []byte(`
3048mergingIntList:
3049  - 1
3050  - 2
3051`),
3052			TwoWay: []byte(`
3053$setElementOrder/mergingIntList:
3054  - 1
3055  - 2
3056  - 3
3057mergingIntList:
3058  - 3
3059`),
3060			Modified: []byte(`
3061mergingIntList:
3062  - 1
3063  - 2
3064  - 3
3065`),
3066			Current: []byte(`
3067mergingIntList:
3068  - 1
3069  - 2
3070  - 3
3071`),
3072			ThreeWay: []byte(`{}`),
3073			Result: []byte(`
3074mergingIntList:
3075  - 1
3076  - 2
3077  - 3
3078`),
3079		},
3080	},
3081	// test case for setElementOrder
3082	{
3083		Description: "add an item in a list of primitives and preserve order",
3084		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3085			Original: []byte(`
3086mergingIntList:
3087- 1
3088- 2
3089`),
3090			TwoWay: []byte(`
3091$setElementOrder/mergingIntList:
3092- 3
3093- 1
3094- 2
3095mergingIntList:
3096- 3
3097`),
3098			Modified: []byte(`
3099mergingIntList:
3100- 3
3101- 1
3102- 2
3103`),
3104			Current: []byte(`
3105mergingIntList:
3106- 1
3107- 4
3108- 2
3109`),
3110			ThreeWay: []byte(`
3111$setElementOrder/mergingIntList:
3112- 3
3113- 1
3114- 2
3115mergingIntList:
3116- 3
3117`),
3118			Result: []byte(`
3119mergingIntList:
3120- 3
3121- 1
3122- 4
3123- 2
3124`),
3125		},
3126	},
3127	{
3128		Description: "delete an item in a list of primitives and preserve order",
3129		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3130			Original: []byte(`
3131mergingIntList:
3132- 1
3133- 2
3134- 3
3135`),
3136			TwoWay: []byte(`
3137$setElementOrder/mergingIntList:
3138- 2
3139- 1
3140$deleteFromPrimitiveList/mergingIntList:
3141- 3
3142`),
3143			Modified: []byte(`
3144mergingIntList:
3145- 2
3146- 1
3147`),
3148			Current: []byte(`
3149mergingIntList:
3150- 1
3151- 2
3152- 3
3153`),
3154			ThreeWay: []byte(`
3155$setElementOrder/mergingIntList:
3156- 2
3157- 1
3158$deleteFromPrimitiveList/mergingIntList:
3159- 3
3160`),
3161			Result: []byte(`
3162mergingIntList:
3163- 2
3164- 1
3165`),
3166		},
3167	},
3168	{
3169		Description: "add an item in a list and preserve order",
3170		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3171			Original: []byte(`
3172mergingList:
3173  - name: 1
3174  - name: 2
3175    value: 2
3176`),
3177			TwoWay: []byte(`
3178$setElementOrder/mergingList:
3179  - name: 3
3180  - name: 1
3181  - name: 2
3182mergingList:
3183  - name: 3
3184    value: 3
3185`),
3186			Modified: []byte(`
3187mergingList:
3188  - name: 3
3189    value: 3
3190  - name: 1
3191  - name: 2
3192    value: 2
3193`),
3194			Current: []byte(`
3195mergingList:
3196  - name: 1
3197    other: a
3198  - name: 2
3199    value: 2
3200    other: b
3201`),
3202			ThreeWay: []byte(`
3203$setElementOrder/mergingList:
3204  - name: 3
3205  - name: 1
3206  - name: 2
3207mergingList:
3208  - name: 3
3209    value: 3
3210`),
3211			Result: []byte(`
3212mergingList:
3213  - name: 3
3214    value: 3
3215  - name: 1
3216    other: a
3217  - name: 2
3218    value: 2
3219    other: b
3220`),
3221		},
3222	},
3223	{
3224		Description: "add multiple items in a list and preserve order",
3225		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3226			Original: []byte(`
3227mergingList:
3228  - name: 1
3229  - name: 2
3230    value: 2
3231`),
3232			TwoWay: []byte(`
3233$setElementOrder/mergingList:
3234  - name: 1
3235  - name: 4
3236  - name: 2
3237  - name: 3
3238mergingList:
3239  - name: 4
3240    value: 4
3241  - name: 3
3242    value: 3
3243`),
3244			Modified: []byte(`
3245mergingList:
3246  - name: 1
3247  - name: 4
3248    value: 4
3249  - name: 2
3250    value: 2
3251  - name: 3
3252    value: 3
3253`),
3254			Current: []byte(`
3255mergingList:
3256  - name: 1
3257    other: a
3258  - name: 2
3259    value: 2
3260    other: b
3261`),
3262			ThreeWay: []byte(`
3263$setElementOrder/mergingList:
3264  - name: 1
3265  - name: 4
3266  - name: 2
3267  - name: 3
3268mergingList:
3269  - name: 4
3270    value: 4
3271  - name: 3
3272    value: 3
3273`),
3274			Result: []byte(`
3275mergingList:
3276  - name: 1
3277    other: a
3278  - name: 4
3279    value: 4
3280  - name: 2
3281    value: 2
3282    other: b
3283  - name: 3
3284    value: 3
3285`),
3286		},
3287	},
3288	{
3289		Description: "delete an item in a list and preserve order",
3290		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3291			Original: []byte(`
3292mergingList:
3293  - name: 1
3294  - name: 3
3295    value: 3
3296  - name: 2
3297    value: 2
3298`),
3299			TwoWay: []byte(`
3300$setElementOrder/mergingList:
3301  - name: 2
3302  - name: 1
3303mergingList:
3304  - name: 3
3305    $patch: delete
3306`),
3307			Modified: []byte(`
3308mergingList:
3309  - name: 2
3310    value: 2
3311  - name: 1
3312`),
3313			Current: []byte(`
3314mergingList:
3315  - name: 1
3316    other: a
3317  - name: 2
3318    value: 2
3319    other: b
3320  - name: 3
3321    value: 3
3322`),
3323			ThreeWay: []byte(`
3324$setElementOrder/mergingList:
3325  - name: 2
3326  - name: 1
3327mergingList:
3328  - name: 3
3329    $patch: delete
3330`),
3331			Result: []byte(`
3332mergingList:
3333  - name: 2
3334    value: 2
3335    other: b
3336  - name: 1
3337    other: a
3338`),
3339		},
3340	},
3341	{
3342		Description: "change an item in a list and preserve order",
3343		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3344			Original: []byte(`
3345mergingList:
3346  - name: 1
3347  - name: 3
3348    value: 3
3349  - name: 2
3350    value: 2
3351`),
3352			TwoWay: []byte(`
3353$setElementOrder/mergingList:
3354  - name: 2
3355  - name: 3
3356  - name: 1
3357mergingList:
3358  - name: 3
3359    value: x
3360`),
3361			Modified: []byte(`
3362mergingList:
3363  - name: 2
3364    value: 2
3365  - name: 3
3366    value: x
3367  - name: 1
3368`),
3369			Current: []byte(`
3370mergingList:
3371  - name: 1
3372    other: a
3373  - name: 2
3374    value: 2
3375    other: b
3376  - name: 3
3377    value: 3
3378`),
3379			ThreeWay: []byte(`
3380$setElementOrder/mergingList:
3381  - name: 2
3382  - name: 3
3383  - name: 1
3384mergingList:
3385  - name: 3
3386    value: x
3387`),
3388			Result: []byte(`
3389mergingList:
3390  - name: 2
3391    value: 2
3392    other: b
3393  - name: 3
3394    value: x
3395  - name: 1
3396    other: a
3397`),
3398		},
3399	},
3400	{
3401		Description: "add and delete an item in a list and preserve order",
3402		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3403			Original: []byte(`
3404mergingList:
3405  - name: 1
3406  - name: 3
3407    value: 3
3408  - name: 2
3409    value: 2
3410`),
3411			TwoWay: []byte(`
3412$setElementOrder/mergingList:
3413  - name: 4
3414  - name: 2
3415  - name: 1
3416mergingList:
3417  - name: 4
3418    value: 4
3419  - name: 3
3420    $patch: delete
3421`),
3422			Modified: []byte(`
3423mergingList:
3424  - name: 4
3425    value: 4
3426  - name: 2
3427    value: 2
3428  - name: 1
3429`),
3430			Current: []byte(`
3431mergingList:
3432  - name: 1
3433    other: a
3434  - name: 2
3435    value: 2
3436    other: b
3437  - name: 3
3438    value: 3
3439`),
3440			ThreeWay: []byte(`
3441$setElementOrder/mergingList:
3442  - name: 4
3443  - name: 2
3444  - name: 1
3445mergingList:
3446  - name: 4
3447    value: 4
3448  - name: 3
3449    $patch: delete
3450`),
3451			Result: []byte(`
3452mergingList:
3453  - name: 4
3454    value: 4
3455  - name: 2
3456    value: 2
3457    other: b
3458  - name: 1
3459    other: a
3460`),
3461		},
3462	},
3463	{
3464		Description: "set elements order in a list",
3465		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3466			Original: []byte(`
3467mergingList:
3468  - name: 1
3469  - name: 3
3470    value: 3
3471  - name: 4
3472    value: 4
3473  - name: 2
3474    value: 2
3475`),
3476			TwoWay: []byte(`
3477$setElementOrder/mergingList:
3478  - name: 4
3479  - name: 2
3480  - name: 3
3481  - name: 1
3482`),
3483			Modified: []byte(`
3484mergingList:
3485  - name: 4
3486    value: 4
3487  - name: 2
3488    value: 2
3489  - name: 3
3490    value: 3
3491  - name: 1
3492`),
3493			Current: []byte(`
3494mergingList:
3495  - name: 1
3496    other: a
3497  - name: 3
3498    value: 3
3499  - name: 4
3500    value: 4
3501  - name: 2
3502    value: 2
3503`),
3504			ThreeWay: []byte(`
3505$setElementOrder/mergingList:
3506  - name: 4
3507  - name: 2
3508  - name: 3
3509  - name: 1
3510`),
3511			Result: []byte(`
3512mergingList:
3513  - name: 4
3514    value: 4
3515  - name: 2
3516    value: 2
3517  - name: 3
3518    value: 3
3519  - name: 1
3520    other: a
3521`),
3522		},
3523	},
3524	{
3525		Description: "set elements order in a list with server-only items",
3526		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3527			Original: []byte(`
3528mergingList:
3529  - name: 1
3530  - name: 3
3531    value: 3
3532  - name: 4
3533    value: 4
3534  - name: 2
3535    value: 2
3536`),
3537			TwoWay: []byte(`
3538$setElementOrder/mergingList:
3539  - name: 4
3540  - name: 2
3541  - name: 3
3542  - name: 1
3543`),
3544			Modified: []byte(`
3545mergingList:
3546  - name: 4
3547    value: 4
3548  - name: 2
3549    value: 2
3550  - name: 3
3551    value: 3
3552  - name: 1
3553`),
3554			Current: []byte(`
3555mergingList:
3556  - name: 1
3557    other: a
3558  - name: 3
3559    value: 3
3560  - name: 4
3561    value: 4
3562  - name: 2
3563    value: 2
3564  - name: 9
3565`),
3566			ThreeWay: []byte(`
3567$setElementOrder/mergingList:
3568  - name: 4
3569  - name: 2
3570  - name: 3
3571  - name: 1
3572`),
3573			Result: []byte(`
3574mergingList:
3575  - name: 4
3576    value: 4
3577  - name: 2
3578    value: 2
3579  - name: 3
3580    value: 3
3581  - name: 1
3582    other: a
3583  - name: 9
3584`),
3585		},
3586	},
3587	{
3588		Description: "set elements order in a list with server-only items 2",
3589		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3590			Original: []byte(`
3591mergingList:
3592  - name: 1
3593  - name: 2
3594    value: 2
3595  - name: 3
3596    value: 3
3597  - name: 4
3598    value: 4
3599`),
3600			TwoWay: []byte(`
3601$setElementOrder/mergingList:
3602  - name: 2
3603  - name: 1
3604  - name: 4
3605  - name: 3
3606`),
3607			Modified: []byte(`
3608mergingList:
3609  - name: 2
3610    value: 2
3611  - name: 1
3612  - name: 4
3613    value: 4
3614  - name: 3
3615    value: 3
3616`),
3617			Current: []byte(`
3618mergingList:
3619  - name: 1
3620    other: a
3621  - name: 2
3622    value: 2
3623  - name: 9
3624  - name: 3
3625    value: 3
3626  - name: 4
3627    value: 4
3628`),
3629			ThreeWay: []byte(`
3630$setElementOrder/mergingList:
3631  - name: 2
3632  - name: 1
3633  - name: 4
3634  - name: 3
3635`),
3636			Result: []byte(`
3637mergingList:
3638  - name: 2
3639    value: 2
3640  - name: 1
3641    other: a
3642  - name: 9
3643  - name: 4
3644    value: 4
3645  - name: 3
3646    value: 3
3647`),
3648		},
3649	},
3650	{
3651		Description: "set elements order in a list with server-only items 3",
3652		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3653			Original: []byte(`
3654mergingList:
3655  - name: 1
3656  - name: 2
3657    value: 2
3658  - name: 3
3659    value: 3
3660  - name: 4
3661    value: 4
3662`),
3663			TwoWay: []byte(`
3664$setElementOrder/mergingList:
3665  - name: 2
3666  - name: 1
3667  - name: 4
3668  - name: 3
3669`),
3670			Modified: []byte(`
3671mergingList:
3672  - name: 2
3673    value: 2
3674  - name: 1
3675  - name: 4
3676    value: 4
3677  - name: 3
3678    value: 3
3679`),
3680			Current: []byte(`
3681mergingList:
3682  - name: 1
3683    other: a
3684  - name: 2
3685    value: 2
3686  - name: 7
3687  - name: 9
3688  - name: 8
3689  - name: 3
3690    value: 3
3691  - name: 4
3692    value: 4
3693`),
3694			ThreeWay: []byte(`
3695$setElementOrder/mergingList:
3696  - name: 2
3697  - name: 1
3698  - name: 4
3699  - name: 3
3700`),
3701			Result: []byte(`
3702mergingList:
3703  - name: 2
3704    value: 2
3705  - name: 1
3706    other: a
3707  - name: 7
3708  - name: 9
3709  - name: 8
3710  - name: 4
3711    value: 4
3712  - name: 3
3713    value: 3
3714`),
3715		},
3716	},
3717	{
3718		Description: "add an item in a int list and preserve order",
3719		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3720			Original: []byte(`
3721mergingIntList:
3722  - 1
3723  - 2
3724`),
3725			TwoWay: []byte(`
3726$setElementOrder/mergingIntList:
3727  - 3
3728  - 1
3729  - 2
3730mergingIntList:
3731  - 3
3732`),
3733			Modified: []byte(`
3734mergingIntList:
3735  - 3
3736  - 1
3737  - 2
3738`),
3739			Current: []byte(`
3740mergingIntList:
3741  - 1
3742  - 2
3743`),
3744			ThreeWay: []byte(`
3745$setElementOrder/mergingIntList:
3746  - 3
3747  - 1
3748  - 2
3749mergingIntList:
3750  - 3
3751`),
3752			Result: []byte(`
3753mergingIntList:
3754  - 3
3755  - 1
3756  - 2
3757`),
3758		},
3759	},
3760	{
3761		Description: "add multiple items in a int list and preserve order",
3762		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3763			Original: []byte(`
3764mergingIntList:
3765  - 1
3766  - 2
3767`),
3768			TwoWay: []byte(`
3769$setElementOrder/mergingIntList:
3770  - 1
3771  - 4
3772  - 2
3773  - 3
3774mergingIntList:
3775  - 4
3776  - 3
3777`),
3778			Modified: []byte(`
3779mergingIntList:
3780  - 1
3781  - 4
3782  - 2
3783  - 3
3784`),
3785			Current: []byte(`
3786mergingIntList:
3787  - 1
3788  - 2
3789`),
3790			ThreeWay: []byte(`
3791$setElementOrder/mergingIntList:
3792  - 1
3793  - 4
3794  - 2
3795  - 3
3796mergingIntList:
3797  - 4
3798  - 3
3799`),
3800			Result: []byte(`
3801mergingIntList:
3802  - 1
3803  - 4
3804  - 2
3805  - 3
3806`),
3807		},
3808	},
3809	{
3810		Description: "delete an item in a int list and preserve order",
3811		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3812			Original: []byte(`
3813mergingIntList:
3814  - 1
3815  - 3
3816  - 2
3817`),
3818			TwoWay: []byte(`
3819$setElementOrder/mergingIntList:
3820  - 2
3821  - 1
3822$deleteFromPrimitiveList/mergingIntList:
3823  - 3
3824`),
3825			Modified: []byte(`
3826mergingIntList:
3827  - 2
3828  - 1
3829`),
3830			Current: []byte(`
3831mergingIntList:
3832  - 1
3833  - 2
3834  - 3
3835`),
3836			ThreeWay: []byte(`
3837$setElementOrder/mergingIntList:
3838  - 2
3839  - 1
3840$deleteFromPrimitiveList/mergingIntList:
3841  - 3
3842`),
3843			Result: []byte(`
3844mergingIntList:
3845  - 2
3846  - 1
3847`),
3848		},
3849	},
3850	{
3851		Description: "add and delete an item in a int list and preserve order",
3852		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3853			Original: []byte(`
3854mergingIntList:
3855  - 1
3856  - 3
3857  - 2
3858`),
3859			TwoWay: []byte(`
3860$setElementOrder/mergingIntList:
3861  - 4
3862  - 2
3863  - 1
3864mergingIntList:
3865  - 4
3866$deleteFromPrimitiveList/mergingIntList:
3867  - 3
3868`),
3869			Modified: []byte(`
3870mergingIntList:
3871  - 4
3872  - 2
3873  - 1
3874`),
3875			Current: []byte(`
3876mergingIntList:
3877  - 1
3878  - 2
3879  - 3
3880`),
3881			ThreeWay: []byte(`
3882$setElementOrder/mergingIntList:
3883  - 4
3884  - 2
3885  - 1
3886mergingIntList:
3887  - 4
3888$deleteFromPrimitiveList/mergingIntList:
3889  - 3
3890`),
3891			Result: []byte(`
3892mergingIntList:
3893  - 4
3894  - 2
3895  - 1
3896`),
3897		},
3898	},
3899	{
3900		Description: "set elements order in a int list",
3901		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3902			Original: []byte(`
3903mergingIntList:
3904  - 1
3905  - 3
3906  - 4
3907  - 2
3908`),
3909			TwoWay: []byte(`
3910$setElementOrder/mergingIntList:
3911  - 4
3912  - 2
3913  - 3
3914  - 1
3915`),
3916			Modified: []byte(`
3917mergingIntList:
3918  - 4
3919  - 2
3920  - 3
3921  - 1
3922`),
3923			Current: []byte(`
3924mergingIntList:
3925  - 1
3926  - 3
3927  - 4
3928  - 2
3929`),
3930			ThreeWay: []byte(`
3931$setElementOrder/mergingIntList:
3932  - 4
3933  - 2
3934  - 3
3935  - 1
3936`),
3937			Result: []byte(`
3938mergingIntList:
3939  - 4
3940  - 2
3941  - 3
3942  - 1
3943`),
3944		},
3945	},
3946	{
3947		Description: "set elements order in a int list with server-only items",
3948		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3949			Original: []byte(`
3950mergingIntList:
3951  - 1
3952  - 3
3953  - 4
3954  - 2
3955`),
3956			TwoWay: []byte(`
3957$setElementOrder/mergingIntList:
3958  - 4
3959  - 2
3960  - 3
3961  - 1
3962`),
3963			Modified: []byte(`
3964mergingIntList:
3965  - 4
3966  - 2
3967  - 3
3968  - 1
3969`),
3970			Current: []byte(`
3971mergingIntList:
3972  - 1
3973  - 3
3974  - 4
3975  - 2
3976  - 9
3977`),
3978			ThreeWay: []byte(`
3979$setElementOrder/mergingIntList:
3980  - 4
3981  - 2
3982  - 3
3983  - 1
3984`),
3985			Result: []byte(`
3986mergingIntList:
3987  - 4
3988  - 2
3989  - 3
3990  - 1
3991  - 9
3992`),
3993		},
3994	},
3995	{
3996		Description: "set elements order in a int list with server-only items 2",
3997		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
3998			Original: []byte(`
3999mergingIntList:
4000  - 1
4001  - 2
4002  - 3
4003  - 4
4004`),
4005			TwoWay: []byte(`
4006$setElementOrder/mergingIntList:
4007  - 2
4008  - 1
4009  - 4
4010  - 3
4011`),
4012			Modified: []byte(`
4013mergingIntList:
4014  - 2
4015  - 1
4016  - 4
4017  - 3
4018`),
4019			Current: []byte(`
4020mergingIntList:
4021  - 1
4022  - 2
4023  - 9
4024  - 3
4025  - 4
4026`),
4027			ThreeWay: []byte(`
4028$setElementOrder/mergingIntList:
4029  - 2
4030  - 1
4031  - 4
4032  - 3
4033`),
4034			Result: []byte(`
4035mergingIntList:
4036  - 2
4037  - 1
4038  - 9
4039  - 4
4040  - 3
4041`),
4042		},
4043	},
4044	{
4045		Description: "set elements order in a int list with server-only items 3",
4046		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4047			Original: []byte(`
4048mergingIntList:
4049  - 1
4050  - 2
4051  - 3
4052  - 4
4053`),
4054			TwoWay: []byte(`
4055$setElementOrder/mergingIntList:
4056  - 2
4057  - 1
4058  - 4
4059  - 3
4060`),
4061			Modified: []byte(`
4062mergingIntList:
4063  - 2
4064  - 1
4065  - 4
4066  - 3
4067`),
4068			Current: []byte(`
4069mergingIntList:
4070  - 1
4071  - 2
4072  - 7
4073  - 9
4074  - 8
4075  - 3
4076  - 4
4077`),
4078			ThreeWay: []byte(`
4079$setElementOrder/mergingIntList:
4080  - 2
4081  - 1
4082  - 4
4083  - 3
4084`),
4085			Result: []byte(`
4086mergingIntList:
4087  - 2
4088  - 1
4089  - 7
4090  - 9
4091  - 8
4092  - 4
4093  - 3
4094`),
4095		},
4096	},
4097	{
4098		// This test case is used just to demonstrate the behavior when dealing with a list with duplicate
4099		Description: "behavior of set element order for a merging list with duplicate",
4100		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4101			Original: []byte(`
4102mergingList:
4103- name: 1
4104- name: 2
4105  value: dup1
4106- name: 3
4107- name: 2
4108  value: dup2
4109- name: 4
4110`),
4111			Current: []byte(`
4112mergingList:
4113- name: 1
4114- name: 2
4115  value: dup1
4116- name: 3
4117- name: 2
4118  value: dup2
4119- name: 4
4120`),
4121			Modified: []byte(`
4122mergingList:
4123- name: 2
4124  value: dup1
4125- name: 1
4126- name: 4
4127- name: 3
4128- name: 2
4129  value: dup2
4130`),
4131			TwoWay: []byte(`
4132$setElementOrder/mergingList:
4133- name: 2
4134- name: 1
4135- name: 4
4136- name: 3
4137- name: 2
4138`),
4139			TwoWayResult: []byte(`
4140mergingList:
4141- name: 2
4142  value: dup1
4143- name: 2
4144  value: dup2
4145- name: 1
4146- name: 4
4147- name: 3
4148`),
4149			ThreeWay: []byte(`
4150$setElementOrder/mergingList:
4151- name: 2
4152- name: 1
4153- name: 4
4154- name: 3
4155- name: 2
4156`),
4157			Result: []byte(`
4158mergingList:
4159- name: 2
4160  value: dup1
4161- name: 2
4162  value: dup2
4163- name: 1
4164- name: 4
4165- name: 3
4166`),
4167		},
4168	},
4169	{
4170		// This test case is used just to demonstrate the behavior when dealing with a list with duplicate
4171		Description: "behavior of set element order for a merging int list with duplicate",
4172		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4173			Original: []byte(`
4174mergingIntList:
4175- 1
4176- 2
4177- 3
4178- 2
4179- 4
4180`),
4181			Current: []byte(`
4182mergingIntList:
4183- 1
4184- 2
4185- 3
4186- 2
4187- 4
4188`),
4189			Modified: []byte(`
4190mergingIntList:
4191- 2
4192- 1
4193- 4
4194- 3
4195- 2
4196`),
4197			TwoWay: []byte(`
4198$setElementOrder/mergingIntList:
4199- 2
4200- 1
4201- 4
4202- 3
4203- 2
4204`),
4205			TwoWayResult: []byte(`
4206mergingIntList:
4207- 2
4208- 2
4209- 1
4210- 4
4211- 3
4212`),
4213			ThreeWay: []byte(`
4214$setElementOrder/mergingIntList:
4215- 2
4216- 1
4217- 4
4218- 3
4219- 2
4220`),
4221			Result: []byte(`
4222mergingIntList:
4223- 2
4224- 2
4225- 1
4226- 4
4227- 3
4228`),
4229		},
4230	},
4231	{
4232		Description: "retainKeys map should clear defaulted field",
4233		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4234			Original: []byte(`{}`),
4235			Current: []byte(`
4236retainKeysMap:
4237  value: foo
4238`),
4239			Modified: []byte(`
4240retainKeysMap:
4241  other: bar
4242`),
4243			TwoWay: []byte(`
4244retainKeysMap:
4245  other: bar
4246`),
4247			ThreeWay: []byte(`
4248retainKeysMap:
4249  $retainKeys:
4250    - other
4251  other: bar
4252`),
4253			Result: []byte(`
4254retainKeysMap:
4255  other: bar
4256`),
4257		},
4258	},
4259	{
4260		Description: "retainKeys map should clear defaulted field with conflict (discriminated union)",
4261		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4262			Original: []byte(`{}`),
4263			Current: []byte(`
4264retainKeysMap:
4265  name: type1
4266  value: foo
4267`),
4268			Modified: []byte(`
4269retainKeysMap:
4270  name: type2
4271  other: bar
4272`),
4273			TwoWay: []byte(`
4274retainKeysMap:
4275  name: type2
4276  other: bar
4277`),
4278			ThreeWay: []byte(`
4279retainKeysMap:
4280  $retainKeys:
4281    - name
4282    - other
4283  name: type2
4284  other: bar
4285`),
4286			Result: []byte(`
4287retainKeysMap:
4288  name: type2
4289  other: bar
4290`),
4291		},
4292	},
4293	{
4294		Description: "retainKeys map adds a field",
4295		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4296			Original: []byte(`
4297retainKeysMap:
4298  name: foo
4299`),
4300			Current: []byte(`
4301retainKeysMap:
4302  name: foo
4303`),
4304			Modified: []byte(`
4305retainKeysMap:
4306  name: foo
4307  value: bar
4308`),
4309			TwoWay: []byte(`
4310retainKeysMap:
4311  $retainKeys:
4312    - name
4313    - value
4314  value: bar
4315`),
4316			ThreeWay: []byte(`
4317retainKeysMap:
4318  $retainKeys:
4319    - name
4320    - value
4321  value: bar
4322`),
4323			Result: []byte(`
4324retainKeysMap:
4325  name: foo
4326  value: bar
4327`),
4328		},
4329	},
4330	{
4331		Description: "retainKeys map adds a field and clear a field",
4332		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4333			Original: []byte(`
4334retainKeysMap:
4335  name: foo
4336`),
4337			Current: []byte(`
4338retainKeysMap:
4339  name: foo
4340  other: a
4341`),
4342			Modified: []byte(`
4343retainKeysMap:
4344  name: foo
4345  value: bar
4346`),
4347			TwoWay: []byte(`
4348retainKeysMap:
4349  $retainKeys:
4350    - name
4351    - value
4352  value: bar
4353`),
4354			ThreeWay: []byte(`
4355retainKeysMap:
4356  $retainKeys:
4357    - name
4358    - value
4359  value: bar
4360`),
4361			Result: []byte(`
4362retainKeysMap:
4363  name: foo
4364  value: bar
4365`),
4366		},
4367	},
4368	{
4369		Description: "retainKeys map deletes a field",
4370		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4371			Original: []byte(`
4372retainKeysMap:
4373  name: foo
4374  value: bar
4375`),
4376			Current: []byte(`
4377retainKeysMap:
4378  name: foo
4379  value: bar
4380`),
4381			Modified: []byte(`
4382retainKeysMap:
4383  name: foo
4384`),
4385			TwoWay: []byte(`
4386retainKeysMap:
4387  $retainKeys:
4388    - name
4389  value: null
4390`),
4391			ThreeWay: []byte(`
4392retainKeysMap:
4393  $retainKeys:
4394    - name
4395  value: null
4396`),
4397			Result: []byte(`
4398retainKeysMap:
4399  name: foo
4400`),
4401		},
4402	},
4403	{
4404		Description: "retainKeys map deletes a field and clears a field",
4405		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4406			Original: []byte(`
4407retainKeysMap:
4408  name: foo
4409  value: bar
4410`),
4411			Current: []byte(`
4412retainKeysMap:
4413  name: foo
4414  value: bar
4415  other: a
4416`),
4417			Modified: []byte(`
4418retainKeysMap:
4419  name: foo
4420`),
4421			TwoWay: []byte(`
4422retainKeysMap:
4423  $retainKeys:
4424    - name
4425  value: null
4426`),
4427			ThreeWay: []byte(`
4428retainKeysMap:
4429  $retainKeys:
4430    - name
4431  value: null
4432`),
4433			Result: []byte(`
4434retainKeysMap:
4435  name: foo
4436`),
4437		},
4438	},
4439	{
4440		Description: "retainKeys map clears a field",
4441		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4442			Original: []byte(`
4443retainKeysMap:
4444  name: foo
4445  value: bar
4446`),
4447			Current: []byte(`
4448retainKeysMap:
4449  name: foo
4450  value: bar
4451  other: a
4452`),
4453			Modified: []byte(`
4454retainKeysMap:
4455  name: foo
4456  value: bar
4457`),
4458			TwoWay: []byte(`{}`),
4459			ThreeWay: []byte(`
4460retainKeysMap:
4461  $retainKeys:
4462    - name
4463    - value
4464`),
4465			Result: []byte(`
4466retainKeysMap:
4467  name: foo
4468  value: bar
4469`),
4470		},
4471	},
4472	{
4473		Description: "retainKeys map nested map with no change",
4474		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4475			Original: []byte(`
4476retainKeysMap:
4477  name: foo
4478  simpleMap:
4479    key1: a
4480`),
4481			Current: []byte(`
4482retainKeysMap:
4483  name: foo
4484  simpleMap:
4485    key1: a
4486`),
4487			Modified: []byte(`
4488retainKeysMap:
4489  name: foo
4490  value: bar
4491  simpleMap:
4492    key1: a
4493`),
4494			TwoWay: []byte(`
4495retainKeysMap:
4496  $retainKeys:
4497    - name
4498    - simpleMap
4499    - value
4500  value: bar
4501`),
4502			ThreeWay: []byte(`
4503retainKeysMap:
4504  $retainKeys:
4505    - name
4506    - simpleMap
4507    - value
4508  value: bar
4509`),
4510			Result: []byte(`
4511retainKeysMap:
4512  name: foo
4513  value: bar
4514  simpleMap:
4515    key1: a
4516`),
4517		},
4518	},
4519	{
4520		Description: "retainKeys map adds a field in a nested map",
4521		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4522			Original: []byte(`
4523retainKeysMap:
4524  name: foo
4525  value: bar
4526  simpleMap:
4527    key1: a
4528`),
4529			Current: []byte(`
4530retainKeysMap:
4531  name: foo
4532  value: bar
4533  simpleMap:
4534    key1: a
4535    key3: c
4536`),
4537			Modified: []byte(`
4538retainKeysMap:
4539  name: foo
4540  value: bar
4541  simpleMap:
4542    key1: a
4543    key2: b
4544`),
4545			TwoWay: []byte(`
4546retainKeysMap:
4547  $retainKeys:
4548    - name
4549    - simpleMap
4550    - value
4551  simpleMap:
4552    key2: b
4553`),
4554			ThreeWay: []byte(`
4555retainKeysMap:
4556  $retainKeys:
4557    - name
4558    - simpleMap
4559    - value
4560  simpleMap:
4561    key2: b
4562`),
4563			Result: []byte(`
4564retainKeysMap:
4565  name: foo
4566  value: bar
4567  simpleMap:
4568    key1: a
4569    key2: b
4570    key3: c
4571`),
4572		},
4573	},
4574	{
4575		Description: "retainKeys map deletes a field in a nested map",
4576		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4577			Original: []byte(`
4578retainKeysMap:
4579  name: foo
4580  value: bar
4581  simpleMap:
4582    key1: a
4583    key2: b
4584`),
4585			Current: []byte(`
4586retainKeysMap:
4587  name: foo
4588  value: bar
4589  simpleMap:
4590    key1: a
4591    key2: b
4592    key3: c
4593`),
4594			Modified: []byte(`
4595retainKeysMap:
4596  name: foo
4597  value: bar
4598  simpleMap:
4599    key1: a
4600`),
4601			TwoWay: []byte(`
4602retainKeysMap:
4603  $retainKeys:
4604    - name
4605    - simpleMap
4606    - value
4607  simpleMap:
4608    key2: null
4609`),
4610			ThreeWay: []byte(`
4611retainKeysMap:
4612  $retainKeys:
4613    - name
4614    - simpleMap
4615    - value
4616  simpleMap:
4617    key2: null
4618`),
4619			Result: []byte(`
4620retainKeysMap:
4621  name: foo
4622  value: bar
4623  simpleMap:
4624    key1: a
4625    key3: c
4626`),
4627		},
4628	},
4629	{
4630		Description: "retainKeys map changes a field in a nested map",
4631		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4632			Original: []byte(`
4633retainKeysMap:
4634  name: foo
4635  value: bar
4636  simpleMap:
4637    key1: a
4638    key2: b
4639`),
4640			Current: []byte(`
4641retainKeysMap:
4642  name: foo
4643  value: bar
4644  simpleMap:
4645    key1: a
4646    key2: b
4647    key3: c
4648`),
4649			Modified: []byte(`
4650retainKeysMap:
4651  name: foo
4652  value: bar
4653  simpleMap:
4654    key1: x
4655    key2: b
4656`),
4657			TwoWay: []byte(`
4658retainKeysMap:
4659  $retainKeys:
4660    - name
4661    - simpleMap
4662    - value
4663  simpleMap:
4664    key1: x
4665`),
4666			ThreeWay: []byte(`
4667retainKeysMap:
4668  $retainKeys:
4669    - name
4670    - simpleMap
4671    - value
4672  simpleMap:
4673    key1: x
4674`),
4675			Result: []byte(`
4676retainKeysMap:
4677  name: foo
4678  value: bar
4679  simpleMap:
4680    key1: x
4681    key2: b
4682    key3: c
4683`),
4684		},
4685	},
4686	{
4687		Description: "retainKeys map changes a field in a nested map with conflict",
4688		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4689			Original: []byte(`
4690retainKeysMap:
4691  name: foo
4692  value: bar
4693  simpleMap:
4694    key1: old
4695    key2: b
4696`),
4697			Current: []byte(`
4698retainKeysMap:
4699  name: foo
4700  value: bar
4701  simpleMap:
4702    key1: new
4703    key2: b
4704    key3: c
4705`),
4706			Modified: []byte(`
4707retainKeysMap:
4708  name: foo
4709  value: bar
4710  simpleMap:
4711    key1: modified
4712    key2: b
4713`),
4714			TwoWay: []byte(`
4715retainKeysMap:
4716  $retainKeys:
4717    - name
4718    - simpleMap
4719    - value
4720  simpleMap:
4721    key1: modified
4722`),
4723			ThreeWay: []byte(`
4724retainKeysMap:
4725  $retainKeys:
4726    - name
4727    - simpleMap
4728    - value
4729  simpleMap:
4730    key1: modified
4731`),
4732			Result: []byte(`
4733retainKeysMap:
4734  name: foo
4735  value: bar
4736  simpleMap:
4737    key1: modified
4738    key2: b
4739    key3: c
4740`),
4741		},
4742	},
4743	{
4744		Description: "retainKeys map replaces non-merging list",
4745		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4746			Original: []byte(`
4747retainKeysMap:
4748  name: foo
4749  value: bar
4750  nonMergingList:
4751  - name: a
4752  - name: b
4753`),
4754			Current: []byte(`
4755retainKeysMap:
4756  name: foo
4757  value: bar
4758  nonMergingList:
4759  - name: a
4760  - name: b
4761`),
4762			Modified: []byte(`
4763retainKeysMap:
4764  name: foo
4765  value: bar
4766  nonMergingList:
4767  - name: a
4768  - name: c
4769  - name: b
4770`),
4771			TwoWay: []byte(`
4772retainKeysMap:
4773  $retainKeys:
4774    - name
4775    - nonMergingList
4776    - value
4777  nonMergingList:
4778  - name: a
4779  - name: c
4780  - name: b
4781`),
4782			ThreeWay: []byte(`
4783retainKeysMap:
4784  $retainKeys:
4785    - name
4786    - nonMergingList
4787    - value
4788  nonMergingList:
4789  - name: a
4790  - name: c
4791  - name: b
4792`),
4793			Result: []byte(`
4794retainKeysMap:
4795  name: foo
4796  value: bar
4797  nonMergingList:
4798  - name: a
4799  - name: c
4800  - name: b
4801`),
4802		},
4803	},
4804	{
4805		Description: "retainKeys map nested non-merging list with no change",
4806		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4807			Original: []byte(`
4808retainKeysMap:
4809  name: foo
4810  nonMergingList:
4811  - name: a
4812  - name: b
4813`),
4814			Current: []byte(`
4815retainKeysMap:
4816  name: foo
4817  nonMergingList:
4818  - name: a
4819  - name: b
4820`),
4821			Modified: []byte(`
4822retainKeysMap:
4823  name: foo
4824  value: bar
4825  nonMergingList:
4826  - name: a
4827  - name: b
4828`),
4829			TwoWay: []byte(`
4830retainKeysMap:
4831  $retainKeys:
4832    - name
4833    - nonMergingList
4834    - value
4835  value: bar
4836`),
4837			ThreeWay: []byte(`
4838retainKeysMap:
4839  $retainKeys:
4840    - name
4841    - nonMergingList
4842    - value
4843  value: bar
4844`),
4845			Result: []byte(`
4846retainKeysMap:
4847  name: foo
4848  value: bar
4849  nonMergingList:
4850  - name: a
4851  - name: b
4852`),
4853		},
4854	},
4855	{
4856		Description: "retainKeys map nested non-merging list with no change with conflict",
4857		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4858			Original: []byte(`
4859retainKeysMap:
4860  name: foo
4861  nonMergingList:
4862  - name: a
4863  - name: b
4864`),
4865			Current: []byte(`
4866retainKeysMap:
4867  name: foo
4868  nonMergingList:
4869  - name: a
4870  - name: b
4871  - name: c
4872`),
4873			Modified: []byte(`
4874retainKeysMap:
4875  name: foo
4876  value: bar
4877  nonMergingList:
4878  - name: a
4879  - name: b
4880`),
4881			TwoWay: []byte(`
4882retainKeysMap:
4883  $retainKeys:
4884    - name
4885    - nonMergingList
4886    - value
4887  value: bar
4888`),
4889			ThreeWay: []byte(`
4890retainKeysMap:
4891  $retainKeys:
4892    - name
4893    - nonMergingList
4894    - value
4895  value: bar
4896  nonMergingList:
4897  - name: a
4898  - name: b
4899`),
4900			Result: []byte(`
4901retainKeysMap:
4902  name: foo
4903  value: bar
4904  nonMergingList:
4905  - name: a
4906  - name: b
4907`),
4908		},
4909	},
4910	{
4911		Description: "retainKeys map deletes nested non-merging list",
4912		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4913			Original: []byte(`
4914retainKeysMap:
4915  name: foo
4916  nonMergingList:
4917  - name: a
4918  - name: b
4919`),
4920			Current: []byte(`
4921retainKeysMap:
4922  name: foo
4923  nonMergingList:
4924  - name: a
4925  - name: b
4926`),
4927			Modified: []byte(`
4928retainKeysMap:
4929  name: foo
4930  value: bar
4931`),
4932			TwoWay: []byte(`
4933retainKeysMap:
4934  $retainKeys:
4935    - name
4936    - value
4937  value: bar
4938  nonMergingList: null
4939`),
4940			ThreeWay: []byte(`
4941retainKeysMap:
4942  $retainKeys:
4943    - name
4944    - value
4945  value: bar
4946  nonMergingList: null
4947`),
4948			Result: []byte(`
4949retainKeysMap:
4950  name: foo
4951  value: bar
4952`),
4953		},
4954	},
4955	{
4956		Description: "retainKeys map delete nested non-merging list with conflict",
4957		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
4958			Original: []byte(`
4959retainKeysMap:
4960  name: foo
4961  nonMergingList:
4962  - name: a
4963  - name: b
4964`),
4965			Current: []byte(`
4966retainKeysMap:
4967  name: foo
4968  nonMergingList:
4969  - name: a
4970  - name: b
4971  - name: c
4972`),
4973			Modified: []byte(`
4974retainKeysMap:
4975  name: foo
4976  value: bar
4977`),
4978			TwoWay: []byte(`
4979retainKeysMap:
4980  $retainKeys:
4981    - name
4982    - value
4983  value: bar
4984  nonMergingList: null
4985`),
4986			ThreeWay: []byte(`
4987retainKeysMap:
4988  $retainKeys:
4989    - name
4990    - value
4991  value: bar
4992  nonMergingList: null
4993`),
4994			Result: []byte(`
4995retainKeysMap:
4996  name: foo
4997  value: bar
4998`),
4999		},
5000	},
5001	{
5002		Description: "retainKeys map nested merging int list with no change",
5003		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5004			Original: []byte(`
5005retainKeysMap:
5006  name: foo
5007  mergingIntList:
5008  - 1
5009  - 2
5010`),
5011			Current: []byte(`
5012retainKeysMap:
5013  name: foo
5014  mergingIntList:
5015  - 1
5016  - 2
5017  - 3
5018`),
5019			Modified: []byte(`
5020retainKeysMap:
5021  name: foo
5022  value: bar
5023  mergingIntList:
5024  - 1
5025  - 2
5026`),
5027			TwoWay: []byte(`
5028retainKeysMap:
5029  $retainKeys:
5030    - mergingIntList
5031    - name
5032    - value
5033  value: bar
5034`),
5035			ThreeWay: []byte(`
5036retainKeysMap:
5037  $retainKeys:
5038    - mergingIntList
5039    - name
5040    - value
5041  $setElementOrder/mergingIntList:
5042    - 1
5043    - 2
5044  value: bar
5045`),
5046			Result: []byte(`
5047retainKeysMap:
5048  name: foo
5049  value: bar
5050  mergingIntList:
5051  - 1
5052  - 2
5053  - 3
5054`),
5055		},
5056	},
5057	{
5058		Description: "retainKeys map adds an item in nested merging int list",
5059		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5060			Original: []byte(`
5061retainKeysMap:
5062  name: foo
5063  mergingIntList:
5064  - 1
5065  - 2
5066`),
5067			Current: []byte(`
5068retainKeysMap:
5069  name: foo
5070  mergingIntList:
5071  - 1
5072  - 2
5073  - 3
5074`),
5075			Modified: []byte(`
5076retainKeysMap:
5077  name: foo
5078  mergingIntList:
5079  - 1
5080  - 2
5081  - 4
5082`),
5083			TwoWay: []byte(`
5084retainKeysMap:
5085  $setElementOrder/mergingIntList:
5086    - 1
5087    - 2
5088    - 4
5089  $retainKeys:
5090    - mergingIntList
5091    - name
5092  mergingIntList:
5093  - 4
5094`),
5095			ThreeWay: []byte(`
5096retainKeysMap:
5097  $setElementOrder/mergingIntList:
5098    - 1
5099    - 2
5100    - 4
5101  $retainKeys:
5102    - mergingIntList
5103    - name
5104  mergingIntList:
5105  - 4
5106`),
5107			Result: []byte(`
5108retainKeysMap:
5109  name: foo
5110  mergingIntList:
5111  - 1
5112  - 2
5113  - 4
5114  - 3
5115`),
5116		},
5117	},
5118	{
5119		Description: "retainKeys map deletes an item in nested merging int list",
5120		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5121			Original: []byte(`
5122retainKeysMap:
5123  name: foo
5124  mergingIntList:
5125  - 1
5126  - 2
5127  - 3
5128`),
5129			Current: []byte(`
5130retainKeysMap:
5131  name: foo
5132  mergingIntList:
5133  - 1
5134  - 2
5135  - 3
5136  - 4
5137`),
5138			Modified: []byte(`
5139retainKeysMap:
5140  name: foo
5141  mergingIntList:
5142  - 1
5143  - 3
5144`),
5145			TwoWay: []byte(`
5146retainKeysMap:
5147  $retainKeys:
5148    - mergingIntList
5149    - name
5150  $deleteFromPrimitiveList/mergingIntList:
5151  - 2
5152  $setElementOrder/mergingIntList:
5153    - 1
5154    - 3
5155`),
5156			ThreeWay: []byte(`
5157retainKeysMap:
5158  $retainKeys:
5159    - mergingIntList
5160    - name
5161  $deleteFromPrimitiveList/mergingIntList:
5162  - 2
5163  $setElementOrder/mergingIntList:
5164    - 1
5165    - 3
5166`),
5167			Result: []byte(`
5168retainKeysMap:
5169  name: foo
5170  mergingIntList:
5171  - 1
5172  - 3
5173  - 4
5174`),
5175		},
5176	},
5177	{
5178		Description: "retainKeys map adds an item and deletes an item in nested merging int list",
5179		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5180			Original: []byte(`
5181retainKeysMap:
5182  name: foo
5183  mergingIntList:
5184  - 1
5185  - 2
5186  - 3
5187`),
5188			Current: []byte(`
5189retainKeysMap:
5190  name: foo
5191  mergingIntList:
5192  - 1
5193  - 2
5194  - 3
5195  - 4
5196`),
5197			Modified: []byte(`
5198retainKeysMap:
5199  name: foo
5200  mergingIntList:
5201  - 1
5202  - 3
5203  - 5
5204`),
5205			TwoWay: []byte(`
5206retainKeysMap:
5207  $retainKeys:
5208    - mergingIntList
5209    - name
5210  mergingIntList:
5211  - 5
5212  $deleteFromPrimitiveList/mergingIntList:
5213  - 2
5214  $setElementOrder/mergingIntList:
5215    - 1
5216    - 3
5217    - 5
5218`),
5219			ThreeWay: []byte(`
5220retainKeysMap:
5221  $retainKeys:
5222    - mergingIntList
5223    - name
5224  mergingIntList:
5225  - 5
5226  $deleteFromPrimitiveList/mergingIntList:
5227  - 2
5228  $setElementOrder/mergingIntList:
5229    - 1
5230    - 3
5231    - 5
5232`),
5233			Result: []byte(`
5234retainKeysMap:
5235  name: foo
5236  mergingIntList:
5237  - 1
5238  - 3
5239  - 5
5240  - 4
5241`),
5242		},
5243	},
5244	{
5245		Description: "retainKeys map deletes nested merging int list",
5246		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5247			Original: []byte(`
5248retainKeysMap:
5249  name: foo
5250  mergingIntList:
5251  - 1
5252  - 2
5253  - 3
5254`),
5255			Current: []byte(`
5256retainKeysMap:
5257  name: foo
5258  mergingIntList:
5259  - 1
5260  - 2
5261  - 3
5262`),
5263			Modified: []byte(`
5264retainKeysMap:
5265  name: foo
5266`),
5267			TwoWay: []byte(`
5268retainKeysMap:
5269  $retainKeys:
5270    - name
5271  mergingIntList: null
5272`),
5273			ThreeWay: []byte(`
5274retainKeysMap:
5275  $retainKeys:
5276    - name
5277  mergingIntList: null
5278`),
5279			Result: []byte(`
5280retainKeysMap:
5281  name: foo
5282`),
5283		},
5284	},
5285	{
5286		Description: "retainKeys map nested merging list with no change",
5287		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5288			Original: []byte(`
5289retainKeysMap:
5290  name: foo
5291  mergingList:
5292  - name: a
5293  - name: b
5294`),
5295			Current: []byte(`
5296retainKeysMap:
5297  name: foo
5298  mergingList:
5299  - name: a
5300  - name: b
5301  - name: c
5302`),
5303			Modified: []byte(`
5304retainKeysMap:
5305  name: foo
5306  value: bar
5307  mergingList:
5308  - name: a
5309  - name: b
5310`),
5311			TwoWay: []byte(`
5312retainKeysMap:
5313  $retainKeys:
5314    - mergingList
5315    - name
5316    - value
5317  value: bar
5318`),
5319			ThreeWay: []byte(`
5320retainKeysMap:
5321  $retainKeys:
5322    - mergingList
5323    - name
5324    - value
5325  $setElementOrder/mergingList:
5326    - name: a
5327    - name: b
5328  value: bar
5329`),
5330			Result: []byte(`
5331retainKeysMap:
5332  name: foo
5333  value: bar
5334  mergingList:
5335  - name: a
5336  - name: b
5337  - name: c
5338`),
5339		},
5340	},
5341	{
5342		Description: "retainKeys map adds an item in nested merging list",
5343		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5344			Original: []byte(`
5345retainKeysMap:
5346  name: foo
5347  mergingList:
5348  - name: a
5349  - name: b
5350`),
5351			Current: []byte(`
5352retainKeysMap:
5353  name: foo
5354  mergingList:
5355  - name: a
5356  - name: b
5357  - name: x
5358`),
5359			Modified: []byte(`
5360retainKeysMap:
5361  name: foo
5362  mergingList:
5363  - name: a
5364  - name: b
5365  - name: c
5366`),
5367			TwoWay: []byte(`
5368retainKeysMap:
5369  $retainKeys:
5370    - mergingList
5371    - name
5372  $setElementOrder/mergingList:
5373    - name: a
5374    - name: b
5375    - name: c
5376  mergingList:
5377  - name: c
5378`),
5379			ThreeWay: []byte(`
5380retainKeysMap:
5381  $retainKeys:
5382    - mergingList
5383    - name
5384  $setElementOrder/mergingList:
5385    - name: a
5386    - name: b
5387    - name: c
5388  mergingList:
5389  - name: c
5390`),
5391			Result: []byte(`
5392retainKeysMap:
5393  name: foo
5394  mergingList:
5395  - name: a
5396  - name: b
5397  - name: c
5398  - name: x
5399`),
5400		},
5401	},
5402	{
5403		Description: "retainKeys map changes an item in nested merging list",
5404		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5405			Original: []byte(`
5406retainKeysMap:
5407  name: foo
5408  mergingList:
5409  - name: a
5410  - name: b
5411    value: foo
5412`),
5413			Current: []byte(`
5414retainKeysMap:
5415  name: foo
5416  mergingList:
5417  - name: a
5418  - name: b
5419    value: foo
5420  - name: x
5421`),
5422			Modified: []byte(`
5423retainKeysMap:
5424  name: foo
5425  mergingList:
5426  - name: a
5427  - name: b
5428    value: bar
5429`),
5430			TwoWay: []byte(`
5431retainKeysMap:
5432  $retainKeys:
5433    - mergingList
5434    - name
5435  $setElementOrder/mergingList:
5436    - name: a
5437    - name: b
5438  mergingList:
5439  - name: b
5440    value: bar
5441`),
5442			ThreeWay: []byte(`
5443retainKeysMap:
5444  $retainKeys:
5445    - mergingList
5446    - name
5447  $setElementOrder/mergingList:
5448    - name: a
5449    - name: b
5450  mergingList:
5451  - name: b
5452    value: bar
5453`),
5454			Result: []byte(`
5455retainKeysMap:
5456  name: foo
5457  mergingList:
5458  - name: a
5459  - name: b
5460    value: bar
5461  - name: x
5462`),
5463		},
5464	},
5465	{
5466		Description: "retainKeys map deletes nested merging list",
5467		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5468			Original: []byte(`
5469retainKeysMap:
5470  name: foo
5471  mergingList:
5472  - name: a
5473  - name: b
5474`),
5475			Current: []byte(`
5476retainKeysMap:
5477  name: foo
5478  mergingList:
5479  - name: a
5480  - name: b
5481`),
5482			Modified: []byte(`
5483retainKeysMap:
5484  name: foo
5485  value: bar
5486`),
5487			TwoWay: []byte(`
5488retainKeysMap:
5489  $retainKeys:
5490    - name
5491    - value
5492  value: bar
5493  mergingList: null
5494`),
5495			ThreeWay: []byte(`
5496retainKeysMap:
5497  $retainKeys:
5498    - name
5499    - value
5500  value: bar
5501  mergingList: null
5502`),
5503			Result: []byte(`
5504retainKeysMap:
5505  name: foo
5506  value: bar
5507`),
5508		},
5509	},
5510	{
5511		Description: "retainKeys map deletes an item in nested merging list",
5512		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5513			Original: []byte(`
5514retainKeysMap:
5515  name: foo
5516  mergingList:
5517  - name: a
5518  - name: b
5519`),
5520			Current: []byte(`
5521retainKeysMap:
5522  name: foo
5523  mergingList:
5524  - name: a
5525  - name: b
5526  - name: x
5527`),
5528			Modified: []byte(`
5529retainKeysMap:
5530  name: foo
5531  mergingList:
5532  - name: a
5533`),
5534			TwoWay: []byte(`
5535retainKeysMap:
5536  $retainKeys:
5537    - mergingList
5538    - name
5539  $setElementOrder/mergingList:
5540    - name: a
5541  mergingList:
5542  - name: b
5543    $patch: delete
5544`),
5545			ThreeWay: []byte(`
5546retainKeysMap:
5547  $retainKeys:
5548    - mergingList
5549    - name
5550  $setElementOrder/mergingList:
5551    - name: a
5552  mergingList:
5553  - name: b
5554    $patch: delete
5555`),
5556			Result: []byte(`
5557retainKeysMap:
5558  name: foo
5559  mergingList:
5560  - name: a
5561  - name: x
5562`),
5563		},
5564	},
5565	{
5566		Description: "retainKeys list of maps clears a field",
5567		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5568			Original: []byte(`
5569retainKeysMergingList:
5570- name: bar
5571- name: foo
5572  value: a
5573`),
5574			Current: []byte(`
5575retainKeysMergingList:
5576- name: bar
5577- name: foo
5578  value: a
5579  other: x
5580`),
5581			Modified: []byte(`
5582retainKeysMergingList:
5583- name: bar
5584- name: foo
5585  value: a
5586`),
5587			TwoWay: []byte(`{}`),
5588			ThreeWay: []byte(`
5589$setElementOrder/retainKeysMergingList:
5590  - name: bar
5591  - name: foo
5592retainKeysMergingList:
5593- $retainKeys:
5594    - name
5595    - value
5596  name: foo
5597`),
5598			Result: []byte(`
5599retainKeysMergingList:
5600- name: bar
5601- name: foo
5602  value: a
5603`),
5604		},
5605	},
5606	{
5607		Description: "retainKeys list of maps clears a field with conflict",
5608		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5609			Original: []byte(`
5610retainKeysMergingList:
5611- name: bar
5612- name: foo
5613  value: old
5614`),
5615			Current: []byte(`
5616retainKeysMergingList:
5617- name: bar
5618- name: foo
5619  value: new
5620  other: x
5621`),
5622			Modified: []byte(`
5623retainKeysMergingList:
5624- name: bar
5625- name: foo
5626  value: modified
5627`),
5628			TwoWay: []byte(`
5629$setElementOrder/retainKeysMergingList:
5630  - name: bar
5631  - name: foo
5632retainKeysMergingList:
5633- $retainKeys:
5634    - name
5635    - value
5636  name: foo
5637  value: modified
5638`),
5639			ThreeWay: []byte(`
5640$setElementOrder/retainKeysMergingList:
5641  - name: bar
5642  - name: foo
5643retainKeysMergingList:
5644- $retainKeys:
5645    - name
5646    - value
5647  name: foo
5648  value: modified
5649`),
5650			Result: []byte(`
5651retainKeysMergingList:
5652- name: bar
5653- name: foo
5654  value: modified
5655`),
5656		},
5657	},
5658	{
5659		Description: "retainKeys list of maps changes a field and clear a field",
5660		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5661			Original: []byte(`
5662retainKeysMergingList:
5663- name: bar
5664- name: foo
5665  value: old
5666`),
5667			Current: []byte(`
5668retainKeysMergingList:
5669- name: bar
5670- name: foo
5671  value: old
5672  other: x
5673`),
5674			Modified: []byte(`
5675retainKeysMergingList:
5676- name: bar
5677- name: foo
5678  value: new
5679`),
5680			TwoWay: []byte(`
5681$setElementOrder/retainKeysMergingList:
5682  - name: bar
5683  - name: foo
5684retainKeysMergingList:
5685- $retainKeys:
5686    - name
5687    - value
5688  name: foo
5689  value: new
5690`),
5691			ThreeWay: []byte(`
5692$setElementOrder/retainKeysMergingList:
5693  - name: bar
5694  - name: foo
5695retainKeysMergingList:
5696- $retainKeys:
5697    - name
5698    - value
5699  name: foo
5700  value: new
5701`),
5702			Result: []byte(`
5703retainKeysMergingList:
5704- name: bar
5705- name: foo
5706  value: new
5707`),
5708		},
5709	},
5710	{
5711		Description: "retainKeys list of maps changes a field and clear a field with conflict",
5712		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5713			Original: []byte(`
5714retainKeysMergingList:
5715- name: bar
5716- name: foo
5717  value: old
5718`),
5719			Current: []byte(`
5720retainKeysMergingList:
5721- name: bar
5722- name: foo
5723  value: modified
5724  other: x
5725`),
5726			Modified: []byte(`
5727retainKeysMergingList:
5728- name: bar
5729- name: foo
5730  value: new
5731`),
5732			TwoWay: []byte(`
5733$setElementOrder/retainKeysMergingList:
5734  - name: bar
5735  - name: foo
5736retainKeysMergingList:
5737- $retainKeys:
5738    - name
5739    - value
5740  name: foo
5741  value: new
5742`),
5743			ThreeWay: []byte(`
5744$setElementOrder/retainKeysMergingList:
5745  - name: bar
5746  - name: foo
5747retainKeysMergingList:
5748- $retainKeys:
5749    - name
5750    - value
5751  name: foo
5752  value: new
5753`),
5754			Result: []byte(`
5755retainKeysMergingList:
5756- name: bar
5757- name: foo
5758  value: new
5759`),
5760		},
5761	},
5762	{
5763		Description: "retainKeys list of maps adds a field",
5764		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5765			Original: []byte(`
5766retainKeysMergingList:
5767- name: bar
5768- name: foo
5769`),
5770			Current: []byte(`
5771retainKeysMergingList:
5772- name: bar
5773- name: foo
5774`),
5775			Modified: []byte(`
5776retainKeysMergingList:
5777- name: bar
5778- name: foo
5779  value: a
5780`),
5781			TwoWay: []byte(`
5782$setElementOrder/retainKeysMergingList:
5783  - name: bar
5784  - name: foo
5785retainKeysMergingList:
5786- $retainKeys:
5787    - name
5788    - value
5789  name: foo
5790  value: a
5791`),
5792			ThreeWay: []byte(`
5793$setElementOrder/retainKeysMergingList:
5794  - name: bar
5795  - name: foo
5796retainKeysMergingList:
5797- $retainKeys:
5798    - name
5799    - value
5800  name: foo
5801  value: a
5802`),
5803			Result: []byte(`
5804retainKeysMergingList:
5805- name: bar
5806- name: foo
5807  value: a
5808`),
5809		},
5810	},
5811	{
5812		Description: "retainKeys list of maps adds a field and clear a field",
5813		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5814			Original: []byte(`
5815retainKeysMergingList:
5816- name: bar
5817- name: foo
5818`),
5819			Current: []byte(`
5820retainKeysMergingList:
5821- name: bar
5822- name: foo
5823  other: x
5824`),
5825			Modified: []byte(`
5826retainKeysMergingList:
5827- name: bar
5828- name: foo
5829  value: a
5830`),
5831			TwoWay: []byte(`
5832$setElementOrder/retainKeysMergingList:
5833  - name: bar
5834  - name: foo
5835retainKeysMergingList:
5836- $retainKeys:
5837    - name
5838    - value
5839  name: foo
5840  value: a
5841`),
5842			ThreeWay: []byte(`
5843$setElementOrder/retainKeysMergingList:
5844  - name: bar
5845  - name: foo
5846retainKeysMergingList:
5847- $retainKeys:
5848    - name
5849    - value
5850  name: foo
5851  value: a
5852`),
5853			Result: []byte(`
5854retainKeysMergingList:
5855- name: bar
5856- name: foo
5857  value: a
5858`),
5859		},
5860	},
5861	{
5862		Description: "retainKeys list of maps deletes a field",
5863		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5864			Original: []byte(`
5865retainKeysMergingList:
5866- name: bar
5867- name: foo
5868  value: a
5869`),
5870			Current: []byte(`
5871retainKeysMergingList:
5872- name: bar
5873- name: foo
5874  value: a
5875`),
5876			Modified: []byte(`
5877retainKeysMergingList:
5878- name: bar
5879- name: foo
5880`),
5881			TwoWay: []byte(`
5882$setElementOrder/retainKeysMergingList:
5883  - name: bar
5884  - name: foo
5885retainKeysMergingList:
5886- $retainKeys:
5887    - name
5888  name: foo
5889  value: null
5890`),
5891			ThreeWay: []byte(`
5892$setElementOrder/retainKeysMergingList:
5893  - name: bar
5894  - name: foo
5895retainKeysMergingList:
5896- $retainKeys:
5897    - name
5898  name: foo
5899  value: null
5900`),
5901			Result: []byte(`
5902retainKeysMergingList:
5903- name: bar
5904- name: foo
5905`),
5906		},
5907	},
5908	{
5909		Description: "retainKeys list of maps deletes a field and clear a field",
5910		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5911			Original: []byte(`
5912retainKeysMergingList:
5913- name: bar
5914- name: foo
5915  value: a
5916`),
5917			Current: []byte(`
5918retainKeysMergingList:
5919- name: bar
5920- name: foo
5921  value: a
5922  other: x
5923`),
5924			Modified: []byte(`
5925retainKeysMergingList:
5926- name: bar
5927- name: foo
5928`),
5929			TwoWay: []byte(`
5930$setElementOrder/retainKeysMergingList:
5931  - name: bar
5932  - name: foo
5933retainKeysMergingList:
5934- $retainKeys:
5935    - name
5936  name: foo
5937  value: null
5938`),
5939			ThreeWay: []byte(`
5940$setElementOrder/retainKeysMergingList:
5941  - name: bar
5942  - name: foo
5943retainKeysMergingList:
5944- $retainKeys:
5945    - name
5946  name: foo
5947  value: null
5948`),
5949			Result: []byte(`
5950retainKeysMergingList:
5951- name: bar
5952- name: foo
5953`),
5954		},
5955	},
5956	{
5957		Description: "delete and reorder in one list, reorder in another",
5958		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
5959			Original: []byte(`
5960mergingList:
5961- name: a
5962  value: a
5963- name: b
5964  value: b
5965mergeItemPtr:
5966- name: c
5967  value: c
5968- name: d
5969  value: d
5970`),
5971			Current: []byte(`
5972mergingList:
5973- name: a
5974  value: a
5975- name: b
5976  value: b
5977mergeItemPtr:
5978- name: c
5979  value: c
5980- name: d
5981  value: d
5982`),
5983			Modified: []byte(`
5984mergingList:
5985- name: b
5986  value: b
5987mergeItemPtr:
5988- name: d
5989  value: d
5990- name: c
5991  value: c
5992`),
5993			TwoWay: []byte(`
5994$setElementOrder/mergingList:
5995- name: b
5996$setElementOrder/mergeItemPtr:
5997- name: d
5998- name: c
5999mergingList:
6000- $patch: delete
6001  name: a
6002`),
6003			ThreeWay: []byte(`
6004$setElementOrder/mergingList:
6005- name: b
6006$setElementOrder/mergeItemPtr:
6007- name: d
6008- name: c
6009mergingList:
6010- $patch: delete
6011  name: a
6012`),
6013			Result: []byte(`
6014mergingList:
6015- name: b
6016  value: b
6017mergeItemPtr:
6018- name: d
6019  value: d
6020- name: c
6021  value: c
6022`),
6023		},
6024	},
6025}
6026
6027func TestStrategicMergePatch(t *testing.T) {
6028	testStrategicMergePatchWithCustomArgumentsUsingStruct(t, "bad struct",
6029		"{}", "{}", []byte("<THIS IS NOT A STRUCT>"), mergepatch.ErrBadArgKind(struct{}{}, []byte{}))
6030
6031	mergeItemOpenapiSchema := PatchMetaFromOpenAPI{
6032		Schema: sptest.GetSchemaOrDie(&fakeMergeItemSchema, "mergeItem"),
6033	}
6034	schemas := []LookupPatchMeta{
6035		mergeItemStructSchema,
6036		mergeItemOpenapiSchema,
6037	}
6038
6039	tc := StrategicMergePatchTestCases{}
6040	err := yaml.Unmarshal(createStrategicMergePatchTestCaseData, &tc)
6041	if err != nil {
6042		t.Errorf("can't unmarshal test cases: %s\n", err)
6043		return
6044	}
6045
6046	for _, schema := range schemas {
6047		testStrategicMergePatchWithCustomArguments(t, "bad original",
6048			"<THIS IS NOT JSON>", "{}", schema, mergepatch.ErrBadJSONDoc)
6049		testStrategicMergePatchWithCustomArguments(t, "bad patch",
6050			"{}", "<THIS IS NOT JSON>", schema, mergepatch.ErrBadJSONDoc)
6051		testStrategicMergePatchWithCustomArguments(t, "nil struct",
6052			"{}", "{}", nil, mergepatch.ErrBadArgKind(struct{}{}, nil))
6053
6054		for _, c := range tc.TestCases {
6055			testTwoWayPatch(t, c, schema)
6056			testThreeWayPatch(t, c, schema)
6057		}
6058
6059		// run multiple times to exercise different map traversal orders
6060		for i := 0; i < 10; i++ {
6061			for _, c := range strategicMergePatchRawTestCases {
6062				testTwoWayPatchForRawTestCase(t, c, schema)
6063				testThreeWayPatchForRawTestCase(t, c, schema)
6064			}
6065		}
6066	}
6067}
6068
6069func testStrategicMergePatchWithCustomArgumentsUsingStruct(t *testing.T, description, original, patch string, dataStruct interface{}, expected error) {
6070	schema, actual := NewPatchMetaFromStruct(dataStruct)
6071	// If actual is not nil, check error. If errors match, return.
6072	if actual != nil {
6073		checkErrorsEqual(t, description, expected, actual, schema)
6074		return
6075	}
6076	testStrategicMergePatchWithCustomArguments(t, description, original, patch, schema, expected)
6077}
6078
6079func testStrategicMergePatchWithCustomArguments(t *testing.T, description, original, patch string, schema LookupPatchMeta, expected error) {
6080	_, actual := StrategicMergePatch([]byte(original), []byte(patch), schema)
6081	checkErrorsEqual(t, description, expected, actual, schema)
6082}
6083
6084func checkErrorsEqual(t *testing.T, description string, expected, actual error, schema LookupPatchMeta) {
6085	if actual != expected {
6086		if actual == nil {
6087			t.Errorf("using %s expected error: %s\ndid not occur in test case: %s", getSchemaType(schema), expected, description)
6088			return
6089		}
6090
6091		if expected == nil || actual.Error() != expected.Error() {
6092			t.Errorf("using %s unexpected error: %s\noccurred in test case: %s", getSchemaType(schema), actual, description)
6093			return
6094		}
6095	}
6096}
6097
6098func testTwoWayPatch(t *testing.T, c StrategicMergePatchTestCase, schema LookupPatchMeta) {
6099	original, expectedPatch, modified, expectedResult := twoWayTestCaseToJSONOrFail(t, c, schema)
6100
6101	actualPatch, err := CreateTwoWayMergePatchUsingLookupPatchMeta(original, modified, schema)
6102	if err != nil {
6103		t.Errorf("using %s error: %s\nin test case: %s\ncannot create two way patch: %s:\n%s\n",
6104			getSchemaType(schema), err, c.Description, original, mergepatch.ToYAMLOrError(c.StrategicMergePatchTestCaseData))
6105		return
6106	}
6107
6108	testPatchCreation(t, expectedPatch, actualPatch, c.Description)
6109	testPatchApplication(t, original, actualPatch, expectedResult, c.Description, "", schema)
6110}
6111
6112func testTwoWayPatchForRawTestCase(t *testing.T, c StrategicMergePatchRawTestCase, schema LookupPatchMeta) {
6113	original, expectedPatch, modified, expectedResult := twoWayRawTestCaseToJSONOrFail(t, c)
6114
6115	actualPatch, err := CreateTwoWayMergePatchUsingLookupPatchMeta(original, modified, schema)
6116	if err != nil {
6117		t.Errorf("error: %s\nin test case: %s\ncannot create two way patch:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
6118			err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
6119		return
6120	}
6121
6122	testPatchCreation(t, expectedPatch, actualPatch, c.Description)
6123	testPatchApplication(t, original, actualPatch, expectedResult, c.Description, c.ExpectedError, schema)
6124}
6125
6126func twoWayTestCaseToJSONOrFail(t *testing.T, c StrategicMergePatchTestCase, schema LookupPatchMeta) ([]byte, []byte, []byte, []byte) {
6127	expectedResult := c.TwoWayResult
6128	if expectedResult == nil {
6129		expectedResult = c.Modified
6130	}
6131	return sortJsonOrFail(t, testObjectToJSONOrFail(t, c.Original), c.Description, schema),
6132		sortJsonOrFail(t, testObjectToJSONOrFail(t, c.TwoWay), c.Description, schema),
6133		sortJsonOrFail(t, testObjectToJSONOrFail(t, c.Modified), c.Description, schema),
6134		sortJsonOrFail(t, testObjectToJSONOrFail(t, expectedResult), c.Description, schema)
6135}
6136
6137func twoWayRawTestCaseToJSONOrFail(t *testing.T, c StrategicMergePatchRawTestCase) ([]byte, []byte, []byte, []byte) {
6138	expectedResult := c.TwoWayResult
6139	if expectedResult == nil {
6140		expectedResult = c.Modified
6141	}
6142	return yamlToJSONOrError(t, c.Original),
6143		yamlToJSONOrError(t, c.TwoWay),
6144		yamlToJSONOrError(t, c.Modified),
6145		yamlToJSONOrError(t, expectedResult)
6146}
6147
6148func testThreeWayPatch(t *testing.T, c StrategicMergePatchTestCase, schema LookupPatchMeta) {
6149	original, modified, current, expected, result := threeWayTestCaseToJSONOrFail(t, c, schema)
6150	actual, err := CreateThreeWayMergePatch(original, modified, current, schema, false)
6151	if err != nil {
6152		if !mergepatch.IsConflict(err) {
6153			t.Errorf("using %s error: %s\nin test case: %s\ncannot create three way patch:\n%s\n",
6154				getSchemaType(schema), err, c.Description, mergepatch.ToYAMLOrError(c.StrategicMergePatchTestCaseData))
6155			return
6156		}
6157
6158		if !strings.Contains(c.Description, "conflict") {
6159			t.Errorf("using %s unexpected conflict: %s\nin test case: %s\ncannot create three way patch:\n%s\n",
6160				getSchemaType(schema), err, c.Description, mergepatch.ToYAMLOrError(c.StrategicMergePatchTestCaseData))
6161			return
6162		}
6163
6164		if len(c.Result) > 0 {
6165			actual, err := CreateThreeWayMergePatch(original, modified, current, schema, true)
6166			if err != nil {
6167				t.Errorf("using %s error: %s\nin test case: %s\ncannot force three way patch application:\n%s\n",
6168					getSchemaType(schema), err, c.Description, mergepatch.ToYAMLOrError(c.StrategicMergePatchTestCaseData))
6169				return
6170			}
6171
6172			testPatchCreation(t, expected, actual, c.Description)
6173			testPatchApplication(t, current, actual, result, c.Description, "", schema)
6174		}
6175
6176		return
6177	}
6178
6179	if strings.Contains(c.Description, "conflict") || len(c.Result) < 1 {
6180		t.Errorf("using %s error in test case: %s\nexpected conflict did not occur:\n%s\n",
6181			getSchemaType(schema), c.Description, mergepatch.ToYAMLOrError(c.StrategicMergePatchTestCaseData))
6182		return
6183	}
6184
6185	testPatchCreation(t, expected, actual, c.Description)
6186	testPatchApplication(t, current, actual, result, c.Description, "", schema)
6187}
6188
6189func testThreeWayPatchForRawTestCase(t *testing.T, c StrategicMergePatchRawTestCase, schema LookupPatchMeta) {
6190	original, modified, current, expected, result := threeWayRawTestCaseToJSONOrFail(t, c)
6191	actual, err := CreateThreeWayMergePatch(original, modified, current, schema, false)
6192	if err != nil {
6193		if !mergepatch.IsConflict(err) {
6194			t.Errorf("using %s error: %s\nin test case: %s\ncannot create three way patch:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
6195				getSchemaType(schema), err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
6196			return
6197		}
6198
6199		if !strings.Contains(c.Description, "conflict") {
6200			t.Errorf("using %s unexpected conflict: %s\nin test case: %s\ncannot create three way patch:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
6201				getSchemaType(schema), err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
6202			return
6203		}
6204
6205		if len(c.Result) > 0 {
6206			actual, err := CreateThreeWayMergePatch(original, modified, current, schema, true)
6207			if err != nil {
6208				t.Errorf("using %s error: %s\nin test case: %s\ncannot force three way patch application:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
6209					getSchemaType(schema), err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
6210				return
6211			}
6212
6213			testPatchCreation(t, expected, actual, c.Description)
6214			testPatchApplication(t, current, actual, result, c.Description, c.ExpectedError, schema)
6215		}
6216
6217		return
6218	}
6219
6220	if strings.Contains(c.Description, "conflict") || len(c.Result) < 1 {
6221		t.Errorf("using %s error: %s\nin test case: %s\nexpected conflict did not occur:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
6222			getSchemaType(schema), err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
6223		return
6224	}
6225
6226	testPatchCreation(t, expected, actual, c.Description)
6227	testPatchApplication(t, current, actual, result, c.Description, c.ExpectedError, schema)
6228}
6229
6230func threeWayTestCaseToJSONOrFail(t *testing.T, c StrategicMergePatchTestCase, schema LookupPatchMeta) ([]byte, []byte, []byte, []byte, []byte) {
6231	return sortJsonOrFail(t, testObjectToJSONOrFail(t, c.Original), c.Description, schema),
6232		sortJsonOrFail(t, testObjectToJSONOrFail(t, c.Modified), c.Description, schema),
6233		sortJsonOrFail(t, testObjectToJSONOrFail(t, c.Current), c.Description, schema),
6234		sortJsonOrFail(t, testObjectToJSONOrFail(t, c.ThreeWay), c.Description, schema),
6235		sortJsonOrFail(t, testObjectToJSONOrFail(t, c.Result), c.Description, schema)
6236}
6237
6238func threeWayRawTestCaseToJSONOrFail(t *testing.T, c StrategicMergePatchRawTestCase) ([]byte, []byte, []byte, []byte, []byte) {
6239	return yamlToJSONOrError(t, c.Original),
6240		yamlToJSONOrError(t, c.Modified),
6241		yamlToJSONOrError(t, c.Current),
6242		yamlToJSONOrError(t, c.ThreeWay),
6243		yamlToJSONOrError(t, c.Result)
6244}
6245
6246func testPatchCreation(t *testing.T, expected, actual []byte, description string) {
6247	if !reflect.DeepEqual(actual, expected) {
6248		t.Errorf("error in test case: %s\nexpected patch:\n%s\ngot:\n%s\n",
6249			description, jsonToYAMLOrError(expected), jsonToYAMLOrError(actual))
6250		return
6251	}
6252}
6253
6254func testPatchApplication(t *testing.T, original, patch, expected []byte, description, expectedError string, schema LookupPatchMeta) {
6255	result, err := StrategicMergePatchUsingLookupPatchMeta(original, patch, schema)
6256	if len(expectedError) != 0 {
6257		if err != nil && strings.Contains(err.Error(), expectedError) {
6258			return
6259		}
6260		t.Errorf("using %s expected error should contain:\n%s\nin test case: %s\nbut got:\n%s\n", getSchemaType(schema), expectedError, description, err)
6261	}
6262	if err != nil {
6263		t.Errorf("using %s error: %s\nin test case: %s\ncannot apply patch:\n%s\nto original:\n%s\n",
6264			getSchemaType(schema), err, description, jsonToYAMLOrError(patch), jsonToYAMLOrError(original))
6265		return
6266	}
6267
6268	if !reflect.DeepEqual(result, expected) {
6269		format := "using error in test case: %s\npatch application failed:\noriginal:\n%s\npatch:\n%s\nexpected:\n%s\ngot:\n%s\n"
6270		t.Errorf(format, description,
6271			jsonToYAMLOrError(original), jsonToYAMLOrError(patch),
6272			jsonToYAMLOrError(expected), jsonToYAMLOrError(result))
6273		return
6274	}
6275}
6276
6277func testObjectToJSONOrFail(t *testing.T, o map[string]interface{}) []byte {
6278	if o == nil {
6279		return nil
6280	}
6281
6282	j, err := toJSON(o)
6283	if err != nil {
6284		t.Error(err)
6285	}
6286	return j
6287}
6288
6289func sortJsonOrFail(t *testing.T, j []byte, description string, schema LookupPatchMeta) []byte {
6290	if j == nil {
6291		return nil
6292	}
6293	r, err := sortMergeListsByName(j, schema)
6294	if err != nil {
6295		t.Errorf("using %s error: %s\n in test case: %s\ncannot sort object:\n%s\n", getSchemaType(schema), err, description, j)
6296		return nil
6297	}
6298
6299	return r
6300}
6301
6302func getSchemaType(schema LookupPatchMeta) string {
6303	return reflect.TypeOf(schema).String()
6304}
6305
6306func jsonToYAMLOrError(j []byte) string {
6307	y, err := jsonToYAML(j)
6308	if err != nil {
6309		return err.Error()
6310	}
6311
6312	return string(y)
6313}
6314
6315func toJSON(v interface{}) ([]byte, error) {
6316	j, err := json.Marshal(v)
6317	if err != nil {
6318		return nil, fmt.Errorf("json marshal failed: %v\n%v\n", err, spew.Sdump(v))
6319	}
6320
6321	return j, nil
6322}
6323
6324func jsonToYAML(j []byte) ([]byte, error) {
6325	y, err := yaml.JSONToYAML(j)
6326	if err != nil {
6327		return nil, fmt.Errorf("json to yaml failed: %v\n%v\n", err, j)
6328	}
6329
6330	return y, nil
6331}
6332
6333func yamlToJSON(y []byte) ([]byte, error) {
6334	j, err := yaml.YAMLToJSON(y)
6335	if err != nil {
6336		return nil, fmt.Errorf("yaml to json failed: %v\n%v\n", err, y)
6337	}
6338
6339	return j, nil
6340}
6341
6342func yamlToJSONOrError(t *testing.T, y []byte) []byte {
6343	j, err := yamlToJSON(y)
6344	if err != nil {
6345		t.Errorf("%v", err)
6346	}
6347
6348	return j
6349}
6350
6351type PrecisionItem struct {
6352	Name    string  `json:"name,omitempty"`
6353	Int32   int32   `json:"int32,omitempty"`
6354	Int64   int64   `json:"int64,omitempty"`
6355	Float32 float32 `json:"float32,omitempty"`
6356	Float64 float64 `json:"float64,omitempty"`
6357}
6358
6359var (
6360	precisionItem             PrecisionItem
6361	precisionItemStructSchema = PatchMetaFromStruct{T: GetTagStructTypeOrDie(precisionItem)}
6362)
6363
6364func TestNumberConversion(t *testing.T) {
6365	testcases := map[string]struct {
6366		Old            string
6367		New            string
6368		ExpectedPatch  string
6369		ExpectedResult string
6370	}{
6371		"empty": {
6372			Old:            `{}`,
6373			New:            `{}`,
6374			ExpectedPatch:  `{}`,
6375			ExpectedResult: `{}`,
6376		},
6377		"int32 medium": {
6378			Old:            `{"int32":1000000}`,
6379			New:            `{"int32":1000000,"name":"newname"}`,
6380			ExpectedPatch:  `{"name":"newname"}`,
6381			ExpectedResult: `{"int32":1000000,"name":"newname"}`,
6382		},
6383		"int32 max": {
6384			Old:            `{"int32":2147483647}`,
6385			New:            `{"int32":2147483647,"name":"newname"}`,
6386			ExpectedPatch:  `{"name":"newname"}`,
6387			ExpectedResult: `{"int32":2147483647,"name":"newname"}`,
6388		},
6389		"int64 medium": {
6390			Old:            `{"int64":1000000}`,
6391			New:            `{"int64":1000000,"name":"newname"}`,
6392			ExpectedPatch:  `{"name":"newname"}`,
6393			ExpectedResult: `{"int64":1000000,"name":"newname"}`,
6394		},
6395		"int64 max": {
6396			Old:            `{"int64":9223372036854775807}`,
6397			New:            `{"int64":9223372036854775807,"name":"newname"}`,
6398			ExpectedPatch:  `{"name":"newname"}`,
6399			ExpectedResult: `{"int64":9223372036854775807,"name":"newname"}`,
6400		},
6401		"float32 max": {
6402			Old:            `{"float32":3.4028234663852886e+38}`,
6403			New:            `{"float32":3.4028234663852886e+38,"name":"newname"}`,
6404			ExpectedPatch:  `{"name":"newname"}`,
6405			ExpectedResult: `{"float32":3.4028234663852886e+38,"name":"newname"}`,
6406		},
6407		"float64 max": {
6408			Old:            `{"float64":1.7976931348623157e+308}`,
6409			New:            `{"float64":1.7976931348623157e+308,"name":"newname"}`,
6410			ExpectedPatch:  `{"name":"newname"}`,
6411			ExpectedResult: `{"float64":1.7976931348623157e+308,"name":"newname"}`,
6412		},
6413	}
6414
6415	precisionItemOpenapiSchema := PatchMetaFromOpenAPI{
6416		Schema: sptest.GetSchemaOrDie(&fakePrecisionItemSchema, "precisionItem"),
6417	}
6418	precisionItemSchemas := []LookupPatchMeta{
6419		precisionItemStructSchema,
6420		precisionItemOpenapiSchema,
6421	}
6422
6423	for _, schema := range precisionItemSchemas {
6424		for k, tc := range testcases {
6425			patch, err := CreateTwoWayMergePatchUsingLookupPatchMeta([]byte(tc.Old), []byte(tc.New), schema)
6426			if err != nil {
6427				t.Errorf("using %s in testcase %s: unexpected error %v", getSchemaType(schema), k, err)
6428				continue
6429			}
6430			if tc.ExpectedPatch != string(patch) {
6431				t.Errorf("using %s in testcase %s: expected %s, got %s", getSchemaType(schema), k, tc.ExpectedPatch, string(patch))
6432				continue
6433			}
6434
6435			result, err := StrategicMergePatchUsingLookupPatchMeta([]byte(tc.Old), patch, schema)
6436			if err != nil {
6437				t.Errorf("using %s in testcase %s: unexpected error %v", getSchemaType(schema), k, err)
6438				continue
6439			}
6440			if tc.ExpectedResult != string(result) {
6441				t.Errorf("using %s in testcase %s: expected %s, got %s", getSchemaType(schema), k, tc.ExpectedResult, string(result))
6442				continue
6443			}
6444		}
6445	}
6446}
6447
6448var replaceRawExtensionPatchTestCases = []StrategicMergePatchRawTestCase{
6449	{
6450		Description: "replace RawExtension field, rest unchanched",
6451		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
6452			Original: []byte(`
6453name: my-object
6454value: some-value
6455other: current-other
6456replacingItem:
6457  Some: Generic
6458  Yaml: Inside
6459  The: RawExtension
6460  Field: Period
6461`),
6462			Current: []byte(`
6463name: my-object
6464value: some-value
6465other: current-other
6466mergingList:
6467  - name: 1
6468  - name: 2
6469  - name: 3
6470replacingItem:
6471  Some: Generic
6472  Yaml: Inside
6473  The: RawExtension
6474  Field: Period
6475`),
6476			Modified: []byte(`
6477name: my-object
6478value: some-value
6479other: current-other
6480mergingList:
6481  - name: 1
6482  - name: 2
6483  - name: 3
6484replacingItem:
6485  Newly: Modified
6486  Yaml: Inside
6487  The: RawExtension
6488`),
6489			TwoWay: []byte(`
6490mergingList:
6491  - name: 1
6492  - name: 2
6493  - name: 3
6494replacingItem:
6495  Newly: Modified
6496  Yaml: Inside
6497  The: RawExtension
6498`),
6499			TwoWayResult: []byte(`
6500name: my-object
6501value: some-value
6502other: current-other
6503mergingList:
6504  - name: 1
6505  - name: 2
6506  - name: 3
6507replacingItem:
6508  Newly: Modified
6509  Yaml: Inside
6510  The: RawExtension
6511`),
6512			ThreeWay: []byte(`
6513replacingItem:
6514  Newly: Modified
6515  Yaml: Inside
6516  The: RawExtension
6517`),
6518			Result: []byte(`
6519name: my-object
6520value: some-value
6521other: current-other
6522mergingList:
6523  - name: 1
6524  - name: 2
6525  - name: 3
6526replacingItem:
6527  Newly: Modified
6528  Yaml: Inside
6529  The: RawExtension
6530`),
6531		},
6532	},
6533	{
6534		Description: "replace RawExtension field and merge list",
6535		StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
6536			Original: []byte(`
6537name: my-object
6538value: some-value
6539other: current-other
6540mergingList:
6541  - name: 1
6542replacingItem:
6543  Some: Generic
6544  Yaml: Inside
6545  The: RawExtension
6546  Field: Period
6547`),
6548			Current: []byte(`
6549name: my-object
6550value: some-value
6551other: current-other
6552mergingList:
6553  - name: 1
6554  - name: 3
6555replacingItem:
6556  Some: Generic
6557  Yaml: Inside
6558  The: RawExtension
6559  Field: Period
6560`),
6561			Modified: []byte(`
6562name: my-object
6563value: some-value
6564other: current-other
6565mergingList:
6566  - name: 1
6567  - name: 2
6568replacingItem:
6569  Newly: Modified
6570  Yaml: Inside
6571  The: RawExtension
6572`),
6573			TwoWay: []byte(`
6574$setElementOrder/mergingList:
6575  - name: 1
6576  - name: 2
6577mergingList:
6578  - name: 2
6579replacingItem:
6580  Newly: Modified
6581  Yaml: Inside
6582  The: RawExtension
6583`),
6584			TwoWayResult: []byte(`
6585name: my-object
6586value: some-value
6587other: current-other
6588mergingList:
6589  - name: 1
6590  - name: 2
6591replacingItem:
6592  Newly: Modified
6593  Yaml: Inside
6594  The: RawExtension
6595`),
6596			ThreeWay: []byte(`
6597$setElementOrder/mergingList:
6598  - name: 1
6599  - name: 2
6600mergingList:
6601  - name: 2
6602replacingItem:
6603  Newly: Modified
6604  Yaml: Inside
6605  The: RawExtension
6606`),
6607			Result: []byte(`
6608name: my-object
6609value: some-value
6610other: current-other
6611mergingList:
6612  - name: 1
6613  - name: 2
6614  - name: 3
6615replacingItem:
6616  Newly: Modified
6617  Yaml: Inside
6618  The: RawExtension
6619`),
6620		},
6621	},
6622}
6623
6624func TestReplaceWithRawExtension(t *testing.T) {
6625	mergeItemOpenapiSchema := PatchMetaFromOpenAPI{
6626		Schema: sptest.GetSchemaOrDie(&fakeMergeItemSchema, "mergeItem"),
6627	}
6628	schemas := []LookupPatchMeta{
6629		mergeItemStructSchema,
6630		mergeItemOpenapiSchema,
6631	}
6632
6633	for _, schema := range schemas {
6634		for _, c := range replaceRawExtensionPatchTestCases {
6635			testTwoWayPatchForRawTestCase(t, c, schema)
6636			testThreeWayPatchForRawTestCase(t, c, schema)
6637		}
6638	}
6639}
6640
6641func TestUnknownField(t *testing.T) {
6642	testcases := map[string]struct {
6643		Original string
6644		Current  string
6645		Modified string
6646
6647		ExpectedTwoWay         string
6648		ExpectedTwoWayErr      string
6649		ExpectedTwoWayResult   string
6650		ExpectedThreeWay       string
6651		ExpectedThreeWayErr    string
6652		ExpectedThreeWayResult string
6653	}{
6654		// cases we can successfully strategically merge
6655		"no diff": {
6656			Original: `{"array":[1,2,3],"complex":{"nested":true},"name":"foo","scalar":true}`,
6657			Current:  `{"array":[1,2,3],"complex":{"nested":true},"name":"foo","scalar":true}`,
6658			Modified: `{"array":[1,2,3],"complex":{"nested":true},"name":"foo","scalar":true}`,
6659
6660			ExpectedTwoWay:         `{}`,
6661			ExpectedTwoWayResult:   `{"array":[1,2,3],"complex":{"nested":true},"name":"foo","scalar":true}`,
6662			ExpectedThreeWay:       `{}`,
6663			ExpectedThreeWayResult: `{"array":[1,2,3],"complex":{"nested":true},"name":"foo","scalar":true}`,
6664		},
6665		"added only": {
6666			Original: `{"name":"foo"}`,
6667			Current:  `{"name":"foo"}`,
6668			Modified: `{"name":"foo","scalar":true,"complex":{"nested":true},"array":[1,2,3]}`,
6669
6670			ExpectedTwoWay:         `{"array":[1,2,3],"complex":{"nested":true},"scalar":true}`,
6671			ExpectedTwoWayResult:   `{"array":[1,2,3],"complex":{"nested":true},"name":"foo","scalar":true}`,
6672			ExpectedThreeWay:       `{"array":[1,2,3],"complex":{"nested":true},"scalar":true}`,
6673			ExpectedThreeWayResult: `{"array":[1,2,3],"complex":{"nested":true},"name":"foo","scalar":true}`,
6674		},
6675		"removed only": {
6676			Original: `{"name":"foo","scalar":true,"complex":{"nested":true}}`,
6677			Current:  `{"name":"foo","scalar":true,"complex":{"nested":true},"array":[1,2,3]}`,
6678			Modified: `{"name":"foo"}`,
6679
6680			ExpectedTwoWay:         `{"complex":null,"scalar":null}`,
6681			ExpectedTwoWayResult:   `{"name":"foo"}`,
6682			ExpectedThreeWay:       `{"complex":null,"scalar":null}`,
6683			ExpectedThreeWayResult: `{"array":[1,2,3],"name":"foo"}`,
6684		},
6685
6686		// cases we cannot successfully strategically merge (expect errors)
6687		"diff": {
6688			Original: `{"array":[1,2,3],"complex":{"nested":true},"name":"foo","scalar":true}`,
6689			Current:  `{"array":[1,2,3],"complex":{"nested":true},"name":"foo","scalar":true}`,
6690			Modified: `{"array":[1,2,3],"complex":{"nested":false},"name":"foo","scalar":true}`,
6691
6692			ExpectedTwoWayErr:   `unable to find api field`,
6693			ExpectedThreeWayErr: `unable to find api field`,
6694		},
6695	}
6696
6697	mergeItemOpenapiSchema := PatchMetaFromOpenAPI{
6698		Schema: sptest.GetSchemaOrDie(&fakeMergeItemSchema, "mergeItem"),
6699	}
6700	schemas := []LookupPatchMeta{
6701		mergeItemStructSchema,
6702		mergeItemOpenapiSchema,
6703	}
6704
6705	for _, k := range sets.StringKeySet(testcases).List() {
6706		tc := testcases[k]
6707		for _, schema := range schemas {
6708			func() {
6709				twoWay, err := CreateTwoWayMergePatchUsingLookupPatchMeta([]byte(tc.Original), []byte(tc.Modified), schema)
6710				if err != nil {
6711					if len(tc.ExpectedTwoWayErr) == 0 {
6712						t.Errorf("using %s in testcase %s: error making two-way patch: %v", getSchemaType(schema), k, err)
6713					}
6714					if !strings.Contains(err.Error(), tc.ExpectedTwoWayErr) {
6715						t.Errorf("using %s in testcase %s: expected error making two-way patch to contain '%s', got %s", getSchemaType(schema), k, tc.ExpectedTwoWayErr, err)
6716					}
6717					return
6718				}
6719
6720				if string(twoWay) != tc.ExpectedTwoWay {
6721					t.Errorf("using %s in testcase %s: expected two-way patch:\n\t%s\ngot\n\t%s", getSchemaType(schema), k, string(tc.ExpectedTwoWay), string(twoWay))
6722					return
6723				}
6724
6725				twoWayResult, err := StrategicMergePatchUsingLookupPatchMeta([]byte(tc.Original), twoWay, schema)
6726				if err != nil {
6727					t.Errorf("using %s in testcase %s: error applying two-way patch: %v", getSchemaType(schema), k, err)
6728					return
6729				}
6730				if string(twoWayResult) != tc.ExpectedTwoWayResult {
6731					t.Errorf("using %s in testcase %s: expected two-way result:\n\t%s\ngot\n\t%s", getSchemaType(schema), k, string(tc.ExpectedTwoWayResult), string(twoWayResult))
6732					return
6733				}
6734			}()
6735
6736			func() {
6737				threeWay, err := CreateThreeWayMergePatch([]byte(tc.Original), []byte(tc.Modified), []byte(tc.Current), schema, false)
6738				if err != nil {
6739					if len(tc.ExpectedThreeWayErr) == 0 {
6740						t.Errorf("using %s in testcase %s: error making three-way patch: %v", getSchemaType(schema), k, err)
6741					} else if !strings.Contains(err.Error(), tc.ExpectedThreeWayErr) {
6742						t.Errorf("using %s in testcase %s: expected error making three-way patch to contain '%s', got %s", getSchemaType(schema), k, tc.ExpectedThreeWayErr, err)
6743					}
6744					return
6745				}
6746
6747				if string(threeWay) != tc.ExpectedThreeWay {
6748					t.Errorf("using %s in testcase %s: expected three-way patch:\n\t%s\ngot\n\t%s", getSchemaType(schema), k, string(tc.ExpectedThreeWay), string(threeWay))
6749					return
6750				}
6751
6752				threeWayResult, err := StrategicMergePatch([]byte(tc.Current), threeWay, schema)
6753				if err != nil {
6754					t.Errorf("using %s in testcase %s: error applying three-way patch: %v", getSchemaType(schema), k, err)
6755					return
6756				} else if string(threeWayResult) != tc.ExpectedThreeWayResult {
6757					t.Errorf("using %s in testcase %s: expected three-way result:\n\t%s\ngot\n\t%s", getSchemaType(schema), k, string(tc.ExpectedThreeWayResult), string(threeWayResult))
6758					return
6759				}
6760			}()
6761		}
6762	}
6763}
6764