1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2// See LICENSE.txt for license information.
3
4package utils_test
5
6import (
7	"fmt"
8	"reflect"
9	"testing"
10
11	"github.com/stretchr/testify/assert"
12	"github.com/stretchr/testify/require"
13
14	"github.com/mattermost/mattermost-server/v6/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.
20func 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.
406func 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
550type evenSimpler struct {
551	B   *bool
552	ES2 *evenSimpler2
553}
554
555func (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
566type evenSimpler2 struct {
567	S *string
568}
569
570func (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
583func 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
667type sliceStruct struct {
668	Sls []string
669}
670
671func 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
733type mapPtr struct {
734	MP map[string]*evenSimpler2
735}
736
737func 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
761type mapPtrState struct {
762	MP map[string]*state
763}
764type state struct {
765	Enable bool
766}
767
768func 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
821type mapPtrState2 struct {
822	MP map[string]*state2
823}
824type state2 struct {
825	Enable bool
826	EPtr   *bool
827}
828
829func 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
853type 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
865type simple2 struct {
866	I   int
867	S   *string
868	Sls []string
869}
870
871func 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).
1075func 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
1165func 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
1197type 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
1235type 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
1273type 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
1310var baseStructEmbed2A, baseStructEmbed2B, baseStructEmbed2C, baseStructEmbed2D testStructEmbed2
1311var baseStructEmbedBaseA, baseStructEmbedBaseB testStructEmbed
1312var base testStruct
1313
1314// the patch structs
1315var patchStructEmbed2A, patchStructEmbed2B, patchStructEmbed2C, patchStructEmbed2D testStructEmbed2
1316var patchStructEmbedBaseA, patchStructEmbedBaseB testStructEmbed
1317var patch testStruct
1318
1319// The merged structs
1320var mergeStructEmbed2A, mergeStructEmbed2B, mergeStructEmbed2C, mergeStructEmbed2D testStructEmbed2
1321var mergeStructEmbedBaseA, mergeStructEmbedBaseB testStructEmbed
1322var expectedMerged testStruct
1323
1324func 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
1547func 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
1556func 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
1565func 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
1574func 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
1583func 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
1592func 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
1601func 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
1610func 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
1619func 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
1628func 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
1637func 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
1646func 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
1655func 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
1664func 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
1673func 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
1682func newBool(b bool) *bool          { return &b }
1683func newInt(n int) *int             { return &n }
1684func newInt64(n int64) *int64       { return &n }
1685func newString(s string) *string    { return &s }
1686func newInt8(n int8) *int8          { return &n }
1687func newInt16(n int16) *int16       { return &n }
1688func newInt32(n int32) *int32       { return &n }
1689func newFloat64(f float64) *float64 { return &f }
1690func newFloat32(f float32) *float32 { return &f }
1691func newUint(n uint) *uint          { return &n }
1692func newUint8(n uint8) *uint8       { return &n }
1693func newUint16(n uint16) *uint16    { return &n }
1694func newUint32(n uint32) *uint32    { return &n }
1695func newUint64(n uint64) *uint64    { return &n }
1696