• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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