Skip to content

Commit

Permalink
Slices should append not overwrite
Browse files Browse the repository at this point in the history
  • Loading branch information
andy-miracl authored and vdemeester committed Nov 8, 2017
1 parent 7fe0c75 commit 0b8c27e
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 15 deletions.
14 changes: 14 additions & 0 deletions merge.go
Expand Up @@ -87,6 +87,18 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
return
}
case reflect.Slice:
srcSlice := reflect.ValueOf(srcElement.Interface())

var dstSlice reflect.Value
if !dstElement.IsValid() || dstElement.IsNil() {
dstSlice = reflect.MakeSlice(srcSlice.Type(), 0, srcSlice.Len())
} else {
dstSlice = reflect.ValueOf(dstElement.Interface())
}

dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
dst.SetMapIndex(key, dstSlice)
}
}
if dstElement.IsValid() && reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map {
Expand All @@ -100,6 +112,8 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
dst.SetMapIndex(key, srcElement)
}
}
case reflect.Slice:
dst.Set(reflect.AppendSlice(dst, src))
case reflect.Ptr:
fallthrough
case reflect.Interface:
Expand Down
71 changes: 56 additions & 15 deletions mergo_test.go
Expand Up @@ -225,30 +225,71 @@ func TestPointerStructNil(t *testing.T) {
}
}

func TestSliceStruct(t *testing.T) {
a := sliceTest{}
b := sliceTest{[]int{1, 2, 3}}
if err := Merge(&a, b); err != nil {
func testSlice(t *testing.T, a []int, b []int) {
bc := b
e := append(a, b...)

sa := sliceTest{a}
sb := sliceTest{b}
if err := Merge(&sa, sb); err != nil {
t.FailNow()
}
if len(b.S) != 3 {
t.FailNow()
if !reflect.DeepEqual(sb.S, bc) {
t.Fatalf("Source slice was modified %d != %d", sb.S, bc)
}
if len(a.S) != len(b.S) {
t.Fatalf("b not merged in a proper way %d != %d", len(a.S), len(b.S))
if !reflect.DeepEqual(sa.S, e) {
t.Fatalf("b not merged in a proper way %d != %d", sa.S, e)
}

a = sliceTest{[]int{1}}
b = sliceTest{[]int{1, 2, 3}}
if err := Merge(&a, b); err != nil {
ma := map[string][]int{"S": a}
mb := map[string][]int{"S": b}
if err := Merge(&ma, mb); err != nil {
t.FailNow()
}
if len(a.S) != 1 {
t.FailNow()
if !reflect.DeepEqual(mb["S"], bc) {
t.Fatalf("Source slice was modified %d != %d", mb["S"], bc)
}
if len(a.S) == len(b.S) {
t.Fatalf("b merged unexpectedly %d != %d", len(a.S), len(b.S))
if !reflect.DeepEqual(ma["S"], e) {
t.Fatalf("b not merged in a proper way %d != %d", ma["S"], e)
}

if a == nil {
// test case with missing dst key
ma := map[string][]int{}
mb := map[string][]int{"S": b}
if err := Merge(&ma, mb); err != nil {
t.FailNow()
}
if !reflect.DeepEqual(mb["S"], bc) {
t.Fatalf("Source slice was modified %d != %d", mb["S"], bc)
}
if !reflect.DeepEqual(ma["S"], e) {
t.Fatalf("b not merged in a proper way %d != %d", ma["S"], e)
}
}

if b == nil {
// test case with missing src key
ma := map[string][]int{"S": a}
mb := map[string][]int{}
if err := Merge(&ma, mb); err != nil {
t.FailNow()
}
if !reflect.DeepEqual(mb["S"], bc) {
t.Fatalf("Source slice was modified %d != %d", mb["S"], bc)
}
if !reflect.DeepEqual(ma["S"], e) {
t.Fatalf("b not merged in a proper way %d != %d", ma["S"], e)
}
}
}

func TestSlice(t *testing.T) {
testSlice(t, nil, []int{1, 2, 3})
testSlice(t, []int{}, []int{1, 2, 3})
testSlice(t, []int{1}, []int{2, 3})
testSlice(t, []int{1}, []int{})
testSlice(t, []int{1}, nil)
}

func TestEmptyMaps(t *testing.T) {
Expand Down

0 comments on commit 0b8c27e

Please sign in to comment.