1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "mozilla/IntegerRange.h"
10 #include "mozilla/UniquePtr.h"
11 #include "mozilla/Vector.h"
13 using mozilla::IntegerRange
;
14 using mozilla::MakeUnique
;
15 using mozilla::UniquePtr
;
16 using mozilla::Vector
;
17 using mozilla::detail::VectorTesting
;
19 struct mozilla::detail::VectorTesting
{
20 static void testReserved();
21 static void testConstRange();
22 static void testEmplaceBack();
23 static void testReverse();
24 static void testExtractRawBuffer();
25 static void testExtractOrCopyRawBuffer();
26 static void testReplaceRawBuffer();
27 static void testInsert();
28 static void testErase();
29 static void testShrinkStorageToFit();
30 static void testAppend();
33 void mozilla::detail::VectorTesting::testReserved() {
36 MOZ_RELEASE_ASSERT(bv
.reserved() == 0);
38 MOZ_RELEASE_ASSERT(bv
.append(true));
39 MOZ_RELEASE_ASSERT(bv
.reserved() == 1);
42 MOZ_RELEASE_ASSERT(otherbv
.append(false));
43 MOZ_RELEASE_ASSERT(otherbv
.append(true));
44 MOZ_RELEASE_ASSERT(bv
.appendAll(otherbv
));
45 MOZ_RELEASE_ASSERT(bv
.reserved() == 3);
47 MOZ_RELEASE_ASSERT(bv
.reserve(5));
48 MOZ_RELEASE_ASSERT(bv
.reserved() == 5);
50 MOZ_RELEASE_ASSERT(bv
.reserve(1));
51 MOZ_RELEASE_ASSERT(bv
.reserved() == 5);
53 Vector
<bool> bv2(std::move(bv
));
54 MOZ_RELEASE_ASSERT(bv
.reserved() == 0);
55 MOZ_RELEASE_ASSERT(bv2
.reserved() == 5);
58 MOZ_RELEASE_ASSERT(bv2
.reserved() == 0);
61 MOZ_RELEASE_ASSERT(iv
.reserved() == 0);
63 MOZ_RELEASE_ASSERT(iv
.append(17));
64 MOZ_RELEASE_ASSERT(iv
.reserved() == 1);
66 Vector
<int, 42> otheriv
;
67 MOZ_RELEASE_ASSERT(otheriv
.append(42));
68 MOZ_RELEASE_ASSERT(otheriv
.append(37));
69 MOZ_RELEASE_ASSERT(iv
.appendAll(otheriv
));
70 MOZ_RELEASE_ASSERT(iv
.reserved() == 3);
72 MOZ_RELEASE_ASSERT(iv
.reserve(5));
73 MOZ_RELEASE_ASSERT(iv
.reserved() == 5);
75 MOZ_RELEASE_ASSERT(iv
.reserve(1));
76 MOZ_RELEASE_ASSERT(iv
.reserved() == 5);
78 MOZ_RELEASE_ASSERT(iv
.reserve(55));
79 MOZ_RELEASE_ASSERT(iv
.reserved() == 55);
81 Vector
<int, 42> iv2(std::move(iv
));
82 MOZ_RELEASE_ASSERT(iv
.reserved() == 0);
83 MOZ_RELEASE_ASSERT(iv2
.reserved() == 55);
86 MOZ_RELEASE_ASSERT(iv2
.reserved() == 0);
90 void mozilla::detail::VectorTesting::testConstRange() {
94 for (int i
= 0; i
< 10; i
++) {
95 MOZ_RELEASE_ASSERT(vec
.append(i
));
98 const auto& vecRef
= vec
;
100 Vector
<int>::ConstRange range
= vecRef
.all();
101 for (int i
= 0; i
< 10; i
++) {
102 MOZ_RELEASE_ASSERT(!range
.empty());
103 MOZ_RELEASE_ASSERT(range
.front() == i
);
115 static size_t constructCount
;
116 static size_t moveCount
;
117 static size_t destructCount
;
119 static void resetCounts() {
125 S(size_t j
, size_t k
) : j(j
), k(MakeUnique
<size_t>(k
)) { constructCount
++; }
127 S(S
&& rhs
) : j(rhs
.j
), k(std::move(rhs
.k
)) {
133 ~S() { destructCount
++; }
135 S
& operator=(S
&& rhs
) {
138 k
= std::move(rhs
.k
);
144 bool operator==(const S
& rhs
) const { return j
== rhs
.j
&& *k
== *rhs
.k
; }
146 S(const S
&) = delete;
147 S
& operator=(const S
&) = delete;
150 size_t S::constructCount
= 0;
151 size_t S::moveCount
= 0;
152 size_t S::destructCount
= 0;
156 void mozilla::detail::VectorTesting::testEmplaceBack() {
160 MOZ_RELEASE_ASSERT(vec
.reserve(20));
162 for (size_t i
= 0; i
< 10; i
++) {
164 MOZ_RELEASE_ASSERT(vec
.append(std::move(s
)));
167 MOZ_RELEASE_ASSERT(vec
.length() == 10);
168 MOZ_RELEASE_ASSERT(S::constructCount
== 10);
169 MOZ_RELEASE_ASSERT(S::moveCount
== 10);
171 for (size_t i
= 10; i
< 20; i
++) {
172 MOZ_RELEASE_ASSERT(vec
.emplaceBack(i
, i
* i
));
175 MOZ_RELEASE_ASSERT(vec
.length() == 20);
176 MOZ_RELEASE_ASSERT(S::constructCount
== 20);
177 MOZ_RELEASE_ASSERT(S::moveCount
== 10);
179 for (size_t i
= 0; i
< 20; i
++) {
180 MOZ_RELEASE_ASSERT(vec
[i
].j
== i
);
181 MOZ_RELEASE_ASSERT(*vec
[i
].k
== i
* i
);
185 void mozilla::detail::VectorTesting::testReverse() {
186 // Use UniquePtr to make sure that reverse() can handler move-only types.
187 Vector
<UniquePtr
<uint8_t>, 0> vec
;
189 // Reverse an odd number of elements.
191 for (uint8_t i
= 0; i
< 5; i
++) {
192 auto p
= MakeUnique
<uint8_t>(i
);
193 MOZ_RELEASE_ASSERT(p
);
194 MOZ_RELEASE_ASSERT(vec
.append(std::move(p
)));
199 MOZ_RELEASE_ASSERT(*vec
[0] == 4);
200 MOZ_RELEASE_ASSERT(*vec
[1] == 3);
201 MOZ_RELEASE_ASSERT(*vec
[2] == 2);
202 MOZ_RELEASE_ASSERT(*vec
[3] == 1);
203 MOZ_RELEASE_ASSERT(*vec
[4] == 0);
205 // Reverse an even number of elements.
210 MOZ_RELEASE_ASSERT(*vec
[0] == 1);
211 MOZ_RELEASE_ASSERT(*vec
[1] == 2);
212 MOZ_RELEASE_ASSERT(*vec
[2] == 3);
213 MOZ_RELEASE_ASSERT(*vec
[3] == 4);
215 // Reverse an empty vector.
218 MOZ_RELEASE_ASSERT(vec
.length() == 0);
220 MOZ_RELEASE_ASSERT(vec
.length() == 0);
222 // Reverse a vector using only inline storage.
224 Vector
<UniquePtr
<uint8_t>, 5> vec2
;
225 for (uint8_t i
= 0; i
< 5; i
++) {
226 auto p
= MakeUnique
<uint8_t>(i
);
227 MOZ_RELEASE_ASSERT(p
);
228 MOZ_RELEASE_ASSERT(vec2
.append(std::move(p
)));
233 MOZ_RELEASE_ASSERT(*vec2
[0] == 4);
234 MOZ_RELEASE_ASSERT(*vec2
[1] == 3);
235 MOZ_RELEASE_ASSERT(*vec2
[2] == 2);
236 MOZ_RELEASE_ASSERT(*vec2
[3] == 1);
237 MOZ_RELEASE_ASSERT(*vec2
[4] == 0);
240 void mozilla::detail::VectorTesting::testExtractRawBuffer() {
244 MOZ_RELEASE_ASSERT(vec
.reserve(5));
245 for (size_t i
= 0; i
< 5; i
++) {
246 vec
.infallibleEmplaceBack(i
, i
* i
);
248 MOZ_RELEASE_ASSERT(vec
.length() == 5);
249 MOZ_ASSERT(vec
.reserved() == 5);
250 MOZ_RELEASE_ASSERT(S::constructCount
== 5);
251 MOZ_RELEASE_ASSERT(S::moveCount
== 0);
252 MOZ_RELEASE_ASSERT(S::destructCount
== 0);
254 S
* buf
= vec
.extractRawBuffer();
255 MOZ_RELEASE_ASSERT(!buf
);
256 MOZ_RELEASE_ASSERT(vec
.length() == 5);
257 MOZ_ASSERT(vec
.reserved() == 5);
258 MOZ_RELEASE_ASSERT(S::constructCount
== 5);
259 MOZ_RELEASE_ASSERT(S::moveCount
== 0);
260 MOZ_RELEASE_ASSERT(S::destructCount
== 0);
262 MOZ_RELEASE_ASSERT(vec
.reserve(10));
263 for (size_t i
= 5; i
< 10; i
++) {
264 vec
.infallibleEmplaceBack(i
, i
* i
);
266 MOZ_RELEASE_ASSERT(vec
.length() == 10);
267 MOZ_ASSERT(vec
.reserved() == 10);
268 MOZ_RELEASE_ASSERT(S::constructCount
== 10);
269 MOZ_RELEASE_ASSERT(S::moveCount
== 5);
270 MOZ_RELEASE_ASSERT(S::destructCount
== 5);
272 buf
= vec
.extractRawBuffer();
273 MOZ_RELEASE_ASSERT(buf
);
274 MOZ_RELEASE_ASSERT(vec
.length() == 0);
275 MOZ_ASSERT(vec
.reserved() == 0);
276 MOZ_RELEASE_ASSERT(S::constructCount
== 10);
277 MOZ_RELEASE_ASSERT(S::moveCount
== 5);
278 MOZ_RELEASE_ASSERT(S::destructCount
== 5);
280 for (size_t i
= 0; i
< 10; i
++) {
281 MOZ_RELEASE_ASSERT(buf
[i
].j
== i
);
282 MOZ_RELEASE_ASSERT(*buf
[i
].k
== i
* i
);
288 void mozilla::detail::VectorTesting::testExtractOrCopyRawBuffer() {
292 MOZ_RELEASE_ASSERT(vec
.reserve(5));
293 for (size_t i
= 0; i
< 5; i
++) {
294 vec
.infallibleEmplaceBack(i
, i
* i
);
296 MOZ_RELEASE_ASSERT(vec
.length() == 5);
297 MOZ_ASSERT(vec
.reserved() == 5);
298 MOZ_RELEASE_ASSERT(S::constructCount
== 5);
299 MOZ_RELEASE_ASSERT(S::moveCount
== 0);
300 MOZ_RELEASE_ASSERT(S::destructCount
== 0);
302 S
* buf
= vec
.extractOrCopyRawBuffer();
303 MOZ_RELEASE_ASSERT(buf
);
304 MOZ_RELEASE_ASSERT(vec
.length() == 0);
305 MOZ_ASSERT(vec
.reserved() == 0);
306 MOZ_RELEASE_ASSERT(S::constructCount
== 5);
307 MOZ_RELEASE_ASSERT(S::moveCount
== 5);
308 MOZ_RELEASE_ASSERT(S::destructCount
== 5);
310 for (size_t i
= 0; i
< 5; i
++) {
311 MOZ_RELEASE_ASSERT(buf
[i
].j
== i
);
312 MOZ_RELEASE_ASSERT(*buf
[i
].k
== i
* i
);
317 MOZ_RELEASE_ASSERT(vec
.reserve(10));
318 for (size_t i
= 0; i
< 10; i
++) {
319 vec
.infallibleEmplaceBack(i
, i
* i
);
321 MOZ_RELEASE_ASSERT(vec
.length() == 10);
322 MOZ_ASSERT(vec
.reserved() == 10);
323 MOZ_RELEASE_ASSERT(S::constructCount
== 10);
324 MOZ_RELEASE_ASSERT(S::moveCount
== 0);
325 MOZ_RELEASE_ASSERT(S::destructCount
== 0);
327 buf
= vec
.extractOrCopyRawBuffer();
328 MOZ_RELEASE_ASSERT(buf
);
329 MOZ_RELEASE_ASSERT(vec
.length() == 0);
330 MOZ_ASSERT(vec
.reserved() == 0);
331 MOZ_RELEASE_ASSERT(S::constructCount
== 10);
332 MOZ_RELEASE_ASSERT(S::moveCount
== 0);
333 MOZ_RELEASE_ASSERT(S::destructCount
== 0);
335 for (size_t i
= 0; i
< 10; i
++) {
336 MOZ_RELEASE_ASSERT(buf
[i
].j
== i
);
337 MOZ_RELEASE_ASSERT(*buf
[i
].k
== i
* i
);
343 void mozilla::detail::VectorTesting::testReplaceRawBuffer() {
350 MOZ_RELEASE_ASSERT(v
.reserve(4));
351 v
.infallibleEmplaceBack(1, 2);
352 v
.infallibleEmplaceBack(3, 4);
353 MOZ_RELEASE_ASSERT(S::constructCount
== 2);
354 s
= v
.extractRawBuffer();
357 MOZ_RELEASE_ASSERT(S::constructCount
== 2);
358 MOZ_RELEASE_ASSERT(S::moveCount
== 0);
359 MOZ_RELEASE_ASSERT(S::destructCount
== 0);
363 v
.replaceRawBuffer(s
, 2);
364 MOZ_ASSERT(v
.reserved() == 2);
365 MOZ_RELEASE_ASSERT(v
.length() == 2);
366 MOZ_RELEASE_ASSERT(v
.capacity() == 10);
367 MOZ_RELEASE_ASSERT(v
[0].j
== 1);
368 MOZ_RELEASE_ASSERT(v
[1].j
== 3);
369 MOZ_RELEASE_ASSERT(S::destructCount
== 2);
372 MOZ_RELEASE_ASSERT(S::constructCount
== 2);
373 MOZ_RELEASE_ASSERT(S::moveCount
== 2);
374 MOZ_RELEASE_ASSERT(S::destructCount
== 4);
380 MOZ_RELEASE_ASSERT(v
.reserve(4));
381 v
.infallibleEmplaceBack(9, 10);
382 MOZ_RELEASE_ASSERT(S::constructCount
== 1);
383 s
= v
.extractRawBuffer();
384 MOZ_RELEASE_ASSERT(S::constructCount
== 1);
385 MOZ_RELEASE_ASSERT(S::moveCount
== 0);
388 MOZ_RELEASE_ASSERT(S::destructCount
== 0);
392 v
.replaceRawBuffer(s
, 1, 4);
393 MOZ_ASSERT(v
.reserved() == 4);
394 MOZ_RELEASE_ASSERT(v
.length() == 1);
395 MOZ_RELEASE_ASSERT(v
.capacity() == 4);
396 MOZ_RELEASE_ASSERT(v
[0].j
== 9);
397 for (size_t i
= 0; i
< 5; i
++) MOZ_RELEASE_ASSERT(v
.emplaceBack(i
, i
));
398 MOZ_ASSERT(v
.reserved() == 6);
399 MOZ_RELEASE_ASSERT(v
.length() == 6);
400 MOZ_RELEASE_ASSERT(S::constructCount
== 6);
401 MOZ_RELEASE_ASSERT(S::moveCount
== 4);
402 MOZ_RELEASE_ASSERT(S::destructCount
== 4);
405 MOZ_RELEASE_ASSERT(S::destructCount
== 10);
408 void mozilla::detail::VectorTesting::testInsert() {
412 MOZ_RELEASE_ASSERT(vec
.reserve(8));
413 for (size_t i
= 0; i
< 7; i
++) {
414 vec
.infallibleEmplaceBack(i
, i
* i
);
417 MOZ_RELEASE_ASSERT(vec
.length() == 7);
418 MOZ_ASSERT(vec
.reserved() == 8);
419 MOZ_RELEASE_ASSERT(S::constructCount
== 7);
420 MOZ_RELEASE_ASSERT(S::moveCount
== 0);
421 MOZ_RELEASE_ASSERT(S::destructCount
== 0);
424 MOZ_RELEASE_ASSERT(vec
.insert(vec
.begin() + 4, std::move(s
)));
426 for (size_t i
= 0; i
< vec
.length(); i
++) {
428 MOZ_RELEASE_ASSERT(s
.k
);
430 MOZ_RELEASE_ASSERT(s
.j
== i
&& *s
.k
== i
* i
);
432 MOZ_RELEASE_ASSERT(s
.j
== 42 && *s
.k
== 43);
434 MOZ_RELEASE_ASSERT(s
.j
== i
- 1 && *s
.k
== (i
- 1) * (i
- 1));
438 MOZ_RELEASE_ASSERT(vec
.length() == 8);
439 MOZ_ASSERT(vec
.reserved() == 8);
440 MOZ_RELEASE_ASSERT(S::constructCount
== 8);
441 MOZ_RELEASE_ASSERT(S::moveCount
== 1 /* move in insert() call */ +
442 1 /* move the back() element */ +
443 3 /* elements to shift */);
444 MOZ_RELEASE_ASSERT(S::destructCount
== 1);
447 void mozilla::detail::VectorTesting::testErase() {
451 MOZ_RELEASE_ASSERT(vec
.reserve(8));
452 for (size_t i
= 0; i
< 7; i
++) {
453 vec
.infallibleEmplaceBack(i
, i
* i
);
456 // vec: [0, 1, 2, 3, 4, 5, 6]
457 MOZ_RELEASE_ASSERT(vec
.length() == 7);
458 MOZ_ASSERT(vec
.reserved() == 8);
459 MOZ_RELEASE_ASSERT(S::constructCount
== 7);
460 MOZ_RELEASE_ASSERT(S::moveCount
== 0);
461 MOZ_RELEASE_ASSERT(S::destructCount
== 0);
465 // vec: [0, 1, 2, 3, 5, 6]
466 MOZ_RELEASE_ASSERT(vec
.length() == 6);
467 MOZ_ASSERT(vec
.reserved() == 8);
468 MOZ_RELEASE_ASSERT(S::constructCount
== 0);
469 // 5 and 6 should have been moved into 4 and 5.
470 MOZ_RELEASE_ASSERT(S::moveCount
== 2);
471 MOZ_RELEASE_ASSERT(S::destructCount
== 1);
472 MOZ_RELEASE_ASSERT(vec
[4] == S(5, 5 * 5));
473 MOZ_RELEASE_ASSERT(vec
[5] == S(6, 6 * 6));
476 vec
.erase(&vec
[3], &vec
[5]);
478 MOZ_RELEASE_ASSERT(vec
.length() == 4);
479 MOZ_ASSERT(vec
.reserved() == 8);
480 MOZ_RELEASE_ASSERT(S::constructCount
== 0);
481 // 6 should have been moved into 3.
482 MOZ_RELEASE_ASSERT(S::moveCount
== 1);
483 MOZ_RELEASE_ASSERT(S::destructCount
== 2);
484 MOZ_RELEASE_ASSERT(vec
[3] == S(6, 6 * 6));
489 vec
.eraseIfEqual(s2
);
491 MOZ_RELEASE_ASSERT(vec
.length() == 3);
492 MOZ_ASSERT(vec
.reserved() == 8);
493 MOZ_RELEASE_ASSERT(S::constructCount
== 0);
494 // 6 should have been moved into 2.
495 MOZ_RELEASE_ASSERT(S::moveCount
== 1);
496 MOZ_RELEASE_ASSERT(S::destructCount
== 1);
497 MOZ_RELEASE_ASSERT(vec
[2] == S(6, 6 * 6));
500 // Predicate to find one element.
501 vec
.eraseIf([](const S
& s
) { return s
.j
== 1; });
503 MOZ_RELEASE_ASSERT(vec
.length() == 2);
504 MOZ_ASSERT(vec
.reserved() == 8);
505 MOZ_RELEASE_ASSERT(S::constructCount
== 0);
506 // 6 should have been moved into 1.
507 MOZ_RELEASE_ASSERT(S::moveCount
== 1);
508 MOZ_RELEASE_ASSERT(S::destructCount
== 1);
509 MOZ_RELEASE_ASSERT(vec
[1] == S(6, 6 * 6));
512 // Generic predicate that flags everything.
513 vec
.eraseIf([](auto&&) { return true; });
515 MOZ_RELEASE_ASSERT(vec
.length() == 0);
516 MOZ_ASSERT(vec
.reserved() == 8);
517 MOZ_RELEASE_ASSERT(S::constructCount
== 0);
518 MOZ_RELEASE_ASSERT(S::moveCount
== 0);
519 MOZ_RELEASE_ASSERT(S::destructCount
== 2);
521 for (size_t i
= 0; i
< 7; i
++) {
522 vec
.infallibleEmplaceBack(i
, i
* i
);
524 // vec: [0, 1, 2, 3, 4, 5, 6]
525 MOZ_RELEASE_ASSERT(vec
.length() == 7);
528 // Predicate that flags all even numbers.
529 vec
.eraseIf([](const S
& s
) { return s
.j
% 2 == 0; });
530 // vec: [1 (was 0), 3 (was 1), 5 (was 2)]
531 MOZ_RELEASE_ASSERT(vec
.length() == 3);
532 MOZ_ASSERT(vec
.reserved() == 8);
533 MOZ_RELEASE_ASSERT(S::constructCount
== 0);
534 MOZ_RELEASE_ASSERT(S::moveCount
== 3);
535 MOZ_RELEASE_ASSERT(S::destructCount
== 4);
538 void mozilla::detail::VectorTesting::testShrinkStorageToFit() {
539 // Vectors not using inline storage realloc capacity to exact length.
542 MOZ_RELEASE_ASSERT(v1
.reserve(10));
543 v1
.infallibleAppend(1);
544 MOZ_ASSERT(v1
.reserved() == 10);
545 MOZ_RELEASE_ASSERT(v1
.length() == 1);
546 MOZ_RELEASE_ASSERT(v1
.capacity() >= 10);
547 v1
.shrinkStorageToFit();
548 MOZ_ASSERT(v1
.reserved() == 1);
549 MOZ_RELEASE_ASSERT(v1
.length() == 1);
550 MOZ_RELEASE_ASSERT(v1
.capacity() == 1);
553 // Vectors using inline storage do nothing.
556 MOZ_RELEASE_ASSERT(v2
.reserve(2));
557 v2
.infallibleAppend(1);
558 MOZ_ASSERT(v2
.reserved() == 2);
559 MOZ_RELEASE_ASSERT(v2
.length() == 1);
560 MOZ_RELEASE_ASSERT(v2
.capacity() == 2);
561 v2
.shrinkStorageToFit();
562 MOZ_ASSERT(v2
.reserved() == 2);
563 MOZ_RELEASE_ASSERT(v2
.length() == 1);
564 MOZ_RELEASE_ASSERT(v2
.capacity() == 2);
567 // shrinkStorageToFit uses inline storage if possible.
570 MOZ_RELEASE_ASSERT(v
.reserve(4));
571 v
.infallibleAppend(1);
572 MOZ_ASSERT(v
.reserved() == 4);
573 MOZ_RELEASE_ASSERT(v
.length() == 1);
574 MOZ_RELEASE_ASSERT(v
.capacity() >= 4);
575 v
.shrinkStorageToFit();
576 MOZ_ASSERT(v
.reserved() == 1);
577 MOZ_RELEASE_ASSERT(v
.length() == 1);
578 MOZ_RELEASE_ASSERT(v
.capacity() == 2);
581 // Non-pod shrinking to non-inline storage.
583 static size_t sConstructCounter
= 0;
584 static size_t sCopyCounter
= 0;
585 static size_t sMoveCounter
= 0;
586 static size_t sDestroyCounter
= 0;
590 NonPod() { sConstructCounter
++; }
592 NonPod(const NonPod
& aOther
) : mSomething(aOther
.mSomething
) {
595 NonPod(NonPod
&& aOther
) : mSomething(aOther
.mSomething
) {
598 ~NonPod() { sDestroyCounter
++; }
602 MOZ_RELEASE_ASSERT(v
.reserve(10));
603 for (size_t i
= 0; i
< 8; ++i
) {
604 v
.infallibleEmplaceBack();
606 MOZ_RELEASE_ASSERT(sConstructCounter
== 8);
607 MOZ_RELEASE_ASSERT(sCopyCounter
== 0);
608 MOZ_RELEASE_ASSERT(sMoveCounter
== 0);
609 MOZ_RELEASE_ASSERT(sDestroyCounter
== 0);
610 MOZ_RELEASE_ASSERT(v
.length() == 8);
611 MOZ_ASSERT(v
.reserved() == 10);
612 MOZ_RELEASE_ASSERT(v
.capacity() >= 10);
613 MOZ_RELEASE_ASSERT(v
.shrinkStorageToFit());
615 MOZ_RELEASE_ASSERT(sConstructCounter
== 8);
616 MOZ_RELEASE_ASSERT(sCopyCounter
== 0);
617 MOZ_RELEASE_ASSERT(sMoveCounter
== 8);
618 MOZ_RELEASE_ASSERT(sDestroyCounter
== 8);
619 MOZ_RELEASE_ASSERT(v
.length() == 8);
620 MOZ_ASSERT(v
.reserved() == 8);
621 MOZ_RELEASE_ASSERT(v
.capacity() == 8);
624 // Non-POD shrinking to inline storage.
626 static size_t sConstructCounter
= 0;
627 static size_t sCopyCounter
= 0;
628 static size_t sMoveCounter
= 0;
629 static size_t sDestroyCounter
= 0;
633 NonPod() { sConstructCounter
++; }
635 NonPod(const NonPod
& aOther
) : mSomething(aOther
.mSomething
) {
638 NonPod(NonPod
&& aOther
) : mSomething(aOther
.mSomething
) {
641 ~NonPod() { sDestroyCounter
++; }
645 MOZ_RELEASE_ASSERT(v
.reserve(10));
646 for (size_t i
= 0; i
< 3; ++i
) {
647 v
.infallibleEmplaceBack();
649 MOZ_RELEASE_ASSERT(sConstructCounter
== 3);
650 MOZ_RELEASE_ASSERT(sCopyCounter
== 0);
651 MOZ_RELEASE_ASSERT(sMoveCounter
== 0);
652 MOZ_RELEASE_ASSERT(sDestroyCounter
== 0);
653 MOZ_RELEASE_ASSERT(v
.length() == 3);
654 MOZ_ASSERT(v
.reserved() == 10);
655 MOZ_RELEASE_ASSERT(v
.capacity() >= 10);
656 MOZ_RELEASE_ASSERT(v
.shrinkStorageToFit());
658 MOZ_RELEASE_ASSERT(sConstructCounter
== 3);
659 MOZ_RELEASE_ASSERT(sCopyCounter
== 0);
660 MOZ_RELEASE_ASSERT(sMoveCounter
== 3);
661 MOZ_RELEASE_ASSERT(sDestroyCounter
== 3);
662 MOZ_RELEASE_ASSERT(v
.length() == 3);
663 MOZ_ASSERT(v
.reserved() == 3);
664 MOZ_RELEASE_ASSERT(v
.capacity() == 5);
668 void mozilla::detail::VectorTesting::testAppend() {
669 // Test moving append/appendAll with a move-only type
670 Vector
<UniquePtr
<int>> bv
;
671 for (const int val
: IntegerRange
<int>(0, 3)) {
672 MOZ_RELEASE_ASSERT(bv
.append(MakeUnique
<int>(val
)));
675 Vector
<UniquePtr
<int>> otherbv
;
676 for (const int val
: IntegerRange
<int>(3, 8)) {
677 MOZ_RELEASE_ASSERT(otherbv
.append(MakeUnique
<int>(val
)));
679 MOZ_RELEASE_ASSERT(bv
.appendAll(std::move(otherbv
)));
681 MOZ_RELEASE_ASSERT(otherbv
.length() == 0);
682 MOZ_RELEASE_ASSERT(bv
.length() == 8);
683 for (const int val
: IntegerRange
<int>(0, 8)) {
684 MOZ_RELEASE_ASSERT(*bv
[val
] == val
);
688 // Vector with no inline storage should occupy the absolute minimum space in
689 // non-debug builds. (Debug adds a laundry list of other constraints, none
690 // directly relevant to shipping builds, that aren't worth precisely modeling.)
693 template <typename T
>
694 struct NoInlineStorageLayout
{
697 struct CRAndStorage
{
702 // Only one of these should be necessary, but test a few of them for good
704 static_assert(sizeof(Vector
<int, 0>) == sizeof(NoInlineStorageLayout
<int>),
705 "Vector of int without inline storage shouldn't occupy dead "
706 "space for that absence of storage");
708 static_assert(sizeof(Vector
<bool, 0>) == sizeof(NoInlineStorageLayout
<bool>),
709 "Vector of bool without inline storage shouldn't occupy dead "
710 "space for that absence of storage");
712 static_assert(sizeof(Vector
<S
, 0>) == sizeof(NoInlineStorageLayout
<S
>),
713 "Vector of S without inline storage shouldn't occupy dead "
714 "space for that absence of storage");
718 static void TestVectorBeginNonNull() {
719 // Vector::begin() should never return nullptr, to accommodate callers that
720 // (either for hygiene, or for semantic reasons) need a non-null pointer even
721 // for zero elements.
723 Vector
<bool, 0> bvec0
;
724 MOZ_RELEASE_ASSERT(bvec0
.length() == 0);
725 MOZ_RELEASE_ASSERT(bvec0
.begin() != nullptr);
727 Vector
<bool, 1> bvec1
;
728 MOZ_RELEASE_ASSERT(bvec1
.length() == 0);
729 MOZ_RELEASE_ASSERT(bvec1
.begin() != nullptr);
731 Vector
<bool, 64> bvec64
;
732 MOZ_RELEASE_ASSERT(bvec64
.length() == 0);
733 MOZ_RELEASE_ASSERT(bvec64
.begin() != nullptr);
735 Vector
<int, 0> ivec0
;
736 MOZ_RELEASE_ASSERT(ivec0
.length() == 0);
737 MOZ_RELEASE_ASSERT(ivec0
.begin() != nullptr);
739 Vector
<int, 1> ivec1
;
740 MOZ_RELEASE_ASSERT(ivec1
.length() == 0);
741 MOZ_RELEASE_ASSERT(ivec1
.begin() != nullptr);
743 Vector
<int, 64> ivec64
;
744 MOZ_RELEASE_ASSERT(ivec64
.length() == 0);
745 MOZ_RELEASE_ASSERT(ivec64
.begin() != nullptr);
747 Vector
<long, 0> lvec0
;
748 MOZ_RELEASE_ASSERT(lvec0
.length() == 0);
749 MOZ_RELEASE_ASSERT(lvec0
.begin() != nullptr);
751 Vector
<long, 1> lvec1
;
752 MOZ_RELEASE_ASSERT(lvec1
.length() == 0);
753 MOZ_RELEASE_ASSERT(lvec1
.begin() != nullptr);
755 Vector
<long, 64> lvec64
;
756 MOZ_RELEASE_ASSERT(lvec64
.length() == 0);
757 MOZ_RELEASE_ASSERT(lvec64
.begin() != nullptr);
759 // Vector<T, N> doesn't guarantee N inline elements -- the actual count is
760 // capped so that any Vector fits in a not-crazy amount of space -- so the
761 // code below won't overflow stacks or anything crazy.
763 int array
[16 * 1024 * 1024];
766 Vector
<VeryBig
, 0> vbvec0
;
767 MOZ_RELEASE_ASSERT(vbvec0
.length() == 0);
768 MOZ_RELEASE_ASSERT(vbvec0
.begin() != nullptr);
770 Vector
<VeryBig
, 1> vbvec1
;
771 MOZ_RELEASE_ASSERT(vbvec1
.length() == 0);
772 MOZ_RELEASE_ASSERT(vbvec1
.begin() != nullptr);
774 Vector
<VeryBig
, 64> vbvec64
;
775 MOZ_RELEASE_ASSERT(vbvec64
.length() == 0);
776 MOZ_RELEASE_ASSERT(vbvec64
.begin() != nullptr);
780 VectorTesting::testReserved();
781 VectorTesting::testConstRange();
782 VectorTesting::testEmplaceBack();
783 VectorTesting::testReverse();
784 VectorTesting::testExtractRawBuffer();
785 VectorTesting::testExtractOrCopyRawBuffer();
786 VectorTesting::testReplaceRawBuffer();
787 VectorTesting::testInsert();
788 VectorTesting::testErase();
789 VectorTesting::testShrinkStorageToFit();
790 VectorTesting::testAppend();
791 TestVectorBeginNonNull();