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