1 module ut.unique_array; 2 3 import ut; 4 import automem.unique_array; 5 6 mixin TestUtils; 7 8 @("default TestAllocator") 9 @system unittest { 10 defaultTest!TestAllocator; 11 } 12 13 14 @("default Mallocator") 15 @system unittest { 16 import stdx.allocator.mallocator: Mallocator; 17 defaultTest!Mallocator; 18 } 19 20 private void defaultTest(T)() { 21 import std.algorithm: move; 22 import std.traits: hasMember; 23 24 enum isGlobal = hasMember!(T, "instance"); 25 26 static if(isGlobal) { 27 alias allocator = T.instance; 28 alias Allocator = T; 29 } else { 30 auto allocator = T(); 31 alias Allocator = T*; 32 } 33 34 auto makeUniqueArray(T, A1, A2, Args...)(ref A2 allocator, Args args) { 35 36 import std.traits: isPointer, hasMember; 37 38 enum isGlobal = hasMember!(A1, "instance"); 39 40 static if(isGlobal) 41 return UniqueArray!(T, A1)(args); 42 else static if(isPointer!A1) 43 return UniqueArray!(T, A1)(&allocator, args); 44 else 45 return UniqueArray!(T, A1)(allocator, args); 46 } 47 48 auto ptr = makeUniqueArray!(Struct, Allocator)(allocator, 3); 49 ptr.length.shouldEqual(3); 50 51 ptr[2].twice.shouldEqual(0); // Struct.init 52 ptr[2] = Struct(5); 53 ptr[2].twice.shouldEqual(10); 54 55 ptr[1..$].shouldEqual([Struct(), Struct(5)]); 56 57 typeof(ptr) ptr2 = ptr.move; 58 59 ptr.length.shouldEqual(0); // moved from 60 (cast(bool)ptr).shouldBeFalse; 61 ptr2.length.shouldEqual(3); 62 (cast(bool)ptr2).shouldBeTrue; 63 64 // not copyable 65 static assert(!__traits(compiles, ptr2 = ptr1)); 66 67 auto ptr3 = ptr2.unique; // same as move 68 ptr3.length.shouldEqual(3); 69 ptr3.shouldEqual([Struct(), Struct(), Struct(5)]); 70 (*ptr3).shouldEqual([Struct(), Struct(), Struct(5)]); 71 72 ptr3 ~= Struct(10); 73 ptr3.shouldEqual([Struct(), Struct(), Struct(5), Struct(10)]); 74 75 ptr3 ~= [Struct(11), Struct(12)]; 76 ptr3.shouldEqual([Struct(), Struct(), Struct(5), Struct(10), Struct(11), Struct(12)]); 77 78 ptr3.length = 3; 79 ptr3.shouldEqual([Struct(), Struct(), Struct(5)]); 80 81 ptr3.length = 4; 82 ptr3.shouldEqual([Struct(), Struct(), Struct(5), Struct()]); 83 84 ptr3.length = 1; 85 86 ptr3 ~= makeUniqueArray!(Struct, Allocator)(allocator, 1); 87 88 ptr3.shouldEqual([Struct(), Struct()]); 89 90 auto ptr4 = makeUniqueArray!(Struct, Allocator)(allocator, 1); 91 92 ptr3 ~= ptr4.unique; 93 ptr3.shouldEqual([Struct(), Struct(), Struct()]); 94 95 ptr3 = [Struct(7), Struct(9)]; 96 ptr3.shouldEqual([Struct(7), Struct(9)]); 97 } 98 99 /// 100 @("@nogc") 101 @system @nogc unittest { 102 103 import stdx.allocator.mallocator: Mallocator; 104 105 auto arr = UniqueArray!(NoGcStruct, Mallocator)(2); 106 assert(arr.length == 2); 107 108 arr[0] = NoGcStruct(1); 109 arr[1] = NoGcStruct(3); 110 111 { 112 NoGcStruct[2] expected = [NoGcStruct(1), NoGcStruct(3)]; 113 assert(arr == expected); 114 } 115 116 auto arr2 = UniqueArray!(NoGcStruct, Mallocator)(1); 117 arr ~= arr2.unique; 118 119 { 120 NoGcStruct[3] expected = [NoGcStruct(1), NoGcStruct(3), NoGcStruct()]; 121 assert(arr == expected); 122 } 123 } 124 125 @("@nogc @safe") 126 @safe @nogc unittest { 127 auto allocator = SafeAllocator(); 128 auto arr = UniqueArray!(NoGcStruct, SafeAllocator)(SafeAllocator(), 6); 129 assert(arr.length == 6); 130 arr ~= NoGcStruct(); 131 assert(arr.length == 7); 132 } 133 134 135 @("init TestAllocator") 136 @system unittest { 137 auto allocator = TestAllocator(); 138 auto arr = UniqueArray!(Struct, TestAllocator*)(&allocator, 2, Struct(7)); 139 arr.shouldEqual([Struct(7), Struct(7)]); 140 } 141 142 @("init Mallocator") 143 @system unittest { 144 import stdx.allocator.mallocator: Mallocator; 145 alias allocator = Mallocator.instance; 146 auto arr = UniqueArray!(Struct, Mallocator)(2, Struct(7)); 147 arr.shouldEqual([Struct(7), Struct(7)]); 148 } 149 150 151 @("range TestAllocator") 152 @system unittest { 153 auto allocator = TestAllocator(); 154 auto arr = UniqueArray!(Struct, TestAllocator*)(&allocator, [Struct(1), Struct(2)]); 155 arr.shouldEqual([Struct(1), Struct(2)]); 156 } 157 158 @("range Mallocator") 159 @system unittest { 160 import stdx.allocator.mallocator: Mallocator; 161 auto arr = UniqueArray!(Struct, Mallocator)([Struct(1), Struct(2)]); 162 arr.shouldEqual([Struct(1), Struct(2)]); 163 } 164 165 166 @("theAllocator") 167 @system unittest { 168 with(theTestAllocator) { 169 auto arr = UniqueArray!Struct(2); 170 arr.shouldEqual([Struct(), Struct()]); 171 } 172 } 173 174 @("issue 1 array") 175 @system unittest { 176 import stdx.allocator.mallocator; 177 UniqueArray!(int, Mallocator) a; 178 a ~= [0, 1]; 179 } 180 181 @("issue 1 value") 182 @system unittest { 183 import stdx.allocator.mallocator; 184 UniqueArray!(int, Mallocator) a; 185 a ~= 7; 186 } 187 188 @("issue 1 UniqueArray") 189 @system unittest { 190 import stdx.allocator.mallocator; 191 UniqueArray!(int, Mallocator) a; 192 a ~= UniqueArray!(int, Mallocator)([1, 2, 3]); 193 } 194 195 @("dereference") 196 unittest { 197 import stdx.allocator.mallocator; 198 UniqueArray!(int, Mallocator) a; 199 a ~= [0, 1]; 200 (*a).shouldEqual([0, 1]); 201 } 202 203 @("reserve from nothing") 204 @system unittest { 205 auto allocator = TestAllocator(); 206 auto a = UniqueArray!(int, TestAllocator*)(&allocator); 207 a.reserve(10); //allocates here 208 a ~= [1, 2, 3]; // should not allocate 209 a ~= [4, 5, 6, 7, 8, 9]; //should not allocate 210 a.shouldEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]); 211 allocator.numAllocations.shouldEqual(1); 212 } 213 214 @("reserve from existing expand") 215 @system unittest { 216 auto allocator = TestAllocator(); 217 auto a = UniqueArray!(int, TestAllocator*)(&allocator, [1, 2]); //allocates here 218 a.reserve(10); //allocates here 219 a ~= [3, 4]; // should not allocate 220 a ~= [5, 6, 7, 8, 9]; //should not allocate 221 a.shouldEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]); 222 allocator.numAllocations.shouldEqual(2); 223 } 224 225 @("reserve from existing reduce") 226 @system unittest { 227 auto allocator = TestAllocator(); 228 auto a = UniqueArray!(int, TestAllocator*)(&allocator, [1, 2, 3, 4, 5]); //allocates here 229 a.reserve(2); // should not allocate, changes length to 2 230 a ~= [5, 6]; // should not allocate 231 a.shouldEqual([1, 2, 5, 6]); 232 allocator.numAllocations.shouldEqual(1); 233 } 234 235 @("Append 2 arrays") 236 @system unittest { 237 auto allocator = TestAllocator(); 238 auto a = UniqueArray!(int, TestAllocator*)(&allocator, [1, 2, 3]) ~ 239 UniqueArray!(int, TestAllocator*)(&allocator, [4, 5]); 240 a.shouldEqual([1, 2, 3, 4, 5]); 241 } 242 243 @("ptr") 244 @system unittest { 245 auto allocator = TestAllocator(); 246 auto a = UniqueArray!(int, TestAllocator*)(&allocator, [1, 2, 3, 4, 5]); 247 auto ptr = a.ptr; 248 ++ptr; 249 (*ptr).shouldEqual(2); 250 } 251 252 @("dup TestAllocator") 253 @system unittest { 254 auto allocator = TestAllocator(); 255 auto a = UniqueArray!(int, TestAllocator*)(&allocator, [1, 2, 3, 4, 5]); 256 auto b = a.dup; 257 allocator.numAllocations.shouldEqual(2); 258 b.shouldEqual([1, 2, 3, 4, 5]); 259 } 260 261 @("dup Mallocator") 262 @system unittest { 263 import stdx.allocator.mallocator: Mallocator; 264 auto a = UniqueArray!(int, Mallocator)([1, 2, 3, 4, 5]); 265 auto b = a.dup; 266 b.shouldEqual([1, 2, 3, 4, 5]); 267 } 268 269 @("dup TestAllocator indirections") 270 @system unittest { 271 auto allocator = TestAllocator(); 272 static struct String { string s; } 273 auto a = UniqueArray!(String, TestAllocator*)(&allocator, [String("foo"), String("bar")]); 274 auto b = a.dup; 275 a[0] = String("quux"); 276 a[1] = String("toto"); 277 allocator.numAllocations.shouldEqual(2); 278 a.shouldEqual([String("quux"), String("toto")]); 279 b.shouldEqual([String("foo"), String("bar")]); 280 } 281 282 @("Set length to the same length") 283 unittest { 284 auto allocator = TestAllocator(); 285 auto a = UniqueArray!(Struct, TestAllocator*)(&allocator, [Struct(2), Struct(3)]); 286 a.length = 2; 287 } 288 289 @("UniqueString TestAllocator append") 290 @safe unittest { 291 auto allocator = TestAllocator(); 292 auto allocatorPtr = () @trusted { return &allocator; }(); 293 auto str = UniqueString!(TestAllocator*)(allocatorPtr); 294 str ~= 'f'; 295 str ~= 'o'; 296 str ~= 'o'; 297 str.shouldEqual("foo"); 298 } 299 300 @("UniqueString TestAllocator init with string") 301 @safe unittest { 302 auto allocator = TestAllocator(); 303 auto allocatorPtr = () @trusted { return &allocator; }(); 304 auto str = UniqueString!(TestAllocator*)(allocatorPtr, "foobar"); 305 str.shouldEqual("foobar"); 306 }