1 module ut.vector; 2 3 4 import ut; 5 import automem.vector; 6 import std.experimental.allocator.mallocator: Mallocator; 7 import test_allocator; 8 9 10 @("length") 11 @safe unittest { 12 vector("foo", "bar", "baz").length.should == 3; 13 vector("quux", "toto").length.should == 2; 14 } 15 16 @("vector.int") 17 @safe unittest { 18 vector(1, 2, 3, 4, 5).range.should == [1, 2, 3, 4, 5]; 19 vector(2, 3, 4).range.should == [2, 3, 4]; 20 vector(2, 3, 4).range.should == [2, 3, 4]; 21 } 22 23 @("vector.double") 24 @safe unittest { 25 vector(33.3).range.should == [33.3]; 26 vector(22.2, 77.7).range.should == [22.2, 77.7]; 27 } 28 29 @("copying") 30 @safe unittest { 31 auto vec1 = vector(1, 2, 3); 32 () @trusted { vec1.reserve(10); }(); 33 auto vec2 = vec1; 34 vec1[1] = 7; 35 36 vec1.range.should == [1, 7, 3]; 37 vec2.range.should == [1, 2, 3]; 38 } 39 40 @("bounds check") 41 @safe unittest { 42 43 auto vec = vector(1, 2, 3); 44 () @trusted { vec.reserve(10); }(); 45 vec[3].shouldThrow!BoundsException; 46 vec[-1].shouldThrow!BoundsException; 47 () @trusted { vec[0 .. 4].shouldThrow!BoundsException; }(); 48 () @trusted { vec[0.. 3]; }(); // shouldn't throw (see #45) 49 } 50 51 @("extend") 52 @system unittest { 53 import std.algorithm: map; 54 55 auto vec = vector(0, 1, 2, 3); 56 57 vec ~= 4; 58 vec.range.should == [0, 1, 2, 3, 4]; 59 60 vec ~= [5, 6]; 61 vec.range.should == [0, 1, 2, 3, 4, 5, 6]; 62 63 vec ~= [1, 2].map!(a => a + 10); 64 vec.range.should == [0, 1, 2, 3, 4, 5, 6, 11, 12]; 65 } 66 67 68 @("put") 69 @system unittest { 70 import std.range: iota; 71 72 auto vec = vector(0, 1, 2, 3); 73 vec.put(4); 74 vec.range.should == [0, 1, 2, 3, 4]; 75 vec.put(2.iota); 76 vec.range.should == [0, 1, 2, 3, 4, 0, 1]; 77 } 78 79 @("append") 80 @system unittest { 81 auto vec1 = vector(0, 1, 2); 82 auto vec2 = vector(3, 4); 83 84 auto vec3 = vec1 ~ vec2; 85 vec3.range.should == [0, 1, 2, 3, 4]; 86 87 vec1[0] = 7; 88 vec2[0] = 9; 89 vec3.range.should == [0, 1, 2, 3, 4]; 90 91 92 // make sure capacity is larger 93 vec1 ~= 100; 94 vec1.capacity.shouldBeGreaterThan(vec1.length); 95 vec1.range.should == [7, 1, 2, 100]; 96 97 vec2 ~= 200; 98 vec2.capacity.shouldBeGreaterThan(vec2.length); 99 vec2.range.should == [9, 4, 200]; 100 101 (vec1 ~ vec2).range.should == [7, 1, 2, 100, 9, 4, 200]; 102 (vec1 ~ vector(11, 12, 13, 14, 15)).range.should == [7, 1, 2, 100, 11, 12, 13, 14, 15]; 103 } 104 105 @("slice") 106 @system unittest { 107 const vec = vector(0, 1, 2, 3, 4, 5); 108 vec[].should == [0, 1, 2, 3, 4, 5]; 109 vec[1 .. 3].should == [1, 2]; 110 vec[1 .. 4].should == [1, 2, 3]; 111 vec[2 .. 5].should == [2, 3, 4]; 112 vec[1 .. $ - 1].should == [1, 2, 3, 4]; 113 vec[0 .. 6].should == [0, 1, 2, 3, 4, 5]; 114 } 115 116 @("opDollar") 117 @system unittest { 118 auto vec = vector(0, 1, 2, 3, 4); 119 vec ~= 5; 120 vec ~= 6; 121 vec.capacity.shouldBeGreaterThan(vec.length); 122 123 vec[1 .. $ - 1].should == [1, 2, 3, 4, 5]; 124 } 125 126 @("assign") 127 @system unittest { 128 import std.range: iota; 129 auto vec = vector(10, 11, 12); 130 vec = 5.iota; 131 vec.range.should == [0, 1, 2, 3, 4]; 132 } 133 134 @("construct from range") 135 @safe unittest { 136 import std.range: iota; 137 vector(5.iota).range.should == [0, 1, 2, 3, 4]; 138 } 139 140 141 @("popBack") 142 @safe unittest { 143 auto vec = vector(0, 1, 2); 144 vec.popBack; 145 vec.range.should == [0, 1]; 146 } 147 148 @("popFront") 149 @safe unittest { 150 auto vec = vector(0, 1, 2, 3, 4); 151 vec.popFront; 152 vec.range.should == [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 @("opSliceAssign") 161 @system unittest { 162 auto vec = vector("foo", "bar", "quux", "toto"); 163 164 vec[] = "haha"; 165 vec.range.should == ["haha", "haha", "haha", "haha"]; 166 167 vec[1..3] = "oops"; 168 vec.range.should == ["haha", "oops", "oops", "haha"]; 169 } 170 171 @("opSliceOpAssign") 172 @system unittest { 173 auto vec = vector("foo", "bar", "quux", "toto"); 174 vec[] ~= "oops"; 175 vec.range.should == ["foooops", "baroops", "quuxoops", "totooops"]; 176 } 177 178 @("opSliceOpAssign range") 179 @system unittest { 180 auto vec = vector("foo", "bar", "quux", "toto"); 181 vec[1..3] ~= "oops"; 182 vec.range.should == ["foo", "baroops", "quuxoops", "toto"]; 183 } 184 185 @("clear") 186 @safe unittest { 187 auto vec = vector(0, 1, 2, 3); 188 vec.clear; 189 int[] empty; 190 vec.range.should ==(empty); 191 } 192 193 194 @("Mallocator elements") 195 @safe @nogc unittest { 196 import std.algorithm: equal; 197 auto vec = vector!Mallocator(0, 1, 2, 3); 198 int[4] exp = [0, 1, 2, 3]; 199 assert(equal(vec.range, exp[])); 200 } 201 202 @("Mallocator range") 203 @safe @nogc unittest { 204 import std.algorithm: equal; 205 import std.range: iota; 206 auto vec = vector!Mallocator(iota(5)); 207 int[5] exp = [0, 1, 2, 3, 4]; 208 assert(equal(vec.range, exp[])); 209 } 210 211 212 @("theAllocator null") 213 @safe unittest { 214 Vector!int vec; 215 } 216 217 218 @("Mallocator null") 219 @safe @nogc unittest { 220 Vector!(int, Mallocator) vec; 221 } 222 223 224 @("escape.range") 225 @safe @nogc unittest { 226 227 alias Ints = typeof(Vector!(int, Mallocator).init.range()); 228 229 Ints ints1; 230 scope vec = vector!Mallocator(0, 1, 2, 3); 231 Ints ints2; 232 233 static assert(!__traits(compiles, ints1 = vec.range)); 234 ints2 = vec.range; // should compile 235 } 236 237 238 @("escape.element") 239 @safe unittest { 240 241 int i = 1; 242 int j = 2; 243 244 int** oops; 245 scope vec = vector(&i, &j); 246 int** ok; 247 248 // Taking address of `ref` return not allowed in older dmd versions 249 static if (__VERSION__ >= 2101) 250 { 251 static assert(!__traits(compiles, oops = &vec[0])); 252 ok = &vec[0]; 253 } 254 } 255 256 257 @("TestAllocator elements capacity") 258 @system unittest { 259 static TestAllocator allocator; 260 261 auto vec = vector(&allocator, 0, 1, 2); 262 vec.range.should == [0, 1, 2]; 263 264 vec ~= 3; 265 vec ~= 4; 266 vec ~= 5; 267 vec ~= 6; 268 vec ~= 7; 269 vec ~= 8; 270 271 vec.range.should == [0, 1, 2, 3, 4, 5, 6, 7, 8]; 272 allocator.numAllocations.shouldBeSmallerThan(4); 273 } 274 275 @("TestAllocator reserve") 276 @system unittest { 277 static TestAllocator allocator; 278 279 auto vec = vector!(TestAllocator*, int)(&allocator); 280 281 vec.reserve(5); 282 () @trusted { vec.empty.should == true; }(); 283 284 vec ~= 0; 285 vec ~= 1; 286 vec ~= 2; 287 vec ~= 3; 288 vec ~= 4; 289 290 vec.range.should == [0, 1, 2, 3, 4]; 291 allocator.numAllocations.should == 1; 292 293 vec ~= 5; 294 vec.range.should == [0, 1, 2, 3, 4, 5]; 295 allocator.numAllocations.should == 2; 296 } 297 298 @("TestAllocator shrink no length") 299 @system unittest { 300 static TestAllocator allocator; 301 302 auto vec = vector!(TestAllocator*, int)(&allocator); 303 vec.reserve(10); 304 305 vec ~= 0; 306 vec ~= 1; 307 vec ~= 2; 308 vec ~= 3; 309 310 vec.length.should == 4; 311 vec.capacity.should == 10; 312 313 vec.shrink; 314 vec.length.should == 4; 315 vec.capacity.should == 4; 316 } 317 318 @("TestAllocator shrink negative number") 319 @system unittest { 320 static TestAllocator allocator; 321 322 auto vec = vector(&allocator, 0); 323 vec ~= 1; 324 vec ~= 2; 325 vec ~= 3; 326 vec.capacity.shouldBeGreaterThan(vec.length); 327 const oldCapacity = vec.capacity; 328 329 vec.shrink(-1).shouldBeFalse; 330 vec.capacity.should == oldCapacity; 331 } 332 333 @("TestAllocator shrink larger than capacity") 334 @system unittest { 335 static TestAllocator allocator; 336 337 auto vec = vector(&allocator, 0); 338 vec ~= 1; 339 vec ~= 2; 340 vec ~= 3; 341 vec.capacity.shouldBeGreaterThan(vec.length); 342 const oldCapacity = vec.capacity; 343 344 vec.shrink(oldCapacity * 2).shouldBeFalse; 345 vec.capacity.should == oldCapacity; 346 } 347 348 349 @("TestAllocator shrink with length") 350 @system unittest { 351 static TestAllocator allocator; 352 353 auto vec = vector(&allocator, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); 354 vec.capacity.should == 10; 355 356 vec.shrink(5); 357 vec.range.should == [0, 1, 2, 3, 4]; 358 vec.capacity.should == 5; 359 360 vec ~= 5; 361 vec.range.should == [0, 1, 2, 3, 4, 5]; 362 allocator.numAllocations.should == 3; 363 364 vec.reserve(10); 365 vec.length.should == 6; 366 vec.capacity.shouldBeGreaterThan(6); 367 } 368 369 @("TestAllocator shrink with length range invalidation") 370 @safe unittest { 371 static TestAllocator allocator; 372 373 scope vec = vector(&allocator, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); 374 vec.capacity.should == 10; 375 scope rng = vec.range; 376 377 foreach(i; 0 .. 5) 378 rng.popFront; 379 rng.empty.should == false; 380 381 () @trusted { vec.shrink(5); }(); 382 rng.empty.should == true; 383 } 384 385 @("TestAllocator copy") 386 @safe unittest { 387 static TestAllocator allocator; 388 389 auto vec1 = vector(&allocator, "foo", "bar", "baz"); 390 allocator.numAllocations.should == 1; 391 392 auto vec2 = vec1; 393 allocator.numAllocations.should == 2; 394 } 395 396 @("TestAllocator move") 397 @safe unittest { 398 static TestAllocator allocator; 399 400 auto vec = vector(&allocator, "foo", "bar", "baz"); 401 allocator.numAllocations.should == 1; 402 403 consumeVec(vec); 404 allocator.numAllocations.should == 1; 405 } 406 407 408 private void consumeVec(T)(auto ref T vec) { 409 410 } 411 412 413 @("set length") 414 @system unittest { 415 Vector!int vec; 416 vec.length = 3; 417 vec.range.should == [0, 0, 0]; 418 } 419 420 421 @("foreach") 422 @safe unittest { 423 // can't be inline in the foreach otherwise disappears before anything happens 424 scope v = vector(7, 7, 7); 425 foreach(e; v.range) { 426 e.should == 7; 427 } 428 } 429 430 431 @("equal") 432 @safe unittest { 433 import std.range: iota; 434 import std.algorithm: equal; 435 436 auto v = vector(0, 1, 2, 3); 437 assert(equal(v.range, 4.iota)); 438 } 439 440 441 @("bool") 442 @safe unittest { 443 vector(0, 1, 2).shouldBeTrue; 444 Vector!int v; 445 if(v) { 446 assert(0); 447 } 448 } 449 450 @("char") 451 @system unittest { 452 { 453 auto vec = vector('f', 'o', 'o'); 454 vec.range.should ==("foo"); 455 vec ~= 'b'; 456 vec ~= ['a', 'r']; 457 vec.range.should ==("foobar"); 458 vec ~= "quux"; 459 vec.range.should ==("foobarquux"); 460 } 461 462 { 463 auto vec = vector("foo"); 464 vec.range.should ==("foo"); 465 vec.popBack; 466 vec.range.should ==("fo"); 467 } 468 469 { 470 auto vec = vector("foo"); 471 vec ~= "bar"; 472 vec.range.should ==("foobar"); 473 } 474 } 475 476 477 @("immutable.append") 478 @system unittest { 479 Vector!(immutable int) vec; 480 vec ~= 42; 481 vec.range.should == [42]; 482 } 483 484 485 @("String") 486 @safe unittest { 487 // can't be inline in the foreach otherwise disappears 488 auto s = String("oooooo"); 489 foreach(c; s.range) 490 c.should == 'o'; 491 } 492 493 @("stringz") 494 @safe unittest { 495 import std.string: fromStringz; 496 auto str = vector("foobar"); 497 const strz = () @trusted { return str.stringz; }(); 498 const back = () @trusted { return fromStringz(strz); }(); 499 back.should == "foobar"; 500 str.range.should ==("foobar"); 501 } 502 503 504 @("ptr") 505 @safe unittest { 506 const vec = vector(0, 1, 2, 3); 507 takesScopePtr(vec.ptr); 508 () @trusted { vec.ptr[1].should == 1; }(); 509 } 510 511 private void takesScopePtr(T)(scope const(T)* ptr) { 512 513 } 514 515 516 @("StackFront") 517 @safe @nogc unittest { 518 import std.algorithm: equal; 519 import std.experimental.allocator.showcase: StackFront; 520 import std.experimental.allocator.mallocator: Mallocator; 521 522 alias Allocator = StackFront!(1024, Mallocator); 523 524 { 525 Vector!(int, Allocator) v; 526 () @trusted { v ~= 1; }(); 527 { 528 int[1] expected = [1]; 529 assert(equal(v.range, expected[])); 530 } 531 } 532 533 { 534 static void fun(Allocator)(ref Allocator allocator) { 535 Vector!(int, Allocator) v; 536 } 537 } 538 } 539 540 541 version(Windows) {} 542 else { 543 @("mmapRegionList") 544 @system unittest { 545 import std.experimental.allocator.showcase: mmapRegionList; 546 import std.experimental.allocator.mallocator: Mallocator; 547 import automem.vector: isAllocator; 548 549 auto v = vector(mmapRegionList(1024), 0, 1, 2); 550 v ~= 3; 551 } 552 } 553 554 555 556 @("2d") 557 @safe unittest { 558 auto v = vector(vector(0, 0, 0), vector(1, 1, 1, 1)); 559 v[0].range.should == [0, 0, 0]; 560 v[1].range.should == [1, 1, 1, 1]; 561 } 562 563 564 @("toString") 565 @safe unittest { 566 import std.conv: text; 567 auto v = vector(1, 2, 3); 568 v.range.text.should == `[1, 2, 3]`; 569 } 570 571 572 @("return") 573 @system unittest { 574 575 static auto fun() { 576 auto v = vector(1, 2, 3); 577 v ~= 4; 578 return v; 579 } 580 581 auto v = fun; 582 v ~= 5; 583 v.range.should == [1, 2, 3, 4, 5]; 584 } 585 586 587 @("noconsume.range") 588 @safe unittest { 589 import std.algorithm: equal; 590 591 scope v = vector(1, 2, 3); 592 593 static void fun(R)(R range) { 594 import std.array: array; 595 assert(equal(range, [1, 2, 3])); 596 } 597 598 fun(v.range); 599 assert(equal(v.range, [1, 2, 3])); 600 } 601 602 603 @("noconsume.foreach") 604 @safe unittest { 605 scope v = vector(1, 2, 3); 606 foreach(e; v.range) {} 607 v.range.should == [1, 2, 3]; 608 } 609 610 611 @("noconsume.map") 612 @safe unittest { 613 import std.algorithm: map; 614 615 scope v = vector(1, 2, 3); 616 v.range.map!(a => a * 2).should == [2, 4, 6]; 617 v.range.should == [1, 2, 3]; 618 } 619 620 621 @("reserve") 622 @safe unittest { 623 scope vec = vector(1, 2, 3); 624 vec.range.should == [1, 2, 3]; 625 () @trusted { vec.reserve(10); }(); 626 vec.range.should == [1, 2, 3]; 627 } 628 629 630 @("range.reserve") 631 @safe unittest { 632 scope vec = vector(1, 2, 3); 633 scope range = vec.range; 634 635 range.save.should == [1, 2, 3]; 636 () @trusted { vec.reserve(10); }(); 637 638 range.should == [1, 2, 3]; 639 } 640 641 642 @("range.const") 643 @safe unittest { 644 const vec = vector(1, 2, 3); 645 vec.range.should == [1, 2, 3]; 646 } 647 648 649 @("range.bounds") 650 @safe unittest { 651 const vec = vector(1, 2, 3, 4, 5); 652 vec.range(1, 4).should == [2, 3, 4]; 653 vec.range(2, vec.length).should == [3, 4, 5]; 654 vec.range(2, -1).should == [3, 4, 5]; 655 vec.range(2, -2).should == [3, 4]; 656 } 657 658 659 @("equals") 660 @safe unittest { 661 import std.range: iota, only; 662 663 const vec = vector(0, 1, 2); 664 665 (vec == 3.iota).should == true; 666 (vec == 2.iota).should == false; 667 (vec == 4.iota).should == false; 668 (vec == only(0)).should == false; 669 }