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 @safe unittest {
44 
45     import std.experimental.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 @safe @nogc unittest {
150 
151     import std.experimental.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     {
219         auto allocator = TestAllocator();
220 
221         auto ptr = Unique!(Struct, TestAllocator*)(&allocator, 5);
222         ptr = Unique!(Struct, TestAllocator*)(&allocator, 7);
223 
224         Struct.numStructs.shouldEqual(1);
225         ptr.twice.shouldEqual(14);
226     }
227 
228     Struct.numStructs.shouldEqual(0);
229 }
230 
231 
232 @("theAllocator")
233 @system unittest {
234     with(theTestAllocator){
235         auto ptr = Unique!Struct(42);
236         (*ptr).shouldEqual(Struct(42));
237         Struct.numStructs.shouldEqual(1);
238     }
239 
240     Struct.numStructs.shouldEqual(0);
241 }
242 
243 
244 @("@nogc class destructor")
245 @nogc unittest {
246 
247     auto allocator = SafeAllocator();
248 
249     {
250         const ptr = Unique!(NoGcClass, SafeAllocator)(SafeAllocator(), 6);
251         // shouldEqual isn't @nogc
252         assert(ptr.i == 6);
253         assert(NoGcClass.numClasses == 1);
254     }
255 
256     assert(NoGcClass.numClasses == 0);
257 }
258 
259 
260 version(DIP1000) {
261     @("borrow")
262         @safe unittest {
263 
264         auto allocator = SafeAllocator();
265 
266         {
267             const ptr = Unique!(Struct, SafeAllocator)(SafeAllocator(), 6);
268             scopeFunc(ptr.borrow).shouldEqual(18);
269         }
270     }
271 
272     private int scopeFunc(scope const(Struct)* s) @safe {
273 
274         return s.i * 3;
275     }
276 }