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 @("back") 137 @safe unittest { 138 const vec = vector("foo", "bar", "baz"); 139 vec.back[].shouldEqual("baz"); 140 } 141 142 @("opSliceAssign") 143 @safe unittest { 144 auto vec = vector("foo", "bar", "quux", "toto"); 145 146 vec[] = "haha"; 147 vec[].shouldEqual(["haha", "haha", "haha", "haha"]); 148 149 vec[1..3] = "oops"; 150 vec[].shouldEqual(["haha", "oops", "oops", "haha"]); 151 } 152 153 @("opSliceOpAssign") 154 @safe unittest { 155 auto vec = vector("foo", "bar", "quux", "toto"); 156 vec[] ~= "oops"; 157 vec[].shouldEqual(["foooops", "baroops", "quuxoops", "totooops"]); 158 } 159 160 @("opSliceOpAssign range") 161 @safe unittest { 162 auto vec = vector("foo", "bar", "quux", "toto"); 163 vec[1..3] ~= "oops"; 164 vec[].shouldEqual(["foo", "baroops", "quuxoops", "toto"]); 165 } 166 167 @("clear") 168 @safe unittest { 169 auto vec = vector(0, 1, 2, 3); 170 vec.clear; 171 int[] empty; 172 vec[].shouldEqual(empty); 173 } 174 175 176 @("Mallocator elements") 177 @safe @nogc unittest { 178 import std.algorithm: equal; 179 auto vec = vector!Mallocator(0, 1, 2, 3); 180 int[4] exp = [0, 1, 2, 3]; 181 assert(equal(vec[], exp[])); 182 } 183 184 @("Mallocator range") 185 @safe @nogc unittest { 186 import std.algorithm: equal; 187 import std.range: iota; 188 auto vec = vector!Mallocator(iota(5)); 189 int[5] exp = [0, 1, 2, 3, 4]; 190 assert(equal(vec[], exp[])); 191 } 192 193 194 @("theAllocator null") 195 @safe unittest { 196 Vector!int vec; 197 } 198 199 200 @("Mallocator null") 201 @safe @nogc unittest { 202 Vector!(int, Mallocator) vec; 203 } 204 205 @("Cannot escape slice") 206 @safe @nogc unittest { 207 int[] ints1; 208 scope vec = vector!Mallocator(0, 1, 2, 3); 209 int[] ints2; 210 211 static assert(!__traits(compiles, ints1 = vec[])); 212 static assert(__traits(compiles, ints2 = vec[])); 213 } 214 215 216 @("TestAllocator elements capacity") 217 @safe unittest { 218 static TestAllocator allocator; 219 220 auto vec = vector(&allocator, 0, 1, 2); 221 vec[].shouldEqual([0, 1, 2]); 222 223 vec ~= 3; 224 vec ~= 4; 225 vec ~= 5; 226 vec ~= 6; 227 vec ~= 7; 228 vec ~= 8; 229 230 vec[].shouldEqual([0, 1, 2, 3, 4, 5, 6, 7, 8]); 231 allocator.numAllocations.shouldBeSmallerThan(4); 232 } 233 234 @("TestAllocator reserve") 235 @safe unittest { 236 static TestAllocator allocator; 237 238 auto vec = vector!(TestAllocator*, int)(&allocator); 239 240 vec.reserve(5); 241 () @trusted { vec.shouldBeEmpty; }(); 242 243 vec ~= 0; 244 vec ~= 1; 245 vec ~= 2; 246 vec ~= 3; 247 vec ~= 4; 248 249 vec[].shouldEqual([0, 1, 2, 3, 4]); 250 allocator.numAllocations.should == 1; 251 252 vec ~= 5; 253 vec[].shouldEqual([0, 1, 2, 3, 4, 5]); 254 allocator.numAllocations.should == 2; 255 } 256 257 @("TestAllocator shrink no length") 258 @safe unittest { 259 static TestAllocator allocator; 260 261 auto vec = vector!(TestAllocator*, int)(&allocator); 262 vec.reserve(10); 263 264 vec ~= 0; 265 vec ~= 1; 266 vec ~= 2; 267 vec ~= 3; 268 269 vec.length.should == 4; 270 vec.capacity.should == 10; 271 272 vec.shrink; 273 vec.length.should == 4; 274 vec.capacity.should == 4; 275 } 276 277 @("TestAllocator shrink negative number") 278 @safe unittest { 279 static TestAllocator allocator; 280 281 auto vec = vector(&allocator, 0); 282 vec ~= 1; 283 vec ~= 2; 284 vec ~= 3; 285 vec.capacity.shouldBeGreaterThan(vec.length); 286 const oldCapacity = vec.capacity; 287 288 vec.shrink(-1).shouldBeFalse; 289 vec.capacity.should == oldCapacity; 290 } 291 292 @("TestAllocator shrink larger than capacity") 293 @safe unittest { 294 static TestAllocator allocator; 295 296 auto vec = vector(&allocator, 0); 297 vec ~= 1; 298 vec ~= 2; 299 vec ~= 3; 300 vec.capacity.shouldBeGreaterThan(vec.length); 301 const oldCapacity = vec.capacity; 302 303 vec.shrink(oldCapacity * 2).shouldBeFalse; 304 vec.capacity.should == oldCapacity; 305 } 306 307 308 @("TestAllocator shrink with length") 309 @safe unittest { 310 static TestAllocator allocator; 311 312 auto vec = vector(&allocator, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); 313 vec.capacity.should == 10; 314 315 vec.shrink(5); 316 vec[].shouldEqual([0, 1, 2, 3, 4]); 317 vec.capacity.should == 5; 318 319 vec ~= 5; 320 vec[].shouldEqual([0, 1, 2, 3, 4, 5]); 321 allocator.numAllocations.should == 3; 322 323 vec.reserve(10); 324 vec.length.should == 6; 325 vec.capacity.shouldBeGreaterThan(6); 326 } 327 328 @("TestAllocator copy") 329 @safe unittest { 330 static TestAllocator allocator; 331 332 auto vec1 = vector(&allocator, "foo", "bar", "baz"); 333 allocator.numAllocations.should == 1; 334 335 auto vec2 = vec1; 336 allocator.numAllocations.should == 2; 337 } 338 339 @("TestAllocator move") 340 @safe unittest { 341 static TestAllocator allocator; 342 343 auto vec = vector(&allocator, "foo", "bar", "baz"); 344 allocator.numAllocations.should == 1; 345 346 consumeVec(vec); 347 allocator.numAllocations.should == 1; 348 } 349 350 351 private void consumeVec(T)(auto ref T vec) { 352 353 } 354 355 356 @("set length") 357 @safe unittest { 358 Vector!int vec; 359 vec.length = 3; 360 vec[].shouldEqual([0, 0, 0]); 361 }