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 struct SafeAllocator { 150 151 import std.experimental.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 }