OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions | |
6 * are met: | |
7 * 1. Redistributions of source code must retain the above copyright | |
8 * notice, this list of conditions and the following disclaimer. | |
9 * 2. Redistributions in binary form must reproduce the above copyright | |
10 * notice, this list of conditions and the following disclaimer in the | |
11 * documentation and/or other materials provided with the distribution. | |
12 * | |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | |
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | |
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
23 * THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 #include "wtf/Deque.h" | |
27 | |
28 #include "testing/gtest/include/gtest/gtest.h" | |
29 #include "wtf/HashSet.h" | |
30 #include "wtf/PtrUtil.h" | |
31 #include <memory> | |
32 | |
33 namespace WTF { | |
34 | |
35 namespace { | |
36 | |
37 TEST(DequeTest, Basic) { | |
38 Deque<int> intDeque; | |
39 EXPECT_TRUE(intDeque.isEmpty()); | |
40 EXPECT_EQ(0ul, intDeque.size()); | |
41 } | |
42 | |
43 template <size_t inlineCapacity> | |
44 void checkNumberSequence(Deque<int, inlineCapacity>& deque, | |
45 int from, | |
46 int to, | |
47 bool increment) { | |
48 auto it = increment ? deque.begin() : deque.end(); | |
49 size_t index = increment ? 0 : deque.size(); | |
50 int step = from < to ? 1 : -1; | |
51 for (int i = from; i != to + step; i += step) { | |
52 if (!increment) { | |
53 --it; | |
54 --index; | |
55 } | |
56 | |
57 EXPECT_EQ(i, *it); | |
58 EXPECT_EQ(i, deque[index]); | |
59 | |
60 if (increment) { | |
61 ++it; | |
62 ++index; | |
63 } | |
64 } | |
65 EXPECT_EQ(increment ? deque.end() : deque.begin(), it); | |
66 EXPECT_EQ(increment ? deque.size() : 0, index); | |
67 } | |
68 | |
69 template <size_t inlineCapacity> | |
70 void checkNumberSequenceReverse(Deque<int, inlineCapacity>& deque, | |
71 int from, | |
72 int to, | |
73 bool increment) { | |
74 auto it = increment ? deque.rbegin() : deque.rend(); | |
75 size_t index = increment ? 0 : deque.size(); | |
76 int step = from < to ? 1 : -1; | |
77 for (int i = from; i != to + step; i += step) { | |
78 if (!increment) { | |
79 --it; | |
80 --index; | |
81 } | |
82 | |
83 EXPECT_EQ(i, *it); | |
84 EXPECT_EQ(i, deque.at(deque.size() - 1 - index)); | |
85 | |
86 if (increment) { | |
87 ++it; | |
88 ++index; | |
89 } | |
90 } | |
91 EXPECT_EQ(increment ? deque.rend() : deque.rbegin(), it); | |
92 EXPECT_EQ(increment ? deque.size() : 0, index); | |
93 } | |
94 | |
95 template <size_t inlineCapacity> | |
96 void reverseTest() { | |
97 Deque<int, inlineCapacity> intDeque; | |
98 intDeque.push_back(10); | |
99 intDeque.push_back(11); | |
100 intDeque.push_back(12); | |
101 intDeque.push_back(13); | |
102 | |
103 checkNumberSequence(intDeque, 10, 13, true); | |
104 checkNumberSequence(intDeque, 13, 10, false); | |
105 checkNumberSequenceReverse(intDeque, 13, 10, true); | |
106 checkNumberSequenceReverse(intDeque, 10, 13, false); | |
107 | |
108 intDeque.push_back(14); | |
109 intDeque.push_back(15); | |
110 EXPECT_EQ(10, intDeque.takeFirst()); | |
111 EXPECT_EQ(15, intDeque.takeLast()); | |
112 checkNumberSequence(intDeque, 11, 14, true); | |
113 checkNumberSequence(intDeque, 14, 11, false); | |
114 checkNumberSequenceReverse(intDeque, 14, 11, true); | |
115 checkNumberSequenceReverse(intDeque, 11, 14, false); | |
116 | |
117 for (int i = 15; i < 200; ++i) | |
118 intDeque.push_back(i); | |
119 checkNumberSequence(intDeque, 11, 199, true); | |
120 checkNumberSequence(intDeque, 199, 11, false); | |
121 checkNumberSequenceReverse(intDeque, 199, 11, true); | |
122 checkNumberSequenceReverse(intDeque, 11, 199, false); | |
123 | |
124 for (int i = 0; i < 180; ++i) { | |
125 EXPECT_EQ(i + 11, intDeque[0]); | |
126 EXPECT_EQ(i + 11, intDeque.takeFirst()); | |
127 } | |
128 checkNumberSequence(intDeque, 191, 199, true); | |
129 checkNumberSequence(intDeque, 199, 191, false); | |
130 checkNumberSequenceReverse(intDeque, 199, 191, true); | |
131 checkNumberSequenceReverse(intDeque, 191, 199, false); | |
132 | |
133 Deque<int, inlineCapacity> intDeque2; | |
134 swap(intDeque, intDeque2); | |
135 | |
136 checkNumberSequence(intDeque2, 191, 199, true); | |
137 checkNumberSequence(intDeque2, 199, 191, false); | |
138 checkNumberSequenceReverse(intDeque2, 199, 191, true); | |
139 checkNumberSequenceReverse(intDeque2, 191, 199, false); | |
140 | |
141 intDeque.swap(intDeque2); | |
142 | |
143 checkNumberSequence(intDeque, 191, 199, true); | |
144 checkNumberSequence(intDeque, 199, 191, false); | |
145 checkNumberSequenceReverse(intDeque, 199, 191, true); | |
146 checkNumberSequenceReverse(intDeque, 191, 199, false); | |
147 | |
148 intDeque.swap(intDeque2); | |
149 | |
150 checkNumberSequence(intDeque2, 191, 199, true); | |
151 checkNumberSequence(intDeque2, 199, 191, false); | |
152 checkNumberSequenceReverse(intDeque2, 199, 191, true); | |
153 checkNumberSequenceReverse(intDeque2, 191, 199, false); | |
154 } | |
155 | |
156 TEST(DequeTest, Reverse) { | |
157 reverseTest<0>(); | |
158 reverseTest<2>(); | |
159 } | |
160 | |
161 class DestructCounter { | |
162 public: | |
163 explicit DestructCounter(int i, int* destructNumber) | |
164 : m_i(i), m_destructNumber(destructNumber) {} | |
165 | |
166 ~DestructCounter() { ++(*m_destructNumber); } | |
167 int get() const { return m_i; } | |
168 | |
169 private: | |
170 int m_i; | |
171 int* m_destructNumber; | |
172 }; | |
173 | |
174 template <typename OwnPtrDeque> | |
175 void ownPtrTest() { | |
176 int destructNumber = 0; | |
177 OwnPtrDeque deque; | |
178 deque.push_back(WTF::wrapUnique(new DestructCounter(0, &destructNumber))); | |
179 deque.push_back(WTF::wrapUnique(new DestructCounter(1, &destructNumber))); | |
180 EXPECT_EQ(2u, deque.size()); | |
181 | |
182 std::unique_ptr<DestructCounter>& counter0 = deque.front(); | |
183 EXPECT_EQ(0, counter0->get()); | |
184 int counter1 = deque.back()->get(); | |
185 EXPECT_EQ(1, counter1); | |
186 EXPECT_EQ(0, destructNumber); | |
187 | |
188 size_t index = 0; | |
189 for (auto iter = deque.begin(); iter != deque.end(); ++iter) { | |
190 std::unique_ptr<DestructCounter>& refCounter = *iter; | |
191 EXPECT_EQ(index, static_cast<size_t>(refCounter->get())); | |
192 EXPECT_EQ(index, static_cast<size_t>((*refCounter).get())); | |
193 index++; | |
194 } | |
195 EXPECT_EQ(0, destructNumber); | |
196 | |
197 auto it = deque.begin(); | |
198 for (index = 0; index < deque.size(); ++index) { | |
199 std::unique_ptr<DestructCounter>& refCounter = *it; | |
200 EXPECT_EQ(index, static_cast<size_t>(refCounter->get())); | |
201 index++; | |
202 ++it; | |
203 } | |
204 EXPECT_EQ(0, destructNumber); | |
205 | |
206 EXPECT_EQ(0, deque.front()->get()); | |
207 deque.pop_front(); | |
208 EXPECT_EQ(1, deque.front()->get()); | |
209 EXPECT_EQ(1u, deque.size()); | |
210 EXPECT_EQ(1, destructNumber); | |
211 | |
212 std::unique_ptr<DestructCounter> ownCounter1 = std::move(deque.front()); | |
213 deque.pop_front(); | |
214 EXPECT_EQ(counter1, ownCounter1->get()); | |
215 EXPECT_EQ(0u, deque.size()); | |
216 EXPECT_EQ(1, destructNumber); | |
217 | |
218 ownCounter1.reset(); | |
219 EXPECT_EQ(2, destructNumber); | |
220 | |
221 size_t count = 1025; | |
222 destructNumber = 0; | |
223 for (size_t i = 0; i < count; ++i) | |
224 deque.push_front(WTF::wrapUnique(new DestructCounter(i, &destructNumber))); | |
225 | |
226 // Deque relocation must not destruct std::unique_ptr element. | |
227 EXPECT_EQ(0, destructNumber); | |
228 EXPECT_EQ(count, deque.size()); | |
229 | |
230 OwnPtrDeque copyDeque; | |
231 deque.swap(copyDeque); | |
232 EXPECT_EQ(0, destructNumber); | |
233 EXPECT_EQ(count, copyDeque.size()); | |
234 EXPECT_EQ(0u, deque.size()); | |
235 | |
236 copyDeque.clear(); | |
237 EXPECT_EQ(count, static_cast<size_t>(destructNumber)); | |
238 } | |
239 | |
240 TEST(DequeTest, OwnPtr) { | |
241 ownPtrTest<Deque<std::unique_ptr<DestructCounter>>>(); | |
242 ownPtrTest<Deque<std::unique_ptr<DestructCounter>, 2>>(); | |
243 } | |
244 | |
245 class MoveOnly { | |
246 public: | |
247 explicit MoveOnly(int i = 0) : m_i(i) {} | |
248 | |
249 MoveOnly(MoveOnly&& other) : m_i(other.m_i) { other.m_i = 0; } | |
250 | |
251 MoveOnly& operator=(MoveOnly&& other) { | |
252 if (this != &other) { | |
253 m_i = other.m_i; | |
254 other.m_i = 0; | |
255 } | |
256 return *this; | |
257 } | |
258 | |
259 int value() const { return m_i; } | |
260 | |
261 private: | |
262 WTF_MAKE_NONCOPYABLE(MoveOnly); | |
263 int m_i; | |
264 }; | |
265 | |
266 TEST(DequeTest, MoveOnlyType) { | |
267 Deque<MoveOnly> deque; | |
268 deque.push_back(MoveOnly(1)); | |
269 deque.push_back(MoveOnly(2)); | |
270 EXPECT_EQ(2u, deque.size()); | |
271 | |
272 ASSERT_EQ(1, deque.front().value()); | |
273 ASSERT_EQ(2, deque.back().value()); | |
274 | |
275 MoveOnly oldFirst = deque.takeFirst(); | |
276 ASSERT_EQ(1, oldFirst.value()); | |
277 EXPECT_EQ(1u, deque.size()); | |
278 | |
279 Deque<MoveOnly> otherDeque; | |
280 deque.swap(otherDeque); | |
281 EXPECT_EQ(1u, otherDeque.size()); | |
282 EXPECT_EQ(0u, deque.size()); | |
283 } | |
284 | |
285 // WrappedInt class will fail if it was memmoved or memcpyed. | |
286 HashSet<void*> constructedWrappedInts; | |
287 | |
288 class WrappedInt { | |
289 public: | |
290 WrappedInt(int i = 0) : m_originalThisPtr(this), m_i(i) { | |
291 constructedWrappedInts.insert(this); | |
292 } | |
293 | |
294 WrappedInt(const WrappedInt& other) | |
295 : m_originalThisPtr(this), m_i(other.m_i) { | |
296 constructedWrappedInts.insert(this); | |
297 } | |
298 | |
299 WrappedInt& operator=(const WrappedInt& other) { | |
300 m_i = other.m_i; | |
301 return *this; | |
302 } | |
303 | |
304 ~WrappedInt() { | |
305 EXPECT_EQ(m_originalThisPtr, this); | |
306 EXPECT_TRUE(constructedWrappedInts.contains(this)); | |
307 constructedWrappedInts.erase(this); | |
308 } | |
309 | |
310 int get() const { return m_i; } | |
311 | |
312 private: | |
313 void* m_originalThisPtr; | |
314 int m_i; | |
315 }; | |
316 | |
317 template <size_t inlineCapacity> | |
318 void swapWithOrWithoutInlineCapacity() { | |
319 Deque<WrappedInt, inlineCapacity> dequeA; | |
320 dequeA.push_back(WrappedInt(1)); | |
321 Deque<WrappedInt, inlineCapacity> dequeB; | |
322 dequeB.push_back(WrappedInt(2)); | |
323 | |
324 ASSERT_EQ(dequeA.size(), dequeB.size()); | |
325 dequeA.swap(dequeB); | |
326 | |
327 ASSERT_EQ(1u, dequeA.size()); | |
328 EXPECT_EQ(2, dequeA.front().get()); | |
329 ASSERT_EQ(1u, dequeB.size()); | |
330 EXPECT_EQ(1, dequeB.front().get()); | |
331 | |
332 dequeA.push_back(WrappedInt(3)); | |
333 | |
334 ASSERT_GT(dequeA.size(), dequeB.size()); | |
335 dequeA.swap(dequeB); | |
336 | |
337 ASSERT_EQ(1u, dequeA.size()); | |
338 EXPECT_EQ(1, dequeA.front().get()); | |
339 ASSERT_EQ(2u, dequeB.size()); | |
340 EXPECT_EQ(2, dequeB.front().get()); | |
341 | |
342 ASSERT_LT(dequeA.size(), dequeB.size()); | |
343 dequeA.swap(dequeB); | |
344 | |
345 ASSERT_EQ(2u, dequeA.size()); | |
346 EXPECT_EQ(2, dequeA.front().get()); | |
347 ASSERT_EQ(1u, dequeB.size()); | |
348 EXPECT_EQ(1, dequeB.front().get()); | |
349 | |
350 dequeA.push_back(WrappedInt(4)); | |
351 dequeA.swap(dequeB); | |
352 | |
353 ASSERT_EQ(1u, dequeA.size()); | |
354 EXPECT_EQ(1, dequeA.front().get()); | |
355 ASSERT_EQ(3u, dequeB.size()); | |
356 EXPECT_EQ(2, dequeB.front().get()); | |
357 | |
358 dequeB.swap(dequeA); | |
359 } | |
360 | |
361 TEST(DequeTest, SwapWithOrWithoutInlineCapacity) { | |
362 swapWithOrWithoutInlineCapacity<0>(); | |
363 swapWithOrWithoutInlineCapacity<2>(); | |
364 } | |
365 | |
366 class LivenessCounter { | |
367 public: | |
368 void ref() { s_live++; } | |
369 void deref() { s_live--; } | |
370 | |
371 static unsigned s_live; | |
372 }; | |
373 | |
374 unsigned LivenessCounter::s_live = 0; | |
375 | |
376 // Filter a few numbers out to improve the running speed of the tests. The | |
377 // test has nested loops, and removing even numbers from 4 and up from the | |
378 // loops makes it run 10 times faster. | |
379 bool interestingNumber(int i) { | |
380 return i < 4 || (i & 1); | |
381 } | |
382 | |
383 template <size_t inlineCapacity> | |
384 void testDestructorAndConstructorCallsWhenSwappingWithInlineCapacity() { | |
385 LivenessCounter::s_live = 0; | |
386 LivenessCounter counter; | |
387 EXPECT_EQ(0u, LivenessCounter::s_live); | |
388 | |
389 Deque<RefPtr<LivenessCounter>, inlineCapacity> deque; | |
390 Deque<RefPtr<LivenessCounter>, inlineCapacity> deque2; | |
391 deque.push_back(&counter); | |
392 deque2.push_back(&counter); | |
393 EXPECT_EQ(2u, LivenessCounter::s_live); | |
394 | |
395 // Add various numbers of elements to deques, then remove various numbers | |
396 // of elements from the head. This creates in-use ranges in the backing | |
397 // that sometimes wrap around the end of the buffer, testing various ways | |
398 // in which the in-use ranges of the inline buffers can overlap when we | |
399 // call swap(). | |
400 for (unsigned i = 0; i < 12; i++) { | |
401 if (!interestingNumber(i)) | |
402 continue; | |
403 for (unsigned j = i; j < 12; j++) { | |
404 if (!interestingNumber(j)) | |
405 continue; | |
406 deque.clear(); | |
407 deque2.clear(); | |
408 EXPECT_EQ(0u, LivenessCounter::s_live); | |
409 for (unsigned k = 0; k < j; k++) | |
410 deque.push_back(&counter); | |
411 EXPECT_EQ(j, LivenessCounter::s_live); | |
412 EXPECT_EQ(j, deque.size()); | |
413 for (unsigned k = 0; k < i; k++) | |
414 deque.pop_front(); | |
415 | |
416 EXPECT_EQ(j - i, LivenessCounter::s_live); | |
417 EXPECT_EQ(j - i, deque.size()); | |
418 deque.swap(deque2); | |
419 EXPECT_EQ(j - i, LivenessCounter::s_live); | |
420 EXPECT_EQ(0u, deque.size()); | |
421 EXPECT_EQ(j - i, deque2.size()); | |
422 deque.swap(deque2); | |
423 EXPECT_EQ(j - i, LivenessCounter::s_live); | |
424 | |
425 deque2.push_back(&counter); | |
426 deque2.push_back(&counter); | |
427 deque2.push_back(&counter); | |
428 | |
429 for (unsigned k = 0; k < 12; k++) { | |
430 EXPECT_EQ(3 + j - i, LivenessCounter::s_live); | |
431 EXPECT_EQ(j - i, deque.size()); | |
432 EXPECT_EQ(3u, deque2.size()); | |
433 deque.swap(deque2); | |
434 EXPECT_EQ(3 + j - i, LivenessCounter::s_live); | |
435 EXPECT_EQ(j - i, deque2.size()); | |
436 EXPECT_EQ(3u, deque.size()); | |
437 deque.swap(deque2); | |
438 EXPECT_EQ(3 + j - i, LivenessCounter::s_live); | |
439 EXPECT_EQ(j - i, deque.size()); | |
440 EXPECT_EQ(3u, deque2.size()); | |
441 | |
442 deque2.pop_front(); | |
443 deque2.push_back(&counter); | |
444 } | |
445 } | |
446 } | |
447 } | |
448 | |
449 TEST(DequeTest, SwapWithConstructorsAndDestructors) { | |
450 testDestructorAndConstructorCallsWhenSwappingWithInlineCapacity<0>(); | |
451 testDestructorAndConstructorCallsWhenSwappingWithInlineCapacity<4>(); | |
452 testDestructorAndConstructorCallsWhenSwappingWithInlineCapacity<9>(); | |
453 } | |
454 | |
455 template <size_t inlineCapacity> | |
456 void testValuesMovedAndSwappedWithInlineCapacity() { | |
457 Deque<unsigned, inlineCapacity> deque; | |
458 Deque<unsigned, inlineCapacity> deque2; | |
459 | |
460 // Add various numbers of elements to deques, then remove various numbers | |
461 // of elements from the head. This creates in-use ranges in the backing | |
462 // that sometimes wrap around the end of the buffer, testing various ways | |
463 // in which the in-use ranges of the inline buffers can overlap when we | |
464 // call swap(). | |
465 for (unsigned pad = 0; pad < 12; pad++) { | |
466 if (!interestingNumber(pad)) | |
467 continue; | |
468 for (unsigned pad2 = 0; pad2 < 12; pad2++) { | |
469 if (!interestingNumber(pad2)) | |
470 continue; | |
471 for (unsigned size = 0; size < 12; size++) { | |
472 if (!interestingNumber(size)) | |
473 continue; | |
474 for (unsigned size2 = 0; size2 < 12; size2++) { | |
475 if (!interestingNumber(size2)) | |
476 continue; | |
477 deque.clear(); | |
478 deque2.clear(); | |
479 for (unsigned i = 0; i < pad; i++) | |
480 deque.push_back(103); | |
481 for (unsigned i = 0; i < pad2; i++) | |
482 deque2.push_back(888); | |
483 for (unsigned i = 0; i < size; i++) | |
484 deque.push_back(i); | |
485 for (unsigned i = 0; i < size2; i++) | |
486 deque2.push_back(i + 42); | |
487 for (unsigned i = 0; i < pad; i++) | |
488 EXPECT_EQ(103u, deque.takeFirst()); | |
489 for (unsigned i = 0; i < pad2; i++) | |
490 EXPECT_EQ(888u, deque2.takeFirst()); | |
491 EXPECT_EQ(size, deque.size()); | |
492 EXPECT_EQ(size2, deque2.size()); | |
493 deque.swap(deque2); | |
494 for (unsigned i = 0; i < size; i++) | |
495 EXPECT_EQ(i, deque2.takeFirst()); | |
496 for (unsigned i = 0; i < size2; i++) | |
497 EXPECT_EQ(i + 42, deque.takeFirst()); | |
498 } | |
499 } | |
500 } | |
501 } | |
502 } | |
503 | |
504 TEST(DequeTest, ValuesMovedAndSwappedWithInlineCapacity) { | |
505 testValuesMovedAndSwappedWithInlineCapacity<0>(); | |
506 testValuesMovedAndSwappedWithInlineCapacity<4>(); | |
507 testValuesMovedAndSwappedWithInlineCapacity<9>(); | |
508 } | |
509 | |
510 TEST(DequeTest, UniquePtr) { | |
511 using Pointer = std::unique_ptr<int>; | |
512 Deque<Pointer> deque; | |
513 deque.push_back(Pointer(new int(1))); | |
514 deque.push_back(Pointer(new int(2))); | |
515 deque.push_front(Pointer(new int(-1))); | |
516 deque.push_front(Pointer(new int(-2))); | |
517 ASSERT_EQ(4u, deque.size()); | |
518 EXPECT_EQ(-2, *deque[0]); | |
519 EXPECT_EQ(-1, *deque[1]); | |
520 EXPECT_EQ(1, *deque[2]); | |
521 EXPECT_EQ(2, *deque[3]); | |
522 | |
523 Pointer first(deque.takeFirst()); | |
524 EXPECT_EQ(-2, *first); | |
525 Pointer last(deque.takeLast()); | |
526 EXPECT_EQ(2, *last); | |
527 | |
528 EXPECT_EQ(2u, deque.size()); | |
529 deque.pop_front(); | |
530 deque.pop_back(); | |
531 EXPECT_EQ(0u, deque.size()); | |
532 | |
533 deque.push_back(Pointer(new int(42))); | |
534 deque[0] = Pointer(new int(24)); | |
535 ASSERT_EQ(1u, deque.size()); | |
536 EXPECT_EQ(24, *deque[0]); | |
537 | |
538 deque.clear(); | |
539 } | |
540 | |
541 class CountCopy final { | |
542 public: | |
543 explicit CountCopy(int* counter = nullptr) : m_counter(counter) {} | |
544 CountCopy(const CountCopy& other) : m_counter(other.m_counter) { | |
545 if (m_counter) | |
546 ++*m_counter; | |
547 } | |
548 CountCopy& operator=(const CountCopy& other) { | |
549 m_counter = other.m_counter; | |
550 if (m_counter) | |
551 ++*m_counter; | |
552 return *this; | |
553 } | |
554 | |
555 private: | |
556 int* m_counter; | |
557 }; | |
558 | |
559 TEST(DequeTest, MoveShouldNotMakeCopy) { | |
560 // Because data in inline buffer may be swapped or moved individually, we | |
561 // force the creation of out-of-line buffer so we can make sure there's no | |
562 // element-wise copy/move. | |
563 Deque<CountCopy, 1> deque; | |
564 int counter = 0; | |
565 deque.push_back(CountCopy(&counter)); | |
566 deque.push_back(CountCopy(&counter)); | |
567 | |
568 Deque<CountCopy, 1> other(deque); | |
569 counter = 0; | |
570 deque = std::move(other); // Move assignment. | |
571 EXPECT_EQ(0, counter); | |
572 | |
573 counter = 0; | |
574 Deque<CountCopy, 1> yetAnother(std::move(deque)); // Move construction. | |
575 EXPECT_EQ(0, counter); | |
576 } | |
577 | |
578 TEST(DequeTest, RemoveWhileIterating) { | |
579 Deque<int> deque; | |
580 for (int i = 0; i < 10; ++i) | |
581 deque.push_back(i); | |
582 | |
583 // All numbers present. | |
584 { | |
585 int i = 0; | |
586 for (int v : deque) | |
587 EXPECT_EQ(i++, v); | |
588 } | |
589 | |
590 // Remove the even numbers while iterating. | |
591 for (auto it = deque.begin(); it != deque.end(); ++it) { | |
592 if (*it % 2 == 0) { | |
593 deque.erase(it); | |
594 --it; | |
595 } | |
596 } | |
597 | |
598 // Only odd numbers left. | |
599 { | |
600 int i = 1; | |
601 for (int v : deque) | |
602 EXPECT_EQ(i + 2, v); | |
603 } | |
604 } | |
605 | |
606 struct Item { | |
607 Item(int value1, int value2) : value1(value1), value2(value2) {} | |
608 int value1; | |
609 int value2; | |
610 }; | |
611 | |
612 TEST(DequeTest, emplace_back) { | |
613 Deque<Item> deque; | |
614 deque.emplace_back(1, 2); | |
615 deque.emplace_back(3, 4); | |
616 | |
617 EXPECT_EQ(2u, deque.size()); | |
618 EXPECT_EQ(1, deque[0].value1); | |
619 EXPECT_EQ(2, deque[0].value2); | |
620 EXPECT_EQ(3, deque[1].value1); | |
621 EXPECT_EQ(4, deque[1].value2); | |
622 } | |
623 | |
624 TEST(DequeTest, emplace_front) { | |
625 Deque<Item> deque; | |
626 deque.emplace_front(1, 2); | |
627 deque.emplace_front(3, 4); | |
628 | |
629 EXPECT_EQ(2u, deque.size()); | |
630 EXPECT_EQ(3, deque[0].value1); | |
631 EXPECT_EQ(4, deque[0].value2); | |
632 EXPECT_EQ(1, deque[1].value1); | |
633 EXPECT_EQ(2, deque[1].value2); | |
634 } | |
635 | |
636 } // anonymous namespace | |
637 | |
638 } // namespace WTF | |
OLD | NEW |