blob: 9e22312c28162ffd02acadcb007a337ab0715031 [file] [log] [blame]
perkj8ff860a2016-10-03 07:30:041/*
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 17:08:3311#include "rtc_base/weak_ptr.h"
12
Yves Gerey3e707812018-11-28 15:47:4913#include <memory>
perkj8ff860a2016-10-03 07:30:0414#include <string>
15
Tommi897e1362017-12-01 17:56:4316#include "rtc_base/event.h"
Danil Chapovalov07122bc2019-03-26 13:37:0117#include "rtc_base/task_queue_for_test.h"
Yves Gerey3e707812018-11-28 15:47:4918#include "test/gtest.h"
perkj8ff860a2016-10-03 07:30:0419
20namespace rtc {
21
22namespace {
23
24struct Base {
25 std::string member;
26};
27struct Derived : public Base {};
28
29struct Target {};
30
31struct Arrow {
32 WeakPtr<Target> target;
33};
34
35struct TargetWithFactory : public Target {
36 TargetWithFactory() : factory(this) {}
37 WeakPtrFactory<Target> factory;
38};
39
40} // namespace
41
42TEST(WeakPtrFactoryTest, Basic) {
43 int data;
44 WeakPtrFactory<int> factory(&data);
45 WeakPtr<int> ptr = factory.GetWeakPtr();
46 EXPECT_EQ(&data, ptr.get());
47}
48
49TEST(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
57TEST(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
67TEST(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
79TEST(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
93TEST(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
105TEST(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
115TEST(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
123TEST(WeakPtrTest, DefaultConstructor) {
124 WeakPtr<int> ptr;
125 EXPECT_EQ(nullptr, ptr.get());
126}
127
128TEST(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
159TEST(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
172TEST(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
193TEST(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
203template <class T>
204std::unique_ptr<T> NewObjectCreatedOnTaskQueue() {
205 std::unique_ptr<T> obj;
Danil Chapovalov07122bc2019-03-26 13:37:01206 webrtc::TaskQueueForTest queue("NewObjectCreatedOnTaskQueue");
Danil Chapovalove519f382022-08-11 10:26:09207 queue.SendTask([&] { obj = std::make_unique<T>(); });
perkj8ff860a2016-10-03 07:30:04208 return obj;
209}
210
211TEST(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
221TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
Danil Chapovalov66cebbd2017-11-09 17:44:31222 // 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.
Mirko Bonadei317a1f02019-09-17 15:06:18225 auto target = std::make_unique<TargetWithFactory>();
Danil Chapovalov66cebbd2017-11-09 17:44:31226 // Create weak ptr on main thread
227 WeakPtr<Target> weak_ptr = target->factory.GetWeakPtr();
Danil Chapovalov07122bc2019-03-26 13:37:01228 webrtc::TaskQueueForTest queue("queue");
Danil Chapovalove519f382022-08-11 10:26:09229 queue.SendTask([&] {
230 // Dereference and invalide weak_ptr on another thread.
231 EXPECT_EQ(weak_ptr.get(), target.get());
232 target.reset();
233 });
perkj8ff860a2016-10-03 07:30:04234}
235
236} // namespace rtc