Update upstream source from tag 'upstream/0.3.8'
Update to upstream version '0.3.8'
with Debian dir f5ffacb38c38a2d940b4c896fb5e0af2c2cdabaa
Dmitry Smirnov
3 years ago
0 | # These are supported funding model platforms | |
1 | ||
2 | ko_fi: dariocc | |
3 | custom: https://beerpay.io/imdario/mergo |
3 | 3 | - go get golang.org/x/tools/cmd/cover |
4 | 4 | - go get github.com/mattn/goveralls |
5 | 5 | script: |
6 | - go test -race -v ./... | |
7 | after_script: | |
6 | 8 | - $HOME/gopath/bin/goveralls -service=travis-ci -repotoken $COVERALLS_TOKEN |
12 | 12 | [![Build Status][1]][2] |
13 | 13 | [![Coverage Status][7]][8] |
14 | 14 | [![Sourcegraph][9]][10] |
15 | [](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield) | |
15 | 16 | |
16 | 17 | [1]: https://travis-ci.org/imdario/mergo.png |
17 | 18 | [2]: https://travis-ci.org/imdario/mergo |
26 | 27 | |
27 | 28 | ### Latest release |
28 | 29 | |
29 | [Release v0.3.4](https://github.com/imdario/mergo/releases/tag/v0.3.4). | |
30 | [Release v0.3.7](https://github.com/imdario/mergo/releases/tag/v0.3.7). | |
30 | 31 | |
31 | 32 | ### Important note |
32 | 33 | |
216 | 217 | |
217 | 218 | Written by [Dario Castañé](http://dario.im). |
218 | 219 | |
220 | ## Top Contributors | |
221 | ||
222 | [](https://sourcerer.io/fame/imdario/imdario/mergo/links/0) | |
223 | [](https://sourcerer.io/fame/imdario/imdario/mergo/links/1) | |
224 | [](https://sourcerer.io/fame/imdario/imdario/mergo/links/2) | |
225 | [](https://sourcerer.io/fame/imdario/imdario/mergo/links/3) | |
226 | [](https://sourcerer.io/fame/imdario/imdario/mergo/links/4) | |
227 | [](https://sourcerer.io/fame/imdario/imdario/mergo/links/5) | |
228 | [](https://sourcerer.io/fame/imdario/imdario/mergo/links/6) | |
229 | [](https://sourcerer.io/fame/imdario/imdario/mergo/links/7) | |
230 | ||
231 | ||
219 | 232 | ## License |
220 | 233 | |
221 | 234 | [BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE). |
235 | ||
236 | ||
237 | [](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_large) |
0 | package mergo | |
1 | ||
2 | import ( | |
3 | "encoding/json" | |
4 | "testing" | |
5 | ) | |
6 | ||
7 | var ( | |
8 | data = `{"FirstSlice":[], "SecondSlice": null}` | |
9 | ) | |
10 | ||
11 | type settings struct { | |
12 | FirstSlice []string `json:"FirstSlice"` | |
13 | SecondSlice []string `json:"SecondSlice"` | |
14 | } | |
15 | ||
16 | func TestIssue125MergeWithOverwrite(t *testing.T) { | |
17 | ||
18 | defaultSettings := settings{ | |
19 | FirstSlice: []string{}, | |
20 | SecondSlice: []string{}, | |
21 | } | |
22 | ||
23 | var something settings | |
24 | if err := json.Unmarshal([]byte(data), &something); err != nil { | |
25 | t.Errorf("Error while Unmarshalling maprequest: %s", err) | |
26 | } | |
27 | if err := Merge(&something, defaultSettings, WithOverrideEmptySlice); err != nil { | |
28 | t.Errorf("Error while merging: %s", err) | |
29 | } | |
30 | if something.FirstSlice == nil { | |
31 | t.Error("Invalid merging first slice") | |
32 | } | |
33 | if something.SecondSlice == nil { | |
34 | t.Error("Invalid merging second slice") | |
35 | } | |
36 | } |
0 | package mergo | |
1 | ||
2 | import ( | |
3 | "testing" | |
4 | ) | |
5 | ||
6 | type DstStructIssue84 struct { | |
7 | A int | |
8 | B int | |
9 | C int | |
10 | } | |
11 | ||
12 | type DstNestedStructIssue84 struct { | |
13 | A struct { | |
14 | A int | |
15 | B int | |
16 | C int | |
17 | } | |
18 | B int | |
19 | C int | |
20 | } | |
21 | ||
22 | func TestIssue84MergeMapWithNilValueToStructWithOverride(t *testing.T) { | |
23 | p1 := DstStructIssue84{ | |
24 | A: 0, B: 1, C: 2, | |
25 | } | |
26 | p2 := map[string]interface{}{ | |
27 | "A": 3, "B": 4, "C": 0, | |
28 | } | |
29 | if err := Map(&p1, p2, WithOverride); err != nil { | |
30 | t.Fatalf("Error during the merge: %v", err) | |
31 | } | |
32 | if p1.C != 0 { | |
33 | t.Error("C field should become '0'") | |
34 | } | |
35 | } | |
36 | ||
37 | func TestIssue84MergeMapWithoutKeyExistsToStructWithOverride(t *testing.T) { | |
38 | p1 := DstStructIssue84{ | |
39 | A: 0, B: 1, C: 2, | |
40 | } | |
41 | p2 := map[string]interface{}{ | |
42 | "A": 3, "B": 4, | |
43 | } | |
44 | if err := Map(&p1, p2, WithOverride); err != nil { | |
45 | t.Fatalf("Error during the merge: %v", err) | |
46 | } | |
47 | if p1.C != 2 { | |
48 | t.Error("C field should be '2'") | |
49 | } | |
50 | } | |
51 | ||
52 | func TestIssue84MergeNestedMapWithNilValueToStructWithOverride(t *testing.T) { | |
53 | p1 := DstNestedStructIssue84{ | |
54 | A: struct { | |
55 | A int | |
56 | B int | |
57 | C int | |
58 | }{A: 1, B: 2, C: 0}, | |
59 | B: 0, | |
60 | C: 2, | |
61 | } | |
62 | p2 := map[string]interface{}{ | |
63 | "A": map[string]interface{}{ | |
64 | "A": 0, "B": 0, "C": 5, | |
65 | }, "B": 4, "C": 0, | |
66 | } | |
67 | if err := Map(&p1, p2, WithOverride); err != nil { | |
68 | t.Fatalf("Error during the merge: %v", err) | |
69 | } | |
70 | if p1.B != 4 { | |
71 | t.Error("A.C field should become '4'") | |
72 | } | |
73 | ||
74 | if p1.A.C != 5 { | |
75 | t.Error("A.C field should become '5'") | |
76 | } | |
77 | ||
78 | if p1.A.B != 0 || p1.A.A != 0 { | |
79 | t.Error("A.A and A.B field should become '0'") | |
80 | } | |
81 | } |
71 | 71 | case reflect.Struct: |
72 | 72 | srcMap := src.Interface().(map[string]interface{}) |
73 | 73 | for key := range srcMap { |
74 | config.overwriteWithEmptyValue = true | |
74 | 75 | srcValue := srcMap[key] |
75 | 76 | fieldName := changeInitialCase(key, unicode.ToUpper) |
76 | 77 | dstElement := dst.FieldByName(fieldName) |
8 | 8 | package mergo |
9 | 9 | |
10 | 10 | import ( |
11 | "fmt" | |
11 | 12 | "reflect" |
12 | 13 | ) |
13 | 14 | |
24 | 25 | } |
25 | 26 | |
26 | 27 | type Config struct { |
27 | Overwrite bool | |
28 | AppendSlice bool | |
29 | Transformers Transformers | |
28 | Overwrite bool | |
29 | AppendSlice bool | |
30 | TypeCheck bool | |
31 | Transformers Transformers | |
32 | overwriteWithEmptyValue bool | |
33 | overwriteSliceWithEmptyValue bool | |
30 | 34 | } |
31 | 35 | |
32 | 36 | type Transformers interface { |
38 | 42 | // short circuiting on recursive types. |
39 | 43 | func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) { |
40 | 44 | overwrite := config.Overwrite |
45 | typeCheck := config.TypeCheck | |
46 | overwriteWithEmptySrc := config.overwriteWithEmptyValue | |
47 | overwriteSliceWithEmptySrc := config.overwriteSliceWithEmptyValue | |
48 | config.overwriteWithEmptyValue = false | |
41 | 49 | |
42 | 50 | if !src.IsValid() { |
43 | 51 | return |
72 | 80 | } |
73 | 81 | } |
74 | 82 | } else { |
75 | if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { | |
83 | if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) { | |
76 | 84 | dst.Set(src) |
77 | 85 | } |
78 | 86 | } |
123 | 131 | dstSlice = reflect.ValueOf(dstElement.Interface()) |
124 | 132 | } |
125 | 133 | |
126 | if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { | |
134 | if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { | |
135 | if typeCheck && srcSlice.Type() != dstSlice.Type() { | |
136 | return fmt.Errorf("cannot override two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type()) | |
137 | } | |
127 | 138 | dstSlice = srcSlice |
128 | 139 | } else if config.AppendSlice { |
140 | if srcSlice.Type() != dstSlice.Type() { | |
141 | return fmt.Errorf("cannot append two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type()) | |
142 | } | |
129 | 143 | dstSlice = reflect.AppendSlice(dstSlice, srcSlice) |
130 | 144 | } |
131 | 145 | dst.SetMapIndex(key, dstSlice) |
132 | 146 | } |
133 | 147 | } |
134 | if dstElement.IsValid() && reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map { | |
148 | if dstElement.IsValid() && !isEmptyValue(dstElement) && (reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map || reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice) { | |
135 | 149 | continue |
136 | 150 | } |
137 | 151 | |
138 | if srcElement.IsValid() && (overwrite || (!dstElement.IsValid() || isEmptyValue(dstElement))) { | |
152 | if srcElement.IsValid() && ((srcElement.Kind() != reflect.Ptr && overwrite) || !dstElement.IsValid() || isEmptyValue(dstElement)) { | |
139 | 153 | if dst.IsNil() { |
140 | 154 | dst.Set(reflect.MakeMap(dst.Type())) |
141 | 155 | } |
146 | 160 | if !dst.CanSet() { |
147 | 161 | break |
148 | 162 | } |
149 | if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { | |
163 | if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { | |
150 | 164 | dst.Set(src) |
151 | 165 | } else if config.AppendSlice { |
166 | if src.Type() != dst.Type() { | |
167 | return fmt.Errorf("cannot append two slice with different type (%s, %s)", src.Type(), dst.Type()) | |
168 | } | |
152 | 169 | dst.Set(reflect.AppendSlice(dst, src)) |
153 | 170 | } |
154 | 171 | case reflect.Ptr: |
157 | 174 | if src.IsNil() { |
158 | 175 | break |
159 | 176 | } |
160 | if src.Kind() != reflect.Interface { | |
177 | ||
178 | if dst.Kind() != reflect.Ptr && src.Type().AssignableTo(dst.Type()) { | |
161 | 179 | if dst.IsNil() || overwrite { |
162 | 180 | if dst.CanSet() && (overwrite || isEmptyValue(dst)) { |
163 | 181 | dst.Set(src) |
164 | 182 | } |
183 | } | |
184 | break | |
185 | } | |
186 | ||
187 | if src.Kind() != reflect.Interface { | |
188 | if dst.IsNil() || (src.Kind() != reflect.Ptr && overwrite) { | |
189 | if dst.CanSet() && (overwrite || isEmptyValue(dst)) { | |
190 | dst.Set(src) | |
191 | } | |
165 | 192 | } else if src.Kind() == reflect.Ptr { |
166 | 193 | if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { |
167 | 194 | return |
183 | 210 | return |
184 | 211 | } |
185 | 212 | default: |
186 | if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { | |
213 | if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) { | |
187 | 214 | dst.Set(src) |
188 | 215 | } |
189 | 216 | } |
217 | ||
190 | 218 | return |
191 | 219 | } |
192 | 220 | |
198 | 226 | return merge(dst, src, opts...) |
199 | 227 | } |
200 | 228 | |
201 | // MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by | |
229 | // MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overridden by | |
202 | 230 | // non-empty src attribute values. |
203 | 231 | // Deprecated: use Merge(…) with WithOverride |
204 | 232 | func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error { |
217 | 245 | config.Overwrite = true |
218 | 246 | } |
219 | 247 | |
220 | // WithAppendSlice will make merge append slices instead of overwriting it | |
248 | // WithOverride will make merge override empty dst slice with empty src slice. | |
249 | func WithOverrideEmptySlice(config *Config) { | |
250 | config.overwriteSliceWithEmptyValue = true | |
251 | } | |
252 | ||
253 | // WithAppendSlice will make merge append slices instead of overwriting it. | |
221 | 254 | func WithAppendSlice(config *Config) { |
222 | 255 | config.AppendSlice = true |
256 | } | |
257 | ||
258 | // WithTypeCheck will make merge check types while overwriting it (must be used with WithOverride). | |
259 | func WithTypeCheck(config *Config) { | |
260 | config.TypeCheck = true | |
223 | 261 | } |
224 | 262 | |
225 | 263 | func merge(dst, src interface{}, opts ...func(*Config)) error { |
0 | package mergo | |
1 | ||
2 | import ( | |
3 | "net/http" | |
4 | "net/http/httptest" | |
5 | "testing" | |
6 | ) | |
7 | ||
8 | type ifaceTypesTest struct { | |
9 | N int | |
10 | Handler http.Handler | |
11 | } | |
12 | ||
13 | type ifaceTypesHandler int | |
14 | ||
15 | func (*ifaceTypesHandler) ServeHTTP(rw http.ResponseWriter, _ *http.Request) { | |
16 | rw.Header().Set("Test", "ifaceTypesHandler") | |
17 | } | |
18 | ||
19 | func TestMergeInterfaceWithDifferentConcreteTypes(t *testing.T) { | |
20 | dst := ifaceTypesTest{ | |
21 | Handler: new(ifaceTypesHandler), | |
22 | } | |
23 | ||
24 | src := ifaceTypesTest{ | |
25 | N: 42, | |
26 | Handler: http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { | |
27 | rw.Header().Set("Test", "handlerFunc") | |
28 | }), | |
29 | } | |
30 | ||
31 | if err := Merge(&dst, src); err != nil { | |
32 | t.Errorf("Error while merging %s", err) | |
33 | } | |
34 | ||
35 | rw := httptest.NewRecorder() | |
36 | dst.Handler.ServeHTTP(rw, nil) | |
37 | ||
38 | if got, want := rw.Header().Get("Test"), "ifaceTypesHandler"; got != want { | |
39 | t.Errorf("Handler not merged in properly: got %q header value %q, want %q", "Test", got, want) | |
40 | } | |
41 | } |
7 | 7 | import ( |
8 | 8 | "io/ioutil" |
9 | 9 | "reflect" |
10 | "strings" | |
10 | 11 | "testing" |
11 | 12 | "time" |
13 | ||
14 | "github.com/stretchr/testify/assert" | |
12 | 15 | |
13 | 16 | "gopkg.in/yaml.v2" |
14 | 17 | ) |
293 | 296 | testSlice(t, nil, []int{1, 2, 3}, []int{1, 2, 3}, WithAppendSlice) |
294 | 297 | testSlice(t, []int{}, []int{1, 2, 3}, []int{1, 2, 3}, WithAppendSlice) |
295 | 298 | testSlice(t, []int{1}, []int{2, 3}, []int{1, 2, 3}, WithAppendSlice) |
299 | testSlice(t, []int{1}, []int{2, 3}, []int{1, 2, 3}, WithAppendSlice, WithOverride) | |
296 | 300 | testSlice(t, []int{1}, []int{}, []int{1}, WithAppendSlice) |
297 | 301 | testSlice(t, []int{1}, nil, []int{1}, WithAppendSlice) |
298 | 302 | } |
344 | 348 | func TestMapsWithOverwrite(t *testing.T) { |
345 | 349 | m := map[string]simpleTest{ |
346 | 350 | "a": {}, // overwritten by 16 |
347 | "b": {42}, // not overwritten by empty value | |
351 | "b": {42}, // overwritten by 0, as map Value is not addressable and it doesn't check for b is set or not set in `n` | |
348 | 352 | "c": {13}, // overwritten by 12 |
349 | 353 | "d": {61}, |
350 | 354 | } |
371 | 375 | } |
372 | 376 | } |
373 | 377 | |
378 | func TestMapWithEmbeddedStructPointer(t *testing.T) { | |
379 | m := map[string]*simpleTest{ | |
380 | "a": {}, // overwritten by 16 | |
381 | "b": {42}, // not overwritten by empty value | |
382 | "c": {13}, // overwritten by 12 | |
383 | "d": {61}, | |
384 | } | |
385 | n := map[string]*simpleTest{ | |
386 | "a": {16}, | |
387 | "b": {}, | |
388 | "c": {12}, | |
389 | "e": {14}, | |
390 | } | |
391 | expect := map[string]*simpleTest{ | |
392 | "a": {16}, | |
393 | "b": {42}, | |
394 | "c": {12}, | |
395 | "d": {61}, | |
396 | "e": {14}, | |
397 | } | |
398 | ||
399 | if err := Merge(&m, n, WithOverride); err != nil { | |
400 | t.Fatalf(err.Error()) | |
401 | } | |
402 | ||
403 | assert.Equalf(t, expect, m, "Test Failed") | |
404 | if !reflect.DeepEqual(m, expect) { | |
405 | t.Fatalf("Test failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", m, expect) | |
406 | } | |
407 | } | |
408 | ||
409 | func TestMergeUsingStructAndMap(t *testing.T) { | |
410 | type multiPtr struct { | |
411 | Text string | |
412 | Number int | |
413 | } | |
414 | type final struct { | |
415 | Msg1 string | |
416 | Msg2 string | |
417 | } | |
418 | type params struct { | |
419 | Name string | |
420 | Multi *multiPtr | |
421 | Final *final | |
422 | } | |
423 | type config struct { | |
424 | Foo string | |
425 | Bar string | |
426 | Params *params | |
427 | } | |
428 | ||
429 | cases := []struct { | |
430 | name string | |
431 | overwrite bool | |
432 | changes *config | |
433 | target *config | |
434 | output *config | |
435 | }{ | |
436 | { | |
437 | name: "Should overwrite values in target for non-nil values in source", | |
438 | overwrite: true, | |
439 | changes: &config{ | |
440 | Bar: "from changes", | |
441 | Params: ¶ms{ | |
442 | Final: &final{ | |
443 | Msg1: "from changes", | |
444 | Msg2: "from changes", | |
445 | }, | |
446 | }, | |
447 | }, | |
448 | target: &config{ | |
449 | Foo: "from target", | |
450 | Params: ¶ms{ | |
451 | Name: "from target", | |
452 | Multi: &multiPtr{ | |
453 | Text: "from target", | |
454 | Number: 5, | |
455 | }, | |
456 | Final: &final{ | |
457 | Msg1: "from target", | |
458 | Msg2: "", | |
459 | }, | |
460 | }, | |
461 | }, | |
462 | output: &config{ | |
463 | Foo: "from target", | |
464 | Bar: "from changes", | |
465 | Params: ¶ms{ | |
466 | Name: "from target", | |
467 | Multi: &multiPtr{ | |
468 | Text: "from target", | |
469 | Number: 5, | |
470 | }, | |
471 | Final: &final{ | |
472 | Msg1: "from changes", | |
473 | Msg2: "from changes", | |
474 | }, | |
475 | }, | |
476 | }, | |
477 | }, | |
478 | { | |
479 | name: "Should not overwrite values in target for non-nil values in source", | |
480 | overwrite: false, | |
481 | changes: &config{ | |
482 | Bar: "from changes", | |
483 | Params: ¶ms{ | |
484 | Final: &final{ | |
485 | Msg1: "from changes", | |
486 | Msg2: "from changes", | |
487 | }, | |
488 | }, | |
489 | }, | |
490 | target: &config{ | |
491 | Foo: "from target", | |
492 | Params: ¶ms{ | |
493 | Name: "from target", | |
494 | Multi: &multiPtr{ | |
495 | Text: "from target", | |
496 | Number: 5, | |
497 | }, | |
498 | Final: &final{ | |
499 | Msg1: "from target", | |
500 | Msg2: "", | |
501 | }, | |
502 | }, | |
503 | }, | |
504 | output: &config{ | |
505 | Foo: "from target", | |
506 | Bar: "from changes", | |
507 | Params: ¶ms{ | |
508 | Name: "from target", | |
509 | Multi: &multiPtr{ | |
510 | Text: "from target", | |
511 | Number: 5, | |
512 | }, | |
513 | Final: &final{ | |
514 | Msg1: "from target", | |
515 | Msg2: "from changes", | |
516 | }, | |
517 | }, | |
518 | }, | |
519 | }, | |
520 | } | |
521 | ||
522 | for _, tc := range cases { | |
523 | t.Run(tc.name, func(t *testing.T) { | |
524 | var err error | |
525 | if tc.overwrite { | |
526 | err = Merge(tc.target, *tc.changes, WithOverride) | |
527 | } else { | |
528 | err = Merge(tc.target, *tc.changes) | |
529 | } | |
530 | if err != nil { | |
531 | t.Error(err) | |
532 | } | |
533 | if !reflect.DeepEqual(tc.target, tc.output) { | |
534 | t.Fatalf("Test failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", tc.target, tc.output) | |
535 | } | |
536 | }) | |
537 | } | |
538 | } | |
374 | 539 | func TestMaps(t *testing.T) { |
375 | 540 | m := map[string]simpleTest{ |
376 | 541 | "a": {}, |
730 | 895 | t.Fatalf("dst.C should be true") |
731 | 896 | } |
732 | 897 | } |
898 | ||
899 | func TestMergeMapWithInnerSliceOfDifferentType(t *testing.T) { | |
900 | testCases := []struct { | |
901 | name string | |
902 | options []func(*Config) | |
903 | err string | |
904 | }{ | |
905 | { | |
906 | "With override and append slice", | |
907 | []func(*Config){WithOverride, WithAppendSlice}, | |
908 | "cannot append two slices with different type", | |
909 | }, | |
910 | { | |
911 | "With override and type check", | |
912 | []func(*Config){WithOverride, WithTypeCheck}, | |
913 | "cannot override two slices with different type", | |
914 | }, | |
915 | } | |
916 | for _, tc := range testCases { | |
917 | t.Run(tc.name, func(t *testing.T) { | |
918 | src := map[string]interface{}{ | |
919 | "foo": []string{"a", "b"}, | |
920 | } | |
921 | dst := map[string]interface{}{ | |
922 | "foo": []int{1, 2}, | |
923 | } | |
924 | ||
925 | if err := Merge(&src, &dst, tc.options...); err == nil || !strings.Contains(err.Error(), tc.err) { | |
926 | t.Fatalf("expected %q, got %q", tc.err, err) | |
927 | } | |
928 | }) | |
929 | } | |
930 | } | |
931 | ||
932 | func TestMergeSlicesIsNotSupported(t *testing.T) { | |
933 | src := []string{"a", "b"} | |
934 | dst := []int{1, 2} | |
935 | ||
936 | if err := Merge(&src, &dst, WithOverride, WithAppendSlice); err != ErrNotSupported { | |
937 | t.Fatalf("expected %q, got %q", ErrNotSupported, err) | |
938 | } | |
939 | } |