Skip to content

Commit cd63603

Browse files
committed
test: Add more tests for deep copy
1 parent 9c00733 commit cd63603

File tree

1 file changed

+327
-0
lines changed

1 file changed

+327
-0
lines changed

deepcopy_test.go

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
package gocache
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
)
7+
8+
// Test for Array types
9+
func TestDeepCopy_Array(t *testing.T) {
10+
// Test array of primitives
11+
original := [3]int{1, 2, 3}
12+
copied := deepCopy(original)
13+
14+
if !reflect.DeepEqual(original, copied) {
15+
t.Errorf("Array copy failed: expected %v, got %v", original, copied)
16+
}
17+
18+
// Verify it's a deep copy by checking type
19+
if reflect.TypeOf(copied) != reflect.TypeOf(original) {
20+
t.Errorf("Array copy type mismatch: expected %T, got %T", original, copied)
21+
}
22+
23+
// Test array of structs
24+
type TestStruct struct {
25+
Name string
26+
Value int
27+
Data []string
28+
}
29+
structArray := [2]TestStruct{
30+
{Name: "first", Value: 1, Data: []string{"a", "b"}},
31+
{Name: "second", Value: 2, Data: []string{"c", "d"}},
32+
}
33+
copiedStructArray := deepCopy(structArray)
34+
35+
if !reflect.DeepEqual(structArray, copiedStructArray) {
36+
t.Errorf("Struct array copy failed: expected %v, got %v", structArray, copiedStructArray)
37+
}
38+
39+
// Verify deep copy by modifying original
40+
copiedArray := copiedStructArray.([2]TestStruct)
41+
copiedArray[0].Data[0] = "modified"
42+
if structArray[0].Data[0] == "modified" {
43+
t.Error("Array was not deep copied - original was modified")
44+
}
45+
}
46+
47+
// Test for Channel types
48+
func TestDeepCopy_Chan(t *testing.T) {
49+
// Test unbuffered channel
50+
original := make(chan int)
51+
copied := deepCopy(original)
52+
53+
// Channels cannot be deep copied meaningfully, should copy reference
54+
if copied != original {
55+
t.Error("Channel should copy reference, not create new channel")
56+
}
57+
58+
// Test buffered channel
59+
bufferedChan := make(chan string, 5)
60+
bufferedChan <- "test"
61+
copiedBuffered := deepCopy(bufferedChan)
62+
63+
if copiedBuffered != bufferedChan {
64+
t.Error("Buffered channel should copy reference")
65+
}
66+
67+
// Verify same channel by receiving from copied
68+
select {
69+
case val := <-copiedBuffered.(chan string):
70+
if val != "test" {
71+
t.Errorf("Expected 'test', got %s", val)
72+
}
73+
default:
74+
t.Error("Should be able to receive from copied channel")
75+
}
76+
}
77+
78+
// Test for Function types
79+
func TestDeepCopy_Func(t *testing.T) {
80+
// Test simple function
81+
original := func(x int) int { return x * 2 }
82+
copied := deepCopy(original)
83+
84+
// Functions are immutable, should copy reference
85+
originalVal := reflect.ValueOf(original)
86+
copiedVal := reflect.ValueOf(copied)
87+
88+
if originalVal.Pointer() != copiedVal.Pointer() {
89+
t.Error("Function should copy reference, not create new function")
90+
}
91+
92+
// Test function execution
93+
result := copied.(func(int) int)(5)
94+
if result != 10 {
95+
t.Errorf("Expected 10, got %d", result)
96+
}
97+
98+
// Test nil function
99+
var nilFunc func()
100+
copiedNilFunc := deepCopy(nilFunc)
101+
if !reflect.DeepEqual(nilFunc, copiedNilFunc) {
102+
t.Error("Nil function should remain equivalent to nil")
103+
}
104+
if !reflect.ValueOf(copiedNilFunc).IsNil() {
105+
t.Error("Copied nil function should be nil")
106+
}
107+
}
108+
109+
// Test for Pointer types
110+
func TestDeepCopy_Ptr(t *testing.T) {
111+
// Test pointer to primitive
112+
original := 42
113+
ptr := &original
114+
copied := deepCopy(ptr)
115+
116+
copiedPtr := copied.(*int)
117+
if *copiedPtr != 42 {
118+
t.Errorf("Expected 42, got %d", *copiedPtr)
119+
}
120+
121+
// Verify it's a deep copy - modifying copied shouldn't affect original
122+
*copiedPtr = 100
123+
if original != 42 {
124+
t.Error("Original value was modified - not a deep copy")
125+
}
126+
127+
// Test pointer to struct
128+
type TestStruct struct {
129+
Name string
130+
Value int
131+
Data []string
132+
}
133+
structPtr := &TestStruct{
134+
Name: "test",
135+
Value: 123,
136+
Data: []string{"x", "y", "z"},
137+
}
138+
copiedStructPtr := deepCopy(structPtr)
139+
140+
copied_struct := copiedStructPtr.(*TestStruct)
141+
if !reflect.DeepEqual(*structPtr, *copied_struct) {
142+
t.Error("Struct pointer content not copied correctly")
143+
}
144+
145+
// Verify deep copy of nested slice
146+
copied_struct.Data[0] = "modified"
147+
if structPtr.Data[0] == "modified" {
148+
t.Error("Original struct slice was modified - not a deep copy")
149+
}
150+
151+
// Test nil pointer
152+
var nilPtr *int
153+
copiedNilPtr := deepCopy(nilPtr)
154+
if !reflect.DeepEqual(nilPtr, copiedNilPtr) {
155+
t.Error("Nil pointer should remain equivalent to nil")
156+
}
157+
if !reflect.ValueOf(copiedNilPtr).IsNil() {
158+
t.Error("Copied nil pointer should be nil")
159+
}
160+
// Verify type is preserved for nil pointers
161+
if reflect.TypeOf(copiedNilPtr) != reflect.TypeOf(nilPtr) {
162+
t.Error("Nil pointer type not preserved")
163+
}
164+
165+
// Test typed nil pointer
166+
var typedNilPtr *TestStruct
167+
copiedTypedNil := deepCopy(typedNilPtr)
168+
if !reflect.DeepEqual(typedNilPtr, copiedTypedNil) {
169+
t.Error("Typed nil pointer should remain equivalent to nil")
170+
}
171+
if !reflect.ValueOf(copiedTypedNil).IsNil() {
172+
t.Error("Copied typed nil pointer should be nil")
173+
}
174+
// Verify type is preserved for typed nil pointers
175+
if reflect.TypeOf(copiedTypedNil) != reflect.TypeOf(typedNilPtr) {
176+
t.Error("Typed nil pointer type not preserved")
177+
}
178+
}
179+
180+
// Test for Interface types
181+
func TestDeepCopy_Interface(t *testing.T) {
182+
// Test nil interface
183+
var nilInterface interface{}
184+
copiedNilInterface := deepCopy(nilInterface)
185+
if copiedNilInterface != nil {
186+
t.Error("Nil interface should remain nil")
187+
}
188+
189+
// Test empty interface with various types
190+
var emptyInterface interface{}
191+
192+
// Test with struct
193+
type TestStruct struct {
194+
Name string
195+
Value int
196+
Data []string
197+
}
198+
emptyInterface = TestStruct{Name: "test", Value: 456, Data: []string{"a", "b"}}
199+
copiedEmpty := deepCopy(emptyInterface)
200+
if !reflect.DeepEqual(emptyInterface, copiedEmpty) {
201+
t.Error("Empty interface with struct not copied correctly")
202+
}
203+
204+
// Test with slice
205+
emptyInterface = []int{1, 2, 3, 4}
206+
copiedSlice := deepCopy(emptyInterface)
207+
slice := copiedSlice.([]int)
208+
slice[0] = 999
209+
if emptyInterface.([]int)[0] == 999 {
210+
t.Error("Original slice in interface was modified - not a deep copy")
211+
}
212+
213+
// Test with map
214+
emptyInterface = map[string]int{"a": 1, "b": 2}
215+
copiedMap := deepCopy(emptyInterface)
216+
mapVal := copiedMap.(map[string]int)
217+
mapVal["a"] = 999
218+
if emptyInterface.(map[string]int)["a"] == 999 {
219+
t.Error("Original map in interface was modified - not a deep copy")
220+
}
221+
222+
// Test interface with concrete type containing pointer
223+
type StructWithPointer struct {
224+
Value *int
225+
}
226+
val := 42
227+
emptyInterface = StructWithPointer{Value: &val}
228+
copiedStructWithPtr := deepCopy(emptyInterface)
229+
structPtr := copiedStructWithPtr.(StructWithPointer)
230+
*structPtr.Value = 999
231+
if *emptyInterface.(StructWithPointer).Value == 999 {
232+
t.Error("Original struct pointer in interface was modified - not a deep copy")
233+
}
234+
}
235+
236+
// Test complex nested structures combining multiple types
237+
func TestDeepCopy_ComplexNested(t *testing.T) {
238+
type TestImpl struct {
239+
Data string
240+
}
241+
242+
type ComplexStruct struct {
243+
StringArray [3]string
244+
IntPtr *int
245+
Interface interface{}
246+
Channel chan bool
247+
Function func(int) int
248+
}
249+
250+
intVal := 42
251+
original := ComplexStruct{
252+
StringArray: [3]string{"a", "b", "c"},
253+
IntPtr: &intVal,
254+
Interface: TestImpl{Data: "interface data"},
255+
Channel: make(chan bool, 1),
256+
Function: func(x int) int { return x * 3 },
257+
}
258+
259+
original.Channel <- true
260+
261+
copied := deepCopy(original)
262+
copiedStruct := copied.(ComplexStruct)
263+
264+
// Verify array was copied
265+
if !reflect.DeepEqual(original.StringArray, copiedStruct.StringArray) {
266+
t.Error("Array in complex struct not copied correctly")
267+
}
268+
269+
// Verify pointer was deep copied
270+
*copiedStruct.IntPtr = 999
271+
if *original.IntPtr == 999 {
272+
t.Error("Pointer in complex struct was not deep copied")
273+
}
274+
275+
// Verify interface was deep copied
276+
copiedImpl := copiedStruct.Interface.(TestImpl)
277+
copiedImpl.Data = "modified"
278+
if original.Interface.(TestImpl).Data == "modified" {
279+
t.Error("Interface in complex struct was not deep copied")
280+
}
281+
282+
// Verify channel reference was copied (not deep copied)
283+
if copiedStruct.Channel != original.Channel {
284+
t.Error("Channel should copy reference")
285+
}
286+
287+
// Verify function reference was copied
288+
originalFuncPtr := reflect.ValueOf(original.Function).Pointer()
289+
copiedFuncPtr := reflect.ValueOf(copiedStruct.Function).Pointer()
290+
if originalFuncPtr != copiedFuncPtr {
291+
t.Error("Function should copy reference")
292+
}
293+
}
294+
295+
// Test edge cases
296+
func TestDeepCopy_EdgeCases(t *testing.T) {
297+
// Test nil input
298+
result := deepCopy(nil)
299+
if result != nil {
300+
t.Error("deepCopy(nil) should return nil")
301+
}
302+
303+
// Test empty array
304+
emptyArray := [0]int{}
305+
copiedEmpty := deepCopy(emptyArray)
306+
if !reflect.DeepEqual(emptyArray, copiedEmpty) {
307+
t.Error("Empty array not copied correctly")
308+
}
309+
310+
// Test pointer to array
311+
arrayPtr := &[2]string{"x", "y"}
312+
copiedArrayPtr := deepCopy(arrayPtr)
313+
copiedArray := copiedArrayPtr.(*[2]string)
314+
copiedArray[0] = "modified"
315+
if arrayPtr[0] == "modified" {
316+
t.Error("Array through pointer was not deep copied")
317+
}
318+
319+
// Test array of pointers
320+
val1, val2 := 10, 20
321+
ptrArray := [2]*int{&val1, &val2}
322+
copiedPtrArray := deepCopy(ptrArray).([2]*int)
323+
*copiedPtrArray[0] = 999
324+
if val1 == 999 {
325+
t.Error("Array of pointers was not deep copied")
326+
}
327+
}

0 commit comments

Comments
 (0)