1
+ using RecursiveArrayTools, Test
2
+
3
+ # Test structures for struct-aware recursivecopy
4
+ struct SimpleStruct
5
+ a:: Int
6
+ b:: Float64
7
+ end
8
+
9
+ mutable struct MutableStruct
10
+ a:: Vector{Float64}
11
+ b:: Matrix{Int}
12
+ c:: String
13
+ end
14
+
15
+ struct NestedStruct
16
+ simple:: SimpleStruct
17
+ mutable:: MutableStruct
18
+ array:: Vector{Int}
19
+ end
20
+
21
+ struct ParametricStruct{T}
22
+ data:: Vector{T}
23
+ metadata:: T
24
+ end
25
+
26
+ @testset " Struct recursivecopy tests" begin
27
+
28
+ @testset " Simple immutable struct" begin
29
+ original = SimpleStruct (42 , 3.14 )
30
+ copied = recursivecopy (original)
31
+
32
+ @test copied isa SimpleStruct
33
+ @test copied. a == original. a
34
+ @test copied. b == original. b
35
+ # Note: For immutable structs with only primitive types, Julia may optimize
36
+ # to use the same memory location, so we test functionality rather than identity
37
+ end
38
+
39
+ @testset " Mutable struct with arrays" begin
40
+ original = MutableStruct ([1.0 , 2.0 , 3.0 ], [1 2 ; 3 4 ], " test" )
41
+
42
+ # Should error for mutable structs
43
+ @test_throws ErrorException (" recursivecopy for mutable structs is not currently implemented. Use deepcopy instead." ) recursivecopy (original)
44
+ end
45
+
46
+ @testset " Nested struct" begin
47
+ simple = SimpleStruct (10 , 2.5 )
48
+ # Create a nested struct with only immutable components
49
+ struct ImmutableNested
50
+ simple:: SimpleStruct
51
+ array:: Vector{Int}
52
+ name:: String
53
+ end
54
+
55
+ original = ImmutableNested (simple, [100 , 200 , 300 ], " nested" )
56
+ copied = recursivecopy (original)
57
+
58
+ @test copied isa ImmutableNested
59
+ @test copied. simple. a == original. simple. a
60
+ @test copied. simple. b == original. simple. b
61
+ @test copied. array == original. array
62
+ @test copied. name == original. name
63
+
64
+ @test copied != = original
65
+ @test copied. array != = original. array
66
+
67
+ # Test independence
68
+ original. array[1 ] = 999
69
+ @test copied. array[1 ] == 100 # Should remain unchanged
70
+ end
71
+
72
+ @testset " Parametric struct" begin
73
+ original = ParametricStruct ([1 , 2 , 3 ], 42 )
74
+ copied = recursivecopy (original)
75
+
76
+ @test copied isa ParametricStruct{Int}
77
+ @test copied. data == original. data
78
+ @test copied. metadata == original. metadata
79
+ @test copied != = original
80
+ @test copied. data != = original. data
81
+ end
82
+
83
+ @testset " Compatibility with existing types" begin
84
+ # Test that arrays still work
85
+ arr = [1 , 2 , 3 ]
86
+ copied_arr = recursivecopy (arr)
87
+ @test copied_arr == arr
88
+ @test copied_arr != = arr
89
+
90
+ # Test that numbers still work
91
+ num = 42
92
+ copied_num = recursivecopy (num)
93
+ @test copied_num == num
94
+
95
+ # Test that strings still work
96
+ str = " hello"
97
+ copied_str = recursivecopy (str)
98
+ @test copied_str == str
99
+ end
100
+
101
+ @testset " ArrayPartition with structs" begin
102
+ simple1 = SimpleStruct (1 , 1.0 )
103
+ simple2 = SimpleStruct (2 , 2.0 )
104
+ ap = ArrayPartition ([simple1, simple2])
105
+ copied_ap = recursivecopy (ap)
106
+
107
+ @test copied_ap isa ArrayPartition
108
+ @test length (copied_ap. x) == length (ap. x)
109
+ @test copied_ap. x[1 ][1 ]. a == ap. x[1 ][1 ]. a
110
+ @test copied_ap != = ap
111
+ @test copied_ap. x[1 ] != = ap. x[1 ]
112
+ end
113
+
114
+ @testset " Array dispatch still works correctly" begin
115
+ # Test that our struct method doesn't interfere with existing array methods
116
+
117
+ # Arrays of numbers should use copy
118
+ num_array = [1 , 2 , 3 ]
119
+ copied_num = recursivecopy (num_array)
120
+ @test copied_num == num_array
121
+ @test copied_num != = num_array
122
+
123
+ # Arrays of arrays should recursively copy
124
+ nested_array = [[1 , 2 ], [3 , 4 ]]
125
+ copied_nested = recursivecopy (nested_array)
126
+ @test copied_nested == nested_array
127
+ @test copied_nested != = nested_array
128
+ @test copied_nested[1 ] != = nested_array[1 ]
129
+ @test copied_nested[2 ] != = nested_array[2 ]
130
+
131
+ # AbstractVectorOfArray should use its method
132
+ ap = ArrayPartition ([1.0 , 2.0 ], [3 , 4 ])
133
+ copied_ap = recursivecopy (ap)
134
+ @test copied_ap isa ArrayPartition
135
+ @test copied_ap. x[1 ] == ap. x[1 ]
136
+ @test copied_ap. x[1 ] != = ap. x[1 ]
137
+
138
+ # Test that structs containing arrays still work
139
+ struct StructWithArrays
140
+ data:: Vector{Vector{Int}}
141
+ metadata:: String
142
+ end
143
+
144
+ original_struct = StructWithArrays ([[1 , 2 ], [3 , 4 ]], " test" )
145
+ copied_struct = recursivecopy (original_struct)
146
+ @test copied_struct. data == original_struct. data
147
+ @test copied_struct. data != = original_struct. data
148
+ @test copied_struct. data[1 ] != = original_struct. data[1 ]
149
+ @test copied_struct. metadata == original_struct. metadata
150
+ end
151
+ end
0 commit comments