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