1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "util/weak_ptr.h"
6
7 #include "gtest/gtest.h"
8
9 namespace openscreen {
10 namespace {
11
12 class SomeClass {
13 public:
14 virtual ~SomeClass() = default;
GetValue() const15 virtual int GetValue() const { return 42; }
16 };
17
18 struct SomeSubclass final : public SomeClass {
19 public:
20 ~SomeSubclass() final = default;
GetValueopenscreen::__anon9b33f1940111::SomeSubclass21 int GetValue() const override { return 999; }
22 };
23
TEST(WeakPtrTest,InteractsWithNullptr)24 TEST(WeakPtrTest, InteractsWithNullptr) {
25 WeakPtr<const int> default_constructed; // Invoke default constructor.
26 EXPECT_TRUE(default_constructed == nullptr);
27 EXPECT_TRUE(nullptr == default_constructed);
28 EXPECT_FALSE(default_constructed != nullptr);
29 EXPECT_FALSE(nullptr != default_constructed);
30
31 WeakPtr<const int> null_constructed = nullptr; // Invoke construct-from-null.
32 EXPECT_TRUE(null_constructed == nullptr);
33 EXPECT_TRUE(nullptr == null_constructed);
34 EXPECT_FALSE(null_constructed != nullptr);
35 EXPECT_FALSE(nullptr != null_constructed);
36
37 const int foo = 42;
38 WeakPtrFactory<const int> factory(&foo);
39 WeakPtr<const int> not_null = factory.GetWeakPtr();
40 EXPECT_TRUE(not_null != nullptr);
41 EXPECT_TRUE(nullptr != not_null);
42 EXPECT_FALSE(not_null == nullptr);
43 EXPECT_FALSE(nullptr == not_null);
44 }
45
TEST(WeakPtrTest,CopyConstructsAndAssigns)46 TEST(WeakPtrTest, CopyConstructsAndAssigns) {
47 SomeSubclass foo;
48 WeakPtrFactory<SomeSubclass> factory(&foo);
49
50 WeakPtr<SomeSubclass> weak_ptr = factory.GetWeakPtr();
51 EXPECT_TRUE(weak_ptr);
52 EXPECT_EQ(&foo, weak_ptr.get());
53
54 // Normal copy constructor.
55 WeakPtr<SomeSubclass> copied0 = weak_ptr;
56 EXPECT_EQ(&foo, weak_ptr.get()); // Did not mutate original.
57 EXPECT_TRUE(copied0);
58 EXPECT_EQ(&foo, copied0.get());
59
60 // Copy constructor, adding const qualifier.
61 WeakPtr<const SomeSubclass> copied1 = weak_ptr;
62 EXPECT_EQ(&foo, weak_ptr.get()); // Did not mutate original.
63 EXPECT_TRUE(copied1);
64 EXPECT_EQ(&foo, copied1.get());
65
66 // Normal copy assignment.
67 WeakPtr<SomeSubclass> assigned0;
68 EXPECT_FALSE(assigned0);
69 assigned0 = copied0;
70 EXPECT_EQ(&foo, copied0.get()); // Did not mutate original.
71 EXPECT_TRUE(assigned0);
72 EXPECT_EQ(&foo, assigned0.get());
73
74 // Copy assignment, adding const qualifier.
75 WeakPtr<const SomeSubclass> assigned1;
76 EXPECT_FALSE(assigned1);
77 assigned1 = copied0;
78 EXPECT_EQ(&foo, copied0.get()); // Did not mutate original.
79 EXPECT_TRUE(assigned1);
80 EXPECT_EQ(&foo, assigned1.get());
81
82 // Upcast copy constructor.
83 WeakPtr<SomeClass> copied2 = weak_ptr;
84 EXPECT_EQ(&foo, weak_ptr.get()); // Did not mutate original.
85 EXPECT_TRUE(copied2);
86 EXPECT_EQ(&foo, copied2.get());
87 EXPECT_EQ(999, (*copied2).GetValue());
88 EXPECT_EQ(999, copied2->GetValue());
89
90 // Upcast copy assignment.
91 WeakPtr<SomeClass> assigned2;
92 EXPECT_FALSE(assigned2);
93 assigned2 = weak_ptr;
94 EXPECT_EQ(&foo, weak_ptr.get()); // Did not mutate original.
95 EXPECT_TRUE(assigned2);
96 EXPECT_EQ(&foo, assigned2.get());
97 EXPECT_EQ(999, (*assigned2).GetValue());
98 EXPECT_EQ(999, assigned2->GetValue());
99 }
100
TEST(WeakPtrTest,MoveConstructsAndAssigns)101 TEST(WeakPtrTest, MoveConstructsAndAssigns) {
102 SomeSubclass foo;
103 WeakPtrFactory<SomeSubclass> factory(&foo);
104
105 // Normal move constructor.
106 WeakPtr<SomeSubclass> weak_ptr = factory.GetWeakPtr();
107 WeakPtr<SomeSubclass> moved0 = std::move(weak_ptr);
108 EXPECT_FALSE(weak_ptr); // Original becomes null.
109 EXPECT_TRUE(moved0);
110 EXPECT_EQ(&foo, moved0.get());
111
112 // Move constructor, adding const qualifier.
113 weak_ptr = factory.GetWeakPtr();
114 WeakPtr<const SomeSubclass> moved1 = std::move(weak_ptr);
115 EXPECT_FALSE(weak_ptr); // Original becomes null.
116 EXPECT_TRUE(moved1);
117 EXPECT_EQ(&foo, moved1.get());
118
119 // Normal move assignment.
120 weak_ptr = factory.GetWeakPtr();
121 WeakPtr<SomeSubclass> assigned0;
122 EXPECT_FALSE(assigned0);
123 assigned0 = std::move(weak_ptr);
124 EXPECT_FALSE(weak_ptr); // Original becomes null.
125 EXPECT_TRUE(assigned0);
126 EXPECT_EQ(&foo, assigned0.get());
127
128 // Move assignment, adding const qualifier.
129 weak_ptr = factory.GetWeakPtr();
130 WeakPtr<const SomeSubclass> assigned1;
131 EXPECT_FALSE(assigned1);
132 assigned1 = std::move(weak_ptr);
133 EXPECT_FALSE(weak_ptr); // Original becomes null.
134 EXPECT_TRUE(assigned1);
135 EXPECT_EQ(&foo, assigned1.get());
136
137 // Upcast move constructor.
138 weak_ptr = factory.GetWeakPtr();
139 WeakPtr<SomeClass> moved2 = std::move(weak_ptr);
140 EXPECT_FALSE(weak_ptr); // Original becomes null.
141 EXPECT_TRUE(moved2);
142 EXPECT_EQ(&foo, moved2.get());
143 EXPECT_EQ(999, (*moved2).GetValue()); // Result from subclass's GetValue().
144 EXPECT_EQ(999, moved2->GetValue()); // Result from subclass's GetValue().
145
146 // Upcast move assignment.
147 weak_ptr = factory.GetWeakPtr();
148 WeakPtr<SomeClass> assigned2;
149 EXPECT_FALSE(assigned2);
150 assigned2 = std::move(weak_ptr);
151 EXPECT_FALSE(weak_ptr); // Original becomes null.
152 EXPECT_TRUE(assigned2);
153 EXPECT_EQ(&foo, assigned2.get());
154 EXPECT_EQ(999,
155 (*assigned2).GetValue()); // Result from subclass's GetValue().
156 EXPECT_EQ(999, assigned2->GetValue()); // Result from subclass's GetValue().
157 }
158
TEST(WeakPtrTest,InvalidatesWeakPtrs)159 TEST(WeakPtrTest, InvalidatesWeakPtrs) {
160 const int foo = 1337;
161 WeakPtrFactory<const int> factory(&foo);
162
163 // Thrice: Create weak pointers and invalidate them. This is done more than
164 // once to confirm the factory can create valid WeakPtrs again after each
165 // InvalidateWeakPtrs() call.
166 for (int i = 0; i < 3; ++i) {
167 // Create three WeakPtrs, two from the factory, one as a copy of another
168 // WeakPtr.
169 WeakPtr<const int> ptr0 = factory.GetWeakPtr();
170 WeakPtr<const int> ptr1 = factory.GetWeakPtr();
171 WeakPtr<const int> ptr2 = ptr1;
172 EXPECT_EQ(&foo, ptr0.get());
173 EXPECT_EQ(&foo, ptr1.get());
174 EXPECT_EQ(&foo, ptr2.get());
175
176 // Invalidate all outstanding WeakPtrs from the factory, and confirm all
177 // outstanding WeakPtrs become null.
178 factory.InvalidateWeakPtrs();
179 EXPECT_FALSE(ptr0);
180 EXPECT_FALSE(ptr1);
181 EXPECT_FALSE(ptr2);
182 }
183 }
184
185 } // namespace
186 } // namespace openscreen
187