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