...

Source file src/sigs.k8s.io/structured-merge-diff/v4/merge/nested_test.go

Documentation: sigs.k8s.io/structured-merge-diff/v4/merge

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

View as plain text