7 | 7 |
import (
|
8 | 8 |
"reflect"
|
9 | 9 |
"testing"
|
|
10 |
"time"
|
|
11 |
|
|
12 |
"gopkg.in/yaml.v1"
|
10 | 13 |
)
|
11 | 14 |
|
12 | 15 |
type simpleTest struct {
|
|
16 | 19 |
type complexTest struct {
|
17 | 20 |
St simpleTest
|
18 | 21 |
sz int
|
19 | |
Id string
|
|
22 |
ID string
|
20 | 23 |
}
|
21 | 24 |
|
22 | 25 |
type moreComplextText struct {
|
|
98 | 101 |
|
99 | 102 |
func TestComplexStruct(t *testing.T) {
|
100 | 103 |
a := complexTest{}
|
101 | |
a.Id = "athing"
|
|
104 |
a.ID = "athing"
|
102 | 105 |
b := complexTest{simpleTest{42}, 1, "bthing"}
|
103 | 106 |
if err := Merge(&a, b); err != nil {
|
104 | 107 |
t.FailNow()
|
|
109 | 112 |
if a.sz == 1 {
|
110 | 113 |
t.Fatalf("a's private field sz not preserved from merge: a.sz(%d) == b.sz(%d)", a.sz, b.sz)
|
111 | 114 |
}
|
112 | |
if a.Id == b.Id {
|
113 | |
t.Fatalf("a's field Id merged unexpectedly: a.Id(%s) == b.Id(%s)", a.Id, b.Id)
|
|
115 |
if a.ID == b.ID {
|
|
116 |
t.Fatalf("a's field ID merged unexpectedly: a.ID(%s) == b.ID(%s)", a.ID, b.ID)
|
114 | 117 |
}
|
115 | 118 |
}
|
116 | 119 |
|
|
241 | 244 |
|
242 | 245 |
func TestMapsWithOverwrite(t *testing.T) {
|
243 | 246 |
m := map[string]simpleTest{
|
244 | |
"a": simpleTest{}, // overwritten by 16
|
245 | |
"b": simpleTest{42}, // not overwritten by empty value
|
246 | |
"c": simpleTest{13}, // overwritten by 12
|
247 | |
"d": simpleTest{61},
|
|
247 |
"a": {}, // overwritten by 16
|
|
248 |
"b": {42}, // not overwritten by empty value
|
|
249 |
"c": {13}, // overwritten by 12
|
|
250 |
"d": {61},
|
248 | 251 |
}
|
249 | 252 |
n := map[string]simpleTest{
|
250 | |
"a": simpleTest{16},
|
251 | |
"b": simpleTest{},
|
252 | |
"c": simpleTest{12},
|
253 | |
"e": simpleTest{14},
|
|
253 |
"a": {16},
|
|
254 |
"b": {},
|
|
255 |
"c": {12},
|
|
256 |
"e": {14},
|
254 | 257 |
}
|
255 | 258 |
expect := map[string]simpleTest{
|
256 | |
"a": simpleTest{16},
|
257 | |
"b": simpleTest{},
|
258 | |
"c": simpleTest{12},
|
259 | |
"d": simpleTest{61},
|
260 | |
"e": simpleTest{14},
|
|
259 |
"a": {16},
|
|
260 |
"b": {},
|
|
261 |
"c": {12},
|
|
262 |
"d": {61},
|
|
263 |
"e": {14},
|
261 | 264 |
}
|
262 | 265 |
|
263 | 266 |
if err := MergeWithOverwrite(&m, n); err != nil {
|
|
271 | 274 |
|
272 | 275 |
func TestMaps(t *testing.T) {
|
273 | 276 |
m := map[string]simpleTest{
|
274 | |
"a": simpleTest{},
|
275 | |
"b": simpleTest{42},
|
276 | |
"c": simpleTest{13},
|
277 | |
"d": simpleTest{61},
|
|
277 |
"a": {},
|
|
278 |
"b": {42},
|
|
279 |
"c": {13},
|
|
280 |
"d": {61},
|
278 | 281 |
}
|
279 | 282 |
n := map[string]simpleTest{
|
280 | |
"a": simpleTest{16},
|
281 | |
"b": simpleTest{},
|
282 | |
"c": simpleTest{12},
|
283 | |
"e": simpleTest{14},
|
|
283 |
"a": {16},
|
|
284 |
"b": {},
|
|
285 |
"c": {12},
|
|
286 |
"e": {14},
|
284 | 287 |
}
|
285 | 288 |
expect := map[string]simpleTest{
|
286 | |
"a": simpleTest{0},
|
287 | |
"b": simpleTest{42},
|
288 | |
"c": simpleTest{13},
|
289 | |
"d": simpleTest{61},
|
290 | |
"e": simpleTest{14},
|
|
289 |
"a": {0},
|
|
290 |
"b": {42},
|
|
291 |
"c": {13},
|
|
292 |
"d": {61},
|
|
293 |
"e": {14},
|
291 | 294 |
}
|
292 | 295 |
|
293 | 296 |
if err := Merge(&m, n); err != nil {
|
|
307 | 310 |
t.Fatalf(`n overwritten in m: m["c"].Value(%d) != n["c"].Value(%d)`, m["c"].Value, n["c"].Value)
|
308 | 311 |
}
|
309 | 312 |
}
|
|
313 |
<<<<<<< HEAD
|
|
314 |
=======
|
|
315 |
|
|
316 |
func TestYAMLMaps(t *testing.T) {
|
|
317 |
thing := loadYAML("testdata/thing.yml")
|
|
318 |
license := loadYAML("testdata/license.yml")
|
|
319 |
ft := thing["fields"].(map[interface{}]interface{})
|
|
320 |
fl := license["fields"].(map[interface{}]interface{})
|
|
321 |
expectedLength := len(ft) + len(fl)
|
|
322 |
if err := Merge(&license, thing); err != nil {
|
|
323 |
t.Fatal(err.Error())
|
|
324 |
}
|
|
325 |
currentLength := len(license["fields"].(map[interface{}]interface{}))
|
|
326 |
if currentLength != expectedLength {
|
|
327 |
t.Fatalf(`thing not merged in license properly, license must have %d elements instead of %d`, expectedLength, currentLength)
|
|
328 |
}
|
|
329 |
fields := license["fields"].(map[interface{}]interface{})
|
|
330 |
if _, ok := fields["id"]; !ok {
|
|
331 |
t.Fatalf(`thing not merged in license properly, license must have a new id field from thing`)
|
|
332 |
}
|
|
333 |
}
|
|
334 |
|
|
335 |
func TestTwoPointerValues(t *testing.T) {
|
|
336 |
a := &simpleTest{}
|
|
337 |
b := &simpleTest{42}
|
|
338 |
if err := Merge(a, b); err != nil {
|
|
339 |
t.Fatalf(`Boom. You crossed the streams: %s`, err)
|
|
340 |
}
|
|
341 |
}
|
|
342 |
|
|
343 |
func TestMap(t *testing.T) {
|
|
344 |
a := complexTest{}
|
|
345 |
a.ID = "athing"
|
|
346 |
c := moreComplextText{a, simpleTest{}, simpleTest{}}
|
|
347 |
b := map[string]interface{}{
|
|
348 |
"ct": map[string]interface{}{
|
|
349 |
"st": map[string]interface{}{
|
|
350 |
"value": 42,
|
|
351 |
},
|
|
352 |
"sz": 1,
|
|
353 |
"id": "bthing",
|
|
354 |
},
|
|
355 |
"st": &simpleTest{144}, // Mapping a reference
|
|
356 |
"zt": simpleTest{299}, // Mapping a missing field (zt doesn't exist)
|
|
357 |
"nt": simpleTest{3},
|
|
358 |
}
|
|
359 |
if err := Map(&c, b); err != nil {
|
|
360 |
t.FailNow()
|
|
361 |
}
|
|
362 |
m := b["ct"].(map[string]interface{})
|
|
363 |
n := m["st"].(map[string]interface{})
|
|
364 |
o := b["st"].(*simpleTest)
|
|
365 |
p := b["nt"].(simpleTest)
|
|
366 |
if c.Ct.St.Value != 42 {
|
|
367 |
t.Fatalf("b not merged in properly: c.Ct.St.Value(%d) != b.Ct.St.Value(%d)", c.Ct.St.Value, n["value"])
|
|
368 |
}
|
|
369 |
if c.St.Value != 144 {
|
|
370 |
t.Fatalf("b not merged in properly: c.St.Value(%d) != b.St.Value(%d)", c.St.Value, o.Value)
|
|
371 |
}
|
|
372 |
if c.Nt.Value != 3 {
|
|
373 |
t.Fatalf("b not merged in properly: c.Nt.Value(%d) != b.Nt.Value(%d)", c.St.Value, p.Value)
|
|
374 |
}
|
|
375 |
if c.Ct.sz == 1 {
|
|
376 |
t.Fatalf("a's private field sz not preserved from merge: c.Ct.sz(%d) == b.Ct.sz(%d)", c.Ct.sz, m["sz"])
|
|
377 |
}
|
|
378 |
if c.Ct.ID == m["id"] {
|
|
379 |
t.Fatalf("a's field ID merged unexpectedly: c.Ct.ID(%s) == b.Ct.ID(%s)", c.Ct.ID, m["id"])
|
|
380 |
}
|
|
381 |
}
|
|
382 |
|
|
383 |
func TestSimpleMap(t *testing.T) {
|
|
384 |
a := simpleTest{}
|
|
385 |
b := map[string]interface{}{
|
|
386 |
"value": 42,
|
|
387 |
}
|
|
388 |
if err := Map(&a, b); err != nil {
|
|
389 |
t.FailNow()
|
|
390 |
}
|
|
391 |
if a.Value != 42 {
|
|
392 |
t.Fatalf("b not merged in properly: a.Value(%d) != b.Value(%v)", a.Value, b["value"])
|
|
393 |
}
|
|
394 |
}
|
|
395 |
|
|
396 |
type pointerMapTest struct {
|
|
397 |
A int
|
|
398 |
hidden int
|
|
399 |
B *simpleTest
|
|
400 |
}
|
|
401 |
|
|
402 |
func TestBackAndForth(t *testing.T) {
|
|
403 |
pt := pointerMapTest{42, 1, &simpleTest{66}}
|
|
404 |
m := make(map[string]interface{})
|
|
405 |
if err := Map(&m, pt); err != nil {
|
|
406 |
t.FailNow()
|
|
407 |
}
|
|
408 |
var (
|
|
409 |
v interface{}
|
|
410 |
ok bool
|
|
411 |
)
|
|
412 |
if v, ok = m["a"]; v.(int) != pt.A || !ok {
|
|
413 |
t.Fatalf("pt not merged in properly: m[`a`](%d) != pt.A(%d)", v, pt.A)
|
|
414 |
}
|
|
415 |
if v, ok = m["b"]; !ok {
|
|
416 |
t.Fatalf("pt not merged in properly: B is missing in m")
|
|
417 |
}
|
|
418 |
var st *simpleTest
|
|
419 |
if st = v.(*simpleTest); st.Value != 66 {
|
|
420 |
t.Fatalf("something went wrong while mapping pt on m, B wasn't copied")
|
|
421 |
}
|
|
422 |
bpt := pointerMapTest{}
|
|
423 |
if err := Map(&bpt, m); err != nil {
|
|
424 |
t.Fatal(err)
|
|
425 |
}
|
|
426 |
if bpt.A != pt.A {
|
|
427 |
t.Fatalf("pt not merged in properly: bpt.A(%d) != pt.A(%d)", bpt.A, pt.A)
|
|
428 |
}
|
|
429 |
if bpt.hidden == pt.hidden {
|
|
430 |
t.Fatalf("pt unexpectedly merged: bpt.hidden(%d) == pt.hidden(%d)", bpt.hidden, pt.hidden)
|
|
431 |
}
|
|
432 |
if bpt.B.Value != pt.B.Value {
|
|
433 |
t.Fatalf("pt not merged in properly: bpt.B.Value(%d) != pt.B.Value(%d)", bpt.B.Value, pt.B.Value)
|
|
434 |
}
|
|
435 |
}
|
|
436 |
|
|
437 |
type structWithTimePointer struct {
|
|
438 |
Birth *time.Time
|
|
439 |
}
|
|
440 |
|
|
441 |
func TestTime(t *testing.T) {
|
|
442 |
now := time.Now()
|
|
443 |
dataStruct := structWithTimePointer{
|
|
444 |
Birth: &now,
|
|
445 |
}
|
|
446 |
dataMap := map[string]interface{}{
|
|
447 |
"Birth": &now,
|
|
448 |
}
|
|
449 |
b := structWithTimePointer{}
|
|
450 |
if err := Merge(&b, dataStruct); err != nil {
|
|
451 |
t.FailNow()
|
|
452 |
}
|
|
453 |
if b.Birth.IsZero() {
|
|
454 |
t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataStruct['Birth'](%v)", b.Birth, dataStruct.Birth)
|
|
455 |
}
|
|
456 |
if b.Birth != dataStruct.Birth {
|
|
457 |
t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataStruct['Birth'](%v)", b.Birth, dataStruct.Birth)
|
|
458 |
}
|
|
459 |
b = structWithTimePointer{}
|
|
460 |
if err := Map(&b, dataMap); err != nil {
|
|
461 |
t.FailNow()
|
|
462 |
}
|
|
463 |
if b.Birth.IsZero() {
|
|
464 |
t.Fatalf("time.Time not merged in properly: b.Birth(%v) != dataMap['Birth'](%v)", b.Birth, dataMap["Birth"])
|
|
465 |
}
|
|
466 |
}
|
|
467 |
|
|
468 |
type simpleNested struct {
|
|
469 |
A int
|
|
470 |
}
|
|
471 |
|
|
472 |
type structWithNestedPtrValueMap struct {
|
|
473 |
NestedPtrValue map[string]*simpleNested
|
|
474 |
}
|
|
475 |
|
|
476 |
func TestNestedPtrValueInMap(t *testing.T) {
|
|
477 |
src := &structWithNestedPtrValueMap{
|
|
478 |
NestedPtrValue: map[string]*simpleNested{
|
|
479 |
"x": {
|
|
480 |
A: 1,
|
|
481 |
},
|
|
482 |
},
|
|
483 |
}
|
|
484 |
dst := &structWithNestedPtrValueMap{
|
|
485 |
NestedPtrValue: map[string]*simpleNested{
|
|
486 |
"x": {},
|
|
487 |
},
|
|
488 |
}
|
|
489 |
if err := Map(dst, src); err != nil {
|
|
490 |
t.FailNow()
|
|
491 |
}
|
|
492 |
if dst.NestedPtrValue["x"].A == 0 {
|
|
493 |
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)
|
|
494 |
}
|
|
495 |
}
|
|
496 |
|
|
497 |
func loadYAML(path string) (m map[string]interface{}) {
|
|
498 |
m = make(map[string]interface{})
|
|
499 |
raw, _ := ioutil.ReadFile(path)
|
|
500 |
_ = yaml.Unmarshal(raw, &m)
|
|
501 |
return
|
|
502 |
}
|
|
503 |
|
|
504 |
type structWithMap struct {
|
|
505 |
m map[string]structWithUnexportedProperty
|
|
506 |
}
|
|
507 |
|
|
508 |
type structWithUnexportedProperty struct {
|
|
509 |
s string
|
|
510 |
}
|
|
511 |
|
|
512 |
func TestUnexportedProperty(t *testing.T) {
|
|
513 |
a := structWithMap{map[string]structWithUnexportedProperty{
|
|
514 |
"key": structWithUnexportedProperty{"hello"},
|
|
515 |
}}
|
|
516 |
b := structWithMap{map[string]structWithUnexportedProperty{
|
|
517 |
"key": structWithUnexportedProperty{"hi"},
|
|
518 |
}}
|
|
519 |
defer func() {
|
|
520 |
if r := recover(); r != nil {
|
|
521 |
t.Errorf("Should not have panicked")
|
|
522 |
}
|
|
523 |
}()
|
|
524 |
Merge(&a, b)
|
|
525 |
}
|
|
526 |
>>>>>>> upstream/0.2.2
|