-
Notifications
You must be signed in to change notification settings - Fork 0
/
deepcopy_test.go
160 lines (146 loc) · 3.66 KB
/
deepcopy_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package darkness
import (
"reflect"
"testing"
"unsafe"
)
func TestDeepCopy(t *testing.T) {
// this variable is here to make sure that the unsafe.Pointer points to a
// valid address, just typing in a random number makes the go runtime crash
// when cleaning up the test as it tries to deallocate whatever is pointed
// by the value. eg. unsafe.Pointer(uintptr(4)) will end up trying to
// deallocate the memory at 0x4.
var aValidAddress struct{}
tests := []struct {
i interface{}
}{
{"5"}, // 0, string
{true}, // 1, bool
{1729}, // 2, int
{3.141592}, // 3, float64
{complex(1, 2)}, // 4, complex
{[4]float32{1, 2, 3, 4}}, // 5, array
{[]bool{true, false, true, false}}, // 6, slice
{map[int]float32{1: 1.2, 3: 3.4, 4: 4.5, 5: 5.5}}, // 7, map
{struct {
a int
b float32
}{5, 999.999}}, // 8
{func() *int {
i := 9
return &i
}()}, // 9, pointer to int
{
struct {
a int
b []float32
c struct {
d complex64
}
e *bool
}{
a: 5,
b: []float32{1.1, 2.2, 3.3, 4.4},
c: struct {
d complex64
}{d: complex(9.9, 8.8)},
e: func() *bool {
mybool := true
return &mybool
}(),
},
}, // 10, more complex test
{uintptr(unsafe.Pointer(&aValidAddress))}, // 11, uintptr
{unsafe.Pointer(&aValidAddress)}, // 12, unsafe.Pointer
}
for i, test := range tests {
t.Logf("starting test %d, on %+v", i, test.i)
j := DeepCopy(test.i)
if !reflect.DeepEqual(test.i, j) {
t.Errorf("[%d] problem want %v, got %v", i, test.i, j)
}
}
}
func TestDeepCopyStringExceptions(t *testing.T) {
s := "Hello world!"
r := struct {
s0 string
s1 string
}{
s0: s,
s1: s[:5],
}
u := DeepCopy(r)
if !reflect.DeepEqual(u, r) {
t.Fatalf("not equal got %v, want %v", u, r)
}
}
// TestDeepCopyChannel tests the copying of channels, reflect.DeepEqual doesn't
// work on those.
func TestDeepCopyChannel(t *testing.T) {
c := make(chan struct{})
v, ok := DeepCopy(c).(chan struct{})
if !ok {
t.Errorf("expected a chan struct{}, got %T", v)
}
}
// TestDeepCopyPointers
func TestDeepCopyPointers(t *testing.T) {
var i int
ptr := &i
cp, ok := DeepCopy(ptr).(*int)
if !ok {
t.Fatal("expected a *int")
}
if cp == ptr {
t.Fatalf("pointers should be different, %v", cp)
}
if *cp != *ptr {
t.Fatalf("pointed values should be the same, got %d, want %d", *cp, *ptr)
}
}
// TestNilInterfaces tests that interfaces which dont literally == nil but are
// equal nil via reflect.Value.InNil don't panic and just do what you expect
// them to.
func TestNilInterfaces(t *testing.T) {
type deepInterface interface {
deepCopy(i interface{}) interface{}
}
i := deepInterface((*deepCopier)(nil))
cp := DeepCopy(i)
if reflect.TypeOf(i) != reflect.TypeOf(cp) {
t.Fatalf("types are expected to be the same, %T != %T", i, cp)
}
}
// TestDeepCopyRing tests that a circular reference doesn't go out of control
// and allocate everything.
func TestDeepCopyRing(t *testing.T) {
type T struct {
a int
next *T
}
// make a circular reference
t0, t1, t2 := &T{a: 0}, &T{a: 1}, &T{a: 2}
t0.next = t1
t1.next = t2
t2.next = t0
i := DeepCopy(t0)
r0, ok := i.(*T)
if !ok {
t.Fatalf("did not receive a *T, but a %T", i)
}
if r0.next == nil {
t.Fatal("r0.next was nil ?")
}
r1 := r0.next
if r1.next == nil {
t.Fatal("r1.next was nil ?")
}
r2 := r1.next
if r2.next != r0 {
t.Fatal("r2.next wasn't linked back to r0")
}
if t0.a != r0.a || t1.a != r1.a || t2.a != r2.a {
t.Fatalf("data not copied correctly %v, %v, %v != %v, %v, %v", t0, t1, t2, r0, r1, r2)
}
}