Bug 1879774 [wpt PR 44524] - WebKit export: Implement field-sizing support for input...
[gecko.git] / mfbt / tests / TestWeakPtr.cpp
blob0599975a9c33b601437afd9cfa2beb3529c7b31b
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/WeakPtr.h"
9 using mozilla::SupportsWeakPtr;
10 using mozilla::WeakPtr;
12 static char IamB[] = "B";
13 static char IamC[] = "C";
14 static char IamD[] = "D";
16 class B : public SupportsWeakPtr {
17 public:
18 char const* whoAmI() const { return IamB; }
21 // To have a class C support weak pointers, inherit from SupportsWeakPtr.
22 class C : public SupportsWeakPtr {
23 public:
24 int mNum;
26 C() : mNum(0) {}
28 ~C() {
29 // Setting mNum in the destructor allows us to test against use-after-free
30 // below
31 mNum = 0xDEAD;
34 char const* whoAmI() const { return IamC; }
36 void act() {}
38 bool isConst() { return false; }
40 bool isConst() const { return true; }
43 // Derived from a class that supports weakptr, but doesn't implement itself
44 // To check upcast works as expected
45 class D : public B {
46 public:
47 char const* whoAmI() const { return IamD; }
50 bool isConst(C*) { return false; }
52 bool isConst(const C*) { return true; }
54 int main() {
55 C* c1 = new C;
56 MOZ_RELEASE_ASSERT(c1->mNum == 0);
58 // Get weak pointers to c1. The first time,
59 // a reference-counted WeakReference object is created that
60 // can live beyond the lifetime of 'c1'. The WeakReference
61 // object will be notified of 'c1's destruction.
62 WeakPtr<C> w1 = c1;
63 // Test a weak pointer for validity before using it.
64 MOZ_RELEASE_ASSERT(w1);
65 MOZ_RELEASE_ASSERT(w1 == c1);
66 w1->mNum = 1;
67 w1->act();
69 // Test taking another WeakPtr<C> to c1
70 WeakPtr<C> w2 = c1;
71 MOZ_RELEASE_ASSERT(w2);
72 MOZ_RELEASE_ASSERT(w2 == c1);
73 MOZ_RELEASE_ASSERT(w2 == w1);
74 MOZ_RELEASE_ASSERT(w2->mNum == 1);
76 // Test a WeakPtr<const C>
77 WeakPtr<const C> w3const = c1;
78 MOZ_RELEASE_ASSERT(w3const);
79 MOZ_RELEASE_ASSERT(w3const == c1);
80 MOZ_RELEASE_ASSERT(w3const == w1);
81 MOZ_RELEASE_ASSERT(w3const == w2);
82 MOZ_RELEASE_ASSERT(w3const->mNum == 1);
84 // Test const-correctness of operator-> and operator T*
85 MOZ_RELEASE_ASSERT(!w1->isConst());
86 MOZ_RELEASE_ASSERT(w3const->isConst());
87 MOZ_RELEASE_ASSERT(!isConst(w1));
88 MOZ_RELEASE_ASSERT(isConst(w3const));
90 // Test that when a WeakPtr is destroyed, it does not destroy the object that
91 // it points to, and it does not affect other WeakPtrs pointing to the same
92 // object (e.g. it does not destroy the WeakReference object).
94 WeakPtr<C> w4local = c1;
95 MOZ_RELEASE_ASSERT(w4local == c1);
97 // Now w4local has gone out of scope. If that had destroyed c1, then the
98 // following would fail for sure (see C::~C()).
99 MOZ_RELEASE_ASSERT(c1->mNum == 1);
100 // Check that w4local going out of scope hasn't affected other WeakPtr's
101 // pointing to c1
102 MOZ_RELEASE_ASSERT(w1 == c1);
103 MOZ_RELEASE_ASSERT(w2 == c1);
105 // Now construct another C object and test changing what object a WeakPtr
106 // points to
107 C* c2 = new C;
108 c2->mNum = 2;
109 MOZ_RELEASE_ASSERT(w2->mNum == 1); // w2 was pointing to c1
110 w2 = c2;
111 MOZ_RELEASE_ASSERT(w2);
112 MOZ_RELEASE_ASSERT(w2 == c2);
113 MOZ_RELEASE_ASSERT(w2 != c1);
114 MOZ_RELEASE_ASSERT(w2 != w1);
115 MOZ_RELEASE_ASSERT(w2->mNum == 2);
117 // Destroying the underlying object clears weak pointers to it.
118 // It should not affect pointers that are not currently pointing to it.
119 delete c1;
120 MOZ_RELEASE_ASSERT(!w1, "Deleting an object should clear WeakPtr's to it.");
121 MOZ_RELEASE_ASSERT(!w3const,
122 "Deleting an object should clear WeakPtr's to it.");
123 MOZ_RELEASE_ASSERT(w2,
124 "Deleting an object should not clear WeakPtr that are not "
125 "pointing to it.");
127 delete c2;
128 MOZ_RELEASE_ASSERT(!w2, "Deleting an object should clear WeakPtr's to it.");
130 // Check that we correctly upcast to the base class supporting weakptr
131 D* d = new D;
132 WeakPtr<B> db = d;
134 // You should be able to use WeakPtr<D> even if it's a base class which
135 // implements SupportsWeakPtr.
136 WeakPtr<D> weakd = d;
138 MOZ_RELEASE_ASSERT(db->whoAmI() == IamB);
139 MOZ_RELEASE_ASSERT(weakd.get() == db.get());
141 delete d;
143 MOZ_RELEASE_ASSERT(!db);
144 MOZ_RELEASE_ASSERT(!weakd);