1 package copystructure
2
3 import (
4 "fmt"
5 "reflect"
6 "sync"
7 "testing"
8 "time"
9 "unsafe"
10 )
11
12 func TestCopy_complex(t *testing.T) {
13 v := map[string]interface{}{
14 "foo": []string{"a", "b"},
15 "bar": "baz",
16 }
17
18 result, err := Copy(v)
19 if err != nil {
20 t.Fatalf("err: %s", err)
21 }
22
23 if !reflect.DeepEqual(result, v) {
24 t.Fatalf("bad: %#v", result)
25 }
26 }
27
28 func TestCopy_interfacePointer(t *testing.T) {
29 type Nested struct {
30 Field string
31 }
32
33 type Test struct {
34 Value *interface{}
35 }
36
37 ifacePtr := func(v interface{}) *interface{} {
38 return &v
39 }
40
41 v := Test{
42 Value: ifacePtr(Nested{Field: "111"}),
43 }
44 result, err := Copy(v)
45 if err != nil {
46 t.Fatalf("err: %s", err)
47 }
48
49 if !reflect.DeepEqual(result, v) {
50 t.Fatalf("bad: %#v", result)
51 }
52 }
53
54 func TestCopy_primitive(t *testing.T) {
55 cases := []interface{}{
56 42,
57 "foo",
58 1.2,
59 }
60
61 for _, tc := range cases {
62 result, err := Copy(tc)
63 if err != nil {
64 t.Fatalf("err: %s", err)
65 }
66 if result != tc {
67 t.Fatalf("bad: %#v", result)
68 }
69 }
70 }
71
72 func TestCopy_primitivePtr(t *testing.T) {
73 i := 42
74 s := "foo"
75 f := 1.2
76 cases := []interface{}{
77 &i,
78 &s,
79 &f,
80 }
81
82 for i, tc := range cases {
83 result, err := Copy(tc)
84 if err != nil {
85 t.Fatalf("err: %s", err)
86 }
87
88 if !reflect.DeepEqual(result, tc) {
89 t.Fatalf("%d exptected: %#v\nbad: %#v", i, tc, result)
90 }
91 }
92 }
93
94 func TestCopy_map(t *testing.T) {
95 v := map[string]interface{}{
96 "bar": "baz",
97 }
98
99 result, err := Copy(v)
100 if err != nil {
101 t.Fatalf("err: %s", err)
102 }
103
104 if !reflect.DeepEqual(result, v) {
105 t.Fatalf("bad: %#v", result)
106 }
107 }
108
109 func TestCopy_array(t *testing.T) {
110 v := [2]string{"bar", "baz"}
111
112 result, err := Copy(v)
113 if err != nil {
114 t.Fatalf("err: %s", err)
115 }
116
117 if !reflect.DeepEqual(result, v) {
118 t.Fatalf("bad: %#v", result)
119 }
120 }
121
122 func TestCopy_pointerToArray(t *testing.T) {
123 v := &[2]string{"bar", "baz"}
124
125 result, err := Copy(v)
126 if err != nil {
127 t.Fatalf("err: %s", err)
128 }
129
130 if !reflect.DeepEqual(result, v) {
131 t.Fatalf("bad: %#v", result)
132 }
133 }
134
135 func TestCopy_slice(t *testing.T) {
136 v := []string{"bar", "baz"}
137
138 result, err := Copy(v)
139 if err != nil {
140 t.Fatalf("err: %s", err)
141 }
142
143 if !reflect.DeepEqual(result, v) {
144 t.Fatalf("bad: %#v", result)
145 }
146 }
147
148 func TestCopy_pointerToSlice(t *testing.T) {
149 v := &[]string{"bar", "baz"}
150
151 result, err := Copy(v)
152 if err != nil {
153 t.Fatalf("err: %s", err)
154 }
155
156 if !reflect.DeepEqual(result, v) {
157 t.Fatalf("bad: %#v", result)
158 }
159 }
160
161 func TestCopy_pointerToMap(t *testing.T) {
162 v := &map[string]string{"bar": "baz"}
163
164 result, err := Copy(v)
165 if err != nil {
166 t.Fatalf("err: %s", err)
167 }
168
169 if !reflect.DeepEqual(result, v) {
170 t.Fatalf("bad: %#v", result)
171 }
172 }
173
174 func TestCopy_struct(t *testing.T) {
175 type test struct {
176 Value string
177 }
178
179 v := test{Value: "foo"}
180
181 result, err := Copy(v)
182 if err != nil {
183 t.Fatalf("err: %s", err)
184 }
185
186 if !reflect.DeepEqual(result, v) {
187 t.Fatalf("bad: %#v", result)
188 }
189 }
190
191 func TestCopy_structPtr(t *testing.T) {
192 type test struct {
193 Value string
194 }
195
196 v := &test{Value: "foo"}
197
198 result, err := Copy(v)
199 if err != nil {
200 t.Fatalf("err: %s", err)
201 }
202
203 if !reflect.DeepEqual(result, v) {
204 t.Fatalf("bad: %#v", result)
205 }
206 }
207
208 func TestCopy_structNil(t *testing.T) {
209 type test struct {
210 Value string
211 }
212
213 var v *test
214 result, err := Copy(v)
215 if err != nil {
216 t.Fatalf("err: %s", err)
217 }
218 if v, ok := result.(*test); !ok {
219 t.Fatalf("bad: %#v", result)
220 } else if v != nil {
221 t.Fatalf("bad: %#v", v)
222 }
223 }
224
225 func TestCopy_structShallow(t *testing.T) {
226 type test struct {
227 Value string
228 Value2 *string `copy:"shallow"`
229 }
230
231 value2 := "bar"
232 value2ptr := &value2
233 v := test{Value: "foo", Value2: value2ptr}
234
235 result, err := Copy(v)
236 if err != nil {
237 t.Fatalf("err: %s", err)
238 }
239 if !reflect.DeepEqual(result, v) {
240 t.Fatalf("bad: %#v", result)
241 }
242
243 vcopy := result.(test)
244 if vcopy.Value2 != v.Value2 {
245 t.Fatal("should shallow copy the pointer")
246 }
247 }
248
249 func TestCopy_structShallowWithUnsafe(t *testing.T) {
250 type nested struct {
251 v unsafe.Pointer
252 }
253
254 type test struct {
255 Value string
256 Value2 *nested `copy:"shallow"`
257 }
258
259 value2 := &nested{}
260 v := test{Value: "foo", Value2: value2}
261
262 result, err := Copy(v)
263 if err != nil {
264 t.Fatalf("err: %s", err)
265 }
266 if !reflect.DeepEqual(result, v) {
267 t.Fatalf("bad: %#v", result)
268 }
269
270 vcopy := result.(test)
271 if vcopy.Value2 != v.Value2 {
272 t.Fatal("should shallow copy the pointer")
273 }
274 }
275
276 func TestCopy_structIgnore(t *testing.T) {
277 type test struct {
278 Value string
279 Value2 *string `copy:"ignore"`
280 }
281
282 value2 := "bar"
283 value2ptr := &value2
284 v := test{Value: "foo", Value2: value2ptr}
285
286 result, err := Copy(v)
287 if err != nil {
288 t.Fatalf("err: %s", err)
289 }
290 vcopy := result.(test)
291 if vcopy.Value2 != nil {
292 t.Fatal("should be nil")
293 }
294 }
295
296 func TestCopy_structNested(t *testing.T) {
297 type TestInner struct{}
298
299 type Test struct {
300 Test *TestInner
301 }
302
303 v := Test{}
304
305 result, err := Copy(v)
306 if err != nil {
307 t.Fatalf("err: %s", err)
308 }
309
310 if !reflect.DeepEqual(result, v) {
311 t.Fatalf("bad: %#v", result)
312 }
313 }
314
315 func TestCopy_structWithNestedArray(t *testing.T) {
316 type TestInner struct {
317 Value string
318 }
319
320 type Test struct {
321 Value [2]TestInner
322 }
323
324 v := Test{
325 Value: [2]TestInner{
326 {Value: "bar"},
327 {Value: "baz"},
328 },
329 }
330
331 result, err := Copy(v)
332 if err != nil {
333 t.Fatalf("err: %s", err)
334 }
335
336 if !reflect.DeepEqual(result, v) {
337 t.Fatalf("bad: %#v", result)
338 }
339 }
340
341 func TestCopy_structWithPointerToSliceField(t *testing.T) {
342 type Test struct {
343 Value *[]string
344 }
345
346 v := Test{
347 Value: &[]string{"bar", "baz"},
348 }
349
350 result, err := Copy(v)
351 if err != nil {
352 t.Fatalf("err: %s", err)
353 }
354
355 if !reflect.DeepEqual(result, v) {
356 t.Fatalf("bad: %#v", result)
357 }
358 }
359
360 func TestCopy_structWithPointerToArrayField(t *testing.T) {
361 type Test struct {
362 Value *[2]string
363 }
364
365 v := Test{
366 Value: &[2]string{"bar", "baz"},
367 }
368
369 result, err := Copy(v)
370 if err != nil {
371 t.Fatalf("err: %s", err)
372 }
373
374 if !reflect.DeepEqual(result, v) {
375 t.Fatalf("bad: %#v", result)
376 }
377 }
378
379 func TestCopy_structWithPointerToMapField(t *testing.T) {
380 type Test struct {
381 Value *map[string]string
382 }
383
384 v := Test{
385 Value: &map[string]string{"bar": "baz"},
386 }
387
388 result, err := Copy(v)
389 if err != nil {
390 t.Fatalf("err: %s", err)
391 }
392
393 if !reflect.DeepEqual(result, v) {
394 t.Fatalf("bad: %#v", result)
395 }
396 }
397
398 func TestCopy_structUnexported(t *testing.T) {
399 type test struct {
400 Value string
401
402 private string
403 }
404
405 v := test{Value: "foo"}
406
407 result, err := Copy(v)
408 if err != nil {
409 t.Fatalf("err: %s", err)
410 }
411
412 if !reflect.DeepEqual(result, v) {
413 t.Fatalf("bad: %#v", result)
414 }
415 }
416
417 func TestCopy_structUnexportedMap(t *testing.T) {
418 type Sub struct {
419 Foo map[string]interface{}
420 }
421
422 type test struct {
423 Value string
424
425 private Sub
426 }
427
428 v := test{
429 Value: "foo",
430 private: Sub{
431 Foo: map[string]interface{}{
432 "yo": 42,
433 },
434 },
435 }
436
437 result, err := Copy(v)
438 if err != nil {
439 t.Fatalf("err: %s", err)
440 }
441
442
443 v.private = Sub{}
444 if !reflect.DeepEqual(result, v) {
445 t.Fatalf("bad:\n\n%#v\n\n%#v", result, v)
446 }
447 }
448
449 func TestCopy_structUnexportedArray(t *testing.T) {
450 type Sub struct {
451 Foo [2]string
452 }
453
454 type test struct {
455 Value string
456
457 private Sub
458 }
459
460 v := test{
461 Value: "foo",
462 private: Sub{
463 Foo: [2]string{"bar", "baz"},
464 },
465 }
466
467 result, err := Copy(v)
468 if err != nil {
469 t.Fatalf("err: %s", err)
470 }
471
472
473 v.private = Sub{}
474 if !reflect.DeepEqual(result, v) {
475 t.Fatalf("bad:\n\n%#v\n\n%#v", result, v)
476 }
477 }
478
479
480
481 func TestCopy_structUnexportedPtrMap(t *testing.T) {
482 type Foo interface{}
483
484 type Sub struct {
485 List []Foo
486 }
487
488 type test struct {
489 Value string
490
491 private *Sub
492 }
493
494 v := test{
495 Value: "foo",
496 private: &Sub{
497 List: []Foo{&Sub{}},
498 },
499 }
500
501 result, err := Copy(v)
502 if err != nil {
503 t.Fatalf("err: %s", err)
504 }
505
506
507 v.private = nil
508 if !reflect.DeepEqual(result, v) {
509 t.Fatalf("bad:\n\n%#v\n\n%#v", result, v)
510 }
511 }
512
513 func TestCopy_nestedStructUnexported(t *testing.T) {
514 type subTest struct {
515 mine string
516 }
517
518 type test struct {
519 Value string
520 private subTest
521 }
522
523 v := test{Value: "foo"}
524
525 result, err := Copy(v)
526 if err != nil {
527 t.Fatalf("err: %s", err)
528 }
529
530 if !reflect.DeepEqual(result, v) {
531 t.Fatalf("bad: %#v", result)
532 }
533 }
534
535 func TestCopy_time(t *testing.T) {
536 type test struct {
537 Value time.Time
538 }
539
540 v := test{Value: time.Now().UTC()}
541
542 result, err := Copy(v)
543 if err != nil {
544 t.Fatalf("err: %s", err)
545 }
546
547 if !reflect.DeepEqual(result, v) {
548 t.Fatalf("bad: %#v", result)
549 }
550 }
551
552 func TestCopy_aliased(t *testing.T) {
553 type (
554 Int int
555 Str string
556 Map map[Int]interface{}
557 Slice []Str
558 )
559
560 v := Map{
561 1: Map{10: 20},
562 2: Map(nil),
563 3: Slice{"a", "b"},
564 }
565
566 result, err := Copy(v)
567 if err != nil {
568 t.Fatalf("err: %s", err)
569 }
570
571 if !reflect.DeepEqual(result, v) {
572 t.Fatalf("bad: %#v", result)
573 }
574 }
575
576 type EmbeddedLocker struct {
577 sync.Mutex
578 Map map[int]int
579 }
580
581 func TestCopy_embeddedLocker(t *testing.T) {
582 v := &EmbeddedLocker{
583 Map: map[int]int{42: 111},
584 }
585
586 v.Lock()
587
588 var result interface{}
589 var err error
590
591 copied := make(chan bool)
592
593 go func() {
594 result, err = Config{Lock: true}.Copy(v)
595 close(copied)
596 }()
597
598
599 select {
600 case <-copied:
601 t.Fatal("copy completed while locked!")
602 case <-time.After(100 * time.Millisecond):
603 v.Unlock()
604 }
605
606 <-copied
607
608
609 result.(*EmbeddedLocker).Lock()
610 result.(*EmbeddedLocker).Unlock()
611
612 if err != nil {
613 t.Fatalf("err: %s", err)
614 }
615
616 if !reflect.DeepEqual(result, v) {
617 t.Fatalf("bad: %#v", result)
618 }
619 }
620
621
622
623 func TestCopy_lockRace(t *testing.T) {
624 v := &EmbeddedLocker{
625 Map: map[int]int{},
626 }
627
628 var wg sync.WaitGroup
629 for i := 0; i < 100; i++ {
630 wg.Add(1)
631 go func() {
632 defer wg.Done()
633 for i := 0; i < 100; i++ {
634 v.Lock()
635 v.Map[i] = i
636 v.Unlock()
637 }
638 }()
639 wg.Add(1)
640 go func() {
641 defer wg.Done()
642 Config{Lock: true}.Copy(v)
643 }()
644 }
645
646 wg.Wait()
647 result, err := Config{Lock: true}.Copy(v)
648
649
650 result.(*EmbeddedLocker).Lock()
651 result.(*EmbeddedLocker).Unlock()
652
653 if err != nil {
654 t.Fatalf("err: %s", err)
655 }
656
657 if !reflect.DeepEqual(result, v) {
658 t.Fatalf("bad: %#v", result)
659 }
660 }
661
662 type LockedField struct {
663 String string
664 Locker *EmbeddedLocker
665
666 Mutex sync.Mutex
667 nilMutex *sync.Mutex
668 }
669
670 func TestCopy_lockedField(t *testing.T) {
671 v := &LockedField{
672 String: "orig",
673 Locker: &EmbeddedLocker{
674 Map: map[int]int{42: 111},
675 },
676 }
677
678
679 v.Locker.Lock()
680 v.Mutex.Lock()
681
682 var result interface{}
683 var err error
684
685 copied := make(chan bool)
686
687 go func() {
688 result, err = Config{Lock: true}.Copy(v)
689 close(copied)
690 }()
691
692
693 select {
694 case <-copied:
695 t.Fatal("copy completed while locked!")
696 case <-time.After(100 * time.Millisecond):
697 v.Locker.Unlock()
698 }
699
700 <-copied
701
702
703 result.(*LockedField).Locker.Lock()
704 result.(*LockedField).Locker.Unlock()
705 result.(*LockedField).Mutex.Lock()
706 result.(*LockedField).Mutex.Unlock()
707
708
709 v.Mutex.Unlock()
710
711 if err != nil {
712 t.Fatalf("err: %s", err)
713 }
714
715 if !reflect.DeepEqual(result, v) {
716 t.Fatalf("expected:\n%#v\nbad:\n%#v\n", v, result)
717 }
718 }
719
720
721 type lockedMap map[int]int
722
723 var mapLock sync.Mutex
724
725 func (m lockedMap) Lock() { mapLock.Lock() }
726 func (m lockedMap) Unlock() { mapLock.Unlock() }
727
728 func TestCopy_lockedMap(t *testing.T) {
729 v := lockedMap{1: 2}
730 v.Lock()
731
732 var result interface{}
733 var err error
734
735 copied := make(chan bool)
736
737 go func() {
738 result, err = Config{Lock: true}.Copy(&v)
739 close(copied)
740 }()
741
742
743 select {
744 case <-copied:
745 t.Fatal("copy completed while locked!")
746 case <-time.After(100 * time.Millisecond):
747 v.Unlock()
748 }
749
750 <-copied
751
752
753 result.(*lockedMap).Lock()
754 result.(*lockedMap).Unlock()
755
756 if err != nil {
757 t.Fatalf("err: %s", err)
758 }
759
760 if !reflect.DeepEqual(result, &v) {
761 t.Fatalf("bad: %#v", result)
762 }
763 }
764
765
766 type RLocker struct {
767 sync.RWMutex
768 Map map[int]int
769 }
770
771 func TestCopy_rLocker(t *testing.T) {
772 v := &RLocker{
773 Map: map[int]int{1: 2},
774 }
775 v.Lock()
776
777 var result interface{}
778 var err error
779
780 copied := make(chan bool)
781
782 go func() {
783 result, err = Config{Lock: true}.Copy(v)
784 close(copied)
785 }()
786
787
788 select {
789 case <-copied:
790 t.Fatal("copy completed while locked!")
791 case <-time.After(100 * time.Millisecond):
792 v.Unlock()
793 }
794
795 <-copied
796
797
798 vCopy := result.(*RLocker)
799 vCopy.Lock()
800 vCopy.Unlock()
801 vCopy.RLock()
802 vCopy.RUnlock()
803
804
805 v.RLock()
806 result, err = Config{Lock: true}.Copy(v)
807 if err != nil {
808 t.Fatal(err)
809 }
810 v.RUnlock()
811
812 vCopy = result.(*RLocker)
813 vCopy.Lock()
814 vCopy.Unlock()
815 vCopy.RLock()
816 vCopy.RUnlock()
817
818 if !reflect.DeepEqual(result, v) {
819 t.Fatalf("bad: %#v", result)
820 }
821 }
822
823
824 func TestCopy_missingLockedField(t *testing.T) {
825 v := &LockedField{
826 String: "orig",
827 }
828
829 result, err := Config{Lock: true}.Copy(v)
830
831 if err != nil {
832 t.Fatalf("err: %s", err)
833 }
834
835 if !reflect.DeepEqual(result, v) {
836 t.Fatalf("expected:\n%#v\nbad:\n%#v\n", v, result)
837 }
838 }
839
840 type PointerLocker struct {
841 Mu sync.Mutex
842 }
843
844 func (p *PointerLocker) Lock() { p.Mu.Lock() }
845 func (p *PointerLocker) Unlock() { p.Mu.Unlock() }
846
847 func TestCopy_pointerLockerNil(t *testing.T) {
848 v := struct {
849 P *PointerLocker
850 }{}
851
852 _, err := Config{Lock: true}.Copy(&v)
853 if err != nil {
854 t.Fatalf("err: %s", err)
855 }
856 }
857
858 func TestCopy_sliceWithNil(t *testing.T) {
859 v := [](*int){nil}
860
861 result, err := Copy(v)
862 if err != nil {
863 t.Fatalf("err: %s", err)
864 }
865
866 if !reflect.DeepEqual(result, v) {
867 t.Fatalf("expected:\n%#v\ngot:\n%#v", v, result)
868 }
869 }
870
871 func TestCopy_mapWithNil(t *testing.T) {
872 v := map[int](*int){0: nil}
873
874 result, err := Copy(v)
875 if err != nil {
876 t.Fatalf("err: %s", err)
877 }
878
879 if !reflect.DeepEqual(result, v) {
880 t.Fatalf("expected:\n%#v\ngot:\n%#v", v, result)
881 }
882 }
883
884
885
886 func TestCopy_valueWithLockPointer(t *testing.T) {
887 v := struct {
888 *sync.Mutex
889 X int
890 }{
891 Mutex: &sync.Mutex{},
892 X: 3,
893 }
894
895 _, err := Config{Lock: true}.Copy(v)
896
897 if err != errPointerRequired {
898 t.Fatalf("expected errPointerRequired, got: %v", err)
899 }
900 }
901
902 func TestCopy_mapWithPointers(t *testing.T) {
903 type T struct {
904 S string
905 }
906 v := map[string]interface{}{
907 "a": &T{S: "hello"},
908 }
909
910 result, err := Copy(v)
911 if err != nil {
912 t.Fatal(err)
913 }
914
915 if !reflect.DeepEqual(v, result) {
916 t.Fatalf("%#v", result)
917 }
918 }
919
920 func TestCopy_structWithMapWithPointers(t *testing.T) {
921 type T struct {
922 S string
923 M map[string]interface{}
924 }
925 v := &T{
926 S: "a",
927 M: map[string]interface{}{
928 "b": &T{
929 S: "b",
930 },
931 },
932 }
933
934 result, err := Copy(v)
935 if err != nil {
936 t.Fatal(err)
937 }
938
939 if !reflect.DeepEqual(v, result) {
940 t.Fatal(result)
941 }
942 }
943
944 type testT struct {
945 N int
946 Spp **string
947 X testX
948 Xp *testX
949 Xpp **testX
950 }
951
952 type testX struct {
953 Tp *testT
954 Tpp **testT
955 Ip *interface{}
956 Ep *error
957 S fmt.Stringer
958 }
959
960 type stringer struct{}
961
962 func (s *stringer) String() string {
963 return "test string"
964 }
965
966 func TestCopy_structWithPointersAndInterfaces(t *testing.T) {
967
968 s := "val"
969 sp := &s
970 spp := &sp
971 i := interface{}(11)
972
973 tp := &testT{
974 N: 2,
975 }
976
977 xp := &testX{
978 Tp: tp,
979 Tpp: &tp,
980 Ip: &i,
981 S: &stringer{},
982 }
983
984 v := &testT{
985 N: 1,
986 Spp: spp,
987 X: testX{},
988 Xp: xp,
989 Xpp: &xp,
990 }
991
992 result, err := Copy(v)
993 if err != nil {
994 t.Fatal(err)
995 }
996
997 if !reflect.DeepEqual(v, result) {
998 t.Fatal(result)
999 }
1000 }
1001
1002 func Test_pointerInterfacePointer(t *testing.T) {
1003 s := "hi"
1004 si := interface{}(&s)
1005 sip := &si
1006
1007 result, err := Copy(sip)
1008 if err != nil {
1009 t.Fatal(err)
1010 }
1011
1012 if !reflect.DeepEqual(sip, result) {
1013 t.Fatalf("%#v != %#v\n", sip, result)
1014 }
1015 }
1016
1017 func Test_pointerInterfacePointer2(t *testing.T) {
1018 type T struct {
1019 I *interface{}
1020 J **fmt.Stringer
1021 }
1022
1023 x := 1
1024 y := &stringer{}
1025
1026 i := interface{}(&x)
1027 j := fmt.Stringer(y)
1028 jp := &j
1029
1030 v := &T{
1031 I: &i,
1032 J: &jp,
1033 }
1034 result, err := Copy(v)
1035 if err != nil {
1036 t.Fatal(err)
1037 }
1038
1039 if !reflect.DeepEqual(v, result) {
1040 t.Fatalf("%#v != %#v\n", v, result)
1041 }
1042 }
1043
1044
1045
1046 func TestCopy_unexportedFieldFirst(t *testing.T) {
1047 type P struct {
1048 mu sync.Mutex
1049 Old, New string
1050 }
1051
1052 type T struct {
1053 M map[string]*P
1054 }
1055
1056 v := &T{
1057 M: map[string]*P{
1058 "a": &P{Old: "", New: "2"},
1059 },
1060 }
1061
1062 result, err := Copy(v)
1063 if err != nil {
1064 t.Fatal(err)
1065 }
1066
1067 if !reflect.DeepEqual(v, result) {
1068 t.Fatalf("\n%#v\n\n%#v", v, result)
1069 }
1070 }
1071
1072 func TestCopy_nilPointerInSlice(t *testing.T) {
1073 type T struct {
1074 Ps []*int
1075 }
1076
1077 v := &T{
1078 Ps: []*int{nil},
1079 }
1080
1081 result, err := Copy(v)
1082 if err != nil {
1083 t.Fatal(err)
1084 }
1085
1086 if !reflect.DeepEqual(v, result) {
1087 t.Fatalf("\n%#v\n\n%#v", v, result)
1088 }
1089 }
1090
1091
1092
1093
1094
1095
1096 func TestCopy_timePointer(t *testing.T) {
1097 type T struct {
1098 Value *time.Time
1099 }
1100
1101 now := time.Now()
1102 v := &T{
1103 Value: &now,
1104 }
1105
1106 result, err := Copy(v)
1107 if err != nil {
1108 t.Fatal(err)
1109 }
1110
1111 if !reflect.DeepEqual(v, result) {
1112 t.Fatalf("\n%#v\n\n%#v", v, result)
1113 }
1114 }
1115
1116 func TestCopy_timeNonPointer(t *testing.T) {
1117 type T struct {
1118 Value time.Time
1119 }
1120
1121 v := &T{
1122 Value: time.Now(),
1123 }
1124
1125 result, err := Copy(v)
1126 if err != nil {
1127 t.Fatal(err)
1128 }
1129
1130 if !reflect.DeepEqual(v, result) {
1131 t.Fatalf("\n%#v\n\n%#v", v, result)
1132 }
1133 }
1134
1135 func TestCopy_timeDoublePointer(t *testing.T) {
1136 type T struct {
1137 Value **time.Time
1138 }
1139
1140 now := time.Now()
1141 nowP := &now
1142 nowPP := &nowP
1143 v := &T{
1144 Value: nowPP,
1145 }
1146
1147 result, err := Copy(v)
1148 if err != nil {
1149 t.Fatal(err)
1150 }
1151
1152 if !reflect.DeepEqual(v, result) {
1153 t.Fatalf("\n%#v\n\n%#v", v, result)
1154 }
1155 }
1156
1157 type nestedValue struct {
1158 v string
1159 }
1160
1161 func TestCopy_customCopierConfig(t *testing.T) {
1162 type T struct {
1163 Val *nestedValue
1164 }
1165
1166 v := &T{
1167 Val: &nestedValue{v: "original"},
1168 }
1169
1170 cfg := Config{
1171 Copiers: map[reflect.Type]CopierFunc{
1172 reflect.TypeOf(nestedValue{}): customCopier,
1173 },
1174 }
1175 result, err := cfg.Copy(v)
1176 if err != nil {
1177 t.Fatal(err)
1178 }
1179
1180 copiedVal := result.(*T)
1181
1182 if !reflect.DeepEqual(v.Val.v, copiedVal.Val.v) {
1183 t.Fatalf("\nexpected: %#v\ngiven: %#v", v.Val.v, copiedVal.Val.v)
1184 }
1185 }
1186
1187 func customCopier(v interface{}) (interface{}, error) {
1188 return v.(nestedValue), nil
1189 }
1190
1191 func TestCopy_customCopierShallowValue(t *testing.T) {
1192 type T struct{}
1193 v := &T{}
1194
1195 cfg := Config{
1196 ShallowCopiers: map[reflect.Type]struct{}{
1197 reflect.TypeOf(T{}): struct{}{},
1198 },
1199 }
1200 result, err := cfg.Copy(v)
1201 if err != nil {
1202 t.Fatal(err)
1203 }
1204
1205 copiedVal := result.(*T)
1206
1207 if v != copiedVal {
1208 t.Fatal("value not shallow copied")
1209 }
1210 }
1211
View as plain text