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