github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/utils/merge_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package utils_test
     5  
     6  import (
     7  	"fmt"
     8  	"reflect"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"github.com/vnforks/kid/v5/utils"
    15  )
    16  
    17  // Test merging maps alone. This isolates the complexity of merging maps from merging maps recursively in
    18  // a struct/ptr/etc.
    19  // Remember that for our purposes, "merging" means replacing base with patch if patch is /anything/ other than nil.
    20  func TestMergeWithMaps(t *testing.T) {
    21  	t.Run("merge maps where patch is longer", func(t *testing.T) {
    22  		m1 := map[string]int{"this": 1, "is": 2, "a map": 3}
    23  		m2 := map[string]int{"this": 1, "is": 3, "a second map": 3, "another key": 4}
    24  
    25  		expected := map[string]int{"this": 1, "is": 3, "a second map": 3, "another key": 4}
    26  		merged, err := mergeStringIntMap(m1, m2)
    27  		require.NoError(t, err)
    28  
    29  		assert.Equal(t, expected, merged)
    30  	})
    31  
    32  	t.Run("merge maps where base is longer", func(t *testing.T) {
    33  		m1 := map[string]int{"this": 1, "is": 2, "a map": 3, "with": 4, "more keys": -12}
    34  		m2 := map[string]int{"this": 1, "is": 3, "a second map": 3}
    35  		expected := map[string]int{"this": 1, "is": 3, "a second map": 3}
    36  
    37  		merged, err := mergeStringIntMap(m1, m2)
    38  		require.NoError(t, err)
    39  
    40  		assert.Equal(t, expected, merged)
    41  	})
    42  
    43  	t.Run("merge maps where base is empty", func(t *testing.T) {
    44  		m1 := make(map[string]int)
    45  		m2 := map[string]int{"this": 1, "is": 3, "a second map": 3, "another key": 4}
    46  
    47  		expected := map[string]int{"this": 1, "is": 3, "a second map": 3, "another key": 4}
    48  		merged, err := mergeStringIntMap(m1, m2)
    49  		require.NoError(t, err)
    50  
    51  		assert.Equal(t, expected, merged)
    52  	})
    53  
    54  	t.Run("merge maps where patch is empty", func(t *testing.T) {
    55  		m1 := map[string]int{"this": 1, "is": 3, "a map": 3, "another key": 4}
    56  		var m2 map[string]int
    57  		expected := map[string]int{"this": 1, "is": 3, "a map": 3, "another key": 4}
    58  
    59  		merged, err := mergeStringIntMap(m1, m2)
    60  		require.NoError(t, err)
    61  
    62  		assert.Equal(t, expected, merged)
    63  	})
    64  
    65  	t.Run("merge map[string]*int patch with different keys and values", func(t *testing.T) {
    66  		m1 := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(3)}
    67  		m2 := map[string]*int{"this": newInt(2), "is": newInt(3), "a key": newInt(4)}
    68  		expected := map[string]*int{"this": newInt(2), "is": newInt(3), "a key": newInt(4)}
    69  
    70  		merged, err := mergeStringPtrIntMap(m1, m2)
    71  		require.NoError(t, err)
    72  
    73  		assert.Equal(t, expected, merged)
    74  	})
    75  
    76  	t.Run("merge map[string]*int patch has nil keys -- doesn't matter, maps overwrite completely", func(t *testing.T) {
    77  		m1 := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(3)}
    78  		m2 := map[string]*int{"this": newInt(1), "is": nil, "a key": newInt(3)}
    79  		expected := map[string]*int{"this": newInt(1), "is": nil, "a key": newInt(3)}
    80  
    81  		merged, err := mergeStringPtrIntMap(m1, m2)
    82  		require.NoError(t, err)
    83  
    84  		assert.Equal(t, expected, merged)
    85  	})
    86  
    87  	t.Run("merge map[string]*int base has nil vals -- overwrite base with patch", func(t *testing.T) {
    88  		m1 := map[string]*int{"this": newInt(1), "is": nil, "base key": newInt(4)}
    89  		m2 := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(3)}
    90  		expected := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(3)}
    91  
    92  		merged, err := mergeStringPtrIntMap(m1, m2)
    93  		require.NoError(t, err)
    94  
    95  		assert.Equal(t, expected, merged)
    96  	})
    97  
    98  	t.Run("merge map[string]*int base has nil vals -- but patch is nil, so keep base", func(t *testing.T) {
    99  		m1 := map[string]*int{"this": newInt(1), "is": nil, "base key": newInt(4)}
   100  		var m2 map[string]*int
   101  		expected := map[string]*int{"this": newInt(1), "is": nil, "base key": newInt(4)}
   102  
   103  		merged, err := mergeStringPtrIntMap(m1, m2)
   104  		require.NoError(t, err)
   105  
   106  		assert.Equal(t, expected, merged)
   107  	})
   108  
   109  	t.Run("merge map[string]*int pointers are not copied - change in base do not affect merged", func(t *testing.T) {
   110  		// that should never happen, since patch overwrites completely
   111  		m1 := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(4)}
   112  		m2 := map[string]*int{"this": newInt(1), "a key": newInt(5)}
   113  		expected := map[string]*int{"this": newInt(1), "a key": newInt(5)}
   114  
   115  		merged, err := mergeStringPtrIntMap(m1, m2)
   116  		require.NoError(t, err)
   117  
   118  		assert.Equal(t, expected, merged)
   119  		*m1["this"] = 6
   120  		assert.Equal(t, 1, *merged["this"])
   121  	})
   122  
   123  	t.Run("merge map[string]*int pointers are not copied - change in patched do not affect merged", func(t *testing.T) {
   124  		m1 := map[string]*int{"this": newInt(1), "is": newInt(3), "a key": newInt(4)}
   125  		m2 := map[string]*int{"this": newInt(2), "a key": newInt(5)}
   126  		expected := map[string]*int{"this": newInt(2), "a key": newInt(5)}
   127  
   128  		merged, err := mergeStringPtrIntMap(m1, m2)
   129  		require.NoError(t, err)
   130  
   131  		assert.Equal(t, expected, merged)
   132  		*m2["this"] = 6
   133  		assert.Equal(t, 2, *merged["this"])
   134  	})
   135  
   136  	t.Run("merge map[string][]int overwrite base with patch", func(t *testing.T) {
   137  		m1 := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}}
   138  		m2 := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}}
   139  		expected := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}}
   140  
   141  		merged, err := mergeStringSliceIntMap(m1, m2)
   142  		require.NoError(t, err)
   143  
   144  		assert.Equal(t, expected, merged)
   145  	})
   146  
   147  	t.Run("merge map[string][]int nil in patch /does/ overwrite base", func(t *testing.T) {
   148  		m1 := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}}
   149  		m2 := map[string][]int{"this": {1, 2, 3}, "is": nil}
   150  		expected := map[string][]int{"this": {1, 2, 3}, "is": nil}
   151  
   152  		merged, err := mergeStringSliceIntMap(m1, m2)
   153  		require.NoError(t, err)
   154  
   155  		assert.Equal(t, expected, merged)
   156  	})
   157  
   158  	t.Run("merge map[string][]int nil in base is overwritten", func(t *testing.T) {
   159  		m1 := map[string][]int{"this": {1, 2, 3}, "is": nil}
   160  		m2 := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}}
   161  		expected := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}}
   162  		merged, err := mergeStringSliceIntMap(m1, m2)
   163  		require.NoError(t, err)
   164  
   165  		assert.Equal(t, expected, merged)
   166  	})
   167  
   168  	t.Run("merge map[string][]int nil in base is overwritten even without matching key", func(t *testing.T) {
   169  		m1 := map[string][]int{"this": {1, 2, 3}, "is": nil}
   170  		m2 := map[string][]int{"this": {1, 2, 3}, "new": {4, 5, 6}}
   171  		expected := map[string][]int{"this": {1, 2, 3}, "new": {4, 5, 6}}
   172  
   173  		merged, err := mergeStringSliceIntMap(m1, m2)
   174  		require.NoError(t, err)
   175  
   176  		assert.Equal(t, expected, merged)
   177  	})
   178  
   179  	t.Run("merge map[string][]int slice is cloned - change in base does not affect merged", func(t *testing.T) {
   180  		// shouldn't, is patch clobbers
   181  		m1 := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}}
   182  		m2 := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}}
   183  		expected := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}}
   184  
   185  		merged, err := mergeStringSliceIntMap(m1, m2)
   186  		require.NoError(t, err)
   187  
   188  		assert.Equal(t, expected, merged)
   189  		m1["this"][0] = 99
   190  		assert.Equal(t, 1, merged["this"][0])
   191  	})
   192  
   193  	t.Run("merge map[string][]int slice is cloned - change in patch does not affect merged", func(t *testing.T) {
   194  		m1 := map[string][]int{"this": {1, 2, 3}, "is": {4, 5, 6}}
   195  		m2 := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}}
   196  		expected := map[string][]int{"this": {1, 2, 3}, "new": {7, 8, 9}}
   197  
   198  		merged, err := mergeStringSliceIntMap(m1, m2)
   199  		require.NoError(t, err)
   200  
   201  		assert.Equal(t, expected, merged)
   202  		m2["new"][1] = 0
   203  		assert.Equal(t, 8, merged["new"][1])
   204  	})
   205  
   206  	t.Run("merge map[string]map[string]*int", func(t *testing.T) {
   207  		m1 := map[string]map[string]*int{"this": {"second": newInt(99)}, "base": {"level": newInt(10)}}
   208  		m2 := map[string]map[string]*int{"this": {"second": newInt(77)}, "patch": {"level": newInt(15)}}
   209  		expected := map[string]map[string]*int{"this": {"second": newInt(77)}, "patch": {"level": newInt(15)}}
   210  
   211  		merged, err := mergeMapOfMap(m1, m2)
   212  		require.NoError(t, err)
   213  
   214  		assert.Equal(t, expected, merged)
   215  	})
   216  
   217  	t.Run("merge map[string]map[string]*int, patch has nil keys -- /do/ overwrite base with nil", func(t *testing.T) {
   218  		m1 := map[string]map[string]*int{"this": {"second": newInt(99)}, "base": {"level": newInt(10)}}
   219  		m2 := map[string]map[string]*int{"this": {"second": nil}, "base": nil, "patch": {"level": newInt(15)}}
   220  		expected := map[string]map[string]*int{"this": {"second": nil}, "base": nil, "patch": {"level": newInt(15)}}
   221  
   222  		merged, err := mergeMapOfMap(m1, m2)
   223  		require.NoError(t, err)
   224  
   225  		assert.Equal(t, expected, merged)
   226  	})
   227  
   228  	t.Run("merge map[string]map[string]*int, base has nil vals -- overwrite base with patch", func(t *testing.T) {
   229  		m1 := map[string]map[string]*int{"this": {"second": nil}, "base": nil}
   230  		m2 := map[string]map[string]*int{"this": {"second": newInt(77)}, "base": {"level": newInt(10)}, "patch": {"level": newInt(15)}}
   231  		expected := map[string]map[string]*int{"this": {"second": newInt(77)}, "base": {"level": newInt(10)}, "patch": {"level": newInt(15)}}
   232  
   233  		merged, err := mergeMapOfMap(m1, m2)
   234  		require.NoError(t, err)
   235  
   236  		assert.Equal(t, expected, merged)
   237  	})
   238  
   239  	t.Run("merge map[string]map[string]*int, pointers are not copied - change in base does not affect merged", func(t *testing.T) {
   240  		// shouldn't, if we're overwriting completely
   241  		m1 := map[string]map[string]*int{"this": {"second": newInt(99)}, "base": {"level": newInt(10)}, "are belong": {"to us": newInt(23)}}
   242  		m2 := map[string]map[string]*int{"base": {"level": newInt(10)}}
   243  		expected := map[string]map[string]*int{"base": {"level": newInt(10)}}
   244  
   245  		merged, err := mergeMapOfMap(m1, m2)
   246  		require.NoError(t, err)
   247  
   248  		assert.Equal(t, expected, merged)
   249  
   250  		// test changing the map entry's referenced value
   251  		*m1["base"]["level"] = 347
   252  		assert.Equal(t, 10, *merged["base"]["level"])
   253  
   254  		// test replacing map entry
   255  		m1["base"]["level"] = newInt(12)
   256  		assert.Equal(t, 10, *merged["base"]["level"])
   257  
   258  		// test replacing a referenced map
   259  		m1["base"] = map[string]*int{"third": newInt(777)}
   260  		assert.Equal(t, 10, *merged["base"]["level"])
   261  
   262  	})
   263  
   264  	t.Run("merge map[string]map[string]*int, pointers are not copied - change in patch do not affect merged", func(t *testing.T) {
   265  		m1 := map[string]map[string]*int{"base": {"level": newInt(15)}}
   266  		m2 := map[string]map[string]*int{"this": {"second": newInt(99)}, "patch": {"level": newInt(10)},
   267  			"are belong": {"to us": newInt(23)}}
   268  		expected := map[string]map[string]*int{"this": {"second": newInt(99)}, "patch": {"level": newInt(10)},
   269  			"are belong": {"to us": newInt(23)}}
   270  
   271  		merged, err := mergeMapOfMap(m1, m2)
   272  		require.NoError(t, err)
   273  
   274  		assert.Equal(t, expected, merged)
   275  
   276  		// test replacing a referenced map
   277  		m2["this"] = map[string]*int{"third": newInt(777)}
   278  		assert.Equal(t, 99, *merged["this"]["second"])
   279  
   280  		// test replacing map entry
   281  		m2["patch"]["level"] = newInt(12)
   282  		assert.Equal(t, 10, *merged["patch"]["level"])
   283  
   284  		// test changing the map entry's referenced value
   285  		*m2["are belong"]["to us"] = 347
   286  		assert.Equal(t, 23, *merged["are belong"]["to us"])
   287  	})
   288  
   289  	t.Run("merge map[string]interface{}", func(t *testing.T) {
   290  		m1 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)},
   291  			"base": map[string]*int{"level": newInt(10)}}
   292  		m2 := map[string]interface{}{"this": map[string]*int{"second": newInt(77)},
   293  			"patch": map[string]*int{"level": newInt(15)}}
   294  		expected := map[string]interface{}{"this": map[string]*int{"second": newInt(77)},
   295  			"patch": map[string]*int{"level": newInt(15)}}
   296  
   297  		merged, err := mergeInterfaceMap(m1, m2)
   298  		require.NoError(t, err)
   299  
   300  		assert.Equal(t, expected, merged)
   301  	})
   302  
   303  	t.Run("merge map[string]interface{}, patch has nil keys -- /do/ overwrite base with nil", func(t *testing.T) {
   304  		m1 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)}}
   305  		m2 := map[string]interface{}{"this": map[string]*int{"second": nil}}
   306  		expected := map[string]interface{}{"this": map[string]*int{"second": nil}}
   307  
   308  		merged, err := mergeInterfaceMap(m1, m2)
   309  		require.NoError(t, err)
   310  
   311  		assert.Equal(t, expected, merged)
   312  	})
   313  
   314  	t.Run("merge map[string]interface{}, patch has nil keys -- /do/ overwrite base with nil (more complex)", func(t *testing.T) {
   315  		m1 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)},
   316  			"base": map[string]*int{"level": newInt(10)}}
   317  		m2 := map[string]interface{}{"this": map[string]*int{"second": nil},
   318  			"base": nil, "patch": map[string]*int{"level": newInt(15)}}
   319  		expected := map[string]interface{}{"this": map[string]*int{"second": nil},
   320  			"base": nil, "patch": map[string]*int{"level": newInt(15)}}
   321  
   322  		merged, err := mergeInterfaceMap(m1, m2)
   323  		require.NoError(t, err)
   324  
   325  		assert.Equal(t, expected, merged)
   326  	})
   327  
   328  	t.Run("merge map[string]map[string]*int, base has nil vals -- overwrite base with patch", func(t *testing.T) {
   329  		m1 := map[string]interface{}{"base": nil}
   330  		m2 := map[string]interface{}{"base": map[string]*int{"level": newInt(10)}}
   331  		expected := map[string]interface{}{"base": map[string]*int{"level": newInt(10)}}
   332  
   333  		merged, err := mergeInterfaceMap(m1, m2)
   334  		require.NoError(t, err)
   335  
   336  		assert.Equal(t, expected, merged)
   337  	})
   338  
   339  	t.Run("merge map[string]map[string]*int, base has nil vals -- overwrite base with patch (more complex)", func(t *testing.T) {
   340  		m1 := map[string]interface{}{"this": map[string]*int{"second": nil}, "base": nil}
   341  		m2 := map[string]interface{}{"this": map[string]*int{"second": newInt(77)},
   342  			"base": map[string]*int{"level": newInt(10)}, "patch": map[string]*int{"level": newInt(15)}}
   343  		expected := map[string]interface{}{"this": map[string]*int{"second": newInt(77)},
   344  			"base": map[string]*int{"level": newInt(10)}, "patch": map[string]*int{"level": newInt(15)}}
   345  
   346  		merged, err := mergeInterfaceMap(m1, m2)
   347  		require.NoError(t, err)
   348  
   349  		assert.Equal(t, expected, merged)
   350  	})
   351  
   352  	t.Run("merge map[string]interface{}, pointers are not copied - changes in base do not affect merged", func(t *testing.T) {
   353  		m1 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)},
   354  			"base": map[string]*int{"level": newInt(10)}, "are belong": map[string]*int{"to us": newInt(23)}}
   355  		m2 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)},
   356  			"base": map[string]*int{"level": newInt(10)}, "are belong": map[string]*int{"to us": newInt(23)}}
   357  		expected := map[string]interface{}{"this": map[string]*int{"second": newInt(99)},
   358  			"base": map[string]*int{"level": newInt(10)}, "are belong": map[string]*int{"to us": newInt(23)}}
   359  
   360  		merged, err := mergeInterfaceMap(m1, m2)
   361  		require.NoError(t, err)
   362  
   363  		assert.Equal(t, expected, merged)
   364  
   365  		// test replacing a referenced map
   366  		m1["this"] = map[string]*int{"third": newInt(777)}
   367  		assert.Equal(t, 99, *merged["this"].(map[string]*int)["second"])
   368  
   369  		// test replacing map entry
   370  		m1["base"].(map[string]*int)["level"] = newInt(12)
   371  		assert.Equal(t, 10, *merged["base"].(map[string]*int)["level"])
   372  
   373  		// test changing the map entry's referenced value
   374  		*m1["are belong"].(map[string]*int)["to us"] = 347
   375  		assert.Equal(t, 23, *merged["are belong"].(map[string]*int)["to us"])
   376  	})
   377  
   378  	t.Run("merge map[string]interface{}, pointers are not copied - change in patch do not affect merged", func(t *testing.T) {
   379  		m1 := map[string]interface{}{"base": map[string]*int{"level": newInt(15)}}
   380  		m2 := map[string]interface{}{"this": map[string]*int{"second": newInt(99)},
   381  			"patch": map[string]*int{"level": newInt(10)}, "are belong": map[string]*int{"to us": newInt(23)}}
   382  		expected := map[string]interface{}{"this": map[string]*int{"second": newInt(99)},
   383  			"patch": map[string]*int{"level": newInt(10)}, "are belong": map[string]*int{"to us": newInt(23)}}
   384  
   385  		merged, err := mergeInterfaceMap(m1, m2)
   386  		require.NoError(t, err)
   387  
   388  		assert.Equal(t, expected, merged)
   389  
   390  		// test replacing a referenced map
   391  		m2["this"] = map[string]*int{"third": newInt(777)}
   392  		assert.Equal(t, 99, *merged["this"].(map[string]*int)["second"])
   393  
   394  		// test replacing map entry
   395  		m2["patch"].(map[string]*int)["level"] = newInt(12)
   396  		assert.Equal(t, 10, *merged["patch"].(map[string]*int)["level"])
   397  
   398  		// test changing the map entry's referenced value
   399  		*m2["are belong"].(map[string]*int)["to us"] = 347
   400  		assert.Equal(t, 23, *merged["are belong"].(map[string]*int)["to us"])
   401  	})
   402  }
   403  
   404  // Test merging slices alone. This isolates the complexity of merging slices from merging slices
   405  // recursively in a struct/ptr/etc.
   406  func TestMergeWithSlices(t *testing.T) {
   407  	t.Run("patch overwrites base slice", func(t *testing.T) {
   408  		m1 := []string{"this", "will", "be", "overwritten"}
   409  		m2 := []string{"this one", "will", "replace the other", "one", "and", "is", "longer"}
   410  		expected := []string{"this one", "will", "replace the other", "one", "and", "is", "longer"}
   411  
   412  		merged, err := mergeStringSlices(m1, m2)
   413  		require.NoError(t, err)
   414  
   415  		assert.Equal(t, expected, merged)
   416  	})
   417  
   418  	t.Run("patch overwrites base even when base is longer", func(t *testing.T) {
   419  		m1 := []string{"this", "will", "be", "overwritten", "but", "not", "this"}
   420  		m2 := []string{"this one", "will", "replace the other", "one"}
   421  		expected := []string{"this one", "will", "replace the other", "one"}
   422  
   423  		merged, err := mergeStringSlices(m1, m2)
   424  		require.NoError(t, err)
   425  
   426  		assert.Equal(t, expected, merged)
   427  	})
   428  
   429  	t.Run("patch overwrites  when base is empty slice", func(t *testing.T) {
   430  		m1 := []string{}
   431  		m2 := []string{"this one", "will", "replace the other", "one"}
   432  		expected := []string{"this one", "will", "replace the other", "one"}
   433  
   434  		merged, err := mergeStringSlices(m1, m2)
   435  		require.NoError(t, err)
   436  
   437  		assert.Equal(t, expected, merged)
   438  	})
   439  
   440  	t.Run("patch overwrites when base is nil", func(t *testing.T) {
   441  		var m1 []string
   442  		m2 := []string{"this one", "will", "replace the other", "one"}
   443  		expected := []string{"this one", "will", "replace the other", "one"}
   444  
   445  		merged, err := mergeStringSlices(m1, m2)
   446  		require.NoError(t, err)
   447  
   448  		assert.Equal(t, expected, merged)
   449  	})
   450  
   451  	t.Run("patch overwites when patch is empty struct", func(t *testing.T) {
   452  		m1 := []string{"this", "will", "be", "overwritten"}
   453  		m2 := []string{}
   454  		expected := []string{}
   455  
   456  		merged, err := mergeStringSlices(m1, m2)
   457  		require.NoError(t, err)
   458  
   459  		assert.Equal(t, expected, merged)
   460  	})
   461  
   462  	t.Run("use base where patch is nil", func(t *testing.T) {
   463  		m1 := []string{"this", "will", "not", "be", "overwritten"}
   464  		var m2 []string
   465  		expected := []string{"this", "will", "not", "be", "overwritten"}
   466  
   467  		merged, err := mergeStringSlices(m1, m2)
   468  		require.NoError(t, err)
   469  
   470  		assert.Equal(t, expected, merged)
   471  	})
   472  
   473  	t.Run("return nil where both are nil", func(t *testing.T) {
   474  		var m1 []string
   475  		var m2 []string
   476  		expected := []string(nil)
   477  
   478  		merged, err := mergeStringSlices(m1, m2)
   479  		require.NoError(t, err)
   480  
   481  		assert.Equal(t, expected, merged)
   482  	})
   483  
   484  	t.Run("return empty struct where both are empty", func(t *testing.T) {
   485  		m1 := []string{}
   486  		m2 := []string{}
   487  		expected := []string{}
   488  
   489  		merged, err := mergeStringSlices(m1, m2)
   490  		require.NoError(t, err)
   491  
   492  		assert.Equal(t, expected, merged)
   493  	})
   494  
   495  	t.Run("patch is nil, slice is not copied. change in base will not affect merged", func(t *testing.T) {
   496  		m1 := []string{"this", "will", "not", "be", "overwritten"}
   497  		var m2 []string
   498  		expected := []string{"this", "will", "not", "be", "overwritten"}
   499  
   500  		merged, err := mergeStringSlices(m1, m2)
   501  		require.NoError(t, err)
   502  
   503  		assert.Equal(t, expected, merged)
   504  		m1[0] = "THAT"
   505  		assert.Equal(t, "this", merged[0])
   506  	})
   507  
   508  	t.Run("patch empty, slice is not copied. change in patch will not affect merged", func(t *testing.T) {
   509  		m1 := []string{"this", "will", "not", "be", "overwritten"}
   510  		m2 := []string{}
   511  		expected := []string{}
   512  
   513  		merged, err := mergeStringSlices(m1, m2)
   514  		require.NoError(t, err)
   515  
   516  		assert.Equal(t, expected, merged)
   517  		// of course this won't change merged, even if it did copy... but just in case.
   518  		m2 = append(m2, "test")
   519  		assert.Len(t, m2, 1)
   520  		assert.Empty(t, merged)
   521  	})
   522  
   523  	t.Run("slice is not copied. change in patch will not affect merged", func(t *testing.T) {
   524  		var m1 []string
   525  		m2 := []string{"this", "will", "not", "be", "overwritten"}
   526  		expected := []string{"this", "will", "not", "be", "overwritten"}
   527  
   528  		merged, err := mergeStringSlices(m1, m2)
   529  		require.NoError(t, err)
   530  
   531  		assert.Equal(t, expected, merged)
   532  		m2[0] = "THAT"
   533  		assert.Equal(t, "this", merged[0])
   534  	})
   535  
   536  	t.Run("base overwritten, slice is not copied. change in patch will not affect merged", func(t *testing.T) {
   537  		m1 := []string{"this", "will", "be", "overwritten"}
   538  		m2 := []string{"that", "overwrote", "it"}
   539  		expected := []string{"that", "overwrote", "it"}
   540  
   541  		merged, err := mergeStringSlices(m1, m2)
   542  		require.NoError(t, err)
   543  
   544  		assert.Equal(t, expected, merged)
   545  		m2[0] = "THAT!!"
   546  		assert.Equal(t, "that", merged[0])
   547  	})
   548  }
   549  
   550  type evenSimpler struct {
   551  	B   *bool
   552  	ES2 *evenSimpler2
   553  }
   554  
   555  func (e *evenSimpler) String() string {
   556  	if e == nil {
   557  		return "nil"
   558  	}
   559  	sb := "nil"
   560  	if e.B != nil {
   561  		sb = fmt.Sprintf("%t", *e.B)
   562  	}
   563  	return fmt.Sprintf("ES{B: %s, ES2: %s}", sb, e.ES2.String())
   564  }
   565  
   566  type evenSimpler2 struct {
   567  	S *string
   568  }
   569  
   570  func (e *evenSimpler2) String() string {
   571  	if e == nil {
   572  		return "nil"
   573  	}
   574  	var s string
   575  	if e.S == nil {
   576  		s = "nil"
   577  	} else {
   578  		s = *e.S
   579  	}
   580  	return fmt.Sprintf("ES2{S: %s}", s)
   581  }
   582  
   583  func TestMergeWithEvenSimpler(t *testing.T) {
   584  	t.Run("evenSimplerStruct: base nils are overwritten by patch", func(t *testing.T) {
   585  		t1 := evenSimpler{newBool(true), &evenSimpler2{nil}}
   586  		t2 := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}}
   587  		expected := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}}
   588  
   589  		merged, err := mergeEvenSimpler(t1, t2)
   590  		require.NoError(t, err)
   591  
   592  		assert.Equal(t, expected, *merged)
   593  	})
   594  
   595  	t.Run("evenSimplerStruct: patch nils are ignored", func(t *testing.T) {
   596  		t1 := evenSimpler{newBool(true), &evenSimpler2{newString("base")}}
   597  		t2 := evenSimpler{nil, &evenSimpler2{nil}}
   598  		expected := evenSimpler{newBool(true), &evenSimpler2{newString("base")}}
   599  
   600  		merged, err := mergeEvenSimpler(t1, t2)
   601  		require.NoError(t, err)
   602  
   603  		assert.Equal(t, expected, *merged)
   604  	})
   605  
   606  	t.Run("evenSimplerStruct: can handle both nils, merged will have nil (not zero value)", func(t *testing.T) {
   607  		t1 := evenSimpler{nil, &evenSimpler2{nil}}
   608  		t2 := evenSimpler{nil, &evenSimpler2{nil}}
   609  		expected := evenSimpler{nil, &evenSimpler2{nil}}
   610  
   611  		merged, err := mergeEvenSimpler(t1, t2)
   612  		require.NoError(t, err)
   613  
   614  		assert.Equal(t, expected, *merged)
   615  	})
   616  
   617  	t.Run("evenSimplerStruct: can handle both nils (ptr to ptr), merged will have nil (not zero value)", func(t *testing.T) {
   618  		t1 := evenSimpler{newBool(true), nil}
   619  		t2 := evenSimpler{newBool(true), nil}
   620  		expected := evenSimpler{newBool(true), nil}
   621  
   622  		merged, err := mergeEvenSimpler(t1, t2)
   623  		require.NoError(t, err)
   624  
   625  		assert.Equal(t, expected, *merged)
   626  	})
   627  
   628  	t.Run("evenSimplerStruct: base nils (ptr to ptr) are overwritten by patch", func(t *testing.T) {
   629  		t1 := evenSimpler{newBool(true), nil}
   630  		t2 := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}}
   631  		expected := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}}
   632  
   633  		merged, err := mergeEvenSimpler(t1, t2)
   634  		require.NoError(t, err)
   635  
   636  		assert.Equal(t, expected, *merged)
   637  	})
   638  
   639  	t.Run("evenSimplerStruct: base nils (ptr to ptr) are overwritten by patch, and not copied - changes in patch don't affect merged", func(t *testing.T) {
   640  		t1 := evenSimpler{newBool(true), nil}
   641  		t2 := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}}
   642  		expected := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}}
   643  
   644  		merged, err := mergeEvenSimpler(t1, t2)
   645  		require.NoError(t, err)
   646  
   647  		assert.Equal(t, expected, *merged)
   648  		*t2.ES2.S = "new patch"
   649  		assert.Equal(t, "patch", *merged.ES2.S)
   650  	})
   651  
   652  	t.Run("evenSimplerStruct: patch nils (ptr to ptr) do not overwrite base, and are not copied - changes in base don't affect merged", func(t *testing.T) {
   653  		t1 := evenSimpler{newBool(true), &evenSimpler2{newString("base")}}
   654  		t2 := evenSimpler{newBool(false), nil}
   655  		expected := evenSimpler{newBool(false), &evenSimpler2{newString("base")}}
   656  
   657  		merged, err := mergeEvenSimpler(t1, t2)
   658  		require.NoError(t, err)
   659  
   660  		assert.Equal(t, expected, *merged)
   661  		*t1.ES2.S = "new base"
   662  		assert.Equal(t, "base", *merged.ES2.S)
   663  	})
   664  
   665  }
   666  
   667  type sliceStruct struct {
   668  	Sls []string
   669  }
   670  
   671  func TestMergeWithSliceStruct(t *testing.T) {
   672  	t.Run("patch nils are ignored - sliceStruct", func(t *testing.T) {
   673  		t1 := sliceStruct{[]string{"this", "is", "base"}}
   674  		t2 := sliceStruct{nil}
   675  		expected := sliceStruct{[]string{"this", "is", "base"}}
   676  
   677  		merged, err := mergeSliceStruct(t1, t2)
   678  		require.NoError(t, err)
   679  
   680  		assert.Equal(t, expected, *merged)
   681  	})
   682  
   683  	t.Run("base nils are overwritten by patch - sliceStruct", func(t *testing.T) {
   684  		t1 := sliceStruct{nil}
   685  		t2 := sliceStruct{[]string{"this", "is", "patch"}}
   686  		expected := sliceStruct{[]string{"this", "is", "patch"}}
   687  
   688  		merged, err := mergeSliceStruct(t1, t2)
   689  		require.NoError(t, err)
   690  
   691  		assert.Equal(t, expected, *merged)
   692  	})
   693  
   694  	t.Run("slices are not being copied or modified", func(t *testing.T) {
   695  		t1 := sliceStruct{[]string{"this", "is", "base"}}
   696  		t2 := sliceStruct{nil}
   697  		expected := sliceStruct{[]string{"this", "is", "base"}}
   698  
   699  		merged, err := mergeSliceStruct(t1, t2)
   700  		require.NoError(t, err)
   701  
   702  		assert.Equal(t, expected, *merged)
   703  
   704  		// changes in base do not affect merged
   705  		t1.Sls[0] = "test0"
   706  		assert.Equal(t, "this", merged.Sls[0])
   707  
   708  		// changes in merged (on slice that was cloned from base) do not affect base
   709  		merged.Sls[1] = "test222"
   710  		assert.Equal(t, "is", t1.Sls[1])
   711  	})
   712  
   713  	t.Run("slices are not being copied or modified", func(t *testing.T) {
   714  		t1 := sliceStruct{nil}
   715  		t2 := sliceStruct{[]string{"this", "is", "patch"}}
   716  		expected := sliceStruct{[]string{"this", "is", "patch"}}
   717  
   718  		merged, err := mergeSliceStruct(t1, t2)
   719  		require.NoError(t, err)
   720  
   721  		assert.Equal(t, expected, *merged)
   722  
   723  		// changes in patch do not affect merged
   724  		t2.Sls[0] = "test0"
   725  		assert.Equal(t, "this", merged.Sls[0])
   726  
   727  		// changes in merged (on slice that was cloned from patch) do not affect patch
   728  		merged.Sls[1] = "test222"
   729  		assert.Equal(t, "is", t2.Sls[1])
   730  	})
   731  }
   732  
   733  type mapPtr struct {
   734  	MP map[string]*evenSimpler2
   735  }
   736  
   737  func TestMergeWithMapPtr(t *testing.T) {
   738  	t.Run("patch nils overwrite - mapPtr - maps overwrite completely", func(t *testing.T) {
   739  		t1 := mapPtr{map[string]*evenSimpler2{"base key": {newString("base")}}}
   740  		t2 := mapPtr{map[string]*evenSimpler2{"base key": {nil}}}
   741  		expected := mapPtr{map[string]*evenSimpler2{"base key": {nil}}}
   742  
   743  		merged, err := mergeMapPtr(t1, t2)
   744  		require.NoError(t, err)
   745  
   746  		assert.Equal(t, expected, *merged)
   747  	})
   748  
   749  	t.Run("patch nil structs are ignored - mapPtr - maps overwrite ", func(t *testing.T) {
   750  		t1 := mapPtr{map[string]*evenSimpler2{"base key": {newString("base")}}}
   751  		t2 := mapPtr{map[string]*evenSimpler2{"base key": nil}}
   752  		expected := mapPtr{map[string]*evenSimpler2{"base key": nil}}
   753  
   754  		merged, err := mergeMapPtr(t1, t2)
   755  		require.NoError(t, err)
   756  
   757  		assert.Equal(t, expected, *merged)
   758  	})
   759  }
   760  
   761  type mapPtrState struct {
   762  	MP map[string]*state
   763  }
   764  type state struct {
   765  	Enable bool
   766  }
   767  
   768  func TestMergeWithMapPtrState(t *testing.T) {
   769  	t.Run("inside structs, patch map overwrites completely - mapPtrState", func(t *testing.T) {
   770  		t1 := mapPtrState{map[string]*state{"base key": {true}}}
   771  		t2 := mapPtrState{map[string]*state{"base key": nil}}
   772  		expected := mapPtrState{map[string]*state{"base key": nil}}
   773  
   774  		merged, err := mergeMapPtrState(t1, t2)
   775  		require.NoError(t, err)
   776  
   777  		assert.Equal(t, expected, *merged)
   778  	})
   779  
   780  	t.Run("merge identical structs - simple", func(t *testing.T) {
   781  		t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true),
   782  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   783  			simple2{30, newString("test"), []string{"test1", "test2"}},
   784  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   785  		t2 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true),
   786  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   787  			simple2{30, newString("test"), []string{"test1", "test2"}},
   788  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   789  		expected := simple{42, 0, nil, newInt(45), newBool(true),
   790  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   791  			simple2{30, newString("test"), []string{"test1", "test2"}},
   792  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   793  
   794  		merged, err := mergeSimple(t1, t2)
   795  		require.NoError(t, err)
   796  
   797  		assert.Equal(t, expected, *merged)
   798  	})
   799  
   800  	t.Run("base nils are overwritten by patch", func(t *testing.T) {
   801  		t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), nil,
   802  			[]int{1, 2, 3}, nil,
   803  			simple2{30, nil, nil},
   804  			nil}
   805  		t2 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true),
   806  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   807  			simple2{30, newString("test"), []string{"test1", "test2"}},
   808  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   809  		expected := simple{42, 0, nil, newInt(45), newBool(true),
   810  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   811  			simple2{30, newString("test"), []string{"test1", "test2"}},
   812  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   813  
   814  		merged, err := mergeSimple(t1, t2)
   815  		require.NoError(t, err)
   816  
   817  		assert.Equal(t, expected, *merged)
   818  	})
   819  }
   820  
   821  type mapPtrState2 struct {
   822  	MP map[string]*state2
   823  }
   824  type state2 struct {
   825  	Enable bool
   826  	EPtr   *bool
   827  }
   828  
   829  func TestMergeWithMapPtrState2(t *testing.T) {
   830  	t.Run("inside structs, maps overwrite completely - mapPtrState2", func(t *testing.T) {
   831  		t1 := mapPtrState2{map[string]*state2{"base key": {true, newBool(true)}}}
   832  		t2 := mapPtrState2{map[string]*state2{"base key": {false, nil}}}
   833  		expected := mapPtrState2{map[string]*state2{"base key": {false, nil}}}
   834  
   835  		merged, err := mergeMapPtrState2(t1, t2)
   836  		require.NoError(t, err)
   837  
   838  		assert.Equal(t, expected, *merged)
   839  	})
   840  
   841  	t.Run("inside structs, maps overwrite completely - mapPtrState2 2", func(t *testing.T) {
   842  		t1 := mapPtrState2{map[string]*state2{"base key": {true, newBool(true)}}} //
   843  		t2 := mapPtrState2{map[string]*state2{"base key": nil}}
   844  		expected := mapPtrState2{map[string]*state2{"base key": nil}}
   845  
   846  		merged, err := mergeMapPtrState2(t1, t2)
   847  		require.NoError(t, err)
   848  
   849  		assert.Equal(t, expected, *merged)
   850  	})
   851  }
   852  
   853  type simple struct {
   854  	I   int
   855  	f   float64
   856  	fp  *float64
   857  	Ip  *int
   858  	B   *bool
   859  	Sli []int
   860  	Msi map[string]int
   861  	S2  simple2
   862  	S3  *simple2
   863  }
   864  
   865  type simple2 struct {
   866  	I   int
   867  	S   *string
   868  	Sls []string
   869  }
   870  
   871  func TestMergeWithSimpleStruct(t *testing.T) {
   872  	t.Run("patch nils are ignored", func(t *testing.T) {
   873  		t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true),
   874  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   875  			simple2{30, newString("test base"), []string{"test1", "test2"}},
   876  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   877  		t2 := simple{42, 42.2, newFloat64(932.2), nil, nil,
   878  			nil, nil,
   879  			simple2{30, nil, nil},
   880  			&simple2{42, nil, nil}}
   881  		expected := simple{42, 0, nil, newInt(45), newBool(true),
   882  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   883  			simple2{30, newString("test base"), []string{"test1", "test2"}},
   884  			&simple2{42, newString("test2"), []string{"test3", "test4", "test5"}}}
   885  
   886  		merged, err := mergeSimple(t1, t2)
   887  		require.NoError(t, err)
   888  
   889  		assert.Equal(t, expected, *merged)
   890  	})
   891  
   892  	t.Run("patch nilled structs are ignored", func(t *testing.T) {
   893  		t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true),
   894  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   895  			simple2{30, newString("test base"), []string{"test1", "test2"}},
   896  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   897  		t2 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true),
   898  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   899  			simple2{30, newString("test base"), []string{"test1", "test2"}},
   900  			nil}
   901  		expected := simple{42, 0, nil, newInt(45), newBool(true),
   902  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   903  			simple2{30, newString("test base"), []string{"test1", "test2"}},
   904  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   905  
   906  		merged, err := mergeSimple(t1, t2)
   907  		require.NoError(t, err)
   908  
   909  		assert.Equal(t, expected, *merged)
   910  	})
   911  
   912  	t.Run("can handle both nils", func(t *testing.T) {
   913  		t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), nil,
   914  			[]int{1, 2, 3}, nil,
   915  			simple2{30, nil, nil},
   916  			nil}
   917  		t2 := simple{42, 42.2, newFloat64(932.2), newInt(45), nil,
   918  			[]int{1, 2, 3}, nil,
   919  			simple2{30, nil, nil},
   920  			nil}
   921  		expected := simple{42, 0, nil, newInt(45), nil,
   922  			[]int{1, 2, 3}, nil,
   923  			simple2{30, nil, nil},
   924  			nil}
   925  
   926  		merged, err := mergeSimple(t1, t2)
   927  		require.NoError(t, err)
   928  
   929  		assert.Equal(t, expected, *merged)
   930  	})
   931  
   932  	t.Run("different base vals are overwritten by patch, and unexported fields are ignored", func(t *testing.T) {
   933  		t1 := simple{42, 42.2, newFloat64(932.2), newInt(45), newBool(true),
   934  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   935  			simple2{30, newString("test"), []string{"test1", "test2"}},
   936  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   937  		t2 := simple{13, 53.1, newFloat64(932.2), newInt(46), newBool(false),
   938  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   939  			simple2{30, newString("testpatch"), []string{"test1", "test99"}},
   940  			&simple2{45, nil, []string{"test3", "test123", "test5"}}}
   941  		expected := simple{13, 0, nil, newInt(46), newBool(false),
   942  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   943  			simple2{30, newString("testpatch"), []string{"test1", "test99"}},
   944  			&simple2{45, newString("test2"), []string{"test3", "test123", "test5"}}}
   945  
   946  		merged, err := mergeSimple(t1, t2)
   947  		require.NoError(t, err)
   948  
   949  		assert.NotEqual(t, t1, *merged)
   950  		assert.Equal(t, expected, *merged)
   951  	})
   952  
   953  	t.Run("pointers are not being copied or modified", func(t *testing.T) {
   954  		t1 := simple{42, 42.2, newFloat64(932.2), newInt(99), newBool(true),
   955  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   956  			simple2{30, newString("test"), []string{"test1", "test2"}},
   957  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   958  		t2 := simple{13, 53.1, newFloat64(932.2), nil, newBool(false),
   959  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   960  			simple2{30, newString("testpatch"), []string{"test1", "test2"}},
   961  			&simple2{45, nil, []string{"test3", "test4", "test5"}}}
   962  		expected := simple{13, 0, nil, newInt(99), newBool(false),
   963  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   964  			simple2{30, newString("testpatch"), []string{"test1", "test2"}},
   965  			&simple2{45, newString("test2"), []string{"test3", "test4", "test5"}}}
   966  
   967  		merged, err := mergeSimple(t1, t2)
   968  		require.NoError(t, err)
   969  
   970  		assert.NotEqual(t, t1, *merged)
   971  		assert.Equal(t, expected, *merged)
   972  
   973  		// changes in originals do not affect merged
   974  		*t1.S3.S = "testBASE"
   975  		assert.Equal(t, "test2", *merged.S3.S)
   976  		*t2.B = true
   977  		assert.Equal(t, false, *merged.B)
   978  
   979  		// changes in base do not affect patched
   980  		*t1.S2.S = "test from base"
   981  		assert.NotEqual(t, *t1.S2.S, *t2.S2.S)
   982  
   983  		// changes in merged (on pointers that were cloned from base or patch) do not affect base or patch
   984  		*merged.Ip = 0
   985  		assert.Equal(t, 99, *t1.Ip)
   986  		*merged.S2.S = "testMERGED"
   987  		assert.NotEqual(t, *t2.S2.S, *merged.S2.S)
   988  	})
   989  
   990  	t.Run("slices are not being copied or modified", func(t *testing.T) {
   991  		t1 := simple{42, 42.2, newFloat64(932.2), newInt(99), newBool(true),
   992  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   993  			simple2{30, newString("test"), []string{"test1", "test2"}},
   994  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
   995  		t2 := simple{13, 53.1, newFloat64(932.2), nil, newBool(false),
   996  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
   997  			simple2{30, newString("testpatch"), nil},
   998  			&simple2{45, nil, []string{"test3", "test4", "test99"}}}
   999  		expected := simple{13, 0, nil, newInt(99), newBool(false),
  1000  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
  1001  			simple2{30, newString("testpatch"), []string{"test1", "test2"}},
  1002  			&simple2{45, newString("test2"), []string{"test3", "test4", "test99"}}}
  1003  
  1004  		merged, err := mergeSimple(t1, t2)
  1005  		require.NoError(t, err)
  1006  
  1007  		assert.NotEqual(t, t1, *merged)
  1008  		assert.Equal(t, expected, *merged)
  1009  
  1010  		// changes in base do not affect merged
  1011  		t1.S2.Sls[0] = "test0"
  1012  		assert.Equal(t, "test1", merged.S2.Sls[0])
  1013  
  1014  		// changes in patch do not affect merged
  1015  		t2.S3.Sls[0] = "test0"
  1016  		assert.Equal(t, "test3", merged.S3.Sls[0])
  1017  
  1018  		// changes in merged (on slice that was cloned from base) do not affect base
  1019  		merged.S2.Sls[1] = "test222"
  1020  		assert.Equal(t, "test2", t1.S2.Sls[1])
  1021  	})
  1022  
  1023  	t.Run("maps are not being copied or modified: base -> merged", func(t *testing.T) {
  1024  		t1 := simple{42, 42.2, newFloat64(932.2), newInt(99), newBool(true),
  1025  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
  1026  			simple2{30, newString("test"), []string{"test1", "test2"}},
  1027  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
  1028  		t2 := simple{13, 53.1, newFloat64(932.2), nil, newBool(false),
  1029  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
  1030  			simple2{30, newString("testpatch"), []string{"test1", "test2"}},
  1031  			&simple2{45, nil, []string{"test3", "test4", "test99"}}}
  1032  		expected := simple{13, 0, nil, newInt(99), newBool(false),
  1033  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2},
  1034  			simple2{30, newString("testpatch"), []string{"test1", "test2"}},
  1035  			&simple2{45, newString("test2"), []string{"test3", "test4", "test99"}}}
  1036  
  1037  		merged, err := mergeSimple(t1, t2)
  1038  		require.NoError(t, err)
  1039  
  1040  		assert.NotEqual(t, t1, *merged)
  1041  		assert.Equal(t, expected, *merged)
  1042  
  1043  		// changes in originals do not affect merged
  1044  		t1.Msi["key1"] = 3
  1045  		assert.Equal(t, 1, merged.Msi["key1"])
  1046  		t2.Msi["key5"] = 5
  1047  		_, ok := merged.Msi["key5"]
  1048  		assert.False(t, ok)
  1049  	})
  1050  
  1051  	t.Run("patch map overwrites", func(t *testing.T) {
  1052  		t1 := simple{42, 42.2, newFloat64(932.2), newInt(99), newBool(true),
  1053  			[]int{1, 2, 3}, map[string]int{"key1": 1, "key2": 2, "key4": 4},
  1054  			simple2{30, newString("test"), []string{"test1", "test2"}},
  1055  			&simple2{40, newString("test2"), []string{"test3", "test4", "test5"}}}
  1056  		t2 := simple{13, 53.1, newFloat64(932.2), nil, newBool(false),
  1057  			[]int{1, 2, 3}, map[string]int{"key1": 11, "key2": 2, "key3": 3},
  1058  			simple2{30, newString("testpatch"), []string{"test1", "test2"}},
  1059  			&simple2{45, nil, []string{"test3", "test4", "test99"}}}
  1060  		expected := simple{13, 0, nil, newInt(99), newBool(false),
  1061  			[]int{1, 2, 3}, map[string]int{"key1": 11, "key2": 2, "key3": 3},
  1062  			simple2{30, newString("testpatch"), []string{"test1", "test2"}},
  1063  			&simple2{45, newString("test2"), []string{"test3", "test4", "test99"}}}
  1064  
  1065  		merged, err := mergeSimple(t1, t2)
  1066  		require.NoError(t, err)
  1067  
  1068  		assert.Equal(t, expected, *merged)
  1069  	})
  1070  }
  1071  
  1072  // The following are tests to see if multiply nested structs/maps/slice and pointers to structs/maps/slices
  1073  // will merge. Probably overkill, but if anything goes wrong here, it is best to isolate the problem and
  1074  // make a simplified test (like many of the above tests).
  1075  func TestMergeWithVeryComplexStruct(t *testing.T) {
  1076  	t.Run("merge identical structs", func(t *testing.T) {
  1077  		setupStructs(t)
  1078  
  1079  		merged, err := mergeTestStructs(base, patch)
  1080  		require.NoError(t, err)
  1081  
  1082  		assert.Equal(t, expectedMerged, *merged)
  1083  	})
  1084  
  1085  	t.Run("merge identical structs as pointers", func(t *testing.T) {
  1086  		setupStructs(t)
  1087  
  1088  		merged, err := mergeTestStructsPtrs(&base, &patch)
  1089  		require.NoError(t, err)
  1090  
  1091  		assert.Equal(t, expectedMerged, *merged)
  1092  	})
  1093  
  1094  	t.Run("different base vals are overwritten by patch", func(t *testing.T) {
  1095  		setupStructs(t)
  1096  
  1097  		base.F = 1342.12
  1098  		base.Struct1.Pi = newInt(937)
  1099  		base.Struct1p.Ui = 734
  1100  		base.Struct1.Struct2.Sli = []int{123123, 1243123}
  1101  
  1102  		merged, err := mergeTestStructs(base, patch)
  1103  		require.NoError(t, err)
  1104  
  1105  		assert.NotEqual(t, base, *merged)
  1106  		assert.Equal(t, patch, *merged)
  1107  	})
  1108  
  1109  	t.Run("nil values in patch are ignored", func(t *testing.T) {
  1110  		setupStructs(t)
  1111  
  1112  		patch.Pi = nil
  1113  		patch.Struct1.Pi16 = nil
  1114  
  1115  		merged, err := mergeTestStructs(base, patch)
  1116  		require.NoError(t, err)
  1117  
  1118  		assert.NotEqual(t, patch, *merged)
  1119  		assert.Equal(t, expectedMerged, *merged)
  1120  	})
  1121  
  1122  	t.Run("nil structs in patch are ignored", func(t *testing.T) {
  1123  		setupStructs(t)
  1124  
  1125  		patch.Struct1p = nil
  1126  		patch.Struct1.Struct2p = nil
  1127  
  1128  		merged, err := mergeTestStructs(base, patch)
  1129  		require.NoError(t, err)
  1130  
  1131  		assert.NotEqual(t, patch, *merged)
  1132  		assert.Equal(t, expectedMerged, *merged)
  1133  	})
  1134  
  1135  	t.Run("nil slices in patch are ignored", func(t *testing.T) {
  1136  		setupStructs(t)
  1137  
  1138  		patch.Sls = nil
  1139  		patch.Struct1.Sli = nil
  1140  		patch.Struct1.Struct2p.Slf = nil
  1141  
  1142  		merged, err := mergeTestStructs(base, patch)
  1143  		require.NoError(t, err)
  1144  
  1145  		assert.NotEqual(t, patch, *merged)
  1146  		assert.Equal(t, expectedMerged, *merged)
  1147  	})
  1148  
  1149  	t.Run("nil maps in patch are ignored", func(t *testing.T) {
  1150  		setupStructs(t)
  1151  
  1152  		patch.Msi = nil
  1153  		patch.Mspi = nil
  1154  		patch.Struct1.Mis = nil
  1155  		patch.Struct1.Struct2p.Mspi = nil
  1156  
  1157  		merged, err := mergeTestStructs(base, patch)
  1158  		require.NoError(t, err)
  1159  
  1160  		assert.NotEqual(t, patch, *merged)
  1161  		assert.Equal(t, expectedMerged, *merged)
  1162  	})
  1163  }
  1164  
  1165  func TestMergeWithStructFieldFilter(t *testing.T) {
  1166  	t.Run("filter skips merging from patch", func(t *testing.T) {
  1167  		t1 := evenSimpler{newBool(true), &evenSimpler2{newString("base")}}
  1168  		t2 := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}}
  1169  		expected := evenSimpler{newBool(true), &evenSimpler2{newString("base")}}
  1170  
  1171  		merged, err := mergeEvenSimplerWithConfig(t1, t2, &utils.MergeConfig{
  1172  			StructFieldFilter: func(structField reflect.StructField, base, patch reflect.Value) bool {
  1173  				return false
  1174  			},
  1175  		})
  1176  		require.NoError(t, err)
  1177  
  1178  		assert.Equal(t, expected, *merged)
  1179  	})
  1180  
  1181  	t.Run("filter skips merging configured fields from patch", func(t *testing.T) {
  1182  		t1 := evenSimpler{newBool(true), &evenSimpler2{newString("base")}}
  1183  		t2 := evenSimpler{newBool(false), &evenSimpler2{newString("patch")}}
  1184  		expected := evenSimpler{newBool(false), &evenSimpler2{newString("base")}}
  1185  
  1186  		merged, err := mergeEvenSimplerWithConfig(t1, t2, &utils.MergeConfig{
  1187  			StructFieldFilter: func(structField reflect.StructField, base, patch reflect.Value) bool {
  1188  				return structField.Name == "B"
  1189  			},
  1190  		})
  1191  		require.NoError(t, err)
  1192  
  1193  		assert.Equal(t, expected, *merged)
  1194  	})
  1195  }
  1196  
  1197  type testStruct struct {
  1198  	I        int
  1199  	I8       int8
  1200  	I16      int16
  1201  	I32      int32
  1202  	I64      int64
  1203  	F        float64
  1204  	F32      float32
  1205  	S        string
  1206  	Ui       uint
  1207  	Ui8      uint8
  1208  	Ui16     uint32
  1209  	Ui32     uint32
  1210  	Ui64     uint64
  1211  	Pi       *int
  1212  	Pi8      *int8
  1213  	Pi16     *int16
  1214  	Pi32     *int32
  1215  	Pi64     *int64
  1216  	Pf       *float64
  1217  	Pf32     *float32
  1218  	Ps       *string
  1219  	Pui      *uint
  1220  	Pui8     *uint8
  1221  	Pui16    *uint16
  1222  	Pui32    *uint32
  1223  	Pui64    *uint64
  1224  	Sls      []string
  1225  	Sli      []int
  1226  	Slf      []float64
  1227  	Msi      map[string]int
  1228  	Mis      map[int]string
  1229  	Mspi     map[string]*int
  1230  	Mips     map[int]*string
  1231  	Struct1  testStructEmbed
  1232  	Struct1p *testStructEmbed
  1233  }
  1234  
  1235  type testStructEmbed struct {
  1236  	I        int
  1237  	I8       int8
  1238  	I16      int16
  1239  	I32      int32
  1240  	I64      int64
  1241  	F        float64
  1242  	F32      float32
  1243  	S        string
  1244  	Ui       uint
  1245  	Ui8      uint8
  1246  	Ui16     uint32
  1247  	Ui32     uint32
  1248  	Ui64     uint64
  1249  	Pi       *int
  1250  	Pi8      *int8
  1251  	Pi16     *int16
  1252  	Pi32     *int32
  1253  	Pi64     *int64
  1254  	Pf       *float64
  1255  	Pf32     *float32
  1256  	Ps       *string
  1257  	Pui      *uint
  1258  	Pui8     *uint8
  1259  	Pui16    *uint16
  1260  	Pui32    *uint32
  1261  	Pui64    *uint64
  1262  	Sls      []string
  1263  	Sli      []int
  1264  	Slf      []float64
  1265  	Msi      map[string]int
  1266  	Mis      map[int]string
  1267  	Mspi     map[string]*int
  1268  	Mips     map[int]*string
  1269  	Struct2  testStructEmbed2
  1270  	Struct2p *testStructEmbed2
  1271  }
  1272  
  1273  type testStructEmbed2 struct {
  1274  	I     int
  1275  	I8    int8
  1276  	I16   int16
  1277  	I32   int32
  1278  	I64   int64
  1279  	F     float64
  1280  	F32   float32
  1281  	S     string
  1282  	Ui    uint
  1283  	Ui8   uint8
  1284  	Ui16  uint32
  1285  	Ui32  uint32
  1286  	Ui64  uint64
  1287  	Pi    *int
  1288  	Pi8   *int8
  1289  	Pi16  *int16
  1290  	Pi32  *int32
  1291  	Pi64  *int64
  1292  	Pf    *float64
  1293  	Pf32  *float32
  1294  	Ps    *string
  1295  	Pui   *uint
  1296  	Pui8  *uint8
  1297  	Pui16 *uint16
  1298  	Pui32 *uint32
  1299  	Pui64 *uint64
  1300  	Sls   []string
  1301  	Sli   []int
  1302  	Slf   []float64
  1303  	Msi   map[string]int
  1304  	Mis   map[int]string
  1305  	Mspi  map[string]*int
  1306  	Mips  map[int]*string
  1307  }
  1308  
  1309  // the base structs
  1310  var baseStructEmbed2A, baseStructEmbed2B, baseStructEmbed2C, baseStructEmbed2D testStructEmbed2
  1311  var baseStructEmbedBaseA, baseStructEmbedBaseB testStructEmbed
  1312  var base testStruct
  1313  
  1314  // the patch structs
  1315  var patchStructEmbed2A, patchStructEmbed2B, patchStructEmbed2C, patchStructEmbed2D testStructEmbed2
  1316  var patchStructEmbedBaseA, patchStructEmbedBaseB testStructEmbed
  1317  var patch testStruct
  1318  
  1319  // The merged structs
  1320  var mergeStructEmbed2A, mergeStructEmbed2B, mergeStructEmbed2C, mergeStructEmbed2D testStructEmbed2
  1321  var mergeStructEmbedBaseA, mergeStructEmbedBaseB testStructEmbed
  1322  var expectedMerged testStruct
  1323  
  1324  func setupStructs(t *testing.T) {
  1325  	t.Helper()
  1326  
  1327  	baseStructEmbed2A = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1328  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1329  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1330  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1331  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1332  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1333  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1334  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1335  	}
  1336  
  1337  	baseStructEmbed2B = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1338  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1339  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1340  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1341  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1342  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1343  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1344  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1345  	}
  1346  
  1347  	baseStructEmbed2C = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1348  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1349  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1350  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1351  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1352  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1353  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1354  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1355  	}
  1356  
  1357  	baseStructEmbed2D = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1358  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1359  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1360  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1361  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1362  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1363  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1364  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1365  	}
  1366  
  1367  	baseStructEmbedBaseA = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1368  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1369  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1370  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1371  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1372  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1373  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1374  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1375  		baseStructEmbed2A, &baseStructEmbed2B,
  1376  	}
  1377  
  1378  	baseStructEmbedBaseB = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1379  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1380  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1381  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1382  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1383  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1384  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1385  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1386  		baseStructEmbed2C, &baseStructEmbed2D,
  1387  	}
  1388  
  1389  	base = testStruct{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1390  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1391  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1392  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1393  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1394  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1395  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1396  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1397  		baseStructEmbedBaseA, &baseStructEmbedBaseB,
  1398  	}
  1399  
  1400  	patchStructEmbed2A = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1401  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1402  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1403  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1404  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1405  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1406  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1407  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1408  	}
  1409  
  1410  	patchStructEmbed2B = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1411  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1412  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1413  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1414  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1415  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1416  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1417  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1418  	}
  1419  
  1420  	patchStructEmbed2C = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1421  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1422  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1423  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1424  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1425  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1426  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1427  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1428  	}
  1429  
  1430  	patchStructEmbed2D = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1431  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1432  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1433  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1434  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1435  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1436  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1437  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1438  	}
  1439  
  1440  	patchStructEmbedBaseA = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1441  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1442  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1443  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1444  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1445  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1446  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1447  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1448  		patchStructEmbed2A, &patchStructEmbed2B,
  1449  	}
  1450  
  1451  	patchStructEmbedBaseB = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1452  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1453  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1454  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1455  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1456  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1457  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1458  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1459  		patchStructEmbed2C, &patchStructEmbed2D,
  1460  	}
  1461  
  1462  	patch = testStruct{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1463  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1464  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1465  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1466  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1467  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1468  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1469  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1470  		patchStructEmbedBaseA, &patchStructEmbedBaseB,
  1471  	}
  1472  
  1473  	mergeStructEmbed2A = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1474  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1475  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1476  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1477  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1478  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1479  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1480  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1481  	}
  1482  
  1483  	mergeStructEmbed2B = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1484  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1485  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1486  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1487  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1488  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1489  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1490  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1491  	}
  1492  
  1493  	mergeStructEmbed2C = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1494  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1495  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1496  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1497  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1498  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1499  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1500  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1501  	}
  1502  
  1503  	mergeStructEmbed2D = testStructEmbed2{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1504  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1505  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1506  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1507  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1508  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1509  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1510  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1511  	}
  1512  
  1513  	mergeStructEmbedBaseA = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1514  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1515  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1516  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1517  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1518  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1519  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1520  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1521  		mergeStructEmbed2A, &mergeStructEmbed2B,
  1522  	}
  1523  
  1524  	mergeStructEmbedBaseB = testStructEmbed{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1525  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1526  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1527  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1528  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1529  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1530  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1531  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1532  		mergeStructEmbed2C, &mergeStructEmbed2D,
  1533  	}
  1534  
  1535  	expectedMerged = testStruct{1, 2, 3, 4, 5, 1.1, 2.2, "test", 10, 11, 12, 12, 13,
  1536  		newInt(14), newInt8(15), newInt16(16), newInt32(17), newInt64(18),
  1537  		newFloat64(19.9), newFloat32(20.1), newString("test pointer"),
  1538  		newUint(21), newUint8(22), newUint16(23), newUint32(24), newUint64(25),
  1539  		[]string{"test", "slice", "strings"}, []int{1, 2, 3, 4}, []float64{1.1, 2.2, 3.3},
  1540  		map[string]int{"this": 1, "is": 2, "a": 3, "map": 4}, map[int]string{1: "this", 2: "is", 3: "another"},
  1541  		map[string]*int{"wow": newInt(1), "a map": newInt(2), "of pointers!": newInt(3)},
  1542  		map[int]*string{1: newString("Another"), 2: newString("map of"), 3: newString("pointers, wow!")},
  1543  		mergeStructEmbedBaseA, &mergeStructEmbedBaseB,
  1544  	}
  1545  }
  1546  
  1547  func mergeSimple(base, patch simple) (*simple, error) {
  1548  	ret, err := utils.Merge(base, patch, nil)
  1549  	if err != nil {
  1550  		return nil, err
  1551  	}
  1552  	retS := ret.(simple)
  1553  	return &retS, nil
  1554  }
  1555  
  1556  func mergeEvenSimpler(base, patch evenSimpler) (*evenSimpler, error) {
  1557  	ret, err := utils.Merge(base, patch, nil)
  1558  	if err != nil {
  1559  		return nil, err
  1560  	}
  1561  	retTS := ret.(evenSimpler)
  1562  	return &retTS, nil
  1563  }
  1564  
  1565  func mergeEvenSimplerWithConfig(base, patch evenSimpler, mergeConfig *utils.MergeConfig) (*evenSimpler, error) {
  1566  	ret, err := utils.Merge(base, patch, mergeConfig)
  1567  	if err != nil {
  1568  		return nil, err
  1569  	}
  1570  	retTS := ret.(evenSimpler)
  1571  	return &retTS, nil
  1572  }
  1573  
  1574  func mergeSliceStruct(base, patch sliceStruct) (*sliceStruct, error) {
  1575  	ret, err := utils.Merge(base, patch, nil)
  1576  	if err != nil {
  1577  		return nil, err
  1578  	}
  1579  	retTS := ret.(sliceStruct)
  1580  	return &retTS, nil
  1581  }
  1582  
  1583  func mergeMapPtr(base, patch mapPtr) (*mapPtr, error) {
  1584  	ret, err := utils.Merge(base, patch, nil)
  1585  	if err != nil {
  1586  		return nil, err
  1587  	}
  1588  	retTS := ret.(mapPtr)
  1589  	return &retTS, nil
  1590  }
  1591  
  1592  func mergeMapPtrState(base, patch mapPtrState) (*mapPtrState, error) {
  1593  	ret, err := utils.Merge(base, patch, nil)
  1594  	if err != nil {
  1595  		return nil, err
  1596  	}
  1597  	retTS := ret.(mapPtrState)
  1598  	return &retTS, nil
  1599  }
  1600  
  1601  func mergeMapPtrState2(base, patch mapPtrState2) (*mapPtrState2, error) {
  1602  	ret, err := utils.Merge(base, patch, nil)
  1603  	if err != nil {
  1604  		return nil, err
  1605  	}
  1606  	retTS := ret.(mapPtrState2)
  1607  	return &retTS, nil
  1608  }
  1609  
  1610  func mergeTestStructs(base, patch testStruct) (*testStruct, error) {
  1611  	ret, err := utils.Merge(base, patch, nil)
  1612  	if err != nil {
  1613  		return nil, err
  1614  	}
  1615  	retTS := ret.(testStruct)
  1616  	return &retTS, nil
  1617  }
  1618  
  1619  func mergeStringIntMap(base, patch map[string]int) (map[string]int, error) {
  1620  	ret, err := utils.Merge(base, patch, nil)
  1621  	if err != nil {
  1622  		return nil, err
  1623  	}
  1624  	retTS := ret.(map[string]int)
  1625  	return retTS, nil
  1626  }
  1627  
  1628  func mergeStringPtrIntMap(base, patch map[string]*int) (map[string]*int, error) {
  1629  	ret, err := utils.Merge(base, patch, nil)
  1630  	if err != nil {
  1631  		return nil, err
  1632  	}
  1633  	retTS := ret.(map[string]*int)
  1634  	return retTS, nil
  1635  }
  1636  
  1637  func mergeStringSliceIntMap(base, patch map[string][]int) (map[string][]int, error) {
  1638  	ret, err := utils.Merge(base, patch, nil)
  1639  	if err != nil {
  1640  		return nil, err
  1641  	}
  1642  	retTS := ret.(map[string][]int)
  1643  	return retTS, nil
  1644  }
  1645  
  1646  func mergeMapOfMap(base, patch map[string]map[string]*int) (map[string]map[string]*int, error) {
  1647  	ret, err := utils.Merge(base, patch, nil)
  1648  	if err != nil {
  1649  		return nil, err
  1650  	}
  1651  	retTS := ret.(map[string]map[string]*int)
  1652  	return retTS, nil
  1653  }
  1654  
  1655  func mergeInterfaceMap(base, patch map[string]interface{}) (map[string]interface{}, error) {
  1656  	ret, err := utils.Merge(base, patch, nil)
  1657  	if err != nil {
  1658  		return nil, err
  1659  	}
  1660  	retTS := ret.(map[string]interface{})
  1661  	return retTS, nil
  1662  }
  1663  
  1664  func mergeStringSlices(base, patch []string) ([]string, error) {
  1665  	ret, err := utils.Merge(base, patch, nil)
  1666  	if err != nil {
  1667  		return nil, err
  1668  	}
  1669  	retTS := ret.([]string)
  1670  	return retTS, nil
  1671  }
  1672  
  1673  func mergeTestStructsPtrs(base, patch *testStruct) (*testStruct, error) {
  1674  	ret, err := utils.Merge(base, patch, nil)
  1675  	if err != nil {
  1676  		return nil, err
  1677  	}
  1678  	retTS := ret.(testStruct)
  1679  	return &retTS, nil
  1680  }
  1681  
  1682  func newBool(b bool) *bool          { return &b }
  1683  func newInt(n int) *int             { return &n }
  1684  func newInt64(n int64) *int64       { return &n }
  1685  func newString(s string) *string    { return &s }
  1686  func newInt8(n int8) *int8          { return &n }
  1687  func newInt16(n int16) *int16       { return &n }
  1688  func newInt32(n int32) *int32       { return &n }
  1689  func newFloat64(f float64) *float64 { return &f }
  1690  func newFloat32(f float32) *float32 { return &f }
  1691  func newUint(n uint) *uint          { return &n }
  1692  func newUint8(n uint8) *uint8       { return &n }
  1693  func newUint16(n uint16) *uint16    { return &n }
  1694  func newUint32(n uint32) *uint32    { return &n }
  1695  func newUint64(n uint64) *uint64    { return &n }