1 module ut;
2 
3 public import unit_threaded;
4 public import unit_threaded.should: should;  // FIXME
5 public import test_allocator: TestAllocator;
6 
7 mixin template TestUtils() {
8     import unit_threaded;
9     import test_allocator;
10 
11     /**
12        Returns an object that, while in scope, replaces whatever
13        theAllocator was with TestAllocator.
14     */
15     auto theTestAllocator() {
16         static struct Context {
17             import std.experimental.allocator: theAllocator;
18 
19             TestAllocator testAllocator;
20             typeof(theAllocator) oldAllocator;
21 
22             static auto create() {
23                 import std.experimental.allocator: allocatorObject;
24 
25                 Context ctx;
26 
27                 ctx.oldAllocator = theAllocator;
28                 theAllocator = allocatorObject(ctx.testAllocator);
29 
30                 return ctx;
31             }
32 
33             ~this() {
34                 import std.experimental.allocator: dispose;
35 
36                 // 2.079.0 changed the API - we check here
37                 static if(__traits(compiles, testAllocator.dispose(theAllocator)))
38                     testAllocator.dispose(theAllocator);
39 
40                 theAllocator = oldAllocator;
41             }
42         }
43 
44         return Context.create;
45     }
46 
47     @Setup
48     void before() {
49     }
50 
51     @Shutdown
52     void after() {
53         reset;
54     }
55 
56     void reset() {
57         Struct.numStructs = 0;
58         Class.numClasses = 0;
59         SharedStruct.numStructs = 0;
60         NoGcStruct.numStructs = 0;
61     }
62 
63 
64     void _writelnUt(T...)(T args) {
65         try {
66             () @trusted { writelnUt(args); }();
67         } catch(Exception ex) {
68             assert(false);
69         }
70     }
71 
72     private struct Struct {
73         int i;
74         static int numStructs = 0;
75 
76         this(int i) @safe nothrow {
77             this.i = i;
78 
79             ++numStructs;
80             _writelnUt("Struct ", &this, " normal   ctor, i=", i, ", N=", numStructs);
81         }
82 
83         this(this) @safe nothrow {
84             ++numStructs;
85             _writelnUt("Struct ", &this, " postBlit ctor, i=", i, ", N=", numStructs);
86         }
87 
88         ~this() @safe nothrow const {
89             --numStructs;
90             _writelnUt("Struct ", &this, "          dtor, i=", i, ", N=", numStructs);
91         }
92 
93         int twice() @safe pure const nothrow {
94             return i * 2;
95         }
96     }
97 
98     private struct SharedStruct {
99         int i;
100         static int numStructs = 0;
101 
102         this(int i) @safe nothrow shared {
103             this.i = i;
104 
105             ++numStructs;
106             try () @trusted {
107                     _writelnUt("Struct normal ctor ", &this, ", i=", i, ", N=", numStructs);
108                 }();
109             catch(Exception ex) {}
110         }
111 
112         this(this) @safe nothrow shared {
113             ++numStructs;
114             try () @trusted {
115                     _writelnUt("Struct postBlit ctor ", &this, ", i=", i, ", N=", numStructs);
116                 }();
117             catch(Exception ex) {}
118         }
119 
120         ~this() @safe nothrow {
121             --numStructs;
122             try () @trusted { _writelnUt("Struct dtor ", &this, ", i=", i, ", N=", numStructs); }();
123             catch(Exception ex) {}
124         }
125 
126         int twice() @safe pure const nothrow shared {
127             return i * 2;
128         }
129     }
130 
131     private class Class {
132         int i;
133         static int numClasses = 0;
134 
135         this(int i) @safe nothrow {
136             this.i = i;
137             ++numClasses;
138         }
139 
140         ~this() @safe nothrow {
141             --numClasses;
142         }
143 
144         int twice() @safe pure const nothrow {
145             return i * 2;
146         }
147     }
148 
149     private class SharedClass {
150         int i;
151         static int numClasss = 0;
152 
153         this(int i) @safe nothrow shared {
154             this.i = i;
155 
156             ++numClasss;
157             try () @trusted {
158                     _writelnUt("SharedClass normal ctor ", this, ", i=", i, ", N=", numClasss);
159                 }();
160             catch(Exception ex) {}
161         }
162 
163         ~this() @safe nothrow {
164             --numClasss;
165             try () @trusted { _writelnUt("SharedClass dtor ", this, ", i=", i, ", N=", numClasss); }();
166             catch(Exception ex) {}
167         }
168 
169         int twice() @safe pure const nothrow shared {
170             return i * 2;
171         }
172     }
173 
174 
175     private struct SafeAllocator {
176 
177         import std.experimental.allocator.mallocator: Mallocator;
178 
179         void[] allocate(this T)(size_t i) @trusted nothrow @nogc {
180             return Mallocator.instance.allocate(i);
181         }
182 
183         void deallocate(this T)(void[] bytes) @trusted nothrow @nogc {
184             Mallocator.instance.deallocate(bytes);
185         }
186     }
187 
188     private struct NoGcStruct {
189         int i;
190 
191         static int numStructs = 0;
192 
193         this(int i) @safe @nogc nothrow {
194             this.i = i;
195 
196             ++numStructs;
197         }
198 
199         this(this) @safe @nogc nothrow {
200             ++numStructs;
201         }
202 
203         ~this() @safe @nogc nothrow {
204             --numStructs;
205         }
206 
207     }
208 
209     private class NoGcClass {
210         int i;
211         static int numClasses = 0;
212 
213         this(int i) @safe @nogc nothrow {
214             this.i = i;
215             ++numClasses;
216         }
217 
218         ~this() @safe @nogc nothrow {
219             --numClasses;
220         }
221     }
222 
223     private struct SharedStructWithIndirection {
224         string s;
225         this(string s) shared {
226             this.s = s;
227         }
228     }
229 }