提交 cb2e9c06 编写于 作者: S Sebastian Florek 提交者: GitHub

Fix apiserver-host parameter recognition (#998)

上级 969b727b
......@@ -8,30 +8,9 @@ Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the
## Status
It is ready for production use. It works fine after extensive use in the wild.
It is ready for production use. It works fine although it may use more of testing. Here some projects in the wild using Mergo:
[![Build Status][1]][2]
[![GoDoc][3]][4]
[![GoCard][5]][6]
[1]: https://travis-ci.org/imdario/mergo.png
[2]: https://travis-ci.org/imdario/mergo
[3]: https://godoc.org/github.com/imdario/mergo?status.svg
[4]: https://godoc.org/github.com/imdario/mergo
[5]: https://goreportcard.com/badge/imdario/mergo
[6]: https://goreportcard.com/report/github.com/imdario/mergo
### Important note
Mergo is intended to assign **only** zero value fields on destination with source value. Since April 6th it works like this. Before it didn't work properly, causing some random overwrites. After some issues and PRs I found it didn't merge as I designed it. Thanks to [imdario/mergo#8](https://github.com/imdario/mergo/pull/8) overwriting functions were added and the wrong behavior was clearly detected.
If you were using Mergo **before** April 6th 2015, please check your project works as intended after updating your local copy with ```go get -u github.com/imdario/mergo```. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause (I hope it won't!) in existing projects after the change (release 0.2.0).
### Mergo in the wild
- [docker/docker](https://github.com/docker/docker/)
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
- [imdario/zas](https://github.com/imdario/zas)
- [GoogleCloudPlatform/kubernetes](https://github.com/GoogleCloudPlatform/kubernetes)
- [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy)
- [EagerIO/Stout](https://github.com/EagerIO/Stout)
- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api)
......@@ -40,17 +19,12 @@ If you were using Mergo **before** April 6th 2015, please check your project wor
- [casualjim/exeggutor](https://github.com/casualjim/exeggutor)
- [divshot/gitling](https://github.com/divshot/gitling)
- [RWJMurphy/gorl](https://github.com/RWJMurphy/gorl)
- [andrerocker/deploy42](https://github.com/andrerocker/deploy42)
- [elwinar/rambler](https://github.com/elwinar/rambler)
- [tmaiaroto/gopartman](https://github.com/tmaiaroto/gopartman)
- [jfbus/impressionist](https://github.com/jfbus/impressionist)
- [Jmeyering/zealot](https://github.com/Jmeyering/zealot)
- [godep-migrator/rigger-host](https://github.com/godep-migrator/rigger-host)
- [Dronevery/MultiwaySwitch-Go](https://github.com/Dronevery/MultiwaySwitch-Go)
- [thoas/picfit](https://github.com/thoas/picfit)
- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server)
- [jnuthong/item_search](https://github.com/jnuthong/item_search)
- [Iris Web Framework](https://github.com/kataras/iris)
[![Build Status][1]][2]
[![GoDoc](https://godoc.org/github.com/imdario/mergo?status.svg)](https://godoc.org/github.com/imdario/mergo)
[1]: https://travis-ci.org/imdario/mergo.png
[2]: https://travis-ci.org/imdario/mergo
## Installation
......@@ -79,39 +53,6 @@ Warning: if you map a struct to map, it won't do it recursively. Don't expect Me
More information and examples in [godoc documentation](http://godoc.org/github.com/imdario/mergo).
### Nice example
```go
package main
import (
"fmt"
"github.com/imdario/mergo"
)
type Foo struct {
A string
B int64
}
func main() {
src := Foo{
A: "one",
}
dest := Foo{
A: "two",
B: 2,
}
mergo.Merge(&dest, src)
fmt.Println(dest)
// Will print
// {two 2}
}
```
Note: if test are failing due missing package, please execute:
go get gopkg.in/yaml.v1
......
package mergo
import (
"encoding/json"
"testing"
)
var (
request = `{"timestamp":null, "name": "foo"}`
maprequest = map[string]interface{}{
"timestamp": nil,
"name": "foo",
"newStuff": "foo",
}
)
func TestIssue17MergeWithOverwrite(t *testing.T) {
var something map[string]interface{}
if err := json.Unmarshal([]byte(request), &something); err != nil {
t.Errorf("Error while Unmarshalling maprequest %s", err)
}
if err := MergeWithOverwrite(&something, maprequest); err != nil {
t.Errorf("Error while merging %s", err)
}
}
package mergo
import (
"testing"
"time"
)
type document struct {
Created *time.Time
}
func TestIssue23MergeWithOverwrite(t *testing.T) {
now := time.Now()
dst := document{
&now,
}
expected := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
src := document{
&expected,
}
if err := MergeWithOverwrite(&dst, src); err != nil {
t.Errorf("Error while merging %s", err)
}
if dst.Created != src.Created {
t.Fatalf("Created not merged in properly: dst.Created(%v) != src.Created(%v)", dst.Created, src.Created)
}
}
......@@ -31,7 +31,7 @@ func isExported(field reflect.StructField) bool {
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) {
if dst.CanAddr() {
addr := dst.UnsafeAddr()
h := 17 * addr
......@@ -57,7 +57,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
}
fieldName := field.Name
fieldName = changeInitialCase(fieldName, unicode.ToLower)
if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) {
if v, ok := dstMap[fieldName]; !ok || isEmptyValue(reflect.ValueOf(v)) {
dstMap[fieldName] = src.Field(i).Interface()
}
}
......@@ -89,12 +89,12 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
continue
}
if srcKind == dstKind {
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
if err = deepMerge(dstElement, srcElement, visited, depth+1); err != nil {
return
}
} else {
if srcKind == reflect.Map {
if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
if err = deepMap(dstElement, srcElement, visited, depth+1); err != nil {
return
}
} else {
......@@ -118,16 +118,6 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
// This is separated method from Merge because it is cleaner and it keeps sane
// semantics: merging equal types, mapping different (restricted) types.
func Map(dst, src interface{}) error {
return _map(dst, src, false)
}
// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overriden by
// non-empty src attribute values.
func MapWithOverwrite(dst, src interface{}) error {
return _map(dst, src, true)
}
func _map(dst, src interface{}, overwrite bool) error {
var (
vDst, vSrc reflect.Value
err error
......@@ -138,7 +128,7 @@ func _map(dst, src interface{}, overwrite bool) error {
// To be friction-less, we redirect equal-type arguments
// to deepMerge. Only because arguments can be anything.
if vSrc.Kind() == vDst.Kind() {
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0)
}
switch vSrc.Kind() {
case reflect.Struct:
......@@ -152,5 +142,5 @@ func _map(dst, src interface{}, overwrite bool) error {
default:
return ErrNotSupported
}
return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0)
}
......@@ -15,7 +15,7 @@ import (
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) {
if !src.IsValid() {
return
}
......@@ -35,7 +35,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
switch dst.Kind() {
case reflect.Struct:
for i, n := 0, dst.NumField(); i < n; i++ {
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil {
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1); err != nil {
return
}
}
......@@ -46,31 +46,17 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
continue
}
dstElement := dst.MapIndex(key)
switch srcElement.Kind() {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
if srcElement.IsNil() {
continue
}
switch reflect.TypeOf(srcElement.Interface()).Kind() {
case reflect.Struct:
fallthrough
default:
if !srcElement.CanInterface() {
continue
case reflect.Map:
if err = deepMerge(dstElement, srcElement, visited, depth+1); err != nil {
return
}
switch reflect.TypeOf(srcElement.Interface()).Kind() {
case reflect.Struct:
fallthrough
case reflect.Ptr:
fallthrough
case reflect.Map:
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
return
}
}
}
if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) {
if dst.IsNil() {
dst.Set(reflect.MakeMap(dst.Type()))
if !dstElement.IsValid() {
dst.SetMapIndex(key, srcElement)
}
default:
dst.SetMapIndex(key, srcElement)
}
}
......@@ -79,36 +65,28 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
case reflect.Interface:
if src.IsNil() {
break
} else if dst.IsNil() || overwrite {
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
} else if dst.IsNil() {
if dst.CanSet() && isEmptyValue(dst) {
dst.Set(src)
}
} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil {
} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1); err != nil {
return
}
default:
if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
if dst.CanSet() && !isEmptyValue(src) {
dst.Set(src)
}
}
return
}
// Merge will fill any empty for value type attributes on the dst struct using corresponding
// src attributes if they themselves are not empty. dst and src must be valid same-type structs
// and dst must be a pointer to struct.
// It won't merge unexported (private) fields and will do recursively any exported field.
// Merge sets fields' values in dst from src if they have a zero
// value of their type.
// dst and src must be valid same-type structs and dst must be
// a pointer to struct.
// It won't merge unexported (private) fields and will do recursively
// any exported field.
func Merge(dst, src interface{}) error {
return merge(dst, src, false)
}
// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by
// non-empty src attribute values.
func MergeWithOverwrite(dst, src interface{}) error {
return merge(dst, src, true)
}
func merge(dst, src interface{}, overwrite bool) error {
var (
vDst, vSrc reflect.Value
err error
......@@ -119,5 +97,5 @@ func merge(dst, src interface{}, overwrite bool) error {
if vDst.Type() != vSrc.Type() {
return ErrDifferentArgumentsTypes
}
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0)
}
......@@ -6,11 +6,10 @@
package mergo
import (
"gopkg.in/yaml.v1"
"io/ioutil"
"reflect"
"testing"
"time"
"gopkg.in/yaml.v1"
)
type simpleTest struct {
......@@ -20,7 +19,7 @@ type simpleTest struct {
type complexTest struct {
St simpleTest
sz int
ID string
Id string
}
type moreComplextText struct {
......@@ -37,41 +36,6 @@ type sliceTest struct {
S []int
}
func TestKb(t *testing.T) {
type testStruct struct {
Name string
KeyValue map[string]interface{}
}
akv := make(map[string]interface{})
akv["Key1"] = "not value 1"
akv["Key2"] = "value2"
a := testStruct{}
a.Name = "A"
a.KeyValue = akv
bkv := make(map[string]interface{})
bkv["Key1"] = "value1"
bkv["Key3"] = "value3"
b := testStruct{}
b.Name = "B"
b.KeyValue = bkv
ekv := make(map[string]interface{})
ekv["Key1"] = "value1"
ekv["Key2"] = "value2"
ekv["Key3"] = "value3"
expected := testStruct{}
expected.Name = "B"
expected.KeyValue = ekv
Merge(&b, a)
if !reflect.DeepEqual(b, expected) {
t.Errorf("Actual: %#v did not match \nExpected: %#v", b, expected)
}
}
func TestNil(t *testing.T) {
if err := Merge(nil, nil); err != ErrNilArguments {
t.Fail()
......@@ -93,7 +57,7 @@ func TestSimpleStruct(t *testing.T) {
t.FailNow()
}
if a.Value != 42 {
t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%d)", a.Value, b.Value)
t.Fatalf("b not merged in a properly: a.Value(%d) != b.Value(%d)", a.Value, b.Value)
}
if !reflect.DeepEqual(a, b) {
t.FailNow()
......@@ -102,33 +66,19 @@ func TestSimpleStruct(t *testing.T) {
func TestComplexStruct(t *testing.T) {
a := complexTest{}
a.ID = "athing"
a.Id = "athing"
b := complexTest{simpleTest{42}, 1, "bthing"}
if err := Merge(&a, b); err != nil {
t.FailNow()
}
if a.St.Value != 42 {
t.Fatalf("b not merged in properly: a.St.Value(%d) != b.St.Value(%d)", a.St.Value, b.St.Value)
t.Fatalf("b not merged in a properly: a.St.Value(%d) != b.St.Value(%d)", a.St.Value, b.St.Value)
}
if a.sz == 1 {
t.Fatalf("a's private field sz not preserved from merge: a.sz(%d) == b.sz(%d)", a.sz, b.sz)
}
if a.ID == b.ID {
t.Fatalf("a's field ID merged unexpectedly: a.ID(%s) == b.ID(%s)", a.ID, b.ID)
}
}
func TestComplexStructWithOverwrite(t *testing.T) {
a := complexTest{simpleTest{1}, 1, "do-not-overwrite-with-empty-value"}
b := complexTest{simpleTest{42}, 2, ""}
expect := complexTest{simpleTest{42}, 1, "do-not-overwrite-with-empty-value"}
if err := MergeWithOverwrite(&a, b); err != nil {
t.FailNow()
}
if !reflect.DeepEqual(a, expect) {
t.Fatalf("Test failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", a, expect)
if a.Id != b.Id {
t.Fatalf("a's field Id not merged properly: a.Id(%s) != b.Id(%s)", a.Id, b.Id)
}
}
......@@ -141,68 +91,7 @@ func TestPointerStruct(t *testing.T) {
t.FailNow()
}
if a.C.Value != b.C.Value {
t.Fatalf("b not merged in properly: a.C.Value(%d) != b.C.Value(%d)", a.C.Value, b.C.Value)
}
}
type embeddingStruct struct {
embeddedStruct
}
type embeddedStruct struct {
A string
}
func TestEmbeddedStruct(t *testing.T) {
tests := []struct {
src embeddingStruct
dst embeddingStruct
expected embeddingStruct
}{
{
src: embeddingStruct{
embeddedStruct{"foo"},
},
dst: embeddingStruct{
embeddedStruct{""},
},
expected: embeddingStruct{
embeddedStruct{"foo"},
},
},
{
src: embeddingStruct{
embeddedStruct{""},
},
dst: embeddingStruct{
embeddedStruct{"bar"},
},
expected: embeddingStruct{
embeddedStruct{"bar"},
},
},
{
src: embeddingStruct{
embeddedStruct{"foo"},
},
dst: embeddingStruct{
embeddedStruct{"bar"},
},
expected: embeddingStruct{
embeddedStruct{"bar"},
},
},
}
for _, test := range tests {
err := Merge(&test.dst, test.src)
if err != nil {
t.Errorf("unexpected error: %v", err)
continue
}
if !reflect.DeepEqual(test.dst, test.expected) {
t.Errorf("unexpected output\nexpected:\n%+v\nsaw:\n%+v\n", test.expected, test.dst)
}
//t.Fatalf("b not merged in a properly: a.C.Value(%d) != b.C.Value(%d)", a.C.Value, b.C.Value)
}
}
......@@ -227,7 +116,7 @@ func TestSliceStruct(t *testing.T) {
t.FailNow()
}
if len(a.S) != len(b.S) {
t.Fatalf("b not merged in a proper way %d != %d", len(a.S), len(b.S))
t.Fatalf("b not merged in a properly %d != %d", len(a.S), len(b.S))
}
a = sliceTest{[]int{1}}
......@@ -235,63 +124,32 @@ func TestSliceStruct(t *testing.T) {
if err := Merge(&a, b); err != nil {
t.FailNow()
}
if len(a.S) != 1 {
if len(b.S) != 3 {
t.FailNow()
}
if len(a.S) == len(b.S) {
t.Fatalf("b merged unexpectedly %d != %d", len(a.S), len(b.S))
}
}
func TestMapsWithOverwrite(t *testing.T) {
m := map[string]simpleTest{
"a": {}, // overwritten by 16
"b": {42}, // not overwritten by empty value
"c": {13}, // overwritten by 12
"d": {61},
}
n := map[string]simpleTest{
"a": {16},
"b": {},
"c": {12},
"e": {14},
}
expect := map[string]simpleTest{
"a": {16},
"b": {},
"c": {12},
"d": {61},
"e": {14},
}
if err := MergeWithOverwrite(&m, n); err != nil {
t.Fatalf(err.Error())
}
if !reflect.DeepEqual(m, expect) {
t.Fatalf("Test failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", m, expect)
if len(a.S) != len(b.S) {
t.Fatalf("b not merged in a properly %d != %d", len(a.S), len(b.S))
}
}
func TestMaps(t *testing.T) {
m := map[string]simpleTest{
"a": {},
"b": {42},
"c": {13},
"d": {61},
"a": simpleTest{},
"b": simpleTest{42},
"d": simpleTest{61},
}
n := map[string]simpleTest{
"a": {16},
"b": {},
"c": {12},
"e": {14},
"a": simpleTest{16},
"b": simpleTest{},
"c": simpleTest{12},
"e": simpleTest{14},
}
expect := map[string]simpleTest{
"a": {0},
"b": {42},
"c": {13},
"d": {61},
"e": {14},
"a": simpleTest{0},
"b": simpleTest{42},
"c": simpleTest{12},
"d": simpleTest{61},
"e": simpleTest{14},
}
if err := Merge(&m, n); err != nil {
......@@ -307,8 +165,8 @@ func TestMaps(t *testing.T) {
if m["b"].Value != 42 {
t.Fatalf(`n wrongly merged in m: m["b"].Value(%d) != n["b"].Value(%d)`, m["b"].Value, n["b"].Value)
}
if m["c"].Value != 13 {
t.Fatalf(`n overwritten in m: m["c"].Value(%d) != n["c"].Value(%d)`, m["c"].Value, n["c"].Value)
if m["c"].Value != 12 {
t.Fatalf(`n not merged in m: m["c"].Value(%d) != n["c"].Value(%d)`, m["c"].Value, n["c"].Value)
}
}
......@@ -341,7 +199,7 @@ func TestTwoPointerValues(t *testing.T) {
func TestMap(t *testing.T) {
a := complexTest{}
a.ID = "athing"
a.Id = "athing"
c := moreComplextText{a, simpleTest{}, simpleTest{}}
b := map[string]interface{}{
"ct": map[string]interface{}{
......@@ -363,19 +221,19 @@ func TestMap(t *testing.T) {
o := b["st"].(*simpleTest)
p := b["nt"].(simpleTest)
if c.Ct.St.Value != 42 {
t.Fatalf("b not merged in properly: c.Ct.St.Value(%d) != b.Ct.St.Value(%d)", c.Ct.St.Value, n["value"])
t.Fatalf("b not merged in a properly: c.Ct.St.Value(%d) != b.Ct.St.Value(%d)", c.Ct.St.Value, n["value"])
}
if c.St.Value != 144 {
t.Fatalf("b not merged in properly: c.St.Value(%d) != b.St.Value(%d)", c.St.Value, o.Value)
t.Fatalf("b not merged in a properly: c.St.Value(%d) != b.St.Value(%d)", c.St.Value, o.Value)
}
if c.Nt.Value != 3 {
t.Fatalf("b not merged in properly: c.Nt.Value(%d) != b.Nt.Value(%d)", c.St.Value, p.Value)
t.Fatalf("b not merged in a properly: c.Nt.Value(%d) != b.Nt.Value(%d)", c.St.Value, p.Value)
}
if c.Ct.sz == 1 {
t.Fatalf("a's private field sz not preserved from merge: c.Ct.sz(%d) == b.Ct.sz(%d)", c.Ct.sz, m["sz"])
}
if c.Ct.ID == m["id"] {
t.Fatalf("a's field ID merged unexpectedly: c.Ct.ID(%s) == b.Ct.ID(%s)", c.Ct.ID, m["id"])
if c.Ct.Id != m["id"] {
t.Fatalf("a's field Id not merged properly: c.Ct.Id(%s) != b.Ct.Id(%s)", c.Ct.Id, m["id"])
}
}
......@@ -388,7 +246,7 @@ func TestSimpleMap(t *testing.T) {
t.FailNow()
}
if a.Value != 42 {
t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%v)", a.Value, b["value"])
t.Fatalf("b not merged in a properly: a.Value(%d) != b.Value(%v)", a.Value, b["value"])
}
}
......@@ -409,10 +267,10 @@ func TestBackAndForth(t *testing.T) {
ok bool
)
if v, ok = m["a"]; v.(int) != pt.A || !ok {
t.Fatalf("pt not merged in properly: m[`a`](%d) != pt.A(%d)", v, pt.A)
t.Fatalf("pt not merged properly: m[`a`](%d) != pt.A(%d)", v, pt.A)
}
if v, ok = m["b"]; !ok {
t.Fatalf("pt not merged in properly: B is missing in m")
t.Fatalf("pt not merged properly: B is missing in m")
}
var st *simpleTest
if st = v.(*simpleTest); st.Value != 66 {
......@@ -423,73 +281,13 @@ func TestBackAndForth(t *testing.T) {
t.Fatal(err)
}
if bpt.A != pt.A {
t.Fatalf("pt not merged in properly: bpt.A(%d) != pt.A(%d)", bpt.A, pt.A)
t.Fatalf("pt not merged properly: bpt.A(%d) != pt.A(%d)", bpt.A, pt.A)
}
if bpt.hidden == pt.hidden {
t.Fatalf("pt unexpectedly merged: bpt.hidden(%d) == pt.hidden(%d)", bpt.hidden, pt.hidden)
}
if bpt.B.Value != pt.B.Value {
t.Fatalf("pt not merged in properly: bpt.B.Value(%d) != pt.B.Value(%d)", bpt.B.Value, pt.B.Value)
}
}
type structWithTimePointer struct {
Birth *time.Time
}
func TestTime(t *testing.T) {
now := time.Now()
dataStruct := structWithTimePointer{
Birth: &now,
}
dataMap := map[string]interface{}{
"Birth": &now,
}
b := structWithTimePointer{}
if err := Merge(&b, dataStruct); err != nil {
t.FailNow()
}
if b.Birth.IsZero() {
t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataStruct['Birth'](%v)", b.Birth, dataStruct.Birth)
}
if b.Birth != dataStruct.Birth {
t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataStruct['Birth'](%v)", b.Birth, dataStruct.Birth)
}
b = structWithTimePointer{}
if err := Map(&b, dataMap); err != nil {
t.FailNow()
}
if b.Birth.IsZero() {
t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataMap['Birth'](%v)", b.Birth, dataMap["Birth"])
}
}
type simpleNested struct {
A int
}
type structWithNestedPtrValueMap struct {
NestedPtrValue map[string]*simpleNested
}
func TestNestedPtrValueInMap(t *testing.T) {
src := &structWithNestedPtrValueMap{
NestedPtrValue: map[string]*simpleNested{
"x": {
A: 1,
},
},
}
dst := &structWithNestedPtrValueMap{
NestedPtrValue: map[string]*simpleNested{
"x": {},
},
}
if err := Map(dst, src); err != nil {
t.FailNow()
}
if dst.NestedPtrValue["x"].A == 0 {
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)
t.Fatalf("pt not merged properly: bpt.B.Value(%d) != pt.B.Value(%d)", bpt.B.Value, pt.B.Value)
}
}
......@@ -499,49 +297,3 @@ func loadYAML(path string) (m map[string]interface{}) {
_ = yaml.Unmarshal(raw, &m)
return
}
type structWithMap struct {
m map[string]structWithUnexportedProperty
}
type structWithUnexportedProperty struct {
s string
}
func TestUnexportedProperty(t *testing.T) {
a := structWithMap{map[string]structWithUnexportedProperty{
"key": structWithUnexportedProperty{"hello"},
}}
b := structWithMap{map[string]structWithUnexportedProperty{
"key": structWithUnexportedProperty{"hi"},
}}
defer func() {
if r := recover(); r != nil {
t.Errorf("Should not have panicked")
}
}()
Merge(&a, b)
}
type structWithBoolPointer struct {
C *bool
}
func TestBooleanPointer(t *testing.T) {
bt, bf := true, false
src := structWithBoolPointer{
&bt,
}
dst := structWithBoolPointer{
&bf,
}
if err := Merge(&dst, src); err != nil {
t.FailNow()
}
if dst.C == src.C {
t.Fatalf("dst.C should be a different pointer than src.C")
}
if *dst.C != *src.C {
t.Fatalf("dst.C should be true")
}
}
......@@ -715,10 +715,12 @@
"revisionTime": "2016-02-01T17:48:07Z"
},
{
"checksumSHA1": "H9S5xwBvrCqJqte/RGxwl68MWJg=",
"checksumSHA1": "n/llKRPzxcWttjZtpAWA7VW9iJA=",
"path": "github.com/imdario/mergo",
"revision": "50d4dbd4eb0e84778abe37cefef140271d96fade",
"revisionTime": "2016-05-17T06:44:35Z"
"revision": "86cdca063f41835f7acf068df463f14eecd11e17",
"revisionTime": "2015-01-29T15:29:59Z",
"version": "=0.1.4",
"versionExact": "0.1.4"
},
{
"checksumSHA1": "40vJyUB4ezQSn/NSadsKEOrudMc=",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册