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