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 stdx.allocator: theAllocator;
18 
19             TestAllocator testAllocator;
20             typeof(theAllocator) oldAllocator;
21 
22             static auto create() {
23                 import stdx.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 stdx.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 struct SafeAllocator {
150 
151         import stdx.allocator.mallocator: Mallocator;
152 
153         void[] allocate(this T)(size_t i) @trusted nothrow @nogc {
154             return Mallocator.instance.allocate(i);
155         }
156 
157         void deallocate(this T)(void[] bytes) @trusted nothrow @nogc {
158             Mallocator.instance.deallocate(bytes);
159         }
160     }
161 
162     private struct NoGcStruct {
163         int i;
164 
165         static int numStructs = 0;
166 
167         this(int i) @safe @nogc nothrow {
168             this.i = i;
169 
170             ++numStructs;
171         }
172 
173         this(this) @safe @nogc nothrow {
174             ++numStructs;
175         }
176 
177         ~this() @safe @nogc nothrow {
178             --numStructs;
179         }
180 
181     }
182 
183     private class NoGcClass {
184         int i;
185         static int numClasses = 0;
186 
187         this(int i) @safe @nogc nothrow {
188             this.i = i;
189             ++numClasses;
190         }
191 
192         ~this() @safe @nogc nothrow {
193             --numClasses;
194         }
195     }
196 
197     private struct SharedStructWithIndirection {
198         string s;
199         this(string s) shared {
200             this.s = s;
201         }
202     }
203 }