1 // Copyright 2021 The Chromium Authors
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 "base/memory/safe_ref.h"
6
7 #include <optional>
8 #include <utility>
9
10 #include "base/functional/bind.h"
11 #include "base/functional/callback.h"
12 #include "base/memory/raw_ptr_exclusion.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/test/gtest_util.h"
15 #include "base/test/memory/dangling_ptr_instrumentation.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace base {
20 namespace {
21
22 struct ReallyBaseClass {};
23 struct BaseClass : ReallyBaseClass {
24 virtual ~BaseClass() = default;
VirtualMethodbase::__anon02f7b4610111::BaseClass25 void VirtualMethod() {}
26 };
27 struct OtherBaseClass {
28 virtual ~OtherBaseClass() = default;
VirtualMethodbase::__anon02f7b4610111::OtherBaseClass29 virtual void VirtualMethod() {}
30 };
31
32 struct WithWeak final : BaseClass, OtherBaseClass {
~WithWeakbase::__anon02f7b4610111::WithWeak33 ~WithWeak() final { self = nullptr; }
34
Methodbase::__anon02f7b4610111::WithWeak35 void Method() {}
36
37 int i = 1;
38 raw_ptr<WithWeak> self{this};
39 base::WeakPtrFactory<WithWeak> factory{this};
40 };
41
TEST(SafeRefTest,FromWeakPtrFactory)42 TEST(SafeRefTest, FromWeakPtrFactory) {
43 WithWeak with;
44 SafeRef<WithWeak> safe(with.factory.GetSafeRef());
45 }
46
TEST(SafeRefTest,Operators)47 TEST(SafeRefTest, Operators) {
48 WithWeak with;
49 SafeRef<WithWeak> safe(with.factory.GetSafeRef());
50 // operator->.
51 EXPECT_EQ(safe->self->i, 1); // Will crash if not live.
52 // operator*.
53 EXPECT_EQ((*safe).self->i, 1); // Will crash if not live.
54 }
55
TEST(SafeRefTest,ThreeWayComparison)56 TEST(SafeRefTest, ThreeWayComparison) {
57 WithWeak with1;
58 SafeRef<WithWeak> safe1(with1.factory.GetSafeRef());
59 WithWeak with2;
60 SafeRef<WithWeak> safe2(with2.factory.GetSafeRef());
61 EXPECT_EQ(&with1 <=> &with2, safe1 <=> safe2);
62 }
63
TEST(SafeRefTest,CanCopyAndMove)64 TEST(SafeRefTest, CanCopyAndMove) {
65 WithWeak with;
66 SafeRef<WithWeak> safe(with.factory.GetSafeRef());
67 EXPECT_EQ(safe->self->i, 1); // Will crash if not live.
68 SafeRef<WithWeak> safe2 = safe; // Copy.
69 EXPECT_EQ(safe2->self->i, 1); // Will crash if not live.
70 EXPECT_EQ(safe->self->i, 1); // Will crash if not live.
71 SafeRef<WithWeak> safe3 = std::move(safe); // Move.
72 EXPECT_EQ(safe3->self->i, 1); // Will crash if not live.
73 }
74
TEST(SafeRefTest,AssignCopyAndMove)75 TEST(SafeRefTest, AssignCopyAndMove) {
76 WithWeak with;
77 WithWeak with2;
78 WithWeak with3;
79
80 // Ensure `with`s outlive `safe`s
81 SafeRef<WithWeak> safe(with.factory.GetSafeRef());
82 SafeRef<WithWeak> safe2(with2.factory.GetSafeRef());
83 EXPECT_NE(safe->self, &with2);
84 safe = safe2;
85 EXPECT_EQ(safe->self, &with2);
86
87 SafeRef<WithWeak> safe3(with3.factory.GetSafeRef());
88 EXPECT_NE(safe->self, &with3);
89 safe = std::move(safe3);
90 EXPECT_EQ(safe->self, &with3);
91 }
92
TEST(SafeRefDeathTest,ArrowOperatorCrashIfBadPointer)93 TEST(SafeRefDeathTest, ArrowOperatorCrashIfBadPointer) {
94 std::optional<WithWeak> with(std::in_place);
95 SafeRef<WithWeak> safe(with->factory.GetSafeRef());
96 with.reset();
97 EXPECT_CHECK_DEATH(safe.operator->()); // Will crash since not live.
98 }
99
TEST(SafeRefDeathTest,StarOperatorCrashIfBadPointer)100 TEST(SafeRefDeathTest, StarOperatorCrashIfBadPointer) {
101 std::optional<WithWeak> with(std::in_place);
102 SafeRef<WithWeak> safe(with->factory.GetSafeRef());
103 with.reset();
104 EXPECT_CHECK_DEATH(safe.operator*()); // Will crash since not live.
105 }
106
TEST(SafeRefTest,ConversionToBaseClassFromCopyConstruct)107 TEST(SafeRefTest, ConversionToBaseClassFromCopyConstruct) {
108 WithWeak with;
109 SafeRef<WithWeak> safe(with.factory.GetSafeRef());
110 SafeRef<OtherBaseClass> base_safe = safe;
111 EXPECT_EQ(static_cast<WithWeak*>(&*base_safe), &with);
112 }
113
TEST(SafeRefTest,ConversionToBaseClassFromMoveConstruct)114 TEST(SafeRefTest, ConversionToBaseClassFromMoveConstruct) {
115 WithWeak with;
116 SafeRef<WithWeak> safe(with.factory.GetSafeRef());
117 SafeRef<OtherBaseClass> base_safe = std::move(safe);
118 EXPECT_EQ(static_cast<WithWeak*>(&*base_safe), &with);
119 }
120
TEST(SafeRefTest,ConversionToBaseClassFromCopyAssign)121 TEST(SafeRefTest, ConversionToBaseClassFromCopyAssign) {
122 WithWeak with;
123 SafeRef<WithWeak> safe(with.factory.GetSafeRef());
124 SafeRef<OtherBaseClass> base_safe(with.factory.GetSafeRef());
125 base_safe = safe;
126 EXPECT_EQ(static_cast<WithWeak*>(&*base_safe), &with);
127 }
128
TEST(SafeRefTest,ConversionToBaseClassFromMoveAssign)129 TEST(SafeRefTest, ConversionToBaseClassFromMoveAssign) {
130 WithWeak with;
131 SafeRef<WithWeak> safe(with.factory.GetSafeRef());
132 SafeRef<OtherBaseClass> base_safe(with.factory.GetSafeRef());
133 base_safe = std::move(safe);
134 EXPECT_EQ(static_cast<WithWeak*>(&*base_safe), &with);
135 }
136
TEST(SafeRefTest,CanDerefConst)137 TEST(SafeRefTest, CanDerefConst) {
138 WithWeak with;
139 const SafeRef<WithWeak> safe(with.factory.GetSafeRef());
140 EXPECT_EQ(safe->self->i, 1);
141 EXPECT_EQ((*safe).self->i, 1);
142 }
143
TEST(SafeRefTest,InvalidAfterMoveConstruction)144 TEST(SafeRefTest, InvalidAfterMoveConstruction) {
145 WithWeak with;
146 SafeRef<WithWeak> safe(with.factory.GetSafeRef());
147 SafeRef<WithWeak> safe2 = std::move(safe);
148 // Will crash if not live.
149 EXPECT_EQ(safe2->self->i, 1);
150 // `safe` was previously moved-from, so using it in any way should crash now.
151 { EXPECT_CHECK_DEATH(SafeRef<WithWeak> safe3(safe)); }
152 {
153 SafeRef<WithWeak> safe3(with.factory.GetSafeRef());
154 EXPECT_CHECK_DEATH(safe3 = safe);
155 }
156 { EXPECT_CHECK_DEATH(SafeRef<WithWeak> safe3(std::move(safe))); }
157 {
158 SafeRef<WithWeak> safe3(with.factory.GetSafeRef());
159 EXPECT_CHECK_DEATH(safe3 = std::move(safe));
160 }
161 { EXPECT_CHECK_DEATH(SafeRef<BaseClass> safe3(safe)); }
162 {
163 SafeRef<BaseClass> safe3(with.factory.GetSafeRef());
164 EXPECT_CHECK_DEATH(safe3 = safe);
165 }
166 { EXPECT_CHECK_DEATH(SafeRef<BaseClass> safe3(std::move(safe))); }
167 {
168 SafeRef<BaseClass> safe3(with.factory.GetSafeRef());
169 EXPECT_CHECK_DEATH(safe3 = std::move(safe));
170 }
171 EXPECT_CHECK_DEATH((void)safe->self->i);
172 }
173
TEST(SafeRefTest,InvalidAfterMoveAssignment)174 TEST(SafeRefTest, InvalidAfterMoveAssignment) {
175 WithWeak with;
176 SafeRef<WithWeak> safe(with.factory.GetSafeRef());
177 SafeRef<WithWeak> safe2(with.factory.GetSafeRef());
178 safe2 = std::move(safe);
179 // Will crash if not live.
180 EXPECT_EQ(safe2->self->i, 1);
181 // `safe` was previously moved-from, so using it in any way should crash now.
182 { EXPECT_CHECK_DEATH(SafeRef<WithWeak> safe3(safe)); }
183 {
184 SafeRef<WithWeak> safe3(with.factory.GetSafeRef());
185 EXPECT_CHECK_DEATH(safe3 = safe);
186 }
187 { EXPECT_CHECK_DEATH(SafeRef<WithWeak> safe3(std::move(safe))); }
188 {
189 SafeRef<WithWeak> safe3(with.factory.GetSafeRef());
190 EXPECT_CHECK_DEATH(safe3 = std::move(safe));
191 }
192 { EXPECT_CHECK_DEATH(SafeRef<BaseClass> safe3(safe)); }
193 {
194 SafeRef<BaseClass> safe3(with.factory.GetSafeRef());
195 EXPECT_CHECK_DEATH(safe3 = safe);
196 }
197 { EXPECT_CHECK_DEATH(SafeRef<BaseClass> safe3(std::move(safe))); }
198 {
199 SafeRef<BaseClass> safe3(with.factory.GetSafeRef());
200 EXPECT_CHECK_DEATH(safe3 = std::move(safe));
201 }
202 EXPECT_CHECK_DEATH((void)safe->self->i);
203 }
204
TEST(SafeRefTest,InvalidAfterMoveConversionConstruction)205 TEST(SafeRefTest, InvalidAfterMoveConversionConstruction) {
206 WithWeak with;
207 SafeRef<BaseClass> safe(with.factory.GetSafeRef());
208 SafeRef<BaseClass> safe2 = std::move(safe);
209 // Will crash if not live.
210 EXPECT_EQ(static_cast<WithWeak*>(&*safe2)->self->i, 1);
211 // `safe` was previously moved-from, so using it in any way should crash now.
212 { EXPECT_CHECK_DEATH(SafeRef<BaseClass> safe3(safe)); }
213 {
214 SafeRef<BaseClass> safe3(with.factory.GetSafeRef());
215 EXPECT_CHECK_DEATH(safe3 = safe);
216 }
217 { EXPECT_CHECK_DEATH(SafeRef<BaseClass> safe3(std::move(safe))); }
218 {
219 SafeRef<BaseClass> safe3(with.factory.GetSafeRef());
220 EXPECT_CHECK_DEATH(safe3 = std::move(safe));
221 }
222 { EXPECT_CHECK_DEATH(SafeRef<ReallyBaseClass> safe3(safe)); }
223 {
224 SafeRef<ReallyBaseClass> safe3(with.factory.GetSafeRef());
225 EXPECT_CHECK_DEATH(safe3 = safe);
226 }
227 { EXPECT_CHECK_DEATH(SafeRef<ReallyBaseClass> safe3(std::move(safe))); }
228 {
229 SafeRef<ReallyBaseClass> safe3(with.factory.GetSafeRef());
230 EXPECT_CHECK_DEATH(safe3 = std::move(safe));
231 }
232 EXPECT_CHECK_DEATH((void)static_cast<WithWeak*>(&*safe)->self->i);
233 }
234
TEST(SafeRefTest,InvalidAfterMoveConversionAssignment)235 TEST(SafeRefTest, InvalidAfterMoveConversionAssignment) {
236 WithWeak with;
237 SafeRef<BaseClass> safe(with.factory.GetSafeRef());
238 SafeRef<BaseClass> safe2(with.factory.GetSafeRef());
239 safe2 = std::move(safe);
240 // // Will crash if not live.
241 EXPECT_EQ(static_cast<WithWeak*>(&*safe2)->self->i, 1);
242 // `safe` was previously moved-from, so using it in any way should crash now.
243 { EXPECT_CHECK_DEATH(SafeRef<BaseClass> safe3(safe)); }
244 {
245 SafeRef<BaseClass> safe3(with.factory.GetSafeRef());
246 EXPECT_CHECK_DEATH(safe3 = safe);
247 }
248 { EXPECT_CHECK_DEATH(SafeRef<BaseClass> safe3(std::move(safe))); }
249 {
250 SafeRef<BaseClass> safe3(with.factory.GetSafeRef());
251 EXPECT_CHECK_DEATH(safe3 = std::move(safe));
252 }
253 { EXPECT_CHECK_DEATH(SafeRef<ReallyBaseClass> safe3(safe)); }
254 {
255 SafeRef<ReallyBaseClass> safe3(with.factory.GetSafeRef());
256 EXPECT_CHECK_DEATH(safe3 = safe);
257 }
258 { EXPECT_CHECK_DEATH(SafeRef<ReallyBaseClass> safe3(std::move(safe))); }
259 {
260 SafeRef<ReallyBaseClass> safe3(with.factory.GetSafeRef());
261 EXPECT_CHECK_DEATH(safe3 = std::move(safe));
262 }
263 EXPECT_CHECK_DEATH((void)static_cast<WithWeak*>(&*safe)->self->i);
264 }
265
TEST(SafeRefTest,Bind)266 TEST(SafeRefTest, Bind) {
267 WithWeak with;
268 BindOnce(&WithWeak::Method, with.factory.GetSafeRef()).Run();
269 }
270
TEST(SafeRefTest,DanglingPointerDetector)271 TEST(SafeRefTest, DanglingPointerDetector) {
272 auto instrumentation = test::DanglingPtrInstrumentation::Create();
273 if (!instrumentation.has_value()) {
274 GTEST_SKIP() << instrumentation.error();
275 }
276 {
277 auto with = std::make_unique<WithWeak>();
278 SafeRef<WithWeak> safe(with->factory.GetSafeRef());
279 EXPECT_EQ(instrumentation->dangling_ptr_detected(), 0u);
280 EXPECT_EQ(instrumentation->dangling_ptr_released(), 0u);
281
282 with.reset();
283 EXPECT_EQ(instrumentation->dangling_ptr_detected(), 1u);
284 EXPECT_EQ(instrumentation->dangling_ptr_released(), 0u);
285 }
286 EXPECT_EQ(instrumentation->dangling_ptr_detected(), 1u);
287 EXPECT_EQ(instrumentation->dangling_ptr_released(), 1u);
288 }
289
TEST(SafeRefTest,DanglingUntriaged)290 TEST(SafeRefTest, DanglingUntriaged) {
291 auto instrumentation = test::DanglingPtrInstrumentation::Create();
292 if (!instrumentation.has_value()) {
293 GTEST_SKIP() << instrumentation.error();
294 }
295 {
296 auto with = std::make_unique<WithWeak>();
297 SafeRef<WithWeak, SafeRefDanglingUntriaged> safe(
298 with->factory.GetSafeRef());
299 EXPECT_EQ(instrumentation->dangling_ptr_detected(), 0u);
300 EXPECT_EQ(instrumentation->dangling_ptr_released(), 0u);
301
302 with.reset();
303 EXPECT_EQ(instrumentation->dangling_ptr_detected(), 0u);
304 EXPECT_EQ(instrumentation->dangling_ptr_released(), 0u);
305 }
306 EXPECT_EQ(instrumentation->dangling_ptr_detected(), 0u);
307 EXPECT_EQ(instrumentation->dangling_ptr_released(), 0u);
308 }
309
310 } // namespace
311 } // namespace base
312