1/*
2 * Copyright (C) 2015 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 "config.h"
27
28static unsigned s_baseWeakReferences = 0;
29
30#define DID_CREATE_WEAK_PTR_IMPL(p) do { \
31 ++s_baseWeakReferences; \
32} while (0);
33
34#define WILL_DESTROY_WEAK_PTR_IMPL(p) do { \
35 --s_baseWeakReferences; \
36} while (0);
37
38#include "Test.h"
39#include <wtf/HashSet.h>
40#include <wtf/WeakHashSet.h>
41#include <wtf/WeakPtr.h>
42
43namespace TestWebKitAPI {
44
45struct Int : public CanMakeWeakPtr<Int> {
46 Int(int i) : m_i(i) { }
47 operator int() const { return m_i; }
48 bool operator==(const Int& other) const { return m_i == other.m_i; }
49 int m_i;
50};
51
52class Base : public CanMakeWeakPtr<Base> {
53 WTF_MAKE_FAST_ALLOCATED;
54public:
55 Base() { }
56
57 int foo()
58 {
59 return 0;
60 }
61
62 int dummy; // Prevent empty base class optimization, to make testing more interesting.
63};
64
65class Derived : public Base {
66public:
67 Derived() { }
68
69 virtual ~Derived() { } // Force a pointer fixup when casting Base <-> Derived
70
71 int foo()
72 {
73 return 1;
74 }
75};
76
77}
78
79namespace TestWebKitAPI {
80
81TEST(WTF_WeakPtr, Basic)
82{
83 Int dummy(5);
84 WeakPtrFactory<Int>* factory = new WeakPtrFactory<Int>();
85 WeakPtr<Int> weakPtr1 = factory->createWeakPtr(dummy);
86 WeakPtr<Int> weakPtr2 = factory->createWeakPtr(dummy);
87 WeakPtr<Int> weakPtr3 = factory->createWeakPtr(dummy);
88 EXPECT_EQ(weakPtr1.get(), &dummy);
89 EXPECT_EQ(weakPtr2.get(), &dummy);
90 EXPECT_EQ(weakPtr3.get(), &dummy);
91 EXPECT_TRUE(!!weakPtr1);
92 EXPECT_TRUE(!!weakPtr2);
93 EXPECT_TRUE(!!weakPtr3);
94 EXPECT_TRUE(weakPtr1 == weakPtr2);
95 EXPECT_TRUE(weakPtr1 == &dummy);
96 EXPECT_TRUE(&dummy == weakPtr2);
97 delete factory;
98 EXPECT_NULL(weakPtr1.get());
99 EXPECT_NULL(weakPtr2.get());
100 EXPECT_NULL(weakPtr3.get());
101 EXPECT_FALSE(weakPtr1);
102 EXPECT_FALSE(weakPtr2);
103 EXPECT_FALSE(weakPtr3);
104}
105
106TEST(WTF_WeakPtr, Assignment)
107{
108 Int dummy(5);
109 WeakPtr<Int> weakPtr;
110 {
111 WeakPtrFactory<Int> factory;
112 EXPECT_NULL(weakPtr.get());
113 weakPtr = factory.createWeakPtr(dummy);
114 EXPECT_EQ(weakPtr.get(), &dummy);
115 }
116 EXPECT_NULL(weakPtr.get());
117}
118
119TEST(WTF_WeakPtr, MultipleFactories)
120{
121 Int dummy1(5);
122 Int dummy2(7);
123 WeakPtrFactory<Int>* factory1 = new WeakPtrFactory<Int>();
124 WeakPtrFactory<Int>* factory2 = new WeakPtrFactory<Int>();
125 WeakPtr<Int> weakPtr1 = factory1->createWeakPtr(dummy1);
126 WeakPtr<Int> weakPtr2 = factory2->createWeakPtr(dummy2);
127 EXPECT_EQ(weakPtr1.get(), &dummy1);
128 EXPECT_EQ(weakPtr2.get(), &dummy2);
129 EXPECT_TRUE(weakPtr1 != weakPtr2);
130 EXPECT_TRUE(weakPtr1 != &dummy2);
131 EXPECT_TRUE(&dummy1 != weakPtr2);
132 delete factory1;
133 EXPECT_NULL(weakPtr1.get());
134 EXPECT_EQ(weakPtr2.get(), &dummy2);
135 delete factory2;
136 EXPECT_NULL(weakPtr2.get());
137}
138
139TEST(WTF_WeakPtr, RevokeAll)
140{
141 Int dummy(5);
142 WeakPtrFactory<Int> factory;
143 WeakPtr<Int> weakPtr1 = factory.createWeakPtr(dummy);
144 WeakPtr<Int> weakPtr2 = factory.createWeakPtr(dummy);
145 WeakPtr<Int> weakPtr3 = factory.createWeakPtr(dummy);
146 EXPECT_EQ(weakPtr1.get(), &dummy);
147 EXPECT_EQ(weakPtr2.get(), &dummy);
148 EXPECT_EQ(weakPtr3.get(), &dummy);
149 factory.revokeAll();
150 EXPECT_NULL(weakPtr1.get());
151 EXPECT_NULL(weakPtr2.get());
152 EXPECT_NULL(weakPtr3.get());
153}
154
155struct Foo : public CanMakeWeakPtr<Foo> {
156 void bar() { };
157};
158
159TEST(WTF_WeakPtr, Dereference)
160{
161 Foo f;
162 WeakPtrFactory<Foo> factory;
163 WeakPtr<Foo> weakPtr = factory.createWeakPtr(f);
164 weakPtr->bar();
165}
166
167TEST(WTF_WeakPtr, Operators)
168{
169 Foo f;
170 WeakPtrFactory<Foo> factory;
171 WeakPtr<Foo> weakPtr = factory.createWeakPtr(f);
172
173 WeakPtr<Foo> weakPtr2 = weakPtr;
174 EXPECT_EQ(weakPtr2.get(), &f);
175
176 WeakPtr<Foo> weakPtr3;
177 weakPtr3 = weakPtr;
178 EXPECT_EQ(weakPtr3.get(), &f);
179
180 WeakPtr<Foo> weakPtr4 = WTFMove(weakPtr);
181 EXPECT_EQ(weakPtr4.get(), &f);
182 EXPECT_FALSE(weakPtr);
183}
184
185TEST(WTF_WeakPtr, Forget)
186{
187 Int dummy(5);
188 Int dummy2(7);
189
190 WeakPtrFactory<Int> outerFactory;
191 WeakPtr<Int> weakPtr1, weakPtr2, weakPtr3, weakPtr4;
192 {
193 WeakPtrFactory<Int> innerFactory;
194 weakPtr1 = innerFactory.createWeakPtr(dummy);
195 weakPtr2 = innerFactory.createWeakPtr(dummy);
196 weakPtr3 = innerFactory.createWeakPtr(dummy);
197 EXPECT_EQ(weakPtr1.get(), &dummy);
198 EXPECT_EQ(weakPtr2.get(), &dummy);
199 EXPECT_EQ(weakPtr3.get(), &dummy);
200 weakPtr1.clear();
201 weakPtr3 = nullptr;
202 EXPECT_NULL(weakPtr1.get());
203 EXPECT_EQ(weakPtr2.get(), &dummy);
204 EXPECT_NULL(weakPtr3.get());
205 weakPtr1.clear();
206 weakPtr3.clear();
207 EXPECT_NULL(weakPtr1.get());
208 EXPECT_EQ(weakPtr2.get(), &dummy);
209 EXPECT_NULL(weakPtr3.get());
210 weakPtr3 = nullptr;
211 EXPECT_NULL(weakPtr1.get());
212 EXPECT_EQ(weakPtr2.get(), &dummy);
213 EXPECT_NULL(weakPtr3.get());
214
215 weakPtr4 = weakPtr2;
216 EXPECT_EQ(weakPtr2.get(), &dummy);
217 EXPECT_EQ(weakPtr4.get(), &dummy);
218
219 WeakPtr<Int> weakPtr5 = weakPtr2;
220 EXPECT_EQ(weakPtr2.get(), &dummy);
221 EXPECT_EQ(weakPtr5.get(), &dummy);
222 weakPtr5.clear();
223 EXPECT_NULL(weakPtr5.get());
224 EXPECT_EQ(weakPtr2.get(), &dummy);
225
226 weakPtr4 = outerFactory.createWeakPtr(dummy2);
227 EXPECT_EQ(weakPtr2.get(), &dummy);
228 EXPECT_EQ(weakPtr4.get(), &dummy2);
229 }
230
231 EXPECT_NULL(weakPtr1.get());
232 EXPECT_NULL(weakPtr2.get());
233 EXPECT_EQ(weakPtr4.get(), &dummy2);
234
235 WeakPtr<Int> weakPtr5 = weakPtr4;
236 EXPECT_EQ(weakPtr4.get(), &dummy2);
237 EXPECT_EQ(weakPtr5.get(), &dummy2);
238 weakPtr5.clear();
239 EXPECT_NULL(weakPtr5.get());
240 WeakPtr<Int> weakPtr6 = weakPtr5;
241 EXPECT_NULL(weakPtr6.get());
242 EXPECT_EQ(weakPtr5.get(), weakPtr6.get());
243
244 WeakPtr<Int> weakPtr7 = outerFactory.createWeakPtr(dummy2);
245 EXPECT_EQ(weakPtr7.get(), &dummy2);
246 weakPtr7 = nullptr;
247 EXPECT_NULL(weakPtr7.get());
248}
249
250TEST(WTF_WeakPtr, Downcasting)
251{
252 int dummy0(0);
253 int dummy1(1);
254
255 WeakPtr<Base> baseWeakPtr;
256 WeakPtr<Derived> derivedWeakPtr;
257
258 {
259 Derived object;
260 Derived* derivedPtr = &object;
261 Base* basePtr = static_cast<Base*>(&object);
262
263 baseWeakPtr = object.weakPtrFactory().createWeakPtr(object);
264 EXPECT_EQ(basePtr->foo(), dummy0);
265 EXPECT_EQ(baseWeakPtr->foo(), basePtr->foo());
266 EXPECT_EQ(baseWeakPtr.get()->foo(), basePtr->foo());
267
268 derivedWeakPtr = makeWeakPtr(object);
269 EXPECT_EQ(derivedWeakPtr->foo(), dummy1);
270 EXPECT_EQ(derivedWeakPtr->foo(), derivedPtr->foo());
271 EXPECT_EQ(derivedWeakPtr.get()->foo(), derivedPtr->foo());
272
273 EXPECT_EQ(baseWeakPtr.get(), derivedWeakPtr.get());
274 }
275
276 EXPECT_NULL(baseWeakPtr.get());
277 EXPECT_NULL(derivedWeakPtr.get());
278}
279
280TEST(WTF_WeakPtr, DerivedConstructAndAssign)
281{
282 Derived derived;
283 {
284 WeakPtr<Derived> derivedWeakPtr = makeWeakPtr(derived);
285 WeakPtr<Base> baseWeakPtr { WTFMove(derivedWeakPtr) };
286 EXPECT_EQ(baseWeakPtr.get(), &derived);
287 EXPECT_NULL(derivedWeakPtr.get());
288 }
289
290 {
291 WeakPtr<Derived> derivedWeakPtr = makeWeakPtr(derived);
292 WeakPtr<Base> baseWeakPtr { derivedWeakPtr };
293 EXPECT_EQ(baseWeakPtr.get(), &derived);
294 EXPECT_EQ(derivedWeakPtr.get(), &derived);
295 }
296
297 {
298 WeakPtr<Derived> derivedWeakPtr = makeWeakPtr(derived);
299 WeakPtr<Base> baseWeakPtr;
300 baseWeakPtr = WTFMove(derivedWeakPtr);
301 EXPECT_EQ(baseWeakPtr.get(), &derived);
302 EXPECT_NULL(derivedWeakPtr.get());
303 }
304
305 {
306 WeakPtr<Derived> derivedWeakPtr = makeWeakPtr(derived);
307 WeakPtr<Base> baseWeakPtr;
308 baseWeakPtr = derivedWeakPtr;
309 EXPECT_EQ(baseWeakPtr.get(), &derived);
310 EXPECT_EQ(derivedWeakPtr.get(), &derived);
311 }
312}
313
314TEST(WTF_WeakPtr, DerivedConstructAndAssignConst)
315{
316 const Derived derived;
317 {
318 auto derivedWeakPtr = makeWeakPtr(derived);
319 WeakPtr<const Base> baseWeakPtr { WTFMove(derivedWeakPtr) };
320 EXPECT_EQ(baseWeakPtr.get(), &derived);
321 EXPECT_NULL(derivedWeakPtr.get());
322 }
323
324 {
325 auto derivedWeakPtr = makeWeakPtr(derived);
326 WeakPtr<const Base> baseWeakPtr { derivedWeakPtr };
327 EXPECT_EQ(baseWeakPtr.get(), &derived);
328 EXPECT_EQ(derivedWeakPtr.get(), &derived);
329 }
330
331 {
332 auto derivedWeakPtr = makeWeakPtr(derived);
333 WeakPtr<const Base> baseWeakPtr;
334 baseWeakPtr = WTFMove(derivedWeakPtr);
335 EXPECT_EQ(baseWeakPtr.get(), &derived);
336 EXPECT_NULL(derivedWeakPtr.get());
337 }
338
339 {
340 auto derivedWeakPtr = makeWeakPtr(derived);
341 WeakPtr<const Base> baseWeakPtr;
342 baseWeakPtr = derivedWeakPtr;
343 EXPECT_EQ(baseWeakPtr.get(), &derived);
344 EXPECT_EQ(derivedWeakPtr.get(), &derived);
345 }
346}
347
348template <typename T>
349unsigned computeSizeOfWeakHashSet(const HashSet<WeakPtr<T>>& set)
350{
351 unsigned size = 0;
352 for (auto& item : set) {
353 UNUSED_PARAM(item);
354 size++;
355 }
356 return size;
357}
358
359template <typename T>
360unsigned computeSizeOfWeakHashSet(const WeakHashSet<T>& set)
361{
362 unsigned size = 0;
363 for (auto& item : set) {
364 UNUSED_PARAM(item);
365 size++;
366 }
367 return size;
368}
369
370TEST(WTF_WeakPtr, WeakHashSetBasic)
371{
372 {
373 WeakHashSet<Base> weakHashSet;
374 Base object;
375 EXPECT_FALSE(weakHashSet.contains(object));
376 EXPECT_EQ(s_baseWeakReferences, 0u);
377 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
378 weakHashSet.add(object);
379 EXPECT_EQ(s_baseWeakReferences, 1u);
380 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
381 EXPECT_TRUE(weakHashSet.contains(object));
382 weakHashSet.add(object);
383 EXPECT_TRUE(weakHashSet.contains(object));
384 EXPECT_EQ(s_baseWeakReferences, 1u);
385 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
386 weakHashSet.checkConsistency();
387 }
388 EXPECT_EQ(s_baseWeakReferences, 0u);
389
390 {
391 WeakHashSet<Base> weakHashSet;
392 Derived object;
393 EXPECT_FALSE(weakHashSet.contains(object));
394 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
395 EXPECT_EQ(s_baseWeakReferences, 0u);
396 weakHashSet.add(object);
397 EXPECT_TRUE(weakHashSet.contains(object));
398 EXPECT_EQ(s_baseWeakReferences, 1u);
399 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
400 weakHashSet.add(object);
401 EXPECT_TRUE(weakHashSet.contains(object));
402 EXPECT_EQ(s_baseWeakReferences, 1u);
403 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
404 weakHashSet.checkConsistency();
405 }
406 EXPECT_EQ(s_baseWeakReferences, 0u);
407
408 {
409 WeakHashSet<Base> weakHashSet;
410 {
411 Base object;
412 EXPECT_FALSE(weakHashSet.contains(object));
413 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
414 EXPECT_EQ(s_baseWeakReferences, 0u);
415 weakHashSet.add(object);
416 EXPECT_TRUE(weakHashSet.contains(object));
417 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
418 EXPECT_EQ(s_baseWeakReferences, 1u);
419 }
420 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
421 weakHashSet.checkConsistency();
422 }
423 EXPECT_EQ(s_baseWeakReferences, 0u);
424
425 {
426 WeakHashSet<Base> weakHashSet;
427 {
428 Base object1;
429 Base object2;
430 EXPECT_FALSE(weakHashSet.contains(object1));
431 EXPECT_FALSE(weakHashSet.contains(object2));
432 EXPECT_EQ(s_baseWeakReferences, 0u);
433 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
434 weakHashSet.add(object1);
435 EXPECT_TRUE(weakHashSet.contains(object1));
436 EXPECT_FALSE(weakHashSet.contains(object2));
437 EXPECT_EQ(s_baseWeakReferences, 1u);
438 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
439 weakHashSet.add(object2);
440 EXPECT_TRUE(weakHashSet.contains(object1));
441 EXPECT_TRUE(weakHashSet.contains(object2));
442 EXPECT_EQ(s_baseWeakReferences, 2u);
443 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 2u);
444 weakHashSet.remove(object1);
445 EXPECT_FALSE(weakHashSet.contains(object1));
446 EXPECT_TRUE(weakHashSet.contains(object2));
447 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
448 }
449 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
450 weakHashSet.checkConsistency();
451 }
452 EXPECT_EQ(s_baseWeakReferences, 0u);
453
454 {
455 WeakHashSet<Base> weakHashSet;
456 Base object1;
457 Base object2;
458 Base object3;
459 EXPECT_FALSE(weakHashSet.contains(object1));
460 EXPECT_FALSE(weakHashSet.contains(object2));
461 EXPECT_FALSE(weakHashSet.contains(object3));
462 EXPECT_EQ(s_baseWeakReferences, 0u);
463 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
464 weakHashSet.add(object1);
465 weakHashSet.add(object2);
466 EXPECT_TRUE(weakHashSet.contains(object1));
467 EXPECT_TRUE(weakHashSet.contains(object2));
468 EXPECT_FALSE(weakHashSet.contains(object3));
469 EXPECT_EQ(s_baseWeakReferences, 2u);
470 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 2u);
471 weakHashSet.remove(object1);
472 EXPECT_FALSE(weakHashSet.contains(object1));
473 EXPECT_TRUE(weakHashSet.contains(object2));
474 EXPECT_FALSE(weakHashSet.contains(object3));
475 EXPECT_EQ(s_baseWeakReferences, 2u); // Because object2 holds onto WeakReference.
476 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
477 weakHashSet.remove(object3);
478 EXPECT_FALSE(weakHashSet.contains(object1));
479 EXPECT_TRUE(weakHashSet.contains(object2));
480 EXPECT_FALSE(weakHashSet.contains(object3));
481 EXPECT_EQ(s_baseWeakReferences, 2u);
482 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
483 weakHashSet.add(object2);
484 EXPECT_FALSE(weakHashSet.contains(object1));
485 EXPECT_TRUE(weakHashSet.contains(object2));
486 EXPECT_FALSE(weakHashSet.contains(object3));
487 EXPECT_EQ(s_baseWeakReferences, 2u);
488 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
489 weakHashSet.checkConsistency();
490 }
491 EXPECT_EQ(s_baseWeakReferences, 0u);
492}
493
494TEST(WTF_WeakPtr, WeakHashSetConstObjects)
495{
496 {
497 WeakHashSet<Base> weakHashSet;
498 const Base object;
499 EXPECT_FALSE(weakHashSet.contains(object));
500 EXPECT_EQ(s_baseWeakReferences, 0u);
501 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
502 weakHashSet.add(object);
503 EXPECT_EQ(s_baseWeakReferences, 1u);
504 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
505 EXPECT_TRUE(weakHashSet.contains(object));
506 weakHashSet.checkConsistency();
507 weakHashSet.add(object);
508 EXPECT_TRUE(weakHashSet.contains(object));
509 EXPECT_EQ(s_baseWeakReferences, 1u);
510 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
511 weakHashSet.checkConsistency();
512 weakHashSet.remove(object);
513 EXPECT_EQ(s_baseWeakReferences, 1u);
514 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
515 }
516
517 {
518 WeakHashSet<Base> weakHashSet;
519 const Derived object;
520 EXPECT_FALSE(weakHashSet.contains(object));
521 EXPECT_EQ(s_baseWeakReferences, 0u);
522 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
523 weakHashSet.add(object);
524 EXPECT_EQ(s_baseWeakReferences, 1u);
525 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
526 EXPECT_TRUE(weakHashSet.contains(object));
527 weakHashSet.checkConsistency();
528 weakHashSet.add(object);
529 EXPECT_TRUE(weakHashSet.contains(object));
530 EXPECT_EQ(s_baseWeakReferences, 1u);
531 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
532 weakHashSet.checkConsistency();
533 weakHashSet.remove(object);
534 EXPECT_EQ(s_baseWeakReferences, 1u);
535 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
536 }
537
538 {
539 WeakHashSet<Derived> weakHashSet;
540 const Derived object;
541 EXPECT_FALSE(weakHashSet.contains(object));
542 EXPECT_EQ(s_baseWeakReferences, 0u);
543 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
544 weakHashSet.add(object);
545 EXPECT_EQ(s_baseWeakReferences, 1u);
546 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
547 EXPECT_TRUE(weakHashSet.contains(object));
548 weakHashSet.checkConsistency();
549 weakHashSet.add(object);
550 EXPECT_TRUE(weakHashSet.contains(object));
551 EXPECT_EQ(s_baseWeakReferences, 1u);
552 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u);
553 weakHashSet.checkConsistency();
554 weakHashSet.remove(object);
555 EXPECT_EQ(s_baseWeakReferences, 1u);
556 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
557 }
558}
559
560TEST(WTF_WeakPtr, WeakHashSetExpansion)
561{
562 unsigned initialCapacity;
563 static constexpr unsigned maxLoadCap = 3;
564 {
565 WeakHashSet<Base> weakHashSet;
566 Base object;
567 EXPECT_EQ(s_baseWeakReferences, 0u);
568 weakHashSet.add(object);
569 EXPECT_EQ(s_baseWeakReferences, 1u);
570 initialCapacity = weakHashSet.capacity();
571 }
572 EXPECT_EQ(s_baseWeakReferences, 0u);
573
574 for (unsigned i = 0; i < 1; ++i) {
575 WeakHashSet<Base> weakHashSet;
576 Vector<std::unique_ptr<Base>> objects;
577 Vector<std::unique_ptr<Base>> otherObjects;
578
579 EXPECT_EQ(weakHashSet.capacity(), 0u);
580 EXPECT_TRUE(initialCapacity / maxLoadCap);
581 for (unsigned i = 0; i < initialCapacity / maxLoadCap; ++i) {
582 auto object = makeUnique<Base>();
583 weakHashSet.add(*object);
584 objects.append(WTFMove(object));
585 otherObjects.append(makeUnique<Base>());
586 weakHashSet.checkConsistency();
587 }
588 EXPECT_EQ(s_baseWeakReferences, otherObjects.size());
589 EXPECT_EQ(weakHashSet.capacity(), initialCapacity);
590 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), objects.size());
591 for (unsigned i = 0; i < otherObjects.size(); ++i) {
592 EXPECT_TRUE(weakHashSet.contains(*objects[i]));
593 EXPECT_FALSE(weakHashSet.contains(*otherObjects[i]));
594 }
595 objects.clear();
596 weakHashSet.checkConsistency();
597 EXPECT_EQ(s_baseWeakReferences, otherObjects.size());
598 EXPECT_EQ(weakHashSet.capacity(), initialCapacity);
599 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
600 for (auto& object : otherObjects)
601 EXPECT_FALSE(weakHashSet.contains(*object));
602 for (auto& object : otherObjects) {
603 weakHashSet.add(*object);
604 weakHashSet.checkConsistency();
605 }
606 EXPECT_EQ(weakHashSet.capacity(), initialCapacity);
607 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), otherObjects.size());
608 for (auto& object : otherObjects)
609 EXPECT_TRUE(weakHashSet.contains(*object));
610 }
611 EXPECT_EQ(s_baseWeakReferences, 0u);
612
613 for (unsigned i = 0; i < 10; ++i) {
614 WeakHashSet<Base> weakHashSet;
615 Vector<std::unique_ptr<Base>> objects;
616 EXPECT_EQ(weakHashSet.capacity(), 0u);
617 unsigned objectCount = initialCapacity * 2;
618 for (unsigned i = 0; i < objectCount; ++i) {
619 auto object = makeUnique<Base>();
620 weakHashSet.add(*object);
621 objects.append(WTFMove(object));
622 weakHashSet.checkConsistency();
623 }
624 unsigned originalCapacity = weakHashSet.capacity();
625 EXPECT_EQ(s_baseWeakReferences, objects.size());
626 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), objects.size());
627 for (auto& object : objects)
628 EXPECT_TRUE(weakHashSet.contains(*object));
629 objects.clear();
630 weakHashSet.checkConsistency();
631 EXPECT_EQ(s_baseWeakReferences, objectCount);
632 EXPECT_EQ(weakHashSet.capacity(), originalCapacity);
633 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u);
634 }
635}
636
637TEST(WTF_WeakPtr, WeakHashSetComputesEmpty)
638{
639 {
640 WeakHashSet<Base> weakHashSet;
641 {
642 Base object;
643 EXPECT_EQ(s_baseWeakReferences, 0u);
644 weakHashSet.add(object);
645 EXPECT_FALSE(weakHashSet.computesEmpty());
646 }
647 EXPECT_EQ(s_baseWeakReferences, 1u);
648 EXPECT_TRUE(weakHashSet.computesEmpty());
649 }
650
651 {
652 WeakHashSet<Base> weakHashSet;
653 Base object1;
654 EXPECT_EQ(s_baseWeakReferences, 0u);
655 weakHashSet.add(object1);
656 EXPECT_EQ(s_baseWeakReferences, 1u);
657 {
658 Base object2;
659 weakHashSet.add(object2);
660 EXPECT_FALSE(weakHashSet.computesEmpty());
661 }
662 EXPECT_EQ(s_baseWeakReferences, 2u);
663 EXPECT_FALSE(weakHashSet.computesEmpty());
664 weakHashSet.remove(object1);
665 EXPECT_TRUE(weakHashSet.computesEmpty());
666 }
667
668 {
669 WeakHashSet<Base> weakHashSet;
670 Vector<std::unique_ptr<Base>> objects;
671 auto firstObject = makeUnique<Base>();
672 weakHashSet.add(*firstObject);
673 do {
674 auto object = makeUnique<Base>();
675 weakHashSet.add(*object);
676 objects.append(WTFMove(object));
677 } while (weakHashSet.begin().get() == firstObject.get());
678
679 EXPECT_EQ(s_baseWeakReferences, objects.size() + 1);
680 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), objects.size() + 1);
681 EXPECT_FALSE(weakHashSet.computesEmpty());
682 firstObject = nullptr;
683 EXPECT_FALSE(weakHashSet.computesEmpty());
684 EXPECT_EQ(s_baseWeakReferences, objects.size() + 1);
685 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), objects.size());
686 }
687}
688
689TEST(WTF_WeakPtr, WeakHashSetComputeSize)
690{
691 {
692 WeakHashSet<Base> weakHashSet;
693 {
694 Base object;
695 EXPECT_EQ(s_baseWeakReferences, 0u);
696 weakHashSet.add(object);
697 EXPECT_EQ(s_baseWeakReferences, 1u);
698 EXPECT_EQ(weakHashSet.computeSize(), 1u);
699 weakHashSet.checkConsistency();
700 }
701 EXPECT_TRUE(weakHashSet.computesEmpty());
702 EXPECT_EQ(weakHashSet.computeSize(), 0u);
703 EXPECT_EQ(s_baseWeakReferences, 0u);
704 EXPECT_TRUE(weakHashSet.computesEmpty());
705 weakHashSet.checkConsistency();
706 }
707
708 {
709 WeakHashSet<Base> weakHashSet;
710 {
711 Base object1;
712 EXPECT_EQ(s_baseWeakReferences, 0u);
713 weakHashSet.add(object1);
714 EXPECT_EQ(s_baseWeakReferences, 1u);
715 {
716 Base object2;
717 weakHashSet.add(object2);
718 EXPECT_EQ(s_baseWeakReferences, 2u);
719 EXPECT_EQ(weakHashSet.computeSize(), 2u);
720 weakHashSet.checkConsistency();
721 }
722 EXPECT_EQ(s_baseWeakReferences, 2u);
723 EXPECT_EQ(weakHashSet.computeSize(), 1u);
724 EXPECT_EQ(s_baseWeakReferences, 1u);
725 weakHashSet.checkConsistency();
726 weakHashSet.remove(object1);
727 EXPECT_EQ(s_baseWeakReferences, 1u);
728 EXPECT_EQ(weakHashSet.computeSize(), 0u);
729 EXPECT_EQ(s_baseWeakReferences, 1u);
730 weakHashSet.checkConsistency();
731 }
732 EXPECT_EQ(s_baseWeakReferences, 0u);
733 weakHashSet.checkConsistency();
734 }
735
736 while (1) {
737 WeakHashSet<Base> weakHashSet;
738 auto firstObject = makeUnique<Base>();
739 auto lastObject = makeUnique<Base>();
740 weakHashSet.add(*firstObject);
741 weakHashSet.add(*lastObject);
742 if (weakHashSet.begin().get() != firstObject.get())
743 continue;
744 EXPECT_EQ(s_baseWeakReferences, 2u);
745 EXPECT_EQ(weakHashSet.computeSize(), 2u);
746 EXPECT_EQ(s_baseWeakReferences, 2u);
747 weakHashSet.checkConsistency();
748 firstObject = nullptr;
749 EXPECT_EQ(weakHashSet.computeSize(), 1u);
750 EXPECT_EQ(s_baseWeakReferences, 1u);
751 weakHashSet.checkConsistency();
752 lastObject = nullptr;
753 EXPECT_EQ(s_baseWeakReferences, 1u);
754 EXPECT_EQ(weakHashSet.computeSize(), 0u);
755 EXPECT_EQ(s_baseWeakReferences, 0u);
756 weakHashSet.checkConsistency();
757 break;
758 }
759
760 {
761 WeakHashSet<Base> weakHashSet;
762 Vector<std::unique_ptr<Base>> objects;
763 auto nonFirstObject = makeUnique<Base>();
764 weakHashSet.add(*nonFirstObject);
765 do {
766 auto object = makeUnique<Base>();
767 weakHashSet.add(*object);
768 objects.append(WTFMove(object));
769 } while (weakHashSet.begin().get() == nonFirstObject.get());
770
771 unsigned objectsCount = objects.size();
772 EXPECT_EQ(s_baseWeakReferences, objectsCount + 1);
773 EXPECT_EQ(weakHashSet.computeSize(), objectsCount + 1);
774 EXPECT_EQ(s_baseWeakReferences, objectsCount + 1);
775 weakHashSet.checkConsistency();
776 nonFirstObject = nullptr;
777 EXPECT_EQ(weakHashSet.computeSize(), objectsCount);
778 EXPECT_EQ(s_baseWeakReferences, objectsCount);
779 weakHashSet.checkConsistency();
780 objects.clear();
781 EXPECT_EQ(s_baseWeakReferences, objectsCount);
782 EXPECT_EQ(weakHashSet.computeSize(), 0u);
783 EXPECT_EQ(s_baseWeakReferences, 0u);
784 }
785}
786
787} // namespace TestWebKitAPI
788