github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/util/strategicpatch/patch_test.go (about)

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