...

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

View as plain text