1 module ut.unique;
2 
3 
4 import ut;
5 import automem.unique;
6 
7 
8 mixin TestUtils;
9 
10 
11 ///
12 @("with struct and test allocator")
13 @system unittest {
14 
15     auto allocator = TestAllocator();
16     {
17         const foo = Unique!(Struct, TestAllocator*)(&allocator, 5);
18         foo.twice.shouldEqual(10);
19         allocator.numAllocations.shouldEqual(1);
20         Struct.numStructs.shouldEqual(1);
21     }
22 
23     Struct.numStructs.shouldEqual(0);
24 }
25 
26 
27 @("with class and test allocator")
28 @system unittest {
29 
30     auto allocator = TestAllocator();
31     {
32         const foo = Unique!(Class, TestAllocator*)(&allocator, 5);
33         foo.twice.shouldEqual(10);
34         allocator.numAllocations.shouldEqual(1);
35         Class.numClasses.shouldEqual(1);
36     }
37 
38     Class.numClasses.shouldEqual(0);
39 }
40 
41 ///
42 @("with struct and mallocator")
43 @system unittest {
44 
45     import stdx.allocator.mallocator: Mallocator;
46     {
47         const foo = Unique!(Struct, Mallocator)(5);
48         foo.twice.shouldEqual(10);
49         Struct.numStructs.shouldEqual(1);
50     }
51 
52     Struct.numStructs.shouldEqual(0);
53 }
54 
55 @("default constructor")
56 @system unittest {
57     auto allocator = TestAllocator();
58 
59     auto ptr = Unique!(Struct, TestAllocator*)();
60     (cast(bool)ptr).shouldBeFalse;
61     ptr.get.shouldBeNull;
62 
63     ptr = Unique!(Struct, TestAllocator*)(&allocator, 5);
64     ptr.get.shouldNotBeNull;
65     ptr.get.twice.shouldEqual(10);
66     (cast(bool)ptr).shouldBeTrue;
67 }
68 
69 @(".init")
70 @system unittest {
71     auto allocator = TestAllocator();
72 
73     Unique!(Struct, TestAllocator*) ptr;
74     (cast(bool)ptr).shouldBeFalse;
75     ptr.get.shouldBeNull;
76 
77     ptr = Unique!(Struct, TestAllocator*)(&allocator, 5);
78     ptr.get.shouldNotBeNull;
79     ptr.get.twice.shouldEqual(10);
80     (cast(bool)ptr).shouldBeTrue;
81 }
82 
83 @("move")
84 @system unittest {
85     import std.algorithm: move;
86 
87     auto allocator = TestAllocator();
88     auto oldPtr = Unique!(Struct, TestAllocator*)(&allocator, 5);
89     Unique!(Struct, TestAllocator*) newPtr = oldPtr.move;
90     oldPtr.shouldBeNull;
91     newPtr.twice.shouldEqual(10);
92     Struct.numStructs.shouldEqual(1);
93 }
94 
95 @("copy")
96 @system unittest {
97     auto allocator = TestAllocator();
98     auto oldPtr = Unique!(Struct, TestAllocator*)(&allocator, 5);
99     Unique!(Struct, TestAllocator*) newPtr;
100     // non-copyable
101     static assert(!__traits(compiles, newPtr = oldPtr));
102 }
103 
104 @("construct base class")
105 @system unittest {
106     auto allocator = TestAllocator();
107     {
108         Unique!(Object, TestAllocator*) bar = Unique!(Class, TestAllocator*)(&allocator, 5);
109         Class.numClasses.shouldEqual(1);
110     }
111 
112     Class.numClasses.shouldEqual(0);
113 }
114 
115 @("assign base class")
116 @system unittest {
117     auto allocator = TestAllocator();
118     {
119         Unique!(Object, TestAllocator*) bar;
120         bar = Unique!(Class, TestAllocator*)(&allocator, 5);
121         Class.numClasses.shouldEqual(1);
122     }
123 
124     Class.numClasses.shouldEqual(0);
125 }
126 
127 @("Return Unique from function")
128 @system unittest {
129     auto allocator = TestAllocator();
130 
131     auto produce(int i) {
132         return Unique!(Struct, TestAllocator*)(&allocator, i);
133     }
134 
135     auto ptr = produce(4);
136     ptr.twice.shouldEqual(8);
137 }
138 
139 @("unique")
140 @system unittest {
141     auto allocator = TestAllocator();
142     auto oldPtr = Unique!(Struct, TestAllocator*)(&allocator, 5);
143     auto newPtr = oldPtr.unique;
144     newPtr.twice.shouldEqual(10);
145     oldPtr.shouldBeNull;
146 }
147 
148 @("@nogc")
149 @system @nogc unittest {
150 
151     import stdx.allocator.mallocator: Mallocator;
152 
153     {
154         const ptr = Unique!(NoGcStruct, Mallocator)(5);
155         // shouldEqual isn't @nogc
156         assert(ptr.i == 5);
157         assert(NoGcStruct.numStructs == 1);
158     }
159 
160     assert(NoGcStruct.numStructs == 0);
161 }
162 
163 @("@nogc @safe")
164 @safe @nogc unittest {
165 
166     auto allocator = SafeAllocator();
167 
168     {
169         const ptr = Unique!(NoGcStruct, SafeAllocator)(SafeAllocator(), 6);
170         // shouldEqual isn't @nogc
171         assert(ptr.i == 6);
172         assert(NoGcStruct.numStructs == 1);
173     }
174 
175     assert(NoGcStruct.numStructs == 0);
176 }
177 
178 @("deref")
179 @system unittest {
180     {
181         auto allocator = TestAllocator();
182         auto ptr = Unique!(Struct, TestAllocator*)(&allocator, 5);
183         *ptr = Struct(13);
184         ptr.twice.shouldEqual(26);
185         Struct.numStructs.shouldEqual(1);
186     }
187     Struct.numStructs.shouldEqual(0);
188 }
189 
190 @("move from populated other unique")
191 @system unittest {
192 
193     import std.algorithm: move;
194 
195     {
196         auto allocator = TestAllocator();
197 
198         auto ptr1 = Unique!(Struct, TestAllocator*)(&allocator, 5);
199         Struct.numStructs.shouldEqual(1);
200 
201         {
202             auto ptr2 = Unique!(Struct, TestAllocator*)(&allocator, 10);
203             Struct.numStructs.shouldEqual(2);
204             ptr1 = ptr2.move;
205             Struct.numStructs.shouldEqual(1);
206             ptr2.shouldBeNull;
207             ptr1.twice.shouldEqual(20);
208         }
209 
210     }
211 
212     Struct.numStructs.shouldEqual(0);
213 }
214 
215 @("assign to rvalue")
216 @system unittest {
217 
218     import std.algorithm: move;
219 
220     {
221         auto allocator = TestAllocator();
222 
223         auto ptr = Unique!(Struct, TestAllocator*)(&allocator, 5);
224         ptr = Unique!(Struct, TestAllocator*)(&allocator, 7);
225 
226         Struct.numStructs.shouldEqual(1);
227         ptr.twice.shouldEqual(14);
228     }
229 
230     Struct.numStructs.shouldEqual(0);
231 }
232 
233 
234 @("theAllocator")
235 @system unittest {
236     with(theTestAllocator){
237         auto ptr = Unique!Struct(42);
238         (*ptr).shouldEqual(Struct(42));
239         Struct.numStructs.shouldEqual(1);
240     }
241 
242     Struct.numStructs.shouldEqual(0);
243 }
244 
245 
246 @("@nogc class destructor")
247 @nogc unittest {
248 
249     auto allocator = SafeAllocator();
250 
251     {
252         const ptr = Unique!(NoGcClass, SafeAllocator)(SafeAllocator(), 6);
253         // shouldEqual isn't @nogc
254         assert(ptr.i == 6);
255         assert(NoGcClass.numClasses == 1);
256     }
257 
258     assert(NoGcClass.numClasses == 0);
259 }