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{}, []int{1}, WithAppendSlice) 298 testSlice(t, []int{1}, nil, []int{1}, WithAppendSlice) 299} 300 301func TestEmptyMaps(t *testing.T) { 302 a := mapTest{} 303 b := mapTest{ 304 map[int]int{}, 305 } 306 if err := Merge(&a, b); err != nil { 307 t.Fail() 308 } 309 if !reflect.DeepEqual(a, b) { 310 t.FailNow() 311 } 312} 313 314func TestEmptyToEmptyMaps(t *testing.T) { 315 a := mapTest{} 316 b := mapTest{} 317 if err := Merge(&a, b); err != nil { 318 t.Fail() 319 } 320 if !reflect.DeepEqual(a, b) { 321 t.FailNow() 322 } 323} 324 325func TestEmptyToNotEmptyMaps(t *testing.T) { 326 a := mapTest{map[int]int{ 327 1: 2, 328 3: 4, 329 }} 330 aa := mapTest{map[int]int{ 331 1: 2, 332 3: 4, 333 }} 334 b := mapTest{ 335 map[int]int{}, 336 } 337 if err := Merge(&a, b); err != nil { 338 t.Fail() 339 } 340 if !reflect.DeepEqual(a, aa) { 341 t.FailNow() 342 } 343} 344 345func TestMapsWithOverwrite(t *testing.T) { 346 m := map[string]simpleTest{ 347 "a": {}, // overwritten by 16 348 "b": {42}, // not overwritten by empty value 349 "c": {13}, // overwritten by 12 350 "d": {61}, 351 } 352 n := map[string]simpleTest{ 353 "a": {16}, 354 "b": {}, 355 "c": {12}, 356 "e": {14}, 357 } 358 expect := map[string]simpleTest{ 359 "a": {16}, 360 "b": {}, 361 "c": {12}, 362 "d": {61}, 363 "e": {14}, 364 } 365 366 if err := MergeWithOverwrite(&m, n); err != nil { 367 t.Fatalf(err.Error()) 368 } 369 370 if !reflect.DeepEqual(m, expect) { 371 t.Fatalf("Test failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", m, expect) 372 } 373} 374 375func TestMaps(t *testing.T) { 376 m := map[string]simpleTest{ 377 "a": {}, 378 "b": {42}, 379 "c": {13}, 380 "d": {61}, 381 } 382 n := map[string]simpleTest{ 383 "a": {16}, 384 "b": {}, 385 "c": {12}, 386 "e": {14}, 387 } 388 expect := map[string]simpleTest{ 389 "a": {0}, 390 "b": {42}, 391 "c": {13}, 392 "d": {61}, 393 "e": {14}, 394 } 395 396 if err := Merge(&m, n); err != nil { 397 t.Fatalf(err.Error()) 398 } 399 400 if !reflect.DeepEqual(m, expect) { 401 t.Fatalf("Test failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", m, expect) 402 } 403 if m["a"].Value != 0 { 404 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) 405 } 406 if m["b"].Value != 42 { 407 t.Fatalf(`n wrongly merged in m: m["b"].Value(%d) != n["b"].Value(%d)`, m["b"].Value, n["b"].Value) 408 } 409 if m["c"].Value != 13 { 410 t.Fatalf(`n overwritten in m: m["c"].Value(%d) != n["c"].Value(%d)`, m["c"].Value, n["c"].Value) 411 } 412} 413 414func TestMapsWithNilPointer(t *testing.T) { 415 m := map[string]*simpleTest{ 416 "a": nil, 417 "b": nil, 418 } 419 n := map[string]*simpleTest{ 420 "b": nil, 421 "c": nil, 422 } 423 expect := map[string]*simpleTest{ 424 "a": nil, 425 "b": nil, 426 "c": nil, 427 } 428 429 if err := Merge(&m, n, WithOverride); err != nil { 430 t.Fatalf(err.Error()) 431 } 432 433 if !reflect.DeepEqual(m, expect) { 434 t.Fatalf("Test failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", m, expect) 435 } 436} 437 438func TestYAMLMaps(t *testing.T) { 439 thing := loadYAML("testdata/thing.yml") 440 license := loadYAML("testdata/license.yml") 441 ft := thing["fields"].(map[interface{}]interface{}) 442 fl := license["fields"].(map[interface{}]interface{}) 443 // license has one extra field (site) and another already existing in thing (author) that Mergo won't override. 444 expectedLength := len(ft) + len(fl) - 1 445 if err := Merge(&license, thing); err != nil { 446 t.Fatal(err.Error()) 447 } 448 currentLength := len(license["fields"].(map[interface{}]interface{})) 449 if currentLength != expectedLength { 450 t.Fatalf(`thing not merged in license properly, license must have %d elements instead of %d`, expectedLength, currentLength) 451 } 452 fields := license["fields"].(map[interface{}]interface{}) 453 if _, ok := fields["id"]; !ok { 454 t.Fatalf(`thing not merged in license properly, license must have a new id field from thing`) 455 } 456} 457 458func TestTwoPointerValues(t *testing.T) { 459 a := &simpleTest{} 460 b := &simpleTest{42} 461 if err := Merge(a, b); err != nil { 462 t.Fatalf(`Boom. You crossed the streams: %s`, err) 463 } 464} 465 466func TestMap(t *testing.T) { 467 a := complexTest{} 468 a.ID = "athing" 469 c := moreComplextText{a, simpleTest{}, simpleTest{}} 470 b := map[string]interface{}{ 471 "ct": map[string]interface{}{ 472 "st": map[string]interface{}{ 473 "value": 42, 474 }, 475 "sz": 1, 476 "id": "bthing", 477 }, 478 "st": &simpleTest{144}, // Mapping a reference 479 "zt": simpleTest{299}, // Mapping a missing field (zt doesn't exist) 480 "nt": simpleTest{3}, 481 } 482 if err := Map(&c, b); err != nil { 483 t.FailNow() 484 } 485 m := b["ct"].(map[string]interface{}) 486 n := m["st"].(map[string]interface{}) 487 o := b["st"].(*simpleTest) 488 p := b["nt"].(simpleTest) 489 if c.Ct.St.Value != 42 { 490 t.Fatalf("b not merged in properly: c.Ct.St.Value(%d) != b.Ct.St.Value(%d)", c.Ct.St.Value, n["value"]) 491 } 492 if c.St.Value != 144 { 493 t.Fatalf("b not merged in properly: c.St.Value(%d) != b.St.Value(%d)", c.St.Value, o.Value) 494 } 495 if c.Nt.Value != 3 { 496 t.Fatalf("b not merged in properly: c.Nt.Value(%d) != b.Nt.Value(%d)", c.St.Value, p.Value) 497 } 498 if c.Ct.sz == 1 { 499 t.Fatalf("a's private field sz not preserved from merge: c.Ct.sz(%d) == b.Ct.sz(%d)", c.Ct.sz, m["sz"]) 500 } 501 if c.Ct.ID == m["id"] { 502 t.Fatalf("a's field ID merged unexpectedly: c.Ct.ID(%s) == b.Ct.ID(%s)", c.Ct.ID, m["id"]) 503 } 504} 505 506func TestSimpleMap(t *testing.T) { 507 a := simpleTest{} 508 b := map[string]interface{}{ 509 "value": 42, 510 } 511 if err := Map(&a, b); err != nil { 512 t.FailNow() 513 } 514 if a.Value != 42 { 515 t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%v)", a.Value, b["value"]) 516 } 517} 518 519func TestIfcMap(t *testing.T) { 520 a := ifcTest{} 521 b := ifcTest{42} 522 if err := Map(&a, b); err != nil { 523 t.FailNow() 524 } 525 if a.I != 42 { 526 t.Fatalf("b not merged in properly: a.I(%d) != b.I(%d)", a.I, b.I) 527 } 528 if !reflect.DeepEqual(a, b) { 529 t.FailNow() 530 } 531} 532 533func TestIfcMapNoOverwrite(t *testing.T) { 534 a := ifcTest{13} 535 b := ifcTest{42} 536 if err := Map(&a, b); err != nil { 537 t.FailNow() 538 } 539 if a.I != 13 { 540 t.Fatalf("a not left alone: a.I(%d) == b.I(%d)", a.I, b.I) 541 } 542} 543 544func TestIfcMapWithOverwrite(t *testing.T) { 545 a := ifcTest{13} 546 b := ifcTest{42} 547 if err := MapWithOverwrite(&a, b); err != nil { 548 t.FailNow() 549 } 550 if a.I != 42 { 551 t.Fatalf("b not merged in properly: a.I(%d) != b.I(%d)", a.I, b.I) 552 } 553 if !reflect.DeepEqual(a, b) { 554 t.FailNow() 555 } 556} 557 558type pointerMapTest struct { 559 A int 560 hidden int 561 B *simpleTest 562} 563 564func TestBackAndForth(t *testing.T) { 565 pt := pointerMapTest{42, 1, &simpleTest{66}} 566 m := make(map[string]interface{}) 567 if err := Map(&m, pt); err != nil { 568 t.FailNow() 569 } 570 var ( 571 v interface{} 572 ok bool 573 ) 574 if v, ok = m["a"]; v.(int) != pt.A || !ok { 575 t.Fatalf("pt not merged in properly: m[`a`](%d) != pt.A(%d)", v, pt.A) 576 } 577 if v, ok = m["b"]; !ok { 578 t.Fatalf("pt not merged in properly: B is missing in m") 579 } 580 var st *simpleTest 581 if st = v.(*simpleTest); st.Value != 66 { 582 t.Fatalf("something went wrong while mapping pt on m, B wasn't copied") 583 } 584 bpt := pointerMapTest{} 585 if err := Map(&bpt, m); err != nil { 586 t.Fatal(err) 587 } 588 if bpt.A != pt.A { 589 t.Fatalf("pt not merged in properly: bpt.A(%d) != pt.A(%d)", bpt.A, pt.A) 590 } 591 if bpt.hidden == pt.hidden { 592 t.Fatalf("pt unexpectedly merged: bpt.hidden(%d) == pt.hidden(%d)", bpt.hidden, pt.hidden) 593 } 594 if bpt.B.Value != pt.B.Value { 595 t.Fatalf("pt not merged in properly: bpt.B.Value(%d) != pt.B.Value(%d)", bpt.B.Value, pt.B.Value) 596 } 597} 598 599func TestEmbeddedPointerUnpacking(t *testing.T) { 600 tests := []struct{ input pointerMapTest }{ 601 {pointerMapTest{42, 1, nil}}, 602 {pointerMapTest{42, 1, &simpleTest{66}}}, 603 } 604 newValue := 77 605 m := map[string]interface{}{ 606 "b": map[string]interface{}{ 607 "value": newValue, 608 }, 609 } 610 for _, test := range tests { 611 pt := test.input 612 if err := MapWithOverwrite(&pt, m); err != nil { 613 t.FailNow() 614 } 615 if pt.B.Value != newValue { 616 t.Fatalf("pt not mapped properly: pt.A.Value(%d) != m[`b`][`value`](%d)", pt.B.Value, newValue) 617 } 618 619 } 620} 621 622type structWithTimePointer struct { 623 Birth *time.Time 624} 625 626func TestTime(t *testing.T) { 627 now := time.Now() 628 dataStruct := structWithTimePointer{ 629 Birth: &now, 630 } 631 dataMap := map[string]interface{}{ 632 "Birth": &now, 633 } 634 b := structWithTimePointer{} 635 if err := Merge(&b, dataStruct); err != nil { 636 t.FailNow() 637 } 638 if b.Birth.IsZero() { 639 t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataStruct['Birth'](%v)", b.Birth, dataStruct.Birth) 640 } 641 if b.Birth != dataStruct.Birth { 642 t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataStruct['Birth'](%v)", b.Birth, dataStruct.Birth) 643 } 644 b = structWithTimePointer{} 645 if err := Map(&b, dataMap); err != nil { 646 t.FailNow() 647 } 648 if b.Birth.IsZero() { 649 t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataMap['Birth'](%v)", b.Birth, dataMap["Birth"]) 650 } 651} 652 653type simpleNested struct { 654 A int 655} 656 657type structWithNestedPtrValueMap struct { 658 NestedPtrValue map[string]*simpleNested 659} 660 661func TestNestedPtrValueInMap(t *testing.T) { 662 src := &structWithNestedPtrValueMap{ 663 NestedPtrValue: map[string]*simpleNested{ 664 "x": { 665 A: 1, 666 }, 667 }, 668 } 669 dst := &structWithNestedPtrValueMap{ 670 NestedPtrValue: map[string]*simpleNested{ 671 "x": {}, 672 }, 673 } 674 if err := Map(dst, src); err != nil { 675 t.FailNow() 676 } 677 if dst.NestedPtrValue["x"].A == 0 { 678 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) 679 } 680} 681 682func loadYAML(path string) (m map[string]interface{}) { 683 m = make(map[string]interface{}) 684 raw, _ := ioutil.ReadFile(path) 685 _ = yaml.Unmarshal(raw, &m) 686 return 687} 688 689type structWithMap struct { 690 m map[string]structWithUnexportedProperty 691} 692 693type structWithUnexportedProperty struct { 694 s string 695} 696 697func TestUnexportedProperty(t *testing.T) { 698 a := structWithMap{map[string]structWithUnexportedProperty{ 699 "key": {"hello"}, 700 }} 701 b := structWithMap{map[string]structWithUnexportedProperty{ 702 "key": {"hi"}, 703 }} 704 defer func() { 705 if r := recover(); r != nil { 706 t.Errorf("Should not have panicked") 707 } 708 }() 709 Merge(&a, b) 710} 711 712type structWithBoolPointer struct { 713 C *bool 714} 715 716func TestBooleanPointer(t *testing.T) { 717 bt, bf := true, false 718 src := structWithBoolPointer{ 719 &bt, 720 } 721 dst := structWithBoolPointer{ 722 &bf, 723 } 724 if err := Merge(&dst, src); err != nil { 725 t.FailNow() 726 } 727 if dst.C == src.C { 728 t.Fatalf("dst.C should be a different pointer than src.C") 729 } 730 if *dst.C != *src.C { 731 t.Fatalf("dst.C should be true") 732 } 733} 734 735func TestMergeMapWithInnerSliceOfDifferentType(t *testing.T) { 736 src := map[string]interface{}{ 737 "foo": []string{"a", "b"}, 738 } 739 dst := map[string]interface{}{ 740 "foo": []int{1, 2}, 741 } 742 743 if err := Merge(&src, &dst, WithOverride, WithAppendSlice); err == nil { 744 t.Fatal("expected an error, got nothing") 745 } 746} 747 748func TestMergeSliceDifferentType(t *testing.T) { 749 src := []string{"a", "b"} 750 dst := []int{1, 2} 751 752 if err := Merge(&src, &dst, WithOverride, WithAppendSlice); err == nil { 753 t.Fatal("expected an error, got nothing") 754 } 755} 756