xref: /aosp_15_r20/external/webrtc/rtc_base/weak_ptr_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "rtc_base/weak_ptr.h"
12 
13 #include <memory>
14 #include <string>
15 
16 #include "rtc_base/event.h"
17 #include "rtc_base/task_queue_for_test.h"
18 #include "test/gtest.h"
19 
20 namespace rtc {
21 
22 namespace {
23 
24 struct Base {
25   std::string member;
26 };
27 struct Derived : public Base {};
28 
29 struct Target {};
30 
31 struct Arrow {
32   WeakPtr<Target> target;
33 };
34 
35 struct TargetWithFactory : public Target {
TargetWithFactoryrtc::__anon343dfe7f0111::TargetWithFactory36   TargetWithFactory() : factory(this) {}
37   WeakPtrFactory<Target> factory;
38 };
39 
40 }  // namespace
41 
TEST(WeakPtrFactoryTest,Basic)42 TEST(WeakPtrFactoryTest, Basic) {
43   int data;
44   WeakPtrFactory<int> factory(&data);
45   WeakPtr<int> ptr = factory.GetWeakPtr();
46   EXPECT_EQ(&data, ptr.get());
47 }
48 
TEST(WeakPtrFactoryTest,Comparison)49 TEST(WeakPtrFactoryTest, Comparison) {
50   int data;
51   WeakPtrFactory<int> factory(&data);
52   WeakPtr<int> ptr = factory.GetWeakPtr();
53   WeakPtr<int> ptr2 = ptr;
54   EXPECT_EQ(ptr.get(), ptr2.get());
55 }
56 
TEST(WeakPtrFactoryTest,Move)57 TEST(WeakPtrFactoryTest, Move) {
58   int data;
59   WeakPtrFactory<int> factory(&data);
60   WeakPtr<int> ptr = factory.GetWeakPtr();
61   WeakPtr<int> ptr2 = factory.GetWeakPtr();
62   WeakPtr<int> ptr3 = std::move(ptr2);
63   EXPECT_NE(ptr.get(), ptr2.get());
64   EXPECT_EQ(ptr.get(), ptr3.get());
65 }
66 
TEST(WeakPtrFactoryTest,OutOfScope)67 TEST(WeakPtrFactoryTest, OutOfScope) {
68   WeakPtr<int> ptr;
69   EXPECT_EQ(nullptr, ptr.get());
70   {
71     int data;
72     WeakPtrFactory<int> factory(&data);
73     ptr = factory.GetWeakPtr();
74     EXPECT_EQ(&data, ptr.get());
75   }
76   EXPECT_EQ(nullptr, ptr.get());
77 }
78 
TEST(WeakPtrFactoryTest,Multiple)79 TEST(WeakPtrFactoryTest, Multiple) {
80   WeakPtr<int> a, b;
81   {
82     int data;
83     WeakPtrFactory<int> factory(&data);
84     a = factory.GetWeakPtr();
85     b = factory.GetWeakPtr();
86     EXPECT_EQ(&data, a.get());
87     EXPECT_EQ(&data, b.get());
88   }
89   EXPECT_EQ(nullptr, a.get());
90   EXPECT_EQ(nullptr, b.get());
91 }
92 
TEST(WeakPtrFactoryTest,MultipleStaged)93 TEST(WeakPtrFactoryTest, MultipleStaged) {
94   WeakPtr<int> a;
95   {
96     int data;
97     WeakPtrFactory<int> factory(&data);
98     a = factory.GetWeakPtr();
99     { WeakPtr<int> b = factory.GetWeakPtr(); }
100     EXPECT_NE(nullptr, a.get());
101   }
102   EXPECT_EQ(nullptr, a.get());
103 }
104 
TEST(WeakPtrFactoryTest,Dereference)105 TEST(WeakPtrFactoryTest, Dereference) {
106   Base data;
107   data.member = "123456";
108   WeakPtrFactory<Base> factory(&data);
109   WeakPtr<Base> ptr = factory.GetWeakPtr();
110   EXPECT_EQ(&data, ptr.get());
111   EXPECT_EQ(data.member, (*ptr).member);
112   EXPECT_EQ(data.member, ptr->member);
113 }
114 
TEST(WeakPtrFactoryTest,UpCast)115 TEST(WeakPtrFactoryTest, UpCast) {
116   Derived data;
117   WeakPtrFactory<Derived> factory(&data);
118   WeakPtr<Base> ptr = factory.GetWeakPtr();
119   ptr = factory.GetWeakPtr();
120   EXPECT_EQ(ptr.get(), &data);
121 }
122 
TEST(WeakPtrTest,DefaultConstructor)123 TEST(WeakPtrTest, DefaultConstructor) {
124   WeakPtr<int> ptr;
125   EXPECT_EQ(nullptr, ptr.get());
126 }
127 
TEST(WeakPtrFactoryTest,BooleanTesting)128 TEST(WeakPtrFactoryTest, BooleanTesting) {
129   int data;
130   WeakPtrFactory<int> factory(&data);
131 
132   WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
133   EXPECT_TRUE(ptr_to_an_instance);
134   EXPECT_FALSE(!ptr_to_an_instance);
135 
136   if (ptr_to_an_instance) {
137   } else {
138     ADD_FAILURE() << "Pointer to an instance should result in true.";
139   }
140 
141   if (!ptr_to_an_instance) {  // check for operator!().
142     ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
143   }
144 
145   WeakPtr<int> null_ptr;
146   EXPECT_FALSE(null_ptr);
147   EXPECT_TRUE(!null_ptr);
148 
149   if (null_ptr) {
150     ADD_FAILURE() << "Null pointer should result in false.";
151   }
152 
153   if (!null_ptr) {  // check for operator!().
154   } else {
155     ADD_FAILURE() << "Null pointer should result in !x being true.";
156   }
157 }
158 
TEST(WeakPtrFactoryTest,ComparisonToNull)159 TEST(WeakPtrFactoryTest, ComparisonToNull) {
160   int data;
161   WeakPtrFactory<int> factory(&data);
162 
163   WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
164   EXPECT_NE(nullptr, ptr_to_an_instance);
165   EXPECT_NE(ptr_to_an_instance, nullptr);
166 
167   WeakPtr<int> null_ptr;
168   EXPECT_EQ(null_ptr, nullptr);
169   EXPECT_EQ(nullptr, null_ptr);
170 }
171 
TEST(WeakPtrTest,InvalidateWeakPtrs)172 TEST(WeakPtrTest, InvalidateWeakPtrs) {
173   int data;
174   WeakPtrFactory<int> factory(&data);
175   WeakPtr<int> ptr = factory.GetWeakPtr();
176   EXPECT_EQ(&data, ptr.get());
177   EXPECT_TRUE(factory.HasWeakPtrs());
178   factory.InvalidateWeakPtrs();
179   EXPECT_EQ(nullptr, ptr.get());
180   EXPECT_FALSE(factory.HasWeakPtrs());
181 
182   // Test that the factory can create new weak pointers after a
183   // InvalidateWeakPtrs call, and they remain valid until the next
184   // InvalidateWeakPtrs call.
185   WeakPtr<int> ptr2 = factory.GetWeakPtr();
186   EXPECT_EQ(&data, ptr2.get());
187   EXPECT_TRUE(factory.HasWeakPtrs());
188   factory.InvalidateWeakPtrs();
189   EXPECT_EQ(nullptr, ptr2.get());
190   EXPECT_FALSE(factory.HasWeakPtrs());
191 }
192 
TEST(WeakPtrTest,HasWeakPtrs)193 TEST(WeakPtrTest, HasWeakPtrs) {
194   int data;
195   WeakPtrFactory<int> factory(&data);
196   {
197     WeakPtr<int> ptr = factory.GetWeakPtr();
198     EXPECT_TRUE(factory.HasWeakPtrs());
199   }
200   EXPECT_FALSE(factory.HasWeakPtrs());
201 }
202 
203 template <class T>
NewObjectCreatedOnTaskQueue()204 std::unique_ptr<T> NewObjectCreatedOnTaskQueue() {
205   std::unique_ptr<T> obj;
206   webrtc::TaskQueueForTest queue("NewObjectCreatedOnTaskQueue");
207   queue.SendTask([&] { obj = std::make_unique<T>(); });
208   return obj;
209 }
210 
TEST(WeakPtrTest,ObjectAndWeakPtrOnDifferentThreads)211 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
212   // Test that it is OK to create an object with a WeakPtrFactory one thread,
213   // but use it on another.  This tests that we do not trip runtime checks that
214   // ensure that a WeakPtr is not used by multiple threads.
215   std::unique_ptr<TargetWithFactory> target(
216       NewObjectCreatedOnTaskQueue<TargetWithFactory>());
217   WeakPtr<Target> weak_ptr = target->factory.GetWeakPtr();
218   EXPECT_EQ(target.get(), weak_ptr.get());
219 }
220 
TEST(WeakPtrTest,WeakPtrInitiateAndUseOnDifferentThreads)221 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
222   // Test that it is OK to create a WeakPtr on one thread, but use it on
223   // another. This tests that we do not trip runtime checks that ensure that a
224   // WeakPtr is not used by multiple threads.
225   auto target = std::make_unique<TargetWithFactory>();
226   // Create weak ptr on main thread
227   WeakPtr<Target> weak_ptr = target->factory.GetWeakPtr();
228   webrtc::TaskQueueForTest queue("queue");
229   queue.SendTask([&] {
230     // Dereference and invalide weak_ptr on another thread.
231     EXPECT_EQ(weak_ptr.get(), target.get());
232     target.reset();
233   });
234 }
235 
236 }  // namespace rtc
237