github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/utils/merge_test.go (about)

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