1 module ut.unique; 2 3 4 import ut; 5 import automem.unique; 6 7 8 mixin TestUtils; 9 10 11 /// 12 @("with struct and test allocator") 13 @system unittest { 14 15 auto allocator = TestAllocator(); 16 { 17 const foo = Unique!(Struct, TestAllocator*)(&allocator, 5); 18 foo.twice.shouldEqual(10); 19 allocator.numAllocations.shouldEqual(1); 20 Struct.numStructs.shouldEqual(1); 21 } 22 23 Struct.numStructs.shouldEqual(0); 24 } 25 26 27 @("with class and test allocator") 28 @system unittest { 29 30 auto allocator = TestAllocator(); 31 { 32 const foo = Unique!(Class, TestAllocator*)(&allocator, 5); 33 foo.twice.shouldEqual(10); 34 allocator.numAllocations.shouldEqual(1); 35 Class.numClasses.shouldEqual(1); 36 } 37 38 Class.numClasses.shouldEqual(0); 39 } 40 41 /// 42 @("with struct and mallocator") 43 @safe unittest { 44 45 import std.experimental.allocator.mallocator: Mallocator; 46 { 47 const foo = Unique!(Struct, Mallocator)(5); 48 foo.twice.shouldEqual(10); 49 Struct.numStructs.shouldEqual(1); 50 } 51 52 Struct.numStructs.shouldEqual(0); 53 } 54 55 @("default constructor") 56 @system unittest { 57 auto allocator = TestAllocator(); 58 59 auto ptr = Unique!(Struct, TestAllocator*)(); 60 (cast(bool)ptr).shouldBeFalse; 61 ptr.get.shouldBeNull; 62 63 ptr = Unique!(Struct, TestAllocator*)(&allocator, 5); 64 ptr.get.shouldNotBeNull; 65 ptr.get.twice.shouldEqual(10); 66 (cast(bool)ptr).shouldBeTrue; 67 } 68 69 @(".init") 70 @system unittest { 71 auto allocator = TestAllocator(); 72 73 Unique!(Struct, TestAllocator*) ptr; 74 (cast(bool)ptr).shouldBeFalse; 75 ptr.get.shouldBeNull; 76 77 ptr = Unique!(Struct, TestAllocator*)(&allocator, 5); 78 ptr.get.shouldNotBeNull; 79 ptr.get.twice.shouldEqual(10); 80 (cast(bool)ptr).shouldBeTrue; 81 } 82 83 @("move") 84 @system unittest { 85 import std.algorithm: move; 86 87 auto allocator = TestAllocator(); 88 auto oldPtr = Unique!(Struct, TestAllocator*)(&allocator, 5); 89 Unique!(Struct, TestAllocator*) newPtr = oldPtr.move; 90 oldPtr.shouldBeNull; 91 newPtr.twice.shouldEqual(10); 92 Struct.numStructs.shouldEqual(1); 93 } 94 95 @("copy") 96 @system unittest { 97 auto allocator = TestAllocator(); 98 auto oldPtr = Unique!(Struct, TestAllocator*)(&allocator, 5); 99 Unique!(Struct, TestAllocator*) newPtr; 100 // non-copyable 101 static assert(!__traits(compiles, newPtr = oldPtr)); 102 } 103 104 @("construct base class") 105 @system unittest { 106 auto allocator = TestAllocator(); 107 { 108 Unique!(Object, TestAllocator*) bar = Unique!(Class, TestAllocator*)(&allocator, 5); 109 Class.numClasses.shouldEqual(1); 110 } 111 112 Class.numClasses.shouldEqual(0); 113 } 114 115 @("assign base class") 116 @system unittest { 117 auto allocator = TestAllocator(); 118 { 119 Unique!(Object, TestAllocator*) bar; 120 bar = Unique!(Class, TestAllocator*)(&allocator, 5); 121 Class.numClasses.shouldEqual(1); 122 } 123 124 Class.numClasses.shouldEqual(0); 125 } 126 127 @("Return Unique from function") 128 @system unittest { 129 auto allocator = TestAllocator(); 130 131 auto produce(int i) { 132 return Unique!(Struct, TestAllocator*)(&allocator, i); 133 } 134 135 auto ptr = produce(4); 136 ptr.twice.shouldEqual(8); 137 } 138 139 @("unique") 140 @system unittest { 141 auto allocator = TestAllocator(); 142 auto oldPtr = Unique!(Struct, TestAllocator*)(&allocator, 5); 143 auto newPtr = oldPtr.unique; 144 newPtr.twice.shouldEqual(10); 145 oldPtr.shouldBeNull; 146 } 147 148 @("@nogc") 149 @safe @nogc unittest { 150 151 import std.experimental.allocator.mallocator: Mallocator; 152 153 { 154 const ptr = Unique!(NoGcStruct, Mallocator)(5); 155 // shouldEqual isn't @nogc 156 assert(ptr.i == 5); 157 assert(NoGcStruct.numStructs == 1); 158 } 159 160 assert(NoGcStruct.numStructs == 0); 161 } 162 163 @("@nogc @safe") 164 @safe @nogc unittest { 165 166 auto allocator = SafeAllocator(); 167 168 { 169 const ptr = Unique!(NoGcStruct, SafeAllocator)(SafeAllocator(), 6); 170 // shouldEqual isn't @nogc 171 assert(ptr.i == 6); 172 assert(NoGcStruct.numStructs == 1); 173 } 174 175 assert(NoGcStruct.numStructs == 0); 176 } 177 178 @("deref") 179 @system unittest { 180 { 181 auto allocator = TestAllocator(); 182 auto ptr = Unique!(Struct, TestAllocator*)(&allocator, 5); 183 *ptr = Struct(13); 184 ptr.twice.shouldEqual(26); 185 Struct.numStructs.shouldEqual(1); 186 } 187 Struct.numStructs.shouldEqual(0); 188 } 189 190 @("move from populated other unique") 191 @system unittest { 192 193 import std.algorithm: move; 194 195 { 196 auto allocator = TestAllocator(); 197 198 auto ptr1 = Unique!(Struct, TestAllocator*)(&allocator, 5); 199 Struct.numStructs.shouldEqual(1); 200 201 { 202 auto ptr2 = Unique!(Struct, TestAllocator*)(&allocator, 10); 203 Struct.numStructs.shouldEqual(2); 204 ptr1 = ptr2.move; 205 Struct.numStructs.shouldEqual(1); 206 ptr2.shouldBeNull; 207 ptr1.twice.shouldEqual(20); 208 } 209 210 } 211 212 Struct.numStructs.shouldEqual(0); 213 } 214 215 @("assign to rvalue") 216 @system unittest { 217 218 { 219 auto allocator = TestAllocator(); 220 221 auto ptr = Unique!(Struct, TestAllocator*)(&allocator, 5); 222 ptr = Unique!(Struct, TestAllocator*)(&allocator, 7); 223 224 Struct.numStructs.shouldEqual(1); 225 ptr.twice.shouldEqual(14); 226 } 227 228 Struct.numStructs.shouldEqual(0); 229 } 230 231 232 @("theAllocator") 233 @system unittest { 234 with(theTestAllocator){ 235 auto ptr = Unique!Struct(42); 236 (*ptr).shouldEqual(Struct(42)); 237 Struct.numStructs.shouldEqual(1); 238 } 239 240 Struct.numStructs.shouldEqual(0); 241 } 242 243 244 @("@nogc class destructor") 245 @nogc unittest { 246 247 auto allocator = SafeAllocator(); 248 249 { 250 const ptr = Unique!(NoGcClass, SafeAllocator)(SafeAllocator(), 6); 251 // shouldEqual isn't @nogc 252 assert(ptr.i == 6); 253 assert(NoGcClass.numClasses == 1); 254 } 255 256 assert(NoGcClass.numClasses == 0); 257 } 258 259 260 version(DIP1000) { 261 @("borrow") 262 @safe unittest { 263 264 auto allocator = SafeAllocator(); 265 266 { 267 const ptr = Unique!(Struct, SafeAllocator)(SafeAllocator(), 6); 268 scopeFunc(ptr.borrow).shouldEqual(18); 269 } 270 } 271 272 private int scopeFunc(scope const(Struct)* s) @safe { 273 274 return s.i * 3; 275 } 276 }