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