OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 23 matching lines...) Expand all Loading... |
34 | 34 |
35 namespace { | 35 namespace { |
36 | 36 |
37 TEST(DequeTest, Basic) | 37 TEST(DequeTest, Basic) |
38 { | 38 { |
39 Deque<int> intDeque; | 39 Deque<int> intDeque; |
40 EXPECT_TRUE(intDeque.isEmpty()); | 40 EXPECT_TRUE(intDeque.isEmpty()); |
41 EXPECT_EQ(0ul, intDeque.size()); | 41 EXPECT_EQ(0ul, intDeque.size()); |
42 } | 42 } |
43 | 43 |
44 void checkNumberSequence(Deque<int>& deque, int from, int to, bool increment) | 44 template<size_t inlineCapacity> |
| 45 void checkNumberSequence(Deque<int, inlineCapacity>& deque, int from, int to, bo
ol increment) |
45 { | 46 { |
46 Deque<int>::iterator it = increment ? deque.begin() : deque.end(); | 47 typename Deque<int, inlineCapacity>::iterator it = increment ? deque.begin()
: deque.end(); |
47 int step = from < to ? 1 : -1; | 48 int step = from < to ? 1 : -1; |
48 for (int i = from; i != to + step; i += step) { | 49 for (int i = from; i != to + step; i += step) { |
49 if (!increment) | 50 if (!increment) |
50 --it; | 51 --it; |
51 | 52 |
52 EXPECT_EQ(i, *it); | 53 EXPECT_EQ(i, *it); |
53 | 54 |
54 if (increment) | 55 if (increment) |
55 ++it; | 56 ++it; |
56 } | 57 } |
57 EXPECT_EQ(increment ? deque.end() : deque.begin(), it); | 58 EXPECT_EQ(increment ? deque.end() : deque.begin(), it); |
58 } | 59 } |
59 | 60 |
60 void checkNumberSequenceReverse(Deque<int>& deque, int from, int to, bool increm
ent) | 61 template<size_t inlineCapacity> |
| 62 void checkNumberSequenceReverse(Deque<int, inlineCapacity>& deque, int from, int
to, bool increment) |
61 { | 63 { |
62 Deque<int>::reverse_iterator it = increment ? deque.rbegin() : deque.rend(); | 64 typename Deque<int, inlineCapacity>::reverse_iterator it = increment ? deque
.rbegin() : deque.rend(); |
63 int step = from < to ? 1 : -1; | 65 int step = from < to ? 1 : -1; |
64 for (int i = from; i != to + step; i += step) { | 66 for (int i = from; i != to + step; i += step) { |
65 if (!increment) | 67 if (!increment) |
66 --it; | 68 --it; |
67 | 69 |
68 EXPECT_EQ(i, *it); | 70 EXPECT_EQ(i, *it); |
69 | 71 |
70 if (increment) | 72 if (increment) |
71 ++it; | 73 ++it; |
72 } | 74 } |
73 EXPECT_EQ(increment ? deque.rend() : deque.rbegin(), it); | 75 EXPECT_EQ(increment ? deque.rend() : deque.rbegin(), it); |
74 } | 76 } |
75 | 77 |
76 TEST(DequeTest, Reverse) | 78 template<size_t inlineCapacity> |
| 79 void reverseTest() |
77 { | 80 { |
78 Deque<int> intDeque; | 81 Deque<int, inlineCapacity> intDeque; |
79 intDeque.append(10); | 82 intDeque.append(10); |
80 intDeque.append(11); | 83 intDeque.append(11); |
81 intDeque.append(12); | 84 intDeque.append(12); |
82 intDeque.append(13); | 85 intDeque.append(13); |
83 | 86 |
84 checkNumberSequence(intDeque, 10, 13, true); | 87 checkNumberSequence(intDeque, 10, 13, true); |
85 checkNumberSequence(intDeque, 13, 10, false); | 88 checkNumberSequence(intDeque, 13, 10, false); |
86 checkNumberSequenceReverse(intDeque, 13, 10, true); | 89 checkNumberSequenceReverse(intDeque, 13, 10, true); |
87 checkNumberSequenceReverse(intDeque, 10, 13, false); | 90 checkNumberSequenceReverse(intDeque, 10, 13, false); |
88 | 91 |
(...skipping 13 matching lines...) Expand all Loading... |
102 checkNumberSequenceReverse(intDeque, 199, 11, true); | 105 checkNumberSequenceReverse(intDeque, 199, 11, true); |
103 checkNumberSequenceReverse(intDeque, 11, 199, false); | 106 checkNumberSequenceReverse(intDeque, 11, 199, false); |
104 | 107 |
105 for (int i = 0; i < 180; ++i) | 108 for (int i = 0; i < 180; ++i) |
106 EXPECT_EQ(i + 11, intDeque.takeFirst()); | 109 EXPECT_EQ(i + 11, intDeque.takeFirst()); |
107 checkNumberSequence(intDeque, 191, 199, true); | 110 checkNumberSequence(intDeque, 191, 199, true); |
108 checkNumberSequence(intDeque, 199, 191, false); | 111 checkNumberSequence(intDeque, 199, 191, false); |
109 checkNumberSequenceReverse(intDeque, 199, 191, true); | 112 checkNumberSequenceReverse(intDeque, 199, 191, true); |
110 checkNumberSequenceReverse(intDeque, 191, 199, false); | 113 checkNumberSequenceReverse(intDeque, 191, 199, false); |
111 | 114 |
112 Deque<int> intDeque2; | 115 Deque<int, inlineCapacity> intDeque2; |
113 swap(intDeque, intDeque2); | 116 swap(intDeque, intDeque2); |
114 | 117 |
115 checkNumberSequence(intDeque2, 191, 199, true); | 118 checkNumberSequence(intDeque2, 191, 199, true); |
116 checkNumberSequence(intDeque2, 199, 191, false); | 119 checkNumberSequence(intDeque2, 199, 191, false); |
117 checkNumberSequenceReverse(intDeque2, 199, 191, true); | 120 checkNumberSequenceReverse(intDeque2, 199, 191, true); |
118 checkNumberSequenceReverse(intDeque2, 191, 199, false); | 121 checkNumberSequenceReverse(intDeque2, 191, 199, false); |
119 | 122 |
120 intDeque.swap(intDeque2); | 123 intDeque.swap(intDeque2); |
121 | 124 |
122 checkNumberSequence(intDeque, 191, 199, true); | 125 checkNumberSequence(intDeque, 191, 199, true); |
123 checkNumberSequence(intDeque, 199, 191, false); | 126 checkNumberSequence(intDeque, 199, 191, false); |
124 checkNumberSequenceReverse(intDeque, 199, 191, true); | 127 checkNumberSequenceReverse(intDeque, 199, 191, true); |
125 checkNumberSequenceReverse(intDeque, 191, 199, false); | 128 checkNumberSequenceReverse(intDeque, 191, 199, false); |
126 | 129 |
127 intDeque.swap(intDeque2); | 130 intDeque.swap(intDeque2); |
128 | 131 |
129 checkNumberSequence(intDeque2, 191, 199, true); | 132 checkNumberSequence(intDeque2, 191, 199, true); |
130 checkNumberSequence(intDeque2, 199, 191, false); | 133 checkNumberSequence(intDeque2, 199, 191, false); |
131 checkNumberSequenceReverse(intDeque2, 199, 191, true); | 134 checkNumberSequenceReverse(intDeque2, 199, 191, true); |
132 checkNumberSequenceReverse(intDeque2, 191, 199, false); | 135 checkNumberSequenceReverse(intDeque2, 191, 199, false); |
133 } | 136 } |
134 | 137 |
| 138 TEST(DequeTest, Reverse) |
| 139 { |
| 140 reverseTest<0>(); |
| 141 reverseTest<2>(); |
| 142 } |
| 143 |
135 class DestructCounter { | 144 class DestructCounter { |
136 public: | 145 public: |
137 explicit DestructCounter(int i, int* destructNumber) | 146 explicit DestructCounter(int i, int* destructNumber) |
138 : m_i(i) | 147 : m_i(i) |
139 , m_destructNumber(destructNumber) | 148 , m_destructNumber(destructNumber) |
140 { } | 149 { } |
141 | 150 |
142 ~DestructCounter() { ++(*m_destructNumber); } | 151 ~DestructCounter() { ++(*m_destructNumber); } |
143 int get() const { return m_i; } | 152 int get() const { return m_i; } |
144 | 153 |
145 private: | 154 private: |
146 int m_i; | 155 int m_i; |
147 int* m_destructNumber; | 156 int* m_destructNumber; |
148 }; | 157 }; |
149 | 158 |
150 typedef WTF::Deque<OwnPtr<DestructCounter> > OwnPtrDeque; | 159 template<typename OwnPtrDeque> |
151 | 160 void ownPtrTest() |
152 TEST(DequeTest, OwnPtr) | |
153 { | 161 { |
154 int destructNumber = 0; | 162 int destructNumber = 0; |
155 OwnPtrDeque deque; | 163 OwnPtrDeque deque; |
156 deque.append(adoptPtr(new DestructCounter(0, &destructNumber))); | 164 deque.append(adoptPtr(new DestructCounter(0, &destructNumber))); |
157 deque.append(adoptPtr(new DestructCounter(1, &destructNumber))); | 165 deque.append(adoptPtr(new DestructCounter(1, &destructNumber))); |
158 EXPECT_EQ(2u, deque.size()); | 166 EXPECT_EQ(2u, deque.size()); |
159 | 167 |
160 OwnPtr<DestructCounter>& counter0 = deque.first(); | 168 OwnPtr<DestructCounter>& counter0 = deque.first(); |
161 EXPECT_EQ(0, counter0->get()); | 169 EXPECT_EQ(0, counter0->get()); |
162 int counter1 = deque.last()->get(); | 170 int counter1 = deque.last()->get(); |
163 EXPECT_EQ(1, counter1); | 171 EXPECT_EQ(1, counter1); |
164 EXPECT_EQ(0, destructNumber); | 172 EXPECT_EQ(0, destructNumber); |
165 | 173 |
166 size_t index = 0; | 174 size_t index = 0; |
167 for (OwnPtrDeque::iterator iter = deque.begin(); iter != deque.end(); ++iter
) { | 175 for (typename OwnPtrDeque::iterator iter = deque.begin(); iter != deque.end(
); ++iter) { |
168 OwnPtr<DestructCounter>& refCounter = *iter; | 176 OwnPtr<DestructCounter>& refCounter = *iter; |
169 EXPECT_EQ(index, static_cast<size_t>(refCounter->get())); | 177 EXPECT_EQ(index, static_cast<size_t>(refCounter->get())); |
170 EXPECT_EQ(index, static_cast<size_t>((*refCounter).get())); | 178 EXPECT_EQ(index, static_cast<size_t>((*refCounter).get())); |
171 index++; | 179 index++; |
172 } | 180 } |
173 EXPECT_EQ(0, destructNumber); | 181 EXPECT_EQ(0, destructNumber); |
174 | 182 |
175 OwnPtrDeque::iterator it = deque.begin(); | 183 typename OwnPtrDeque::iterator it = deque.begin(); |
176 for (index = 0; index < deque.size(); ++index) { | 184 for (index = 0; index < deque.size(); ++index) { |
177 OwnPtr<DestructCounter>& refCounter = *it; | 185 OwnPtr<DestructCounter>& refCounter = *it; |
178 EXPECT_EQ(index, static_cast<size_t>(refCounter->get())); | 186 EXPECT_EQ(index, static_cast<size_t>(refCounter->get())); |
179 index++; | 187 index++; |
180 ++it; | 188 ++it; |
181 } | 189 } |
182 EXPECT_EQ(0, destructNumber); | 190 EXPECT_EQ(0, destructNumber); |
183 | 191 |
184 EXPECT_EQ(0, deque.first()->get()); | 192 EXPECT_EQ(0, deque.first()->get()); |
185 deque.removeFirst(); | 193 deque.removeFirst(); |
(...skipping 22 matching lines...) Expand all Loading... |
208 OwnPtrDeque copyDeque; | 216 OwnPtrDeque copyDeque; |
209 deque.swap(copyDeque); | 217 deque.swap(copyDeque); |
210 EXPECT_EQ(0, destructNumber); | 218 EXPECT_EQ(0, destructNumber); |
211 EXPECT_EQ(count, copyDeque.size()); | 219 EXPECT_EQ(count, copyDeque.size()); |
212 EXPECT_EQ(0u, deque.size()); | 220 EXPECT_EQ(0u, deque.size()); |
213 | 221 |
214 copyDeque.clear(); | 222 copyDeque.clear(); |
215 EXPECT_EQ(count, static_cast<size_t>(destructNumber)); | 223 EXPECT_EQ(count, static_cast<size_t>(destructNumber)); |
216 } | 224 } |
217 | 225 |
| 226 TEST(DequeTest, OwnPtr) |
| 227 { |
| 228 ownPtrTest<WTF::Deque<OwnPtr<DestructCounter> > >(); |
| 229 ownPtrTest<WTF::Deque<OwnPtr<DestructCounter>, 2> >(); |
| 230 } |
| 231 |
| 232 |
218 // WrappedInt class will fail if it was memmoved or memcpyed. | 233 // WrappedInt class will fail if it was memmoved or memcpyed. |
219 static HashSet<void*> constructedWrappedInts; | 234 static HashSet<void*> constructedWrappedInts; |
220 class WrappedInt { | 235 class WrappedInt { |
221 public: | 236 public: |
222 WrappedInt(int i = 0) | 237 WrappedInt(int i = 0) |
223 : m_originalThisPtr(this) | 238 : m_originalThisPtr(this) |
224 , m_i(i) | 239 , m_i(i) |
225 { | 240 { |
226 constructedWrappedInts.add(this); | 241 constructedWrappedInts.add(this); |
227 } | 242 } |
(...skipping 18 matching lines...) Expand all Loading... |
246 constructedWrappedInts.remove(this); | 261 constructedWrappedInts.remove(this); |
247 } | 262 } |
248 | 263 |
249 int get() const { return m_i; } | 264 int get() const { return m_i; } |
250 | 265 |
251 private: | 266 private: |
252 void* m_originalThisPtr; | 267 void* m_originalThisPtr; |
253 int m_i; | 268 int m_i; |
254 }; | 269 }; |
255 | 270 |
256 TEST(DequeTest, SwapWithoutInlineCapacity) | 271 template<size_t inlineCapacity> |
| 272 void swapWithOrWithoutInlineCapacity() |
257 { | 273 { |
258 Deque<WrappedInt> dequeA; | 274 Deque<WrappedInt, inlineCapacity> dequeA; |
259 dequeA.append(WrappedInt(1)); | 275 dequeA.append(WrappedInt(1)); |
260 Deque<WrappedInt> dequeB; | 276 Deque<WrappedInt, inlineCapacity> dequeB; |
261 dequeB.append(WrappedInt(2)); | 277 dequeB.append(WrappedInt(2)); |
262 | 278 |
263 ASSERT_EQ(dequeA.size(), dequeB.size()); | 279 ASSERT_EQ(dequeA.size(), dequeB.size()); |
264 dequeA.swap(dequeB); | 280 dequeA.swap(dequeB); |
265 | 281 |
266 ASSERT_EQ(1u, dequeA.size()); | 282 ASSERT_EQ(1u, dequeA.size()); |
267 EXPECT_EQ(2, dequeA.first().get()); | 283 EXPECT_EQ(2, dequeA.first().get()); |
268 ASSERT_EQ(1u, dequeB.size()); | 284 ASSERT_EQ(1u, dequeB.size()); |
269 EXPECT_EQ(1, dequeB.first().get()); | 285 EXPECT_EQ(1, dequeB.first().get()); |
270 | 286 |
(...skipping 19 matching lines...) Expand all Loading... |
290 dequeA.swap(dequeB); | 306 dequeA.swap(dequeB); |
291 | 307 |
292 ASSERT_EQ(1u, dequeA.size()); | 308 ASSERT_EQ(1u, dequeA.size()); |
293 EXPECT_EQ(1, dequeA.first().get()); | 309 EXPECT_EQ(1, dequeA.first().get()); |
294 ASSERT_EQ(3u, dequeB.size()); | 310 ASSERT_EQ(3u, dequeB.size()); |
295 EXPECT_EQ(2, dequeB.first().get()); | 311 EXPECT_EQ(2, dequeB.first().get()); |
296 | 312 |
297 dequeB.swap(dequeA); | 313 dequeB.swap(dequeA); |
298 } | 314 } |
299 | 315 |
| 316 TEST(DequeTest, SwapWithOrWithoutInlineCapacity) |
| 317 { |
| 318 swapWithOrWithoutInlineCapacity<0>(); |
| 319 swapWithOrWithoutInlineCapacity<2>(); |
| 320 } |
| 321 |
| 322 class LivenessCounter { |
| 323 public: |
| 324 void ref() { s_live++; } |
| 325 void deref() { s_live--; } |
| 326 |
| 327 static unsigned s_live; |
| 328 }; |
| 329 |
| 330 unsigned LivenessCounter::s_live = 0; |
| 331 |
| 332 // Filter a few numbers out to improve the running speed of the tests. The |
| 333 // test has nested loops, and removing even numbers from 4 and up from the |
| 334 // loops makes it run 10 times faster. |
| 335 bool interestingNumber(int i) |
| 336 { |
| 337 return i < 4 || (i & 1); |
| 338 } |
| 339 |
| 340 template<size_t inlineCapacity> |
| 341 void testDestructorAndConstructorCallsWhenSwappingWithInlineCapacity() |
| 342 { |
| 343 LivenessCounter::s_live = 0; |
| 344 LivenessCounter counter; |
| 345 EXPECT_EQ(0u, LivenessCounter::s_live); |
| 346 |
| 347 Deque<RefPtr<LivenessCounter>, inlineCapacity> deque; |
| 348 Deque<RefPtr<LivenessCounter>, inlineCapacity> deque2; |
| 349 deque.append(&counter); |
| 350 deque2.append(&counter); |
| 351 EXPECT_EQ(2u, LivenessCounter::s_live); |
| 352 |
| 353 // Add various numbers of elements to deques, then remove various numbers |
| 354 // of elements from the head. This creates in-use ranges in the backing |
| 355 // that sometimes wrap around the end of the buffer, testing various ways |
| 356 // in which the in-use ranges of the inline buffers can overlap when we |
| 357 // call swap(). |
| 358 for (unsigned i = 0; i < 12; i++) { |
| 359 if (!interestingNumber(i)) |
| 360 continue; |
| 361 for (unsigned j = i; j < 12; j++) { |
| 362 if (!interestingNumber(j)) |
| 363 continue; |
| 364 deque.clear(); |
| 365 deque2.clear(); |
| 366 EXPECT_EQ(0u, LivenessCounter::s_live); |
| 367 for (unsigned k = 0; k < j; k++) |
| 368 deque.append(&counter); |
| 369 EXPECT_EQ(j, LivenessCounter::s_live); |
| 370 EXPECT_EQ(j, deque.size()); |
| 371 for (unsigned k = 0; k < i; k++) |
| 372 deque.removeFirst(); |
| 373 |
| 374 EXPECT_EQ(j - i, LivenessCounter::s_live); |
| 375 EXPECT_EQ(j - i, deque.size()); |
| 376 deque.swap(deque2); |
| 377 EXPECT_EQ(j - i, LivenessCounter::s_live); |
| 378 EXPECT_EQ(0u, deque.size()); |
| 379 EXPECT_EQ(j - i, deque2.size()); |
| 380 deque.swap(deque2); |
| 381 EXPECT_EQ(j - i, LivenessCounter::s_live); |
| 382 |
| 383 deque2.append(&counter); |
| 384 deque2.append(&counter); |
| 385 deque2.append(&counter); |
| 386 |
| 387 for (unsigned k = 0; k < 12; k++) { |
| 388 EXPECT_EQ(3 + j - i, LivenessCounter::s_live); |
| 389 EXPECT_EQ(j - i, deque.size()); |
| 390 EXPECT_EQ(3u, deque2.size()); |
| 391 deque.swap(deque2); |
| 392 EXPECT_EQ(3 + j - i, LivenessCounter::s_live); |
| 393 EXPECT_EQ(j - i, deque2.size()); |
| 394 EXPECT_EQ(3u, deque.size()); |
| 395 deque.swap(deque2); |
| 396 EXPECT_EQ(3 + j - i, LivenessCounter::s_live); |
| 397 EXPECT_EQ(j - i, deque.size()); |
| 398 EXPECT_EQ(3u, deque2.size()); |
| 399 |
| 400 deque2.removeFirst(); |
| 401 deque2.append(&counter); |
| 402 } |
| 403 } |
| 404 } |
| 405 |
| 406 } |
| 407 |
| 408 TEST(DequeTest, SwapWithConstructorsAndDestructors) |
| 409 { |
| 410 testDestructorAndConstructorCallsWhenSwappingWithInlineCapacity<0>(); |
| 411 testDestructorAndConstructorCallsWhenSwappingWithInlineCapacity<4>(); |
| 412 testDestructorAndConstructorCallsWhenSwappingWithInlineCapacity<9>(); |
| 413 } |
| 414 |
| 415 template<size_t inlineCapacity> |
| 416 void testValuesMovedAndSwappedWithInlineCapacity() |
| 417 { |
| 418 Deque<unsigned, inlineCapacity> deque; |
| 419 Deque<unsigned, inlineCapacity> deque2; |
| 420 |
| 421 // Add various numbers of elements to deques, then remove various numbers |
| 422 // of elements from the head. This creates in-use ranges in the backing |
| 423 // that sometimes wrap around the end of the buffer, testing various ways |
| 424 // in which the in-use ranges of the inline buffers can overlap when we |
| 425 // call swap(). |
| 426 for (unsigned pad = 0; pad < 12; pad++) { |
| 427 if (!interestingNumber(pad)) |
| 428 continue; |
| 429 for (unsigned pad2 = 0; pad2 < 12; pad2++) { |
| 430 if (!interestingNumber(pad2)) |
| 431 continue; |
| 432 for (unsigned size = 0; size < 12; size++) { |
| 433 if (!interestingNumber(size)) |
| 434 continue; |
| 435 for (unsigned size2 = 0; size2 < 12; size2++) { |
| 436 if (!interestingNumber(size2)) |
| 437 continue; |
| 438 deque.clear(); |
| 439 deque2.clear(); |
| 440 for (unsigned i = 0; i < pad; i++) |
| 441 deque.append(103); |
| 442 for (unsigned i = 0; i < pad2; i++) |
| 443 deque2.append(888); |
| 444 for (unsigned i = 0; i < size; i++) |
| 445 deque.append(i); |
| 446 for (unsigned i = 0; i < size2; i++) |
| 447 deque2.append(i + 42); |
| 448 for (unsigned i = 0; i < pad; i++) |
| 449 EXPECT_EQ(103u, deque.takeFirst()); |
| 450 for (unsigned i = 0; i < pad2; i++) |
| 451 EXPECT_EQ(888u, deque2.takeFirst()); |
| 452 EXPECT_EQ(size, deque.size()); |
| 453 EXPECT_EQ(size2, deque2.size()); |
| 454 deque.swap(deque2); |
| 455 for (unsigned i = 0; i < size; i++) |
| 456 EXPECT_EQ(i, deque2.takeFirst()); |
| 457 for (unsigned i = 0; i < size2; i++) |
| 458 EXPECT_EQ(i + 42, deque.takeFirst()); |
| 459 } |
| 460 } |
| 461 } |
| 462 } |
| 463 } |
| 464 |
| 465 TEST(DequeTest, ValuesMovedAndSwappedWithInlineCapacity) |
| 466 { |
| 467 testValuesMovedAndSwappedWithInlineCapacity<0>(); |
| 468 testValuesMovedAndSwappedWithInlineCapacity<4>(); |
| 469 testValuesMovedAndSwappedWithInlineCapacity<9>(); |
| 470 } |
| 471 |
300 } // namespace | 472 } // namespace |
OLD | NEW |