xref: /aosp_15_r20/external/cronet/base/memory/safe_ref_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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