1 module ut.vector; 2 3 import ut; 4 import automem.vector; 5 import stdx.allocator.mallocator: Mallocator; 6 import test_allocator; 7 8 9 @("length") 10 @safe unittest { 11 vector("foo", "bar", "baz").length.should == 3; 12 vector("quux", "toto").length.should == 2; 13 } 14 15 @("vector.int") 16 @safe unittest { 17 vector(1, 2, 3, 4, 5)[].shouldEqual([1, 2, 3, 4, 5]); 18 vector(2, 3, 4)[].shouldEqual([2, 3, 4]); 19 } 20 21 @("vector.double") 22 @safe unittest { 23 vector(33.3)[].shouldEqual([33.3]); 24 vector(22.2, 77.7)[].shouldEqual([22.2, 77.7]); 25 } 26 27 @("copying") 28 @safe unittest { 29 auto vec1 = vector(1, 2, 3); 30 vec1.reserve(10); 31 auto vec2 = vec1; 32 vec1[1] = 7; 33 34 vec1[].shouldEqual([1, 7, 3]); 35 vec2[].shouldEqual([1, 2, 3]); 36 } 37 38 @("bounds check") 39 @safe unittest { 40 41 auto vec = vector(1, 2, 3); 42 vec.reserve(10); 43 vec[3].shouldThrow!BoundsException; 44 vec[-1].shouldThrow!BoundsException; 45 } 46 47 @("extend") 48 @safe unittest { 49 import std.algorithm: map; 50 51 auto vec = vector(0, 1, 2, 3); 52 53 vec ~= 4; 54 vec[].shouldEqual([0, 1, 2, 3, 4]); 55 56 vec ~= [5, 6]; 57 vec[].shouldEqual([0, 1, 2, 3, 4, 5, 6]); 58 59 vec ~= [1, 2].map!(a => a + 10); 60 vec[].shouldEqual([0, 1, 2, 3, 4, 5, 6, 11, 12]); 61 } 62 63 64 @("put") 65 @safe unittest { 66 import std.range: iota; 67 68 auto vec = vector(0, 1, 2, 3); 69 vec.put(4); 70 vec[].shouldEqual([0, 1, 2, 3, 4]); 71 vec.put(2.iota); 72 vec[].shouldEqual([0, 1, 2, 3, 4, 0, 1]); 73 } 74 75 @("append") 76 @safe unittest { 77 auto vec1 = vector(0, 1, 2); 78 auto vec2 = vector(3, 4); 79 80 auto vec3 = vec1 ~ vec2; 81 vec3[].shouldEqual([0, 1, 2, 3, 4]); 82 83 vec1[0] = 7; 84 vec2[0] = 9; 85 vec3[].shouldEqual([0, 1, 2, 3, 4]); 86 87 88 // make sure capacity is larger 89 vec1 ~= 100; 90 vec1.capacity.shouldBeGreaterThan(vec1.length); 91 vec1[].shouldEqual([7, 1, 2, 100]); 92 93 vec2 ~= 200; 94 vec2.capacity.shouldBeGreaterThan(vec2.length); 95 vec2[].shouldEqual([9, 4, 200]); 96 97 (vec1 ~ vec2)[].shouldEqual([7, 1, 2, 100, 9, 4, 200]); 98 (vec1 ~ vector(11, 12, 13, 14, 15))[].shouldEqual([7, 1, 2, 100, 11, 12, 13, 14, 15]); 99 } 100 101 @("slice") 102 @safe unittest { 103 const vec = vector(0, 1, 2, 3, 4, 5); 104 vec[][].shouldEqual([0, 1, 2, 3, 4, 5]); 105 vec[1 .. 3][].shouldEqual([1, 2]); 106 vec[1 .. 4][].shouldEqual([1, 2, 3]); 107 vec[2 .. 5][].shouldEqual([2, 3, 4]); 108 vec[1 .. $ - 1][].shouldEqual([1, 2, 3, 4]); 109 } 110 111 @("opDollar") 112 @safe unittest { 113 auto vec = vector(0, 1, 2, 3, 4); 114 vec ~= 5; 115 vec ~= 6; 116 vec.capacity.shouldBeGreaterThan(vec.length); 117 118 vec[1 .. $ - 1][].shouldEqual([1, 2, 3, 4, 5]); 119 } 120 121 @("assign") 122 @safe unittest { 123 import std.range: iota; 124 auto vec = vector(10, 11, 12); 125 vec = 5.iota; 126 vec[].shouldEqual([0, 1, 2, 3, 4]); 127 } 128 129 @("construct from range") 130 @safe unittest { 131 import std.range: iota; 132 vector(5.iota)[].shouldEqual([0, 1, 2, 3, 4]); 133 } 134 135 @("front") 136 @safe unittest { 137 vector(1, 2, 3).front.should == 1; 138 vector(2, 3).front.should == 2; 139 } 140 141 @("popBack") 142 @safe unittest { 143 auto vec = vector(0, 1, 2); 144 vec.popBack; 145 vec[].shouldEqual([0, 1]); 146 } 147 148 @("popFront") 149 @safe unittest { 150 auto vec = vector(0, 1, 2, 3, 4); 151 vec.popFront; 152 vec[].shouldEqual([1, 2, 3, 4]); 153 vec.empty.shouldBeFalse; 154 155 foreach(i; 0 .. vec.length) vec.popFront; 156 vec.empty.shouldBeTrue; 157 } 158 159 160 @("back") 161 @safe unittest { 162 const vec = vector("foo", "bar", "baz"); 163 vec.back[].shouldEqual("baz"); 164 } 165 166 @("opSliceAssign") 167 @safe unittest { 168 auto vec = vector("foo", "bar", "quux", "toto"); 169 170 vec[] = "haha"; 171 vec[].shouldEqual(["haha", "haha", "haha", "haha"]); 172 173 vec[1..3] = "oops"; 174 vec[].shouldEqual(["haha", "oops", "oops", "haha"]); 175 } 176 177 @("opSliceOpAssign") 178 @safe unittest { 179 auto vec = vector("foo", "bar", "quux", "toto"); 180 vec[] ~= "oops"; 181 vec[].shouldEqual(["foooops", "baroops", "quuxoops", "totooops"]); 182 } 183 184 @("opSliceOpAssign range") 185 @safe unittest { 186 auto vec = vector("foo", "bar", "quux", "toto"); 187 vec[1..3] ~= "oops"; 188 vec[].shouldEqual(["foo", "baroops", "quuxoops", "toto"]); 189 } 190 191 @("clear") 192 @safe unittest { 193 auto vec = vector(0, 1, 2, 3); 194 vec.clear; 195 int[] empty; 196 vec[].shouldEqual(empty); 197 } 198 199 200 @("Mallocator elements") 201 @safe @nogc unittest { 202 import std.algorithm: equal; 203 auto vec = vector!Mallocator(0, 1, 2, 3); 204 int[4] exp = [0, 1, 2, 3]; 205 assert(equal(vec[], exp[])); 206 } 207 208 @("Mallocator range") 209 @safe @nogc unittest { 210 import std.algorithm: equal; 211 import std.range: iota; 212 auto vec = vector!Mallocator(iota(5)); 213 int[5] exp = [0, 1, 2, 3, 4]; 214 assert(equal(vec[], exp[])); 215 } 216 217 218 @("theAllocator null") 219 @safe unittest { 220 Vector!int vec; 221 } 222 223 224 @("Mallocator null") 225 @safe @nogc unittest { 226 Vector!(int, Mallocator) vec; 227 } 228 229 @("Cannot escape slice") 230 @safe @nogc unittest { 231 int[] ints1; 232 scope vec = vector!Mallocator(0, 1, 2, 3); 233 int[] ints2; 234 235 static assert(!__traits(compiles, ints1 = vec[])); 236 static assert(__traits(compiles, ints2 = vec[])); 237 } 238 239 240 @("TestAllocator elements capacity") 241 @safe unittest { 242 static TestAllocator allocator; 243 244 auto vec = vector(&allocator, 0, 1, 2); 245 vec[].shouldEqual([0, 1, 2]); 246 247 vec ~= 3; 248 vec ~= 4; 249 vec ~= 5; 250 vec ~= 6; 251 vec ~= 7; 252 vec ~= 8; 253 254 vec[].shouldEqual([0, 1, 2, 3, 4, 5, 6, 7, 8]); 255 allocator.numAllocations.shouldBeSmallerThan(4); 256 } 257 258 @("TestAllocator reserve") 259 @safe unittest { 260 static TestAllocator allocator; 261 262 auto vec = vector!(TestAllocator*, int)(&allocator); 263 264 vec.reserve(5); 265 () @trusted { vec.shouldBeEmpty; }(); 266 267 vec ~= 0; 268 vec ~= 1; 269 vec ~= 2; 270 vec ~= 3; 271 vec ~= 4; 272 273 vec[].shouldEqual([0, 1, 2, 3, 4]); 274 allocator.numAllocations.should == 1; 275 276 vec ~= 5; 277 vec[].shouldEqual([0, 1, 2, 3, 4, 5]); 278 allocator.numAllocations.should == 2; 279 } 280 281 @("TestAllocator shrink no length") 282 @safe unittest { 283 static TestAllocator allocator; 284 285 auto vec = vector!(TestAllocator*, int)(&allocator); 286 vec.reserve(10); 287 288 vec ~= 0; 289 vec ~= 1; 290 vec ~= 2; 291 vec ~= 3; 292 293 vec.length.should == 4; 294 vec.capacity.should == 10; 295 296 vec.shrink; 297 vec.length.should == 4; 298 vec.capacity.should == 4; 299 } 300 301 @("TestAllocator shrink negative number") 302 @safe unittest { 303 static TestAllocator allocator; 304 305 auto vec = vector(&allocator, 0); 306 vec ~= 1; 307 vec ~= 2; 308 vec ~= 3; 309 vec.capacity.shouldBeGreaterThan(vec.length); 310 const oldCapacity = vec.capacity; 311 312 vec.shrink(-1).shouldBeFalse; 313 vec.capacity.should == oldCapacity; 314 } 315 316 @("TestAllocator shrink larger than capacity") 317 @safe unittest { 318 static TestAllocator allocator; 319 320 auto vec = vector(&allocator, 0); 321 vec ~= 1; 322 vec ~= 2; 323 vec ~= 3; 324 vec.capacity.shouldBeGreaterThan(vec.length); 325 const oldCapacity = vec.capacity; 326 327 vec.shrink(oldCapacity * 2).shouldBeFalse; 328 vec.capacity.should == oldCapacity; 329 } 330 331 332 @("TestAllocator shrink with length") 333 @safe unittest { 334 static TestAllocator allocator; 335 336 auto vec = vector(&allocator, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); 337 vec.capacity.should == 10; 338 339 vec.shrink(5); 340 vec[].shouldEqual([0, 1, 2, 3, 4]); 341 vec.capacity.should == 5; 342 343 vec ~= 5; 344 vec[].shouldEqual([0, 1, 2, 3, 4, 5]); 345 allocator.numAllocations.should == 3; 346 347 vec.reserve(10); 348 vec.length.should == 6; 349 vec.capacity.shouldBeGreaterThan(6); 350 } 351 352 @("TestAllocator copy") 353 @safe unittest { 354 static TestAllocator allocator; 355 356 auto vec1 = vector(&allocator, "foo", "bar", "baz"); 357 allocator.numAllocations.should == 1; 358 359 auto vec2 = vec1; 360 allocator.numAllocations.should == 2; 361 } 362 363 @("TestAllocator move") 364 @safe unittest { 365 static TestAllocator allocator; 366 367 auto vec = vector(&allocator, "foo", "bar", "baz"); 368 allocator.numAllocations.should == 1; 369 370 consumeVec(vec); 371 allocator.numAllocations.should == 1; 372 } 373 374 375 private void consumeVec(T)(auto ref T vec) { 376 377 } 378 379 380 @("set length") 381 @safe unittest { 382 Vector!int vec; 383 vec.length = 3; 384 vec[].shouldEqual([0, 0, 0]); 385 } 386 387 388 @("foreach") 389 @safe unittest { 390 foreach(e; vector(7, 7, 7)) { 391 e.should == 7; 392 } 393 } 394 395 396 @("equal") 397 @safe unittest { 398 import std.range: iota; 399 import std.algorithm: equal; 400 401 auto v = vector(0, 1, 2, 3); 402 assert(equal(v, 4.iota)); 403 } 404 405 406 @("bool") 407 @safe unittest { 408 vector(0, 1, 2).shouldBeTrue; 409 Vector!int v; 410 if(v) { 411 assert(0); 412 } 413 } 414 415 @("char") 416 @safe unittest { 417 { 418 auto vec = vector('f', 'o', 'o'); 419 vec[].shouldEqual("foo"); 420 vec ~= 'b'; 421 vec ~= ['a', 'r']; 422 vec[].shouldEqual("foobar"); 423 vec ~= "quux"; 424 vec[].shouldEqual("foobarquux"); 425 } 426 427 { 428 auto vec = vector("foo"); 429 vec[].shouldEqual("foo"); 430 vec.popBack; 431 vec[].shouldEqual("fo"); 432 } 433 434 { 435 auto vec = vector("foo"); 436 vec ~= "bar"; 437 vec[].shouldEqual("foobar"); 438 } 439 } 440 441 442 @("immutable") 443 @safe unittest { 444 Vector!(immutable int) vec; 445 vec ~= 42; 446 vec[].shouldEqual([42]); 447 } 448 449 450 @("String") 451 @safe unittest { 452 foreach(c; String("oooooo")) 453 c.should == 'o'; 454 } 455 456 @("stringz") 457 @safe unittest { 458 import std.string: fromStringz; 459 auto str = vector("foobar"); 460 const strz = str.stringz; 461 const back = () @trusted { return fromStringz(strz); }(); 462 back.should == "foobar"; 463 str[].shouldEqual("foobar"); 464 } 465 466 467 @("ptr") 468 @safe unittest { 469 const vec = vector(0, 1, 2, 3); 470 takesScopePtr(vec.ptr); 471 () @trusted { vec.ptr[1].shouldEqual(1); }(); 472 } 473 474 private void takesScopePtr(T)(scope const(T)* ptr) { 475 476 } 477 478 479 @safe @nogc unittest { 480 import stdx.allocator.showcase: StackFront; 481 import stdx.allocator.mallocator: Mallocator; 482 483 Vector!(int, StackFront!(1024, Mallocator)) v; 484 v ~= 1; 485 }