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