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/. */
6
7 #include "mozilla/Move.h"
8 #include "mozilla/UniquePtr.h"
9 #include "mozilla/Vector.h"
10
11 using mozilla::detail::VectorTesting;
12 using mozilla::MakeUnique;
13 using mozilla::Move;
14 using mozilla::UniquePtr;
15 using mozilla::Vector;
16
17 struct mozilla::detail::VectorTesting
18 {
19 static void testReserved();
20 static void testConstRange();
21 static void testEmplaceBack();
22 static void testReverse();
23 static void testExtractRawBuffer();
24 static void testExtractOrCopyRawBuffer();
25 };
26
27 void
testReserved()28 mozilla::detail::VectorTesting::testReserved()
29 {
30 #ifdef DEBUG
31 Vector<bool> bv;
32 MOZ_RELEASE_ASSERT(bv.reserved() == 0);
33
34 MOZ_RELEASE_ASSERT(bv.append(true));
35 MOZ_RELEASE_ASSERT(bv.reserved() == 1);
36
37 Vector<bool> otherbv;
38 MOZ_RELEASE_ASSERT(otherbv.append(false));
39 MOZ_RELEASE_ASSERT(otherbv.append(true));
40 MOZ_RELEASE_ASSERT(bv.appendAll(otherbv));
41 MOZ_RELEASE_ASSERT(bv.reserved() == 3);
42
43 MOZ_RELEASE_ASSERT(bv.reserve(5));
44 MOZ_RELEASE_ASSERT(bv.reserved() == 5);
45
46 MOZ_RELEASE_ASSERT(bv.reserve(1));
47 MOZ_RELEASE_ASSERT(bv.reserved() == 5);
48
49 Vector<bool> bv2(Move(bv));
50 MOZ_RELEASE_ASSERT(bv.reserved() == 0);
51 MOZ_RELEASE_ASSERT(bv2.reserved() == 5);
52
53 bv2.clearAndFree();
54 MOZ_RELEASE_ASSERT(bv2.reserved() == 0);
55
56 Vector<int, 42> iv;
57 MOZ_RELEASE_ASSERT(iv.reserved() == 0);
58
59 MOZ_RELEASE_ASSERT(iv.append(17));
60 MOZ_RELEASE_ASSERT(iv.reserved() == 1);
61
62 Vector<int, 42> otheriv;
63 MOZ_RELEASE_ASSERT(otheriv.append(42));
64 MOZ_RELEASE_ASSERT(otheriv.append(37));
65 MOZ_RELEASE_ASSERT(iv.appendAll(otheriv));
66 MOZ_RELEASE_ASSERT(iv.reserved() == 3);
67
68 MOZ_RELEASE_ASSERT(iv.reserve(5));
69 MOZ_RELEASE_ASSERT(iv.reserved() == 5);
70
71 MOZ_RELEASE_ASSERT(iv.reserve(1));
72 MOZ_RELEASE_ASSERT(iv.reserved() == 5);
73
74 MOZ_RELEASE_ASSERT(iv.reserve(55));
75 MOZ_RELEASE_ASSERT(iv.reserved() == 55);
76
77 Vector<int, 42> iv2(Move(iv));
78 MOZ_RELEASE_ASSERT(iv.reserved() == 0);
79 MOZ_RELEASE_ASSERT(iv2.reserved() == 55);
80
81 iv2.clearAndFree();
82 MOZ_RELEASE_ASSERT(iv2.reserved() == 0);
83 #endif
84 }
85
86 void
testConstRange()87 mozilla::detail::VectorTesting::testConstRange()
88 {
89 #ifdef DEBUG
90 Vector<int> vec;
91
92 for (int i = 0; i < 10; i++) {
93 MOZ_RELEASE_ASSERT(vec.append(i));
94 }
95
96 const auto &vecRef = vec;
97
98 Vector<int>::ConstRange range = vecRef.all();
99 for (int i = 0; i < 10; i++) {
100 MOZ_RELEASE_ASSERT(!range.empty());
101 MOZ_RELEASE_ASSERT(range.front() == i);
102 range.popFront();
103 }
104 #endif
105 }
106
107 namespace {
108
109 struct S
110 {
111 size_t j;
112 UniquePtr<size_t> k;
113
114 static size_t constructCount;
115 static size_t moveCount;
116 static size_t destructCount;
117
resetCounts__anon9d01b3e40111::S118 static void resetCounts() {
119 constructCount = 0;
120 moveCount = 0;
121 destructCount = 0;
122 }
123
S__anon9d01b3e40111::S124 S(size_t j, size_t k)
125 : j(j)
126 , k(MakeUnique<size_t>(k))
127 {
128 constructCount++;
129 }
130
S__anon9d01b3e40111::S131 S(S&& rhs)
132 : j(rhs.j)
133 , k(Move(rhs.k))
134 {
135 rhs.j = 0;
136 rhs.k.reset(0);
137 moveCount++;
138 }
139
~S__anon9d01b3e40111::S140 ~S() {
141 destructCount++;
142 }
143
144 S(const S&) = delete;
145 S& operator=(const S&) = delete;
146 };
147
148 size_t S::constructCount = 0;
149 size_t S::moveCount = 0;
150 size_t S::destructCount = 0;
151
152 }
153
154 void
testEmplaceBack()155 mozilla::detail::VectorTesting::testEmplaceBack()
156 {
157 S::resetCounts();
158
159 Vector<S> vec;
160 MOZ_RELEASE_ASSERT(vec.reserve(20));
161
162 for (size_t i = 0; i < 10; i++) {
163 S s(i, i * i);
164 MOZ_RELEASE_ASSERT(vec.append(Move(s)));
165 }
166
167 MOZ_RELEASE_ASSERT(vec.length() == 10);
168 MOZ_RELEASE_ASSERT(S::constructCount == 10);
169 MOZ_RELEASE_ASSERT(S::moveCount == 10);
170
171 for (size_t i = 10; i < 20; i++) {
172 MOZ_RELEASE_ASSERT(vec.emplaceBack(i, i * i));
173 }
174
175 MOZ_RELEASE_ASSERT(vec.length() == 20);
176 MOZ_RELEASE_ASSERT(S::constructCount == 20);
177 MOZ_RELEASE_ASSERT(S::moveCount == 10);
178
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);
182 }
183 }
184
185 void
testReverse()186 mozilla::detail::VectorTesting::testReverse()
187 {
188 // Use UniquePtr to make sure that reverse() can handler move-only types.
189 Vector<UniquePtr<uint8_t>, 0> vec;
190
191 // Reverse an odd number of elements.
192
193 for (uint8_t i = 0; i < 5; i++) {
194 auto p = MakeUnique<uint8_t>(i);
195 MOZ_RELEASE_ASSERT(p);
196 MOZ_RELEASE_ASSERT(vec.append(mozilla::Move(p)));
197 }
198
199 vec.reverse();
200
201 MOZ_RELEASE_ASSERT(*vec[0] == 4);
202 MOZ_RELEASE_ASSERT(*vec[1] == 3);
203 MOZ_RELEASE_ASSERT(*vec[2] == 2);
204 MOZ_RELEASE_ASSERT(*vec[3] == 1);
205 MOZ_RELEASE_ASSERT(*vec[4] == 0);
206
207 // Reverse an even number of elements.
208
209 vec.popBack();
210 vec.reverse();
211
212 MOZ_RELEASE_ASSERT(*vec[0] == 1);
213 MOZ_RELEASE_ASSERT(*vec[1] == 2);
214 MOZ_RELEASE_ASSERT(*vec[2] == 3);
215 MOZ_RELEASE_ASSERT(*vec[3] == 4);
216
217 // Reverse an empty vector.
218
219 vec.clear();
220 MOZ_RELEASE_ASSERT(vec.length() == 0);
221 vec.reverse();
222 MOZ_RELEASE_ASSERT(vec.length() == 0);
223
224 // Reverse a vector using only inline storage.
225
226 Vector<UniquePtr<uint8_t>, 5> vec2;
227 for (uint8_t i = 0; i < 5; i++) {
228 auto p = MakeUnique<uint8_t>(i);
229 MOZ_RELEASE_ASSERT(p);
230 MOZ_RELEASE_ASSERT(vec2.append(mozilla::Move(p)));
231 }
232
233 vec2.reverse();
234
235 MOZ_RELEASE_ASSERT(*vec2[0] == 4);
236 MOZ_RELEASE_ASSERT(*vec2[1] == 3);
237 MOZ_RELEASE_ASSERT(*vec2[2] == 2);
238 MOZ_RELEASE_ASSERT(*vec2[3] == 1);
239 MOZ_RELEASE_ASSERT(*vec2[4] == 0);
240 }
241
242 void
testExtractRawBuffer()243 mozilla::detail::VectorTesting::testExtractRawBuffer()
244 {
245 S::resetCounts();
246
247 Vector<S, 5> vec;
248 MOZ_RELEASE_ASSERT(vec.reserve(5));
249 for (size_t i = 0; i < 5; i++) {
250 vec.infallibleEmplaceBack(i, i * i);
251 }
252 MOZ_RELEASE_ASSERT(vec.length() == 5);
253 MOZ_ASSERT(vec.reserved() == 5);
254 MOZ_RELEASE_ASSERT(S::constructCount == 5);
255 MOZ_RELEASE_ASSERT(S::moveCount == 0);
256 MOZ_RELEASE_ASSERT(S::destructCount == 0);
257
258 S* buf = vec.extractRawBuffer();
259 MOZ_RELEASE_ASSERT(!buf);
260 MOZ_RELEASE_ASSERT(vec.length() == 5);
261 MOZ_ASSERT(vec.reserved() == 5);
262 MOZ_RELEASE_ASSERT(S::constructCount == 5);
263 MOZ_RELEASE_ASSERT(S::moveCount == 0);
264 MOZ_RELEASE_ASSERT(S::destructCount == 0);
265
266 MOZ_RELEASE_ASSERT(vec.reserve(10));
267 for (size_t i = 5; i < 10; i++) {
268 vec.infallibleEmplaceBack(i, i * i);
269 }
270 MOZ_RELEASE_ASSERT(vec.length() == 10);
271 MOZ_ASSERT(vec.reserved() == 10);
272 MOZ_RELEASE_ASSERT(S::constructCount == 10);
273 MOZ_RELEASE_ASSERT(S::moveCount == 5);
274 MOZ_RELEASE_ASSERT(S::destructCount == 5);
275
276 buf = vec.extractRawBuffer();
277 MOZ_RELEASE_ASSERT(buf);
278 MOZ_RELEASE_ASSERT(vec.length() == 0);
279 MOZ_ASSERT(vec.reserved() == 0);
280 MOZ_RELEASE_ASSERT(S::constructCount == 10);
281 MOZ_RELEASE_ASSERT(S::moveCount == 5);
282 MOZ_RELEASE_ASSERT(S::destructCount == 5);
283
284 for (size_t i = 0; i < 10; i++) {
285 MOZ_RELEASE_ASSERT(buf[i].j == i);
286 MOZ_RELEASE_ASSERT(*buf[i].k == i * i);
287 }
288
289 free(buf);
290 }
291
292 void
testExtractOrCopyRawBuffer()293 mozilla::detail::VectorTesting::testExtractOrCopyRawBuffer()
294 {
295 S::resetCounts();
296
297 Vector<S, 5> vec;
298 MOZ_RELEASE_ASSERT(vec.reserve(5));
299 for (size_t i = 0; i < 5; i++) {
300 vec.infallibleEmplaceBack(i, i * i);
301 }
302 MOZ_RELEASE_ASSERT(vec.length() == 5);
303 MOZ_ASSERT(vec.reserved() == 5);
304 MOZ_RELEASE_ASSERT(S::constructCount == 5);
305 MOZ_RELEASE_ASSERT(S::moveCount == 0);
306 MOZ_RELEASE_ASSERT(S::destructCount == 0);
307
308 S* buf = vec.extractOrCopyRawBuffer();
309 MOZ_RELEASE_ASSERT(buf);
310 MOZ_RELEASE_ASSERT(vec.length() == 0);
311 MOZ_ASSERT(vec.reserved() == 0);
312 MOZ_RELEASE_ASSERT(S::constructCount == 5);
313 MOZ_RELEASE_ASSERT(S::moveCount == 5);
314 MOZ_RELEASE_ASSERT(S::destructCount == 5);
315
316 for (size_t i = 0; i < 5; i++) {
317 MOZ_RELEASE_ASSERT(buf[i].j == i);
318 MOZ_RELEASE_ASSERT(*buf[i].k == i * i);
319 }
320
321 S::resetCounts();
322
323 MOZ_RELEASE_ASSERT(vec.reserve(10));
324 for (size_t i = 0; i < 10; i++) {
325 vec.infallibleEmplaceBack(i, i * i);
326 }
327 MOZ_RELEASE_ASSERT(vec.length() == 10);
328 MOZ_ASSERT(vec.reserved() == 10);
329 MOZ_RELEASE_ASSERT(S::constructCount == 10);
330 MOZ_RELEASE_ASSERT(S::moveCount == 0);
331 MOZ_RELEASE_ASSERT(S::destructCount == 0);
332
333 buf = vec.extractOrCopyRawBuffer();
334 MOZ_RELEASE_ASSERT(buf);
335 MOZ_RELEASE_ASSERT(vec.length() == 0);
336 MOZ_ASSERT(vec.reserved() == 0);
337 MOZ_RELEASE_ASSERT(S::constructCount == 10);
338 MOZ_RELEASE_ASSERT(S::moveCount == 0);
339 MOZ_RELEASE_ASSERT(S::destructCount == 0);
340
341 for (size_t i = 0; i < 10; i++) {
342 MOZ_RELEASE_ASSERT(buf[i].j == i);
343 MOZ_RELEASE_ASSERT(*buf[i].k == i * i);
344 }
345
346 free(buf);
347 }
348
349 int
main()350 main()
351 {
352 VectorTesting::testReserved();
353 VectorTesting::testConstRange();
354 VectorTesting::testEmplaceBack();
355 VectorTesting::testReverse();
356 VectorTesting::testExtractRawBuffer();
357 VectorTesting::testExtractOrCopyRawBuffer();
358 }
359