...

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

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

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3   Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6       http://www.apache.org/licenses/LICENSE-2.0
     7   Unless required by applicable law or agreed to in writing, software
     8  distributed under the License is distributed on an "AS IS" BASIS,
     9  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  See the License for the specific language governing permissions and
    11  limitations under the License.
    12  */
    13  
    14  package merge_test
    15  
    16  import (
    17  	"testing"
    18  
    19  	"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
    20  	. "sigs.k8s.io/structured-merge-diff/v4/internal/fixture"
    21  	"sigs.k8s.io/structured-merge-diff/v4/merge"
    22  	"sigs.k8s.io/structured-merge-diff/v4/typed"
    23  )
    24  
    25  // portListParser sets the default value of key "protocol" to "TCP"
    26  var portListParser = func() *typed.Parser {
    27  	parser, err := typed.NewParser(`types:
    28  - name: v1
    29    map:
    30      fields:
    31        - name: containerPorts
    32          type:
    33            list:
    34              elementType:
    35                map:
    36                  fields:
    37                  - name: port
    38                    type:
    39                      scalar: numeric
    40                  - name: protocol
    41                    default: "TCP"
    42                    type:
    43                      scalar: string
    44                  - name: name
    45                    type:
    46                      scalar: string
    47              elementRelationship: associative
    48              keys:
    49              - port
    50              - protocol
    51  `)
    52  	if err != nil {
    53  		panic(err)
    54  	}
    55  	return parser
    56  }()
    57  
    58  func TestDefaultKeysFlat(t *testing.T) {
    59  	tests := map[string]TestCase{
    60  		"apply_missing_defaulted_key_A": {
    61  			Ops: []Operation{
    62  				Apply{
    63  					Manager:    "default",
    64  					APIVersion: "v1",
    65  					Object: `
    66  						containerPorts:
    67  						- port: 80
    68  					`,
    69  				},
    70  			},
    71  			APIVersion: "v1",
    72  			Object: `
    73  				containerPorts:
    74  				- port: 80
    75  			`,
    76  			Managed: fieldpath.ManagedFields{
    77  				"default": fieldpath.NewVersionedSet(
    78  					_NS(
    79  						_P("containerPorts", _KBF("port", 80, "protocol", "TCP")),
    80  						_P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "port"),
    81  					),
    82  					"v1",
    83  					false,
    84  				),
    85  			},
    86  		},
    87  		"apply_missing_defaulted_key_B": {
    88  			Ops: []Operation{
    89  				Apply{
    90  					Manager:    "default",
    91  					APIVersion: "v1",
    92  					Object: `
    93  						containerPorts:
    94  						- port: 80
    95  						- port: 80
    96  						  protocol: UDP
    97  					`,
    98  				},
    99  			},
   100  			APIVersion: "v1",
   101  			Object: `
   102  				containerPorts:
   103  				- port: 80
   104  				- port: 80
   105  				  protocol: UDP
   106  			`,
   107  			Managed: fieldpath.ManagedFields{
   108  				"default": fieldpath.NewVersionedSet(
   109  					_NS(
   110  						_P("containerPorts", _KBF("port", 80, "protocol", "TCP")),
   111  						_P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "port"),
   112  						_P("containerPorts", _KBF("port", 80, "protocol", "UDP")),
   113  						_P("containerPorts", _KBF("port", 80, "protocol", "UDP"), "port"),
   114  						_P("containerPorts", _KBF("port", 80, "protocol", "UDP"), "protocol"),
   115  					),
   116  					"v1",
   117  					false,
   118  				),
   119  			},
   120  		},
   121  		"apply_missing_defaulted_key_with_conflict": {
   122  			Ops: []Operation{
   123  				Apply{
   124  					Manager:    "apply-one",
   125  					APIVersion: "v1",
   126  					Object: `
   127  						containerPorts:
   128  						- port: 80
   129  						  protocol: TCP
   130  						  name: foo
   131  					`,
   132  				},
   133  				Apply{
   134  					Manager:    "apply-two",
   135  					APIVersion: "v1",
   136  					Object: `
   137  						containerPorts:
   138  						- port: 80
   139  						  name: bar
   140  					`,
   141  					Conflicts: merge.Conflicts{
   142  						merge.Conflict{Manager: "apply-one", Path: _P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "name")},
   143  					},
   144  				},
   145  			},
   146  			APIVersion: "v1",
   147  			Object: `
   148  				containerPorts:
   149  				- port: 80
   150  				  protocol: TCP
   151  				  name: foo
   152  			`,
   153  			Managed: fieldpath.ManagedFields{
   154  				"apply-one": fieldpath.NewVersionedSet(
   155  					_NS(
   156  						_P("containerPorts", _KBF("port", 80, "protocol", "TCP")),
   157  						_P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "port"),
   158  						_P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "protocol"),
   159  						_P("containerPorts", _KBF("port", 80, "protocol", "TCP"), "name"),
   160  					),
   161  					"v1",
   162  					false,
   163  				),
   164  			},
   165  		},
   166  	}
   167  
   168  	for name, test := range tests {
   169  		t.Run(name, func(t *testing.T) {
   170  			if err := test.Test(portListParser); err != nil {
   171  				t.Fatal(err)
   172  			}
   173  		})
   174  	}
   175  }
   176  
   177  func TestDefaultKeysFlatErrors(t *testing.T) {
   178  	tests := map[string]TestCase{
   179  		"apply_missing_undefaulted_defaulted_key": {
   180  			Ops: []Operation{
   181  				Apply{
   182  					Manager:    "default",
   183  					APIVersion: "v1",
   184  					Object: `
   185  						containerPorts:
   186  						- protocol: TCP
   187  					`,
   188  				},
   189  			},
   190  		},
   191  		"apply_missing_defaulted_key_ambiguous_A": {
   192  			Ops: []Operation{
   193  				Apply{
   194  					Manager:    "default",
   195  					APIVersion: "v1",
   196  					Object: `
   197  						containerPorts:
   198  						- port: 80
   199  						- port: 80
   200  					`,
   201  				},
   202  			},
   203  		},
   204  		"apply_missing_defaulted_key_ambiguous_B": {
   205  			Ops: []Operation{
   206  				Apply{
   207  					Manager:    "default",
   208  					APIVersion: "v1",
   209  					Object: `
   210  						containerPorts:
   211  						- port: 80
   212  						- port: 80
   213  						  protocol: TCP
   214  					`,
   215  				},
   216  			},
   217  		},
   218  	}
   219  	for name, test := range tests {
   220  		t.Run(name, func(t *testing.T) {
   221  			if test.Test(portListParser) == nil {
   222  				t.Fatal("Should fail")
   223  			}
   224  		})
   225  	}
   226  }
   227  
   228  // bookParser sets the default value of key:
   229  // * "chapter" to 1
   230  // * "section" to "A"
   231  // * "page" to 2,
   232  // * "line" to 3,
   233  var bookParser = func() *typed.Parser {
   234  	parser, err := typed.NewParser(`types:
   235  - name: v1
   236    map:
   237      fields:
   238        - name: book
   239          type:
   240            list:
   241              elementType:
   242                map:
   243                  fields:
   244                  - name: chapter
   245                    default: 1
   246                    type:
   247                      scalar: numeric
   248                  - name: section
   249                    default: "A"
   250                    type:
   251                      scalar: string
   252                  - name: sentences
   253                    type:
   254                      list:
   255                        elementType:
   256                          map:
   257                            fields:
   258                            - name: page
   259                              default: 2.0
   260                              type:
   261                                scalar: numeric
   262                            - name: line
   263                              default: 3
   264                              type:
   265                                scalar: numeric
   266                            - name: text
   267                              type:
   268                                scalar: string
   269                        elementRelationship: associative
   270                        keys:
   271                        - page
   272                        - line
   273              elementRelationship: associative
   274              keys:
   275              - chapter
   276              - section
   277  `)
   278  	if err != nil {
   279  		panic(err)
   280  	}
   281  	return parser
   282  }()
   283  
   284  func TestDefaultKeysNested(t *testing.T) {
   285  	tests := map[string]TestCase{
   286  		"apply_missing_every_key_nested": {
   287  			Ops: []Operation{
   288  				Apply{
   289  					Manager:    "default",
   290  					APIVersion: "v1",
   291  					Object: `
   292  						book:
   293  						- sentences:
   294  						  - text: blah
   295  					`,
   296  				},
   297  			},
   298  			APIVersion: "v1",
   299  			Object: `
   300  				book:
   301  				- sentences:
   302  				  - text: blah
   303  			`,
   304  			Managed: fieldpath.ManagedFields{
   305  				"default": fieldpath.NewVersionedSet(
   306  					_NS(
   307  						_P(
   308  							"book", _KBF("chapter", 1, "section", "A"),
   309  						),
   310  						_P(
   311  							"book", _KBF("chapter", 1, "section", "A"),
   312  							"sentences", _KBF("page", 2, "line", 3),
   313  						),
   314  						_P(
   315  							"book", _KBF("chapter", 1, "section", "A"),
   316  							"sentences", _KBF("page", 2, "line", 3),
   317  							"text",
   318  						),
   319  					),
   320  					"v1",
   321  					false,
   322  				),
   323  			},
   324  		},
   325  		"apply_integer_key_with_float_default": {
   326  			Ops: []Operation{
   327  				Apply{
   328  					Manager:    "default",
   329  					APIVersion: "v1",
   330  					Object: `
   331  						book:
   332  						- sentences:
   333  						  - text: blah
   334  					`,
   335  				},
   336  				Apply{
   337  					Manager:    "default",
   338  					APIVersion: "v1",
   339  					Object: `
   340  						book:
   341  						- sentences:
   342  						  - text: blah
   343  						    page: 2
   344  					`,
   345  				},
   346  			},
   347  			APIVersion: "v1",
   348  			Object: `
   349  				book:
   350  				- sentences:
   351  				  - text: blah
   352  				    page: 2
   353  			`,
   354  			Managed: fieldpath.ManagedFields{
   355  				"default": fieldpath.NewVersionedSet(
   356  					_NS(
   357  						_P(
   358  							"book", _KBF("chapter", 1, "section", "A"),
   359  						),
   360  						_P(
   361  							"book", _KBF("chapter", 1, "section", "A"),
   362  							"sentences", _KBF("page", 2, "line", 3),
   363  						),
   364  						_P(
   365  							"book", _KBF("chapter", 1, "section", "A"),
   366  							"sentences", _KBF("page", 2, "line", 3),
   367  							"text",
   368  						),
   369  						_P(
   370  							"book", _KBF("chapter", 1, "section", "A"),
   371  							"sentences", _KBF("page", 2, "line", 3),
   372  							"page",
   373  						),
   374  					),
   375  					"v1",
   376  					false,
   377  				),
   378  			},
   379  		},
   380  	}
   381  
   382  	for name, test := range tests {
   383  		t.Run(name, func(t *testing.T) {
   384  			if err := test.Test(bookParser); err != nil {
   385  				t.Fatal(err)
   386  			}
   387  		})
   388  	}
   389  }
   390  

View as plain text