blob: 3906fe741e398bd37fd3d56e5cd4c00164ec7b66 [file] [log] [blame]
perkj8ff860a2016-10-03 00:30:04 -07001/*
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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "rtc_base/weak_ptr.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <memory>
perkj8ff860a2016-10-03 00:30:04 -070014#include <string>
15
Yves Gerey3e707812018-11-28 16:47:49 +010016#include "absl/memory/memory.h"
Tommi897e1362017-12-01 18:56:43 +010017#include "rtc_base/event.h"
Danil Chapovalov07122bc2019-03-26 14:37:01 +010018#include "rtc_base/task_queue_for_test.h"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "test/gtest.h"
perkj8ff860a2016-10-03 00:30:04 -070020
21namespace rtc {
22
23namespace {
24
25struct Base {
26 std::string member;
27};
28struct Derived : public Base {};
29
30struct Target {};
31
32struct Arrow {
33 WeakPtr<Target> target;
34};
35
36struct TargetWithFactory : public Target {
37 TargetWithFactory() : factory(this) {}
38 WeakPtrFactory<Target> factory;
39};
40
41} // namespace
42
43TEST(WeakPtrFactoryTest, Basic) {
44 int data;
45 WeakPtrFactory<int> factory(&data);
46 WeakPtr<int> ptr = factory.GetWeakPtr();
47 EXPECT_EQ(&data, ptr.get());
48}
49
50TEST(WeakPtrFactoryTest, Comparison) {
51 int data;
52 WeakPtrFactory<int> factory(&data);
53 WeakPtr<int> ptr = factory.GetWeakPtr();
54 WeakPtr<int> ptr2 = ptr;
55 EXPECT_EQ(ptr.get(), ptr2.get());
56}
57
58TEST(WeakPtrFactoryTest, Move) {
59 int data;
60 WeakPtrFactory<int> factory(&data);
61 WeakPtr<int> ptr = factory.GetWeakPtr();
62 WeakPtr<int> ptr2 = factory.GetWeakPtr();
63 WeakPtr<int> ptr3 = std::move(ptr2);
64 EXPECT_NE(ptr.get(), ptr2.get());
65 EXPECT_EQ(ptr.get(), ptr3.get());
66}
67
68TEST(WeakPtrFactoryTest, OutOfScope) {
69 WeakPtr<int> ptr;
70 EXPECT_EQ(nullptr, ptr.get());
71 {
72 int data;
73 WeakPtrFactory<int> factory(&data);
74 ptr = factory.GetWeakPtr();
75 EXPECT_EQ(&data, ptr.get());
76 }
77 EXPECT_EQ(nullptr, ptr.get());
78}
79
80TEST(WeakPtrFactoryTest, Multiple) {
81 WeakPtr<int> a, b;
82 {
83 int data;
84 WeakPtrFactory<int> factory(&data);
85 a = factory.GetWeakPtr();
86 b = factory.GetWeakPtr();
87 EXPECT_EQ(&data, a.get());
88 EXPECT_EQ(&data, b.get());
89 }
90 EXPECT_EQ(nullptr, a.get());
91 EXPECT_EQ(nullptr, b.get());
92}
93
94TEST(WeakPtrFactoryTest, MultipleStaged) {
95 WeakPtr<int> a;
96 {
97 int data;
98 WeakPtrFactory<int> factory(&data);
99 a = factory.GetWeakPtr();
100 { WeakPtr<int> b = factory.GetWeakPtr(); }
101 EXPECT_NE(nullptr, a.get());
102 }
103 EXPECT_EQ(nullptr, a.get());
104}
105
106TEST(WeakPtrFactoryTest, Dereference) {
107 Base data;
108 data.member = "123456";
109 WeakPtrFactory<Base> factory(&data);
110 WeakPtr<Base> ptr = factory.GetWeakPtr();
111 EXPECT_EQ(&data, ptr.get());
112 EXPECT_EQ(data.member, (*ptr).member);
113 EXPECT_EQ(data.member, ptr->member);
114}
115
116TEST(WeakPtrFactoryTest, UpCast) {
117 Derived data;
118 WeakPtrFactory<Derived> factory(&data);
119 WeakPtr<Base> ptr = factory.GetWeakPtr();
120 ptr = factory.GetWeakPtr();
121 EXPECT_EQ(ptr.get(), &data);
122}
123
124TEST(WeakPtrTest, DefaultConstructor) {
125 WeakPtr<int> ptr;
126 EXPECT_EQ(nullptr, ptr.get());
127}
128
129TEST(WeakPtrFactoryTest, BooleanTesting) {
130 int data;
131 WeakPtrFactory<int> factory(&data);
132
133 WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
134 EXPECT_TRUE(ptr_to_an_instance);
135 EXPECT_FALSE(!ptr_to_an_instance);
136
137 if (ptr_to_an_instance) {
138 } else {
139 ADD_FAILURE() << "Pointer to an instance should result in true.";
140 }
141
142 if (!ptr_to_an_instance) { // check for operator!().
143 ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
144 }
145
146 WeakPtr<int> null_ptr;
147 EXPECT_FALSE(null_ptr);
148 EXPECT_TRUE(!null_ptr);
149
150 if (null_ptr) {
151 ADD_FAILURE() << "Null pointer should result in false.";
152 }
153
154 if (!null_ptr) { // check for operator!().
155 } else {
156 ADD_FAILURE() << "Null pointer should result in !x being true.";
157 }
158}
159
160TEST(WeakPtrFactoryTest, ComparisonToNull) {
161 int data;
162 WeakPtrFactory<int> factory(&data);
163
164 WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
165 EXPECT_NE(nullptr, ptr_to_an_instance);
166 EXPECT_NE(ptr_to_an_instance, nullptr);
167
168 WeakPtr<int> null_ptr;
169 EXPECT_EQ(null_ptr, nullptr);
170 EXPECT_EQ(nullptr, null_ptr);
171}
172
173TEST(WeakPtrTest, InvalidateWeakPtrs) {
174 int data;
175 WeakPtrFactory<int> factory(&data);
176 WeakPtr<int> ptr = factory.GetWeakPtr();
177 EXPECT_EQ(&data, ptr.get());
178 EXPECT_TRUE(factory.HasWeakPtrs());
179 factory.InvalidateWeakPtrs();
180 EXPECT_EQ(nullptr, ptr.get());
181 EXPECT_FALSE(factory.HasWeakPtrs());
182
183 // Test that the factory can create new weak pointers after a
184 // InvalidateWeakPtrs call, and they remain valid until the next
185 // InvalidateWeakPtrs call.
186 WeakPtr<int> ptr2 = factory.GetWeakPtr();
187 EXPECT_EQ(&data, ptr2.get());
188 EXPECT_TRUE(factory.HasWeakPtrs());
189 factory.InvalidateWeakPtrs();
190 EXPECT_EQ(nullptr, ptr2.get());
191 EXPECT_FALSE(factory.HasWeakPtrs());
192}
193
194TEST(WeakPtrTest, HasWeakPtrs) {
195 int data;
196 WeakPtrFactory<int> factory(&data);
197 {
198 WeakPtr<int> ptr = factory.GetWeakPtr();
199 EXPECT_TRUE(factory.HasWeakPtrs());
200 }
201 EXPECT_FALSE(factory.HasWeakPtrs());
202}
203
204template <class T>
205std::unique_ptr<T> NewObjectCreatedOnTaskQueue() {
206 std::unique_ptr<T> obj;
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100207 webrtc::TaskQueueForTest queue("NewObjectCreatedOnTaskQueue");
208 queue.SendTask([&] { obj = absl::make_unique<T>(); });
perkj8ff860a2016-10-03 00:30:04 -0700209 return obj;
210}
211
212TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
213 // Test that it is OK to create an object with a WeakPtrFactory one thread,
214 // but use it on another. This tests that we do not trip runtime checks that
215 // ensure that a WeakPtr is not used by multiple threads.
216 std::unique_ptr<TargetWithFactory> target(
217 NewObjectCreatedOnTaskQueue<TargetWithFactory>());
218 WeakPtr<Target> weak_ptr = target->factory.GetWeakPtr();
219 EXPECT_EQ(target.get(), weak_ptr.get());
220}
221
222TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
Danil Chapovalov66cebbd2017-11-09 18:44:31 +0100223 // Test that it is OK to create a WeakPtr on one thread, but use it on
224 // another. This tests that we do not trip runtime checks that ensure that a
225 // WeakPtr is not used by multiple threads.
Karl Wiberg918f50c2018-07-05 11:40:33 +0200226 auto target = absl::make_unique<TargetWithFactory>();
Danil Chapovalov66cebbd2017-11-09 18:44:31 +0100227 // Create weak ptr on main thread
228 WeakPtr<Target> weak_ptr = target->factory.GetWeakPtr();
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100229 webrtc::TaskQueueForTest queue("queue");
230 queue.SendTask([&] {
Danil Chapovalov66cebbd2017-11-09 18:44:31 +0100231 // Dereference and invalide weak_ptr on another thread.
232 EXPECT_EQ(weak_ptr.get(), target.get());
233 target.reset();
Danil Chapovalov66cebbd2017-11-09 18:44:31 +0100234 });
perkj8ff860a2016-10-03 00:30:04 -0700235}
236
237} // namespace rtc