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