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