1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 module tanya.memory.tests.smartref;
5 
6 import tanya.memory.allocator;
7 import tanya.memory.smartref;
8 import tanya.meta.trait;
9 import tanya.test.stub;
10 
11 @nogc @system unittest
12 {
13     auto rc = defaultAllocator.refCounted!int(5);
14     rc = defaultAllocator.make!int(7);
15     assert(*rc == 7);
16 }
17 
18 @nogc @system unittest
19 {
20     RefCounted!int rc;
21     assert(!rc.isInitialized);
22     rc = null;
23     assert(!rc.isInitialized);
24 }
25 
26 @nogc @system unittest
27 {
28     auto rc = defaultAllocator.refCounted!int(5);
29 
30     void func(RefCounted!int param) @nogc
31     {
32         assert(param.count == 2);
33         param = defaultAllocator.make!int(7);
34         assert(param.count == 1);
35         assert(*param == 7);
36     }
37     func(rc);
38     assert(rc.count == 1);
39     assert(*rc == 5);
40 }
41 
42 @nogc @system unittest
43 {
44     RefCounted!int rc;
45 
46     void func(RefCounted!int param) @nogc
47     {
48         assert(param.count == 0);
49         param = defaultAllocator.make!int(7);
50         assert(param.count == 1);
51         assert(*param == 7);
52     }
53     func(rc);
54     assert(rc.count == 0);
55 }
56 
57 @nogc @system unittest
58 {
59     RefCounted!int rc1, rc2;
60     static assert(is(typeof(rc1 = rc2)));
61 }
62 
63 @nogc @system unittest
64 {
65     auto rc = RefCounted!int(defaultAllocator);
66     assert(!rc.isInitialized);
67     assert(rc.allocator is defaultAllocator);
68 }
69 
70 @nogc @system unittest
71 {
72     auto rc = defaultAllocator.refCounted!int(5);
73     assert(rc.count == 1);
74 
75     void func(RefCounted!int rc) @nogc
76     {
77         assert(rc.count == 2);
78         rc = null;
79         assert(!rc.isInitialized);
80         assert(rc.count == 0);
81     }
82 
83     assert(rc.count == 1);
84     func(rc);
85     assert(rc.count == 1);
86 
87     rc = null;
88     assert(!rc.isInitialized);
89     assert(rc.count == 0);
90 }
91 
92 @nogc @system unittest
93 {
94     auto rc = defaultAllocator.refCounted!int(5);
95     assert(*rc == 5);
96 
97     void func(RefCounted!int rc) @nogc
98     {
99         assert(rc.count == 2);
100         rc = defaultAllocator.refCounted!int(4);
101         assert(*rc == 4);
102         assert(rc.count == 1);
103     }
104     func(rc);
105     assert(*rc == 5);
106 }
107 
108 @nogc @system unittest
109 {
110     auto rc = defaultAllocator.refCounted!(int[])(5);
111     assert(rc.length == 5);
112 }
113 
114 @nogc @system unittest
115 {
116     auto p1 = defaultAllocator.make!int(5);
117     auto p2 = p1;
118     auto rc = RefCounted!int(p1, defaultAllocator);
119     assert(rc.get() is p2);
120 }
121 
122 @nogc @system unittest
123 {
124     size_t destroyed;
125     {
126         auto rc = defaultAllocator.refCounted!WithDtor(destroyed);
127     }
128     assert(destroyed == 1);
129 }
130 
131 @nogc nothrow pure @system unittest
132 {
133     auto s = defaultAllocator.unique!int(5);
134     assert(*s == 5);
135 
136     s = null;
137     assert(s is null);
138 }
139 
140 @nogc nothrow pure @system unittest
141 {
142     auto s = defaultAllocator.unique!int(5);
143     assert(*s == 5);
144 
145     s = defaultAllocator.unique!int(4);
146     assert(*s == 4);
147 }
148 
149 @nogc nothrow pure @system unittest
150 {
151     auto p1 = defaultAllocator.make!int(5);
152     auto p2 = p1;
153 
154     auto rc = Unique!int(p1, defaultAllocator);
155     assert(rc.get() is p2);
156 }
157 
158 @nogc nothrow pure @system unittest
159 {
160     auto rc = Unique!int(defaultAllocator);
161     assert(rc.allocator is defaultAllocator);
162 }
163 
164 @nogc @system unittest
165 {
166     uint destroyed;
167     auto a = defaultAllocator.make!A(destroyed);
168 
169     assert(destroyed == 0);
170     {
171         auto rc = RefCounted!A(a, defaultAllocator);
172         assert(rc.count == 1);
173 
174         void func(RefCounted!A rc) @nogc @system
175         {
176             assert(rc.count == 2);
177         }
178         func(rc);
179 
180         assert(rc.count == 1);
181     }
182     assert(destroyed == 1);
183 
184     RefCounted!int rc;
185     assert(rc.count == 0);
186     rc = defaultAllocator.make!int(8);
187     assert(rc.count == 1);
188 }
189 
190 @nogc nothrow pure @safe unittest
191 {
192     static assert(is(ReturnType!(RefCounted!int.get) == inout int*));
193     static assert(is(ReturnType!(RefCounted!A.get) == inout A));
194     static assert(is(ReturnType!(RefCounted!B.get) == inout B*));
195 }
196 
197 @nogc nothrow pure @safe unittest
198 {
199     static assert(is(RefCounted!B));
200     static assert(is(RefCounted!A));
201 }
202 
203 @nogc @system unittest
204 {
205     struct E
206     {
207     }
208     auto b = defaultAllocator.refCounted!B(15);
209     static assert(is(typeof(b.prop) == int));
210     static assert(!is(typeof(defaultAllocator.refCounted!B())));
211 
212     static assert(is(typeof(defaultAllocator.refCounted!E())));
213     static assert(!is(typeof(defaultAllocator.refCounted!E(5))));
214     {
215         auto rc = defaultAllocator.refCounted!B(3);
216         assert(rc.get().prop == 3);
217     }
218     {
219         auto rc = defaultAllocator.refCounted!E();
220         assert(rc.count);
221     }
222 }
223 
224 @nogc nothrow pure @safe unittest
225 {
226     static assert(is(typeof(defaultAllocator.unique!B(5))));
227     static assert(is(typeof(defaultAllocator.unique!(int[])(5))));
228 }
229 
230 private class A
231 {
232     uint *destroyed;
233 
234     this(ref uint destroyed) @nogc
235     {
236         this.destroyed = &destroyed;
237     }
238 
239     ~this() @nogc
240     {
241         ++(*destroyed);
242     }
243 }
244 
245 private struct B
246 {
247     int prop;
248     @disable this();
249     this(int param1) @nogc
250     {
251         prop = param1;
252     }
253 }