1// Copyright 2013 Dario Castañé. All rights reserved.
2// Copyright 2009 The Go Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6package mergo
7
8import (
9	"io/ioutil"
10	"reflect"
11	"testing"
12	"time"
13
14	"gopkg.in/yaml.v2"
15)
16
17type simpleTest struct {
18	Value int
19}
20
21type complexTest struct {
22	St simpleTest
23	sz int
24	ID string
25}
26
27type mapTest struct {
28	M map[int]int
29}
30
31type ifcTest struct {
32	I interface{}
33}
34
35type moreComplextText struct {
36	Ct complexTest
37	St simpleTest
38	Nt simpleTest
39}
40
41type pointerTest struct {
42	C *simpleTest
43}
44
45type sliceTest struct {
46	S []int
47}
48
49func TestKb(t *testing.T) {
50	type testStruct struct {
51		Name     string
52		KeyValue map[string]interface{}
53	}
54
55	akv := make(map[string]interface{})
56	akv["Key1"] = "not value 1"
57	akv["Key2"] = "value2"
58	a := testStruct{}
59	a.Name = "A"
60	a.KeyValue = akv
61
62	bkv := make(map[string]interface{})
63	bkv["Key1"] = "value1"
64	bkv["Key3"] = "value3"
65	b := testStruct{}
66	b.Name = "B"
67	b.KeyValue = bkv
68
69	ekv := make(map[string]interface{})
70	ekv["Key1"] = "value1"
71	ekv["Key2"] = "value2"
72	ekv["Key3"] = "value3"
73	expected := testStruct{}
74	expected.Name = "B"
75	expected.KeyValue = ekv
76
77	Merge(&b, a)
78
79	if !reflect.DeepEqual(b, expected) {
80		t.Errorf("Actual: %#v did not match \nExpected: %#v", b, expected)
81	}
82}
83
84func TestNil(t *testing.T) {
85	if err := Merge(nil, nil); err != ErrNilArguments {
86		t.Fail()
87	}
88}
89
90func TestDifferentTypes(t *testing.T) {
91	a := simpleTest{42}
92	b := 42
93	if err := Merge(&a, b); err != ErrDifferentArgumentsTypes {
94		t.Fail()
95	}
96}
97
98func TestSimpleStruct(t *testing.T) {
99	a := simpleTest{}
100	b := simpleTest{42}
101	if err := Merge(&a, b); err != nil {
102		t.FailNow()
103	}
104	if a.Value != 42 {
105		t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%d)", a.Value, b.Value)
106	}
107	if !reflect.DeepEqual(a, b) {
108		t.FailNow()
109	}
110}
111
112func TestComplexStruct(t *testing.T) {
113	a := complexTest{}
114	a.ID = "athing"
115	b := complexTest{simpleTest{42}, 1, "bthing"}
116	if err := Merge(&a, b); err != nil {
117		t.FailNow()
118	}
119	if a.St.Value != 42 {
120		t.Fatalf("b not merged in properly: a.St.Value(%d) != b.St.Value(%d)", a.St.Value, b.St.Value)
121	}
122	if a.sz == 1 {
123		t.Fatalf("a's private field sz not preserved from merge: a.sz(%d) == b.sz(%d)", a.sz, b.sz)
124	}
125	if a.ID == b.ID {
126		t.Fatalf("a's field ID merged unexpectedly: a.ID(%s) == b.ID(%s)", a.ID, b.ID)
127	}
128}
129
130func TestComplexStructWithOverwrite(t *testing.T) {
131	a := complexTest{simpleTest{1}, 1, "do-not-overwrite-with-empty-value"}
132	b := complexTest{simpleTest{42}, 2, ""}
133
134	expect := complexTest{simpleTest{42}, 1, "do-not-overwrite-with-empty-value"}
135	if err := MergeWithOverwrite(&a, b); err != nil {
136		t.FailNow()
137	}
138
139	if !reflect.DeepEqual(a, expect) {
140		t.Fatalf("Test failed:\ngot  :\n%#v\n\nwant :\n%#v\n\n", a, expect)
141	}
142}
143
144func TestPointerStruct(t *testing.T) {
145	s1 := simpleTest{}
146	s2 := simpleTest{19}
147	a := pointerTest{&s1}
148	b := pointerTest{&s2}
149	if err := Merge(&a, b); err != nil {
150		t.FailNow()
151	}
152	if a.C.Value != b.C.Value {
153		t.Fatalf("b not merged in properly: a.C.Value(%d) != b.C.Value(%d)", a.C.Value, b.C.Value)
154	}
155}
156
157type embeddingStruct struct {
158	embeddedStruct
159}
160
161type embeddedStruct struct {
162	A string
163}
164
165func TestEmbeddedStruct(t *testing.T) {
166	tests := []struct {
167		src      embeddingStruct
168		dst      embeddingStruct
169		expected embeddingStruct
170	}{
171		{
172			src: embeddingStruct{
173				embeddedStruct{"foo"},
174			},
175			dst: embeddingStruct{
176				embeddedStruct{""},
177			},
178			expected: embeddingStruct{
179				embeddedStruct{"foo"},
180			},
181		},
182		{
183			src: embeddingStruct{
184				embeddedStruct{""},
185			},
186			dst: embeddingStruct{
187				embeddedStruct{"bar"},
188			},
189			expected: embeddingStruct{
190				embeddedStruct{"bar"},
191			},
192		},
193		{
194			src: embeddingStruct{
195				embeddedStruct{"foo"},
196			},
197			dst: embeddingStruct{
198				embeddedStruct{"bar"},
199			},
200			expected: embeddingStruct{
201				embeddedStruct{"bar"},
202			},
203		},
204	}
205
206	for _, test := range tests {
207		err := Merge(&test.dst, test.src)
208		if err != nil {
209			t.Errorf("unexpected error: %v", err)
210			continue
211		}
212		if !reflect.DeepEqual(test.dst, test.expected) {
213			t.Errorf("unexpected output\nexpected:\n%+v\nsaw:\n%+v\n", test.expected, test.dst)
214		}
215	}
216}
217
218func TestPointerStructNil(t *testing.T) {
219	a := pointerTest{nil}
220	b := pointerTest{&simpleTest{19}}
221	if err := Merge(&a, b); err != nil {
222		t.FailNow()
223	}
224	if a.C.Value != b.C.Value {
225		t.Fatalf("b not merged in a properly: a.C.Value(%d) != b.C.Value(%d)", a.C.Value, b.C.Value)
226	}
227}
228
229func testSlice(t *testing.T, a []int, b []int, e []int, opts ...func(*Config)) {
230	t.Helper()
231	bc := b
232
233	sa := sliceTest{a}
234	sb := sliceTest{b}
235	if err := Merge(&sa, sb, opts...); err != nil {
236		t.FailNow()
237	}
238	if !reflect.DeepEqual(sb.S, bc) {
239		t.Fatalf("Source slice was modified %d != %d", sb.S, bc)
240	}
241	if !reflect.DeepEqual(sa.S, e) {
242		t.Fatalf("b not merged in a proper way %d != %d", sa.S, e)
243	}
244
245	ma := map[string][]int{"S": a}
246	mb := map[string][]int{"S": b}
247	if err := Merge(&ma, mb, opts...); err != nil {
248		t.FailNow()
249	}
250	if !reflect.DeepEqual(mb["S"], bc) {
251		t.Fatalf("map value: Source slice was modified %d != %d", mb["S"], bc)
252	}
253	if !reflect.DeepEqual(ma["S"], e) {
254		t.Fatalf("map value: b not merged in a proper way %d != %d", ma["S"], e)
255	}
256
257	if a == nil {
258		// test case with missing dst key
259		ma := map[string][]int{}
260		mb := map[string][]int{"S": b}
261		if err := Merge(&ma, mb); err != nil {
262			t.FailNow()
263		}
264		if !reflect.DeepEqual(mb["S"], bc) {
265			t.Fatalf("missing dst key: Source slice was modified %d != %d", mb["S"], bc)
266		}
267		if !reflect.DeepEqual(ma["S"], e) {
268			t.Fatalf("missing dst key: b not merged in a proper way %d != %d", ma["S"], e)
269		}
270	}
271
272	if b == nil {
273		// test case with missing src key
274		ma := map[string][]int{"S": a}
275		mb := map[string][]int{}
276		if err := Merge(&ma, mb); err != nil {
277			t.FailNow()
278		}
279		if !reflect.DeepEqual(mb["S"], bc) {
280			t.Fatalf("missing src key: Source slice was modified %d != %d", mb["S"], bc)
281		}
282		if !reflect.DeepEqual(ma["S"], e) {
283			t.Fatalf("missing src key: b not merged in a proper way %d != %d", ma["S"], e)
284		}
285	}
286}
287
288func TestSlice(t *testing.T) {
289	testSlice(t, nil, []int{1, 2, 3}, []int{1, 2, 3})
290	testSlice(t, []int{}, []int{1, 2, 3}, []int{1, 2, 3})
291	testSlice(t, []int{1}, []int{2, 3}, []int{1})
292	testSlice(t, []int{1}, []int{}, []int{1})
293	testSlice(t, []int{1}, nil, []int{1})
294	testSlice(t, nil, []int{1, 2, 3}, []int{1, 2, 3}, WithAppendSlice)
295	testSlice(t, []int{}, []int{1, 2, 3}, []int{1, 2, 3}, WithAppendSlice)
296	testSlice(t, []int{1}, []int{2, 3}, []int{1, 2, 3}, WithAppendSlice)
297	testSlice(t, []int{1}, []int{2, 3}, []int{1, 2, 3}, WithAppendSlice, WithOverride)
298	testSlice(t, []int{1}, []int{}, []int{1}, WithAppendSlice)
299	testSlice(t, []int{1}, nil, []int{1}, WithAppendSlice)
300}
301
302func TestEmptyMaps(t *testing.T) {
303	a := mapTest{}
304	b := mapTest{
305		map[int]int{},
306	}
307	if err := Merge(&a, b); err != nil {
308		t.Fail()
309	}
310	if !reflect.DeepEqual(a, b) {
311		t.FailNow()
312	}
313}
314
315func TestEmptyToEmptyMaps(t *testing.T) {
316	a := mapTest{}
317	b := mapTest{}
318	if err := Merge(&a, b); err != nil {
319		t.Fail()
320	}
321	if !reflect.DeepEqual(a, b) {
322		t.FailNow()
323	}
324}
325
326func TestEmptyToNotEmptyMaps(t *testing.T) {
327	a := mapTest{map[int]int{
328		1: 2,
329		3: 4,
330	}}
331	aa := mapTest{map[int]int{
332		1: 2,
333		3: 4,
334	}}
335	b := mapTest{
336		map[int]int{},
337	}
338	if err := Merge(&a, b); err != nil {
339		t.Fail()
340	}
341	if !reflect.DeepEqual(a, aa) {
342		t.FailNow()
343	}
344}
345
346func TestMapsWithOverwrite(t *testing.T) {
347	m := map[string]simpleTest{
348		"a": {},   // overwritten by 16
349		"b": {42}, // not overwritten by empty value
350		"c": {13}, // overwritten by 12
351		"d": {61},
352	}
353	n := map[string]simpleTest{
354		"a": {16},
355		"b": {},
356		"c": {12},
357		"e": {14},
358	}
359	expect := map[string]simpleTest{
360		"a": {16},
361		"b": {},
362		"c": {12},
363		"d": {61},
364		"e": {14},
365	}
366
367	if err := MergeWithOverwrite(&m, n); err != nil {
368		t.Fatalf(err.Error())
369	}
370
371	if !reflect.DeepEqual(m, expect) {
372		t.Fatalf("Test failed:\ngot  :\n%#v\n\nwant :\n%#v\n\n", m, expect)
373	}
374}
375
376func TestMaps(t *testing.T) {
377	m := map[string]simpleTest{
378		"a": {},
379		"b": {42},
380		"c": {13},
381		"d": {61},
382	}
383	n := map[string]simpleTest{
384		"a": {16},
385		"b": {},
386		"c": {12},
387		"e": {14},
388	}
389	expect := map[string]simpleTest{
390		"a": {0},
391		"b": {42},
392		"c": {13},
393		"d": {61},
394		"e": {14},
395	}
396
397	if err := Merge(&m, n); err != nil {
398		t.Fatalf(err.Error())
399	}
400
401	if !reflect.DeepEqual(m, expect) {
402		t.Fatalf("Test failed:\ngot  :\n%#v\n\nwant :\n%#v\n\n", m, expect)
403	}
404	if m["a"].Value != 0 {
405		t.Fatalf(`n merged in m because I solved non-addressable map values TODO: m["a"].Value(%d) != n["a"].Value(%d)`, m["a"].Value, n["a"].Value)
406	}
407	if m["b"].Value != 42 {
408		t.Fatalf(`n wrongly merged in m: m["b"].Value(%d) != n["b"].Value(%d)`, m["b"].Value, n["b"].Value)
409	}
410	if m["c"].Value != 13 {
411		t.Fatalf(`n overwritten in m: m["c"].Value(%d) != n["c"].Value(%d)`, m["c"].Value, n["c"].Value)
412	}
413}
414
415func TestMapsWithNilPointer(t *testing.T) {
416	m := map[string]*simpleTest{
417		"a": nil,
418		"b": nil,
419	}
420	n := map[string]*simpleTest{
421		"b": nil,
422		"c": nil,
423	}
424	expect := map[string]*simpleTest{
425		"a": nil,
426		"b": nil,
427		"c": nil,
428	}
429
430	if err := Merge(&m, n, WithOverride); err != nil {
431		t.Fatalf(err.Error())
432	}
433
434	if !reflect.DeepEqual(m, expect) {
435		t.Fatalf("Test failed:\ngot   :\n%#v\n\nwant :\n%#v\n\n", m, expect)
436	}
437}
438
439func TestYAMLMaps(t *testing.T) {
440	thing := loadYAML("testdata/thing.yml")
441	license := loadYAML("testdata/license.yml")
442	ft := thing["fields"].(map[interface{}]interface{})
443	fl := license["fields"].(map[interface{}]interface{})
444	// license has one extra field (site) and another already existing in thing (author) that Mergo won't override.
445	expectedLength := len(ft) + len(fl) - 1
446	if err := Merge(&license, thing); err != nil {
447		t.Fatal(err.Error())
448	}
449	currentLength := len(license["fields"].(map[interface{}]interface{}))
450	if currentLength != expectedLength {
451		t.Fatalf(`thing not merged in license properly, license must have %d elements instead of %d`, expectedLength, currentLength)
452	}
453	fields := license["fields"].(map[interface{}]interface{})
454	if _, ok := fields["id"]; !ok {
455		t.Fatalf(`thing not merged in license properly, license must have a new id field from thing`)
456	}
457}
458
459func TestTwoPointerValues(t *testing.T) {
460	a := &simpleTest{}
461	b := &simpleTest{42}
462	if err := Merge(a, b); err != nil {
463		t.Fatalf(`Boom. You crossed the streams: %s`, err)
464	}
465}
466
467func TestMap(t *testing.T) {
468	a := complexTest{}
469	a.ID = "athing"
470	c := moreComplextText{a, simpleTest{}, simpleTest{}}
471	b := map[string]interface{}{
472		"ct": map[string]interface{}{
473			"st": map[string]interface{}{
474				"value": 42,
475			},
476			"sz": 1,
477			"id": "bthing",
478		},
479		"st": &simpleTest{144}, // Mapping a reference
480		"zt": simpleTest{299},  // Mapping a missing field (zt doesn't exist)
481		"nt": simpleTest{3},
482	}
483	if err := Map(&c, b); err != nil {
484		t.FailNow()
485	}
486	m := b["ct"].(map[string]interface{})
487	n := m["st"].(map[string]interface{})
488	o := b["st"].(*simpleTest)
489	p := b["nt"].(simpleTest)
490	if c.Ct.St.Value != 42 {
491		t.Fatalf("b not merged in properly: c.Ct.St.Value(%d) != b.Ct.St.Value(%d)", c.Ct.St.Value, n["value"])
492	}
493	if c.St.Value != 144 {
494		t.Fatalf("b not merged in properly: c.St.Value(%d) != b.St.Value(%d)", c.St.Value, o.Value)
495	}
496	if c.Nt.Value != 3 {
497		t.Fatalf("b not merged in properly: c.Nt.Value(%d) != b.Nt.Value(%d)", c.St.Value, p.Value)
498	}
499	if c.Ct.sz == 1 {
500		t.Fatalf("a's private field sz not preserved from merge: c.Ct.sz(%d) == b.Ct.sz(%d)", c.Ct.sz, m["sz"])
501	}
502	if c.Ct.ID == m["id"] {
503		t.Fatalf("a's field ID merged unexpectedly: c.Ct.ID(%s) == b.Ct.ID(%s)", c.Ct.ID, m["id"])
504	}
505}
506
507func TestSimpleMap(t *testing.T) {
508	a := simpleTest{}
509	b := map[string]interface{}{
510		"value": 42,
511	}
512	if err := Map(&a, b); err != nil {
513		t.FailNow()
514	}
515	if a.Value != 42 {
516		t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%v)", a.Value, b["value"])
517	}
518}
519
520func TestIfcMap(t *testing.T) {
521	a := ifcTest{}
522	b := ifcTest{42}
523	if err := Map(&a, b); err != nil {
524		t.FailNow()
525	}
526	if a.I != 42 {
527		t.Fatalf("b not merged in properly: a.I(%d) != b.I(%d)", a.I, b.I)
528	}
529	if !reflect.DeepEqual(a, b) {
530		t.FailNow()
531	}
532}
533
534func TestIfcMapNoOverwrite(t *testing.T) {
535	a := ifcTest{13}
536	b := ifcTest{42}
537	if err := Map(&a, b); err != nil {
538		t.FailNow()
539	}
540	if a.I != 13 {
541		t.Fatalf("a not left alone: a.I(%d) == b.I(%d)", a.I, b.I)
542	}
543}
544
545func TestIfcMapWithOverwrite(t *testing.T) {
546	a := ifcTest{13}
547	b := ifcTest{42}
548	if err := MapWithOverwrite(&a, b); err != nil {
549		t.FailNow()
550	}
551	if a.I != 42 {
552		t.Fatalf("b not merged in properly: a.I(%d) != b.I(%d)", a.I, b.I)
553	}
554	if !reflect.DeepEqual(a, b) {
555		t.FailNow()
556	}
557}
558
559type pointerMapTest struct {
560	A      int
561	hidden int
562	B      *simpleTest
563}
564
565func TestBackAndForth(t *testing.T) {
566	pt := pointerMapTest{42, 1, &simpleTest{66}}
567	m := make(map[string]interface{})
568	if err := Map(&m, pt); err != nil {
569		t.FailNow()
570	}
571	var (
572		v  interface{}
573		ok bool
574	)
575	if v, ok = m["a"]; v.(int) != pt.A || !ok {
576		t.Fatalf("pt not merged in properly: m[`a`](%d) != pt.A(%d)", v, pt.A)
577	}
578	if v, ok = m["b"]; !ok {
579		t.Fatalf("pt not merged in properly: B is missing in m")
580	}
581	var st *simpleTest
582	if st = v.(*simpleTest); st.Value != 66 {
583		t.Fatalf("something went wrong while mapping pt on m, B wasn't copied")
584	}
585	bpt := pointerMapTest{}
586	if err := Map(&bpt, m); err != nil {
587		t.Fatal(err)
588	}
589	if bpt.A != pt.A {
590		t.Fatalf("pt not merged in properly: bpt.A(%d) != pt.A(%d)", bpt.A, pt.A)
591	}
592	if bpt.hidden == pt.hidden {
593		t.Fatalf("pt unexpectedly merged: bpt.hidden(%d) == pt.hidden(%d)", bpt.hidden, pt.hidden)
594	}
595	if bpt.B.Value != pt.B.Value {
596		t.Fatalf("pt not merged in properly: bpt.B.Value(%d) != pt.B.Value(%d)", bpt.B.Value, pt.B.Value)
597	}
598}
599
600func TestEmbeddedPointerUnpacking(t *testing.T) {
601	tests := []struct{ input pointerMapTest }{
602		{pointerMapTest{42, 1, nil}},
603		{pointerMapTest{42, 1, &simpleTest{66}}},
604	}
605	newValue := 77
606	m := map[string]interface{}{
607		"b": map[string]interface{}{
608			"value": newValue,
609		},
610	}
611	for _, test := range tests {
612		pt := test.input
613		if err := MapWithOverwrite(&pt, m); err != nil {
614			t.FailNow()
615		}
616		if pt.B.Value != newValue {
617			t.Fatalf("pt not mapped properly: pt.A.Value(%d) != m[`b`][`value`](%d)", pt.B.Value, newValue)
618		}
619
620	}
621}
622
623type structWithTimePointer struct {
624	Birth *time.Time
625}
626
627func TestTime(t *testing.T) {
628	now := time.Now()
629	dataStruct := structWithTimePointer{
630		Birth: &now,
631	}
632	dataMap := map[string]interface{}{
633		"Birth": &now,
634	}
635	b := structWithTimePointer{}
636	if err := Merge(&b, dataStruct); err != nil {
637		t.FailNow()
638	}
639	if b.Birth.IsZero() {
640		t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataStruct['Birth'](%v)", b.Birth, dataStruct.Birth)
641	}
642	if b.Birth != dataStruct.Birth {
643		t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataStruct['Birth'](%v)", b.Birth, dataStruct.Birth)
644	}
645	b = structWithTimePointer{}
646	if err := Map(&b, dataMap); err != nil {
647		t.FailNow()
648	}
649	if b.Birth.IsZero() {
650		t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataMap['Birth'](%v)", b.Birth, dataMap["Birth"])
651	}
652}
653
654type simpleNested struct {
655	A int
656}
657
658type structWithNestedPtrValueMap struct {
659	NestedPtrValue map[string]*simpleNested
660}
661
662func TestNestedPtrValueInMap(t *testing.T) {
663	src := &structWithNestedPtrValueMap{
664		NestedPtrValue: map[string]*simpleNested{
665			"x": {
666				A: 1,
667			},
668		},
669	}
670	dst := &structWithNestedPtrValueMap{
671		NestedPtrValue: map[string]*simpleNested{
672			"x": {},
673		},
674	}
675	if err := Map(dst, src); err != nil {
676		t.FailNow()
677	}
678	if dst.NestedPtrValue["x"].A == 0 {
679		t.Fatalf("Nested Ptr value not merged in properly: dst.NestedPtrValue[\"x\"].A(%v) != src.NestedPtrValue[\"x\"].A(%v)", dst.NestedPtrValue["x"].A, src.NestedPtrValue["x"].A)
680	}
681}
682
683func loadYAML(path string) (m map[string]interface{}) {
684	m = make(map[string]interface{})
685	raw, _ := ioutil.ReadFile(path)
686	_ = yaml.Unmarshal(raw, &m)
687	return
688}
689
690type structWithMap struct {
691	m map[string]structWithUnexportedProperty
692}
693
694type structWithUnexportedProperty struct {
695	s string
696}
697
698func TestUnexportedProperty(t *testing.T) {
699	a := structWithMap{map[string]structWithUnexportedProperty{
700		"key": {"hello"},
701	}}
702	b := structWithMap{map[string]structWithUnexportedProperty{
703		"key": {"hi"},
704	}}
705	defer func() {
706		if r := recover(); r != nil {
707			t.Errorf("Should not have panicked")
708		}
709	}()
710	Merge(&a, b)
711}
712
713type structWithBoolPointer struct {
714	C *bool
715}
716
717func TestBooleanPointer(t *testing.T) {
718	bt, bf := true, false
719	src := structWithBoolPointer{
720		&bt,
721	}
722	dst := structWithBoolPointer{
723		&bf,
724	}
725	if err := Merge(&dst, src); err != nil {
726		t.FailNow()
727	}
728	if dst.C == src.C {
729		t.Fatalf("dst.C should be a different pointer than src.C")
730	}
731	if *dst.C != *src.C {
732		t.Fatalf("dst.C should be true")
733	}
734}
735
736func TestMergeMapWithInnerSliceOfDifferentType(t *testing.T) {
737	src := map[string]interface{}{
738		"foo": []string{"a", "b"},
739	}
740	dst := map[string]interface{}{
741		"foo": []int{1, 2},
742	}
743
744	if err := Merge(&src, &dst, WithOverride, WithAppendSlice); err == nil {
745		t.Fatal("expected an error, got nothing")
746	}
747}
748
749func TestMergeSliceDifferentType(t *testing.T) {
750	src := []string{"a", "b"}
751	dst := []int{1, 2}
752
753	if err := Merge(&src, &dst, WithOverride, WithAppendSlice); err == nil {
754		t.Fatal("expected an error, got nothing")
755	}
756}
757