Switch to github.com/golang/dep for vendoring
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
This commit is contained in:
parent
d6ab91be27
commit
8e5b17cf13
15431 changed files with 3971413 additions and 8881 deletions
74
vendor/github.com/imdario/mergo/README.md
generated
vendored
74
vendor/github.com/imdario/mergo/README.md
generated
vendored
|
@ -8,8 +8,31 @@ Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the
|
|||
|
||||
## Status
|
||||
|
||||
It is ready for production use. It works fine although it may use more of testing. Here some projects in the wild using Mergo:
|
||||
It is ready for production use. It works fine after extensive use in the wild.
|
||||
|
||||
[![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/)
|
||||
- [GoogleCloudPlatform/kubernetes](https://github.com/GoogleCloudPlatform/kubernetes)
|
||||
- [imdario/zas](https://github.com/imdario/zas)
|
||||
- [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy)
|
||||
- [EagerIO/Stout](https://github.com/EagerIO/Stout)
|
||||
- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api)
|
||||
- [russross/canvasassignments](https://github.com/russross/canvasassignments)
|
||||
|
@ -17,12 +40,16 @@ It is ready for production use. It works fine although it may use more of testin
|
|||
- [casualjim/exeggutor](https://github.com/casualjim/exeggutor)
|
||||
- [divshot/gitling](https://github.com/divshot/gitling)
|
||||
- [RWJMurphy/gorl](https://github.com/RWJMurphy/gorl)
|
||||
|
||||
[![Build Status][1]][2]
|
||||
[](https://godoc.org/github.com/imdario/mergo)
|
||||
|
||||
[1]: https://travis-ci.org/imdario/mergo.png
|
||||
[2]: https://travis-ci.org/imdario/mergo
|
||||
- [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)
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -51,6 +78,39 @@ 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
|
||||
|
|
25
vendor/github.com/imdario/mergo/issue17_test.go
generated
vendored
Normal file
25
vendor/github.com/imdario/mergo/issue17_test.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
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)
|
||||
}
|
||||
}
|
22
vendor/github.com/imdario/mergo/map.go
generated
vendored
22
vendor/github.com/imdario/mergo/map.go
generated
vendored
|
@ -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) (err error) {
|
||||
func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (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) (err
|
|||
}
|
||||
fieldName := field.Name
|
||||
fieldName = changeInitialCase(fieldName, unicode.ToLower)
|
||||
if v, ok := dstMap[fieldName]; !ok || isEmptyValue(reflect.ValueOf(v)) {
|
||||
if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) {
|
||||
dstMap[fieldName] = src.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
|
@ -89,12 +89,12 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err
|
|||
continue
|
||||
}
|
||||
if srcKind == dstKind {
|
||||
if err = deepMerge(dstElement, srcElement, visited, depth+1); err != nil {
|
||||
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if srcKind == reflect.Map {
|
||||
if err = deepMap(dstElement, srcElement, visited, depth+1); err != nil {
|
||||
if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
|
@ -118,6 +118,16 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err
|
|||
// 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
|
||||
|
@ -128,7 +138,7 @@ func Map(dst, src interface{}) 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)
|
||||
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
|
||||
}
|
||||
switch vSrc.Kind() {
|
||||
case reflect.Struct:
|
||||
|
@ -142,5 +152,5 @@ func Map(dst, src interface{}) error {
|
|||
default:
|
||||
return ErrNotSupported
|
||||
}
|
||||
return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0)
|
||||
return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
|
||||
}
|
||||
|
|
60
vendor/github.com/imdario/mergo/merge.go
generated
vendored
60
vendor/github.com/imdario/mergo/merge.go
generated
vendored
|
@ -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) (err error) {
|
||||
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
|
||||
if !src.IsValid() {
|
||||
return
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (e
|
|||
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); err != nil {
|
||||
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -46,15 +46,31 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (e
|
|||
continue
|
||||
}
|
||||
dstElement := dst.MapIndex(key)
|
||||
switch reflect.TypeOf(srcElement.Interface()).Kind() {
|
||||
case reflect.Struct:
|
||||
switch srcElement.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
|
||||
if srcElement.IsNil() {
|
||||
continue
|
||||
}
|
||||
fallthrough
|
||||
case reflect.Map:
|
||||
if err = deepMerge(dstElement, srcElement, visited, depth+1); err != nil {
|
||||
return
|
||||
default:
|
||||
if !srcElement.CanInterface() {
|
||||
continue
|
||||
}
|
||||
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 !dstElement.IsValid() {
|
||||
if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) {
|
||||
if dst.IsNil() {
|
||||
dst.Set(reflect.MakeMap(dst.Type()))
|
||||
}
|
||||
dst.SetMapIndex(key, srcElement)
|
||||
}
|
||||
}
|
||||
|
@ -64,27 +80,35 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (e
|
|||
if src.IsNil() {
|
||||
break
|
||||
} else if dst.IsNil() {
|
||||
if dst.CanSet() && isEmptyValue(dst) {
|
||||
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
|
||||
dst.Set(src)
|
||||
}
|
||||
} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1); err != nil {
|
||||
} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
if dst.CanSet() && !isEmptyValue(src) {
|
||||
if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
|
||||
dst.Set(src)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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.
|
||||
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
|
||||
|
@ -95,5 +119,5 @@ func Merge(dst, src interface{}) error {
|
|||
if vDst.Type() != vSrc.Type() {
|
||||
return ErrDifferentArgumentsTypes
|
||||
}
|
||||
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0)
|
||||
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
|
||||
}
|
||||
|
|
525
vendor/github.com/imdario/mergo/mergo_test.go
generated
vendored
Normal file
525
vendor/github.com/imdario/mergo/mergo_test.go
generated
vendored
Normal file
|
@ -0,0 +1,525 @@
|
|||
// Copyright 2013 Dario Castañé. All rights reserved.
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mergo
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v1"
|
||||
)
|
||||
|
||||
type simpleTest struct {
|
||||
Value int
|
||||
}
|
||||
|
||||
type complexTest struct {
|
||||
St simpleTest
|
||||
sz int
|
||||
ID string
|
||||
}
|
||||
|
||||
type moreComplextText struct {
|
||||
Ct complexTest
|
||||
St simpleTest
|
||||
Nt simpleTest
|
||||
}
|
||||
|
||||
type pointerTest struct {
|
||||
C *simpleTest
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDifferentTypes(t *testing.T) {
|
||||
a := simpleTest{42}
|
||||
b := 42
|
||||
if err := Merge(&a, b); err != ErrDifferentArgumentsTypes {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimpleStruct(t *testing.T) {
|
||||
a := simpleTest{}
|
||||
b := simpleTest{42}
|
||||
if err := Merge(&a, b); err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
if a.Value != 42 {
|
||||
t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%d)", a.Value, b.Value)
|
||||
}
|
||||
if !reflect.DeepEqual(a, b) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestComplexStruct(t *testing.T) {
|
||||
a := complexTest{}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointerStruct(t *testing.T) {
|
||||
s1 := simpleTest{}
|
||||
s2 := simpleTest{19}
|
||||
a := pointerTest{&s1}
|
||||
b := pointerTest{&s2}
|
||||
if err := Merge(&a, b); err != nil {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointerStructNil(t *testing.T) {
|
||||
a := pointerTest{nil}
|
||||
b := pointerTest{&simpleTest{19}}
|
||||
if err := Merge(&a, b); err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
if a.C.Value != b.C.Value {
|
||||
t.Fatalf("b not merged in a properly: a.C.Value(%d) != b.C.Value(%d)", a.C.Value, b.C.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSliceStruct(t *testing.T) {
|
||||
a := sliceTest{}
|
||||
b := sliceTest{[]int{1, 2, 3}}
|
||||
if err := Merge(&a, b); err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
if len(b.S) != 3 {
|
||||
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))
|
||||
}
|
||||
|
||||
a = sliceTest{[]int{1}}
|
||||
b = sliceTest{[]int{1, 2, 3}}
|
||||
if err := Merge(&a, b); err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
if len(a.S) != 1 {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaps(t *testing.T) {
|
||||
m := map[string]simpleTest{
|
||||
"a": {},
|
||||
"b": {42},
|
||||
"c": {13},
|
||||
"d": {61},
|
||||
}
|
||||
n := map[string]simpleTest{
|
||||
"a": {16},
|
||||
"b": {},
|
||||
"c": {12},
|
||||
"e": {14},
|
||||
}
|
||||
expect := map[string]simpleTest{
|
||||
"a": {0},
|
||||
"b": {42},
|
||||
"c": {13},
|
||||
"d": {61},
|
||||
"e": {14},
|
||||
}
|
||||
|
||||
if err := Merge(&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 m["a"].Value != 0 {
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func TestYAMLMaps(t *testing.T) {
|
||||
thing := loadYAML("testdata/thing.yml")
|
||||
license := loadYAML("testdata/license.yml")
|
||||
ft := thing["fields"].(map[interface{}]interface{})
|
||||
fl := license["fields"].(map[interface{}]interface{})
|
||||
expectedLength := len(ft) + len(fl)
|
||||
if err := Merge(&license, thing); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
currentLength := len(license["fields"].(map[interface{}]interface{}))
|
||||
if currentLength != expectedLength {
|
||||
t.Fatalf(`thing not merged in license properly, license must have %d elements instead of %d`, expectedLength, currentLength)
|
||||
}
|
||||
fields := license["fields"].(map[interface{}]interface{})
|
||||
if _, ok := fields["id"]; !ok {
|
||||
t.Fatalf(`thing not merged in license properly, license must have a new id field from thing`)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTwoPointerValues(t *testing.T) {
|
||||
a := &simpleTest{}
|
||||
b := &simpleTest{42}
|
||||
if err := Merge(a, b); err != nil {
|
||||
t.Fatalf(`Boom. You crossed the streams: %s`, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
a := complexTest{}
|
||||
a.ID = "athing"
|
||||
c := moreComplextText{a, simpleTest{}, simpleTest{}}
|
||||
b := map[string]interface{}{
|
||||
"ct": map[string]interface{}{
|
||||
"st": map[string]interface{}{
|
||||
"value": 42,
|
||||
},
|
||||
"sz": 1,
|
||||
"id": "bthing",
|
||||
},
|
||||
"st": &simpleTest{144}, // Mapping a reference
|
||||
"zt": simpleTest{299}, // Mapping a missing field (zt doesn't exist)
|
||||
"nt": simpleTest{3},
|
||||
}
|
||||
if err := Map(&c, b); err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
m := b["ct"].(map[string]interface{})
|
||||
n := m["st"].(map[string]interface{})
|
||||
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"])
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimpleMap(t *testing.T) {
|
||||
a := simpleTest{}
|
||||
b := map[string]interface{}{
|
||||
"value": 42,
|
||||
}
|
||||
if err := Map(&a, b); err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
if a.Value != 42 {
|
||||
t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%v)", a.Value, b["value"])
|
||||
}
|
||||
}
|
||||
|
||||
type pointerMapTest struct {
|
||||
A int
|
||||
hidden int
|
||||
B *simpleTest
|
||||
}
|
||||
|
||||
func TestBackAndForth(t *testing.T) {
|
||||
pt := pointerMapTest{42, 1, &simpleTest{66}}
|
||||
m := make(map[string]interface{})
|
||||
if err := Map(&m, pt); err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
var (
|
||||
v interface{}
|
||||
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)
|
||||
}
|
||||
if v, ok = m["b"]; !ok {
|
||||
t.Fatalf("pt not merged in properly: B is missing in m")
|
||||
}
|
||||
var st *simpleTest
|
||||
if st = v.(*simpleTest); st.Value != 66 {
|
||||
t.Fatalf("something went wrong while mapping pt on m, B wasn't copied")
|
||||
}
|
||||
bpt := pointerMapTest{}
|
||||
if err := Map(&bpt, m); err != nil {
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func loadYAML(path string) (m map[string]interface{}) {
|
||||
m = make(map[string]interface{})
|
||||
raw, _ := ioutil.ReadFile(path)
|
||||
_ = 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)
|
||||
}
|
3
vendor/github.com/imdario/mergo/testdata/license.yml
generated
vendored
Normal file
3
vendor/github.com/imdario/mergo/testdata/license.yml
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
import: ../../../../fossene/db/schema/thing.yml
|
||||
fields:
|
||||
site: string
|
5
vendor/github.com/imdario/mergo/testdata/thing.yml
generated
vendored
Normal file
5
vendor/github.com/imdario/mergo/testdata/thing.yml
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
fields:
|
||||
id: int
|
||||
name: string
|
||||
parent: ref "datu:thing"
|
||||
status: enum(draft, public, private)
|
Loading…
Add table
Add a link
Reference in a new issue