blob: c4dfba3336c5840311202c2064f7aef2d2989cda [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]3125d6462009-09-01 20:50:172// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]4c44b8442012-06-15 16:36:125#include "base/memory/weak_ptr.h"
6
dcheng093de9b2016-04-04 21:25:517#include <memory>
[email protected]4c44b8442012-06-15 16:36:128#include <string>
9
[email protected]4a358652013-06-07 14:32:2310#include "base/debug/leak_annotations.h"
Avi Drissman63e1f992023-01-13 18:54:4311#include "base/functional/bind.h"
skyostil054861d2015-04-30 19:06:1512#include "base/location.h"
[email protected]1edefc42011-08-26 17:32:2913#include "base/synchronization/waitable_event.h"
Patrick Monette643cdf62021-10-15 19:13:4214#include "base/task/single_thread_task_runner.h"
gabc964a852016-08-01 16:39:5615#include "base/test/gtest_util.h"
Nicolas Ouellet-payeurff1eab62018-07-19 18:41:5016#include "base/test/test_timeouts.h"
[email protected]34b99632011-01-01 01:01:0617#include "base/threading/thread.h"
[email protected]4c44b8442012-06-15 16:36:1218#include "testing/gtest/include/gtest/gtest.h"
[email protected]3125d6462009-09-01 20:50:1719
20namespace base {
Joe Mason0f6f6112024-02-08 17:48:1021
22namespace subtle {
23
24class BindWeakPtrFactoryForTesting {
25 public:
26 template <typename T>
27 static void BindToCurrentSequence(WeakPtrFactory<T>& factory) {
28 factory.BindToCurrentSequence(BindWeakPtrFactoryPassKey());
29 }
30};
31
32} // namespace subtle
33
[email protected]3125d6462009-09-01 20:50:1734namespace {
35
dchengefeb19b2016-04-05 20:07:4036WeakPtr<int> PassThru(WeakPtr<int> ptr) {
37 return ptr;
38}
39
[email protected]3125d6462009-09-01 20:50:1740template <class T>
41class OffThreadObjectCreator {
42 public:
43 static T* NewObject() {
44 T* result;
45 {
46 Thread creator_thread("creator_thread");
47 creator_thread.Start();
skyostil054861d2015-04-30 19:06:1548 creator_thread.task_runner()->PostTask(
tzik92b7a422017-04-11 15:00:4449 FROM_HERE,
50 base::BindOnce(OffThreadObjectCreator::CreateObject, &result));
[email protected]3125d6462009-09-01 20:50:1751 }
52 DCHECK(result); // We synchronized on thread destruction above.
53 return result;
54 }
Peter Kasting134ef9af2024-12-28 02:30:0955
[email protected]3125d6462009-09-01 20:50:1756 private:
Peter Kasting134ef9af2024-12-28 02:30:0957 static void CreateObject(T** result) { *result = new T; }
[email protected]3125d6462009-09-01 20:50:1758};
59
[email protected]5d6688f2012-07-11 21:39:0360struct Base {
61 std::string member;
62};
[email protected]c33acdb2013-03-02 02:31:4563struct Derived : public Base {};
[email protected]3125d6462009-09-01 20:50:1764
[email protected]c33acdb2013-03-02 02:31:4565struct TargetBase {};
David Bertonife3114c2024-07-11 17:21:1466
Dave Tapuska4f985bb2024-08-09 15:52:2967struct Target : public TargetBase {
Chris Watkinsbb7211c2017-11-29 07:16:3868 virtual ~Target() = default;
Dave Tapuska4f985bb2024-08-09 15:52:2969 WeakPtr<Target> AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
70
71 private:
72 WeakPtrFactory<Target> weak_ptr_factory_{this};
[email protected]368b94832014-02-12 09:13:3473};
François Degros75d898c2017-11-17 04:03:3374
[email protected]c33acdb2013-03-02 02:31:4575struct DerivedTarget : public Target {};
François Degros75d898c2017-11-17 04:03:3376
77// A class inheriting from Target and defining a nested type called 'Base'.
78// To guard against strange compilation errors.
79struct DerivedTargetWithNestedBase : public Target {
80 using Base = void;
81};
82
83// A struct with a virtual destructor.
84struct VirtualDestructor {
Chris Watkinsbb7211c2017-11-29 07:16:3885 virtual ~VirtualDestructor() = default;
François Degros75d898c2017-11-17 04:03:3386};
87
88// A class inheriting from Target where Target is not the first base, and where
89// the first base has a virtual method table. This creates a structure where the
90// Target base is not positioned at the beginning of
91// DerivedTargetMultipleInheritance.
92struct DerivedTargetMultipleInheritance : public VirtualDestructor,
93 public Target {};
94
[email protected]5d6688f2012-07-11 21:39:0395struct Arrow {
96 WeakPtr<Target> target;
97};
[email protected]7e530912013-08-03 03:13:5298struct TargetWithFactory : public Target {
Sorin Jianu1ed1f6c2024-09-28 00:31:4099 TargetWithFactory() = default;
Jeremy Roman577d88492019-07-05 14:30:23100 WeakPtrFactory<Target> factory{this};
[email protected]7e530912013-08-03 03:13:52101};
[email protected]3125d6462009-09-01 20:50:17102
[email protected]1edefc42011-08-26 17:32:29103// Helper class to create and destroy weak pointer copies
104// and delete objects on a background thread.
105class BackgroundThread : public Thread {
106 public:
[email protected]44106182012-04-06 03:53:02107 BackgroundThread() : Thread("owner_thread") {}
[email protected]1edefc42011-08-26 17:32:29108
dcheng56488182014-10-21 10:54:51109 ~BackgroundThread() override { Stop(); }
[email protected]d583c3a2011-11-02 15:31:56110
[email protected]5d6688f2012-07-11 21:39:03111 void CreateArrowFromTarget(Arrow** arrow, Target* target) {
gab75d72332016-06-01 21:15:33112 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
113 WaitableEvent::InitialState::NOT_SIGNALED);
skyostil054861d2015-04-30 19:06:15114 task_runner()->PostTask(
tzik92b7a422017-04-11 15:00:44115 FROM_HERE, base::BindOnce(&BackgroundThread::DoCreateArrowFromTarget,
116 arrow, target, &completion));
[email protected]1edefc42011-08-26 17:32:29117 completion.Wait();
118 }
119
[email protected]5d6688f2012-07-11 21:39:03120 void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
gab75d72332016-06-01 21:15:33121 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
122 WaitableEvent::InitialState::NOT_SIGNALED);
skyostil054861d2015-04-30 19:06:15123 task_runner()->PostTask(
tzik92b7a422017-04-11 15:00:44124 FROM_HERE, base::BindOnce(&BackgroundThread::DoCreateArrowFromArrow,
125 arrow, other, &completion));
[email protected]1edefc42011-08-26 17:32:29126 completion.Wait();
127 }
128
[email protected]5d6688f2012-07-11 21:39:03129 void DeleteTarget(Target* object) {
gab75d72332016-06-01 21:15:33130 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
131 WaitableEvent::InitialState::NOT_SIGNALED);
skyostil054861d2015-04-30 19:06:15132 task_runner()->PostTask(
[email protected]1edefc42011-08-26 17:32:29133 FROM_HERE,
tzik92b7a422017-04-11 15:00:44134 base::BindOnce(&BackgroundThread::DoDeleteTarget, object, &completion));
[email protected]1edefc42011-08-26 17:32:29135 completion.Wait();
136 }
137
[email protected]c33acdb2013-03-02 02:31:45138 void CopyAndAssignArrow(Arrow* object) {
gab75d72332016-06-01 21:15:33139 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
140 WaitableEvent::InitialState::NOT_SIGNALED);
skyostil054861d2015-04-30 19:06:15141 task_runner()->PostTask(
tzik92b7a422017-04-11 15:00:44142 FROM_HERE, base::BindOnce(&BackgroundThread::DoCopyAndAssignArrow,
143 object, &completion));
[email protected]c33acdb2013-03-02 02:31:45144 completion.Wait();
145 }
146
147 void CopyAndAssignArrowBase(Arrow* object) {
gab75d72332016-06-01 21:15:33148 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
149 WaitableEvent::InitialState::NOT_SIGNALED);
skyostil054861d2015-04-30 19:06:15150 task_runner()->PostTask(
tzik92b7a422017-04-11 15:00:44151 FROM_HERE, base::BindOnce(&BackgroundThread::DoCopyAndAssignArrowBase,
152 object, &completion));
[email protected]c33acdb2013-03-02 02:31:45153 completion.Wait();
154 }
155
[email protected]5d6688f2012-07-11 21:39:03156 void DeleteArrow(Arrow* object) {
gab75d72332016-06-01 21:15:33157 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
158 WaitableEvent::InitialState::NOT_SIGNALED);
skyostil054861d2015-04-30 19:06:15159 task_runner()->PostTask(
[email protected]1edefc42011-08-26 17:32:29160 FROM_HERE,
tzik92b7a422017-04-11 15:00:44161 base::BindOnce(&BackgroundThread::DoDeleteArrow, object, &completion));
[email protected]1edefc42011-08-26 17:32:29162 completion.Wait();
163 }
164
[email protected]5d6688f2012-07-11 21:39:03165 Target* DeRef(const Arrow* arrow) {
gab75d72332016-06-01 21:15:33166 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
167 WaitableEvent::InitialState::NOT_SIGNALED);
dchengefeb19b2016-04-05 20:07:40168 Target* result = nullptr;
tzik92b7a422017-04-11 15:00:44169 task_runner()->PostTask(
170 FROM_HERE, base::BindOnce(&BackgroundThread::DoDeRef, arrow, &result,
171 &completion));
[email protected]1edefc42011-08-26 17:32:29172 completion.Wait();
173 return result;
174 }
175
Joe Mason0f6f6112024-02-08 17:48:10176 void BindToCurrentSequence(TargetWithFactory* target_with_factory) {
177 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
178 WaitableEvent::InitialState::NOT_SIGNALED);
179 task_runner()->PostTask(
180 FROM_HERE, base::BindOnce(&BackgroundThread::DoBindToCurrentSequence,
181 target_with_factory, &completion));
182 completion.Wait();
183 }
184
[email protected]1edefc42011-08-26 17:32:29185 protected:
[email protected]5d6688f2012-07-11 21:39:03186 static void DoCreateArrowFromArrow(Arrow** arrow,
187 const Arrow* other,
188 WaitableEvent* completion) {
189 *arrow = new Arrow;
190 **arrow = *other;
[email protected]1edefc42011-08-26 17:32:29191 completion->Signal();
192 }
193
[email protected]5d6688f2012-07-11 21:39:03194 static void DoCreateArrowFromTarget(Arrow** arrow,
195 Target* target,
196 WaitableEvent* completion) {
197 *arrow = new Arrow;
198 (*arrow)->target = target->AsWeakPtr();
[email protected]1edefc42011-08-26 17:32:29199 completion->Signal();
200 }
201
[email protected]5d6688f2012-07-11 21:39:03202 static void DoDeRef(const Arrow* arrow,
203 Target** result,
[email protected]1edefc42011-08-26 17:32:29204 WaitableEvent* completion) {
[email protected]5d6688f2012-07-11 21:39:03205 *result = arrow->target.get();
[email protected]1edefc42011-08-26 17:32:29206 completion->Signal();
207 }
208
[email protected]5d6688f2012-07-11 21:39:03209 static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
[email protected]1edefc42011-08-26 17:32:29210 delete object;
211 completion->Signal();
212 }
213
[email protected]c33acdb2013-03-02 02:31:45214 static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) {
215 // Copy constructor.
216 Arrow a = *object;
217 // Assignment operator.
218 *object = a;
219 completion->Signal();
220 }
221
Peter Kasting134ef9af2024-12-28 02:30:09222 static void DoCopyAndAssignArrowBase(Arrow* object,
223 WaitableEvent* completion) {
[email protected]c33acdb2013-03-02 02:31:45224 // Copy constructor.
225 WeakPtr<TargetBase> b = object->target;
226 // Assignment operator.
227 WeakPtr<TargetBase> c;
228 c = object->target;
229 completion->Signal();
230 }
231
[email protected]5d6688f2012-07-11 21:39:03232 static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
[email protected]1edefc42011-08-26 17:32:29233 delete object;
234 completion->Signal();
235 }
Joe Mason0f6f6112024-02-08 17:48:10236
237 static void DoBindToCurrentSequence(TargetWithFactory* target_with_factory,
238 WaitableEvent* completion) {
239 subtle::BindWeakPtrFactoryForTesting::BindToCurrentSequence(
240 target_with_factory->factory);
241 completion->Signal();
242 }
[email protected]1edefc42011-08-26 17:32:29243};
244
[email protected]3125d6462009-09-01 20:50:17245} // namespace
246
[email protected]5d6688f2012-07-11 21:39:03247TEST(WeakPtrFactoryTest, Basic) {
[email protected]3125d6462009-09-01 20:50:17248 int data;
249 WeakPtrFactory<int> factory(&data);
250 WeakPtr<int> ptr = factory.GetWeakPtr();
251 EXPECT_EQ(&data, ptr.get());
252}
253
[email protected]5d6688f2012-07-11 21:39:03254TEST(WeakPtrFactoryTest, Comparison) {
[email protected]3125d6462009-09-01 20:50:17255 int data;
256 WeakPtrFactory<int> factory(&data);
257 WeakPtr<int> ptr = factory.GetWeakPtr();
258 WeakPtr<int> ptr2 = ptr;
[email protected]eab9d01a2013-06-04 20:54:20259 EXPECT_EQ(ptr.get(), ptr2.get());
[email protected]3125d6462009-09-01 20:50:17260}
261
mek79016812016-06-24 21:29:04262TEST(WeakPtrFactoryTest, Move) {
263 int data;
264 WeakPtrFactory<int> factory(&data);
265 WeakPtr<int> ptr = factory.GetWeakPtr();
266 WeakPtr<int> ptr2 = factory.GetWeakPtr();
267 WeakPtr<int> ptr3 = std::move(ptr2);
Peter Kasting6218bbad2025-01-10 11:26:40268 EXPECT_NE(ptr.get(), ptr2.get()); // NOLINT(bugprone-use-after-move)
mek79016812016-06-24 21:29:04269 EXPECT_EQ(ptr.get(), ptr3.get());
270}
271
[email protected]5d6688f2012-07-11 21:39:03272TEST(WeakPtrFactoryTest, OutOfScope) {
[email protected]3125d6462009-09-01 20:50:17273 WeakPtr<int> ptr;
dchengefeb19b2016-04-05 20:07:40274 EXPECT_EQ(nullptr, ptr.get());
[email protected]3125d6462009-09-01 20:50:17275 {
276 int data;
277 WeakPtrFactory<int> factory(&data);
278 ptr = factory.GetWeakPtr();
279 }
dchengefeb19b2016-04-05 20:07:40280 EXPECT_EQ(nullptr, ptr.get());
[email protected]3125d6462009-09-01 20:50:17281}
282
[email protected]5d6688f2012-07-11 21:39:03283TEST(WeakPtrFactoryTest, Multiple) {
[email protected]3125d6462009-09-01 20:50:17284 WeakPtr<int> a, b;
285 {
286 int data;
287 WeakPtrFactory<int> factory(&data);
288 a = factory.GetWeakPtr();
289 b = factory.GetWeakPtr();
290 EXPECT_EQ(&data, a.get());
291 EXPECT_EQ(&data, b.get());
292 }
dchengefeb19b2016-04-05 20:07:40293 EXPECT_EQ(nullptr, a.get());
294 EXPECT_EQ(nullptr, b.get());
[email protected]3125d6462009-09-01 20:50:17295}
296
[email protected]5d6688f2012-07-11 21:39:03297TEST(WeakPtrFactoryTest, MultipleStaged) {
[email protected]09733b452011-05-24 23:49:07298 WeakPtr<int> a;
299 {
300 int data;
301 WeakPtrFactory<int> factory(&data);
302 a = factory.GetWeakPtr();
Peter Kasting134ef9af2024-12-28 02:30:09303 { WeakPtr<int> b = factory.GetWeakPtr(); }
dchengefeb19b2016-04-05 20:07:40304 EXPECT_NE(nullptr, a.get());
[email protected]09733b452011-05-24 23:49:07305 }
dchengefeb19b2016-04-05 20:07:40306 EXPECT_EQ(nullptr, a.get());
[email protected]09733b452011-05-24 23:49:07307}
308
[email protected]5d6688f2012-07-11 21:39:03309TEST(WeakPtrFactoryTest, Dereference) {
310 Base data;
311 data.member = "123456";
312 WeakPtrFactory<Base> factory(&data);
313 WeakPtr<Base> ptr = factory.GetWeakPtr();
314 EXPECT_EQ(&data, ptr.get());
315 EXPECT_EQ(data.member, (*ptr).member);
316 EXPECT_EQ(data.member, ptr->member);
317}
318
319TEST(WeakPtrFactoryTest, UpCast) {
[email protected]3125d6462009-09-01 20:50:17320 Derived data;
321 WeakPtrFactory<Derived> factory(&data);
322 WeakPtr<Base> ptr = factory.GetWeakPtr();
323 ptr = factory.GetWeakPtr();
324 EXPECT_EQ(ptr.get(), &data);
325}
326
dchengefeb19b2016-04-05 20:07:40327TEST(WeakPtrTest, ConstructFromNullptr) {
328 WeakPtr<int> ptr = PassThru(nullptr);
329 EXPECT_EQ(nullptr, ptr.get());
330}
331
scheib28aacfca2016-02-23 20:57:19332TEST(WeakPtrFactoryTest, BooleanTesting) {
333 int data;
334 WeakPtrFactory<int> factory(&data);
335
336 WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
337 EXPECT_TRUE(ptr_to_an_instance);
338 EXPECT_FALSE(!ptr_to_an_instance);
339
340 if (ptr_to_an_instance) {
341 } else {
342 ADD_FAILURE() << "Pointer to an instance should result in true.";
343 }
344
345 if (!ptr_to_an_instance) { // check for operator!().
346 ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
347 }
348
349 WeakPtr<int> null_ptr;
350 EXPECT_FALSE(null_ptr);
351 EXPECT_TRUE(!null_ptr);
352
353 if (null_ptr) {
354 ADD_FAILURE() << "Null pointer should result in false.";
355 }
356
357 if (!null_ptr) { // check for operator!().
358 } else {
359 ADD_FAILURE() << "Null pointer should result in !x being true.";
360 }
361}
362
wezb9820d42016-06-22 23:41:04363TEST(WeakPtrFactoryTest, ComparisonToNull) {
364 int data;
365 WeakPtrFactory<int> factory(&data);
366
367 WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
368 EXPECT_NE(nullptr, ptr_to_an_instance);
369 EXPECT_NE(ptr_to_an_instance, nullptr);
370
371 WeakPtr<int> null_ptr;
372 EXPECT_EQ(null_ptr, nullptr);
373 EXPECT_EQ(nullptr, null_ptr);
374}
375
danakjcfcdfb7a2023-02-23 01:05:35376struct ReallyBaseClass {};
377struct BaseClass : ReallyBaseClass {
378 virtual ~BaseClass() = default;
379 void VirtualMethod() {}
380};
381struct OtherBaseClass {
382 virtual ~OtherBaseClass() = default;
383 virtual void VirtualMethod() {}
384};
385struct WithWeak final : BaseClass, OtherBaseClass {
386 WeakPtrFactory<WithWeak> factory{this};
387};
388
389TEST(WeakPtrTest, ConversionOffsetsPointer) {
390 WithWeak with;
391 WeakPtr<WithWeak> ptr(with.factory.GetWeakPtr());
392 {
393 // Copy construction.
394 WeakPtr<OtherBaseClass> base_ptr(ptr);
395 EXPECT_EQ(static_cast<WithWeak*>(&*base_ptr), &with);
396 }
397 {
398 // Move construction.
399 WeakPtr<OtherBaseClass> base_ptr(std::move(ptr));
400 EXPECT_EQ(static_cast<WithWeak*>(&*base_ptr), &with);
401 }
402
403 // WeakPtr doesn't have conversion operators for assignment.
404}
405
[email protected]3125d6462009-09-01 20:50:17406TEST(WeakPtrTest, InvalidateWeakPtrs) {
407 int data;
408 WeakPtrFactory<int> factory(&data);
409 WeakPtr<int> ptr = factory.GetWeakPtr();
410 EXPECT_EQ(&data, ptr.get());
[email protected]59326aac2009-09-25 23:34:34411 EXPECT_TRUE(factory.HasWeakPtrs());
[email protected]3125d6462009-09-01 20:50:17412 factory.InvalidateWeakPtrs();
dchengefeb19b2016-04-05 20:07:40413 EXPECT_EQ(nullptr, ptr.get());
[email protected]59326aac2009-09-25 23:34:34414 EXPECT_FALSE(factory.HasWeakPtrs());
[email protected]d0a98b62014-06-21 13:34:07415
416 // Test that the factory can create new weak pointers after a
417 // InvalidateWeakPtrs call, and they remain valid until the next
418 // InvalidateWeakPtrs call.
419 WeakPtr<int> ptr2 = factory.GetWeakPtr();
420 EXPECT_EQ(&data, ptr2.get());
421 EXPECT_TRUE(factory.HasWeakPtrs());
422 factory.InvalidateWeakPtrs();
dchengefeb19b2016-04-05 20:07:40423 EXPECT_EQ(nullptr, ptr2.get());
[email protected]d0a98b62014-06-21 13:34:07424 EXPECT_FALSE(factory.HasWeakPtrs());
[email protected]59326aac2009-09-25 23:34:34425}
426
François Dorayd1a2bfde2025-06-20 00:39:30427TEST(WeakPtrTest, InvalidateWeakPtrsAndDoom) {
428 int data;
429 WeakPtrFactory<int> factory(&data);
430 WeakPtr<int> ptr = factory.GetWeakPtr();
431 EXPECT_EQ(&data, ptr.get());
432 EXPECT_TRUE(factory.HasWeakPtrs());
433 factory.InvalidateWeakPtrsAndDoom();
434 EXPECT_EQ(nullptr, ptr.get());
435 EXPECT_FALSE(factory.HasWeakPtrs());
436
437 EXPECT_DCHECK_DEATH({
438 // Cannot get a WeakPtr from a doomed factory.
439 WeakPtr<int> other_ptr = factory.GetWeakPtr();
440 });
441}
442
Trent Apted30f97fd2018-08-21 09:03:47443// Tests that WasInvalidated() is true only for invalidated WeakPtrs (not
Trent Apted453d0b5b2018-08-23 00:13:22444// nullptr) and doesn't DCHECK (e.g. because of a dereference attempt).
Trent Apted30f97fd2018-08-21 09:03:47445TEST(WeakPtrTest, WasInvalidatedByFactoryDestruction) {
446 WeakPtr<int> ptr;
447 EXPECT_FALSE(ptr.WasInvalidated());
448
Trent Apted453d0b5b2018-08-23 00:13:22449 // Test |data| destroyed. That is, the typical pattern when |data| (and its
450 // associated factory) go out of scope.
Trent Apted30f97fd2018-08-21 09:03:47451 {
Trent Apted453d0b5b2018-08-23 00:13:22452 int data = 0;
Trent Apted30f97fd2018-08-21 09:03:47453 WeakPtrFactory<int> factory(&data);
454 ptr = factory.GetWeakPtr();
455
Trent Apted453d0b5b2018-08-23 00:13:22456 // Verify that a live WeakPtr is not reported as Invalidated.
Trent Apted30f97fd2018-08-21 09:03:47457 EXPECT_FALSE(ptr.WasInvalidated());
458 }
Trent Apted453d0b5b2018-08-23 00:13:22459
460 // Checking validity shouldn't read beyond the stack frame.
461 EXPECT_TRUE(ptr.WasInvalidated());
Trent Apted30f97fd2018-08-21 09:03:47462 ptr = nullptr;
463 EXPECT_FALSE(ptr.WasInvalidated());
464}
465
466// As above, but testing InvalidateWeakPtrs().
467TEST(WeakPtrTest, WasInvalidatedByInvalidateWeakPtrs) {
Trent Apted453d0b5b2018-08-23 00:13:22468 int data = 0;
Trent Apted30f97fd2018-08-21 09:03:47469 WeakPtrFactory<int> factory(&data);
470 WeakPtr<int> ptr = factory.GetWeakPtr();
471 EXPECT_FALSE(ptr.WasInvalidated());
472 factory.InvalidateWeakPtrs();
473 EXPECT_TRUE(ptr.WasInvalidated());
474 ptr = nullptr;
475 EXPECT_FALSE(ptr.WasInvalidated());
476}
477
Trent Apted453d0b5b2018-08-23 00:13:22478// A WeakPtr should not be reported as 'invalidated' if nullptr was assigned to
479// it.
Trent Apted30f97fd2018-08-21 09:03:47480TEST(WeakPtrTest, WasInvalidatedWhilstNull) {
Trent Apted453d0b5b2018-08-23 00:13:22481 int data = 0;
Trent Apted30f97fd2018-08-21 09:03:47482 WeakPtrFactory<int> factory(&data);
483 WeakPtr<int> ptr = factory.GetWeakPtr();
484 EXPECT_FALSE(ptr.WasInvalidated());
485 ptr = nullptr;
486 EXPECT_FALSE(ptr.WasInvalidated());
487 factory.InvalidateWeakPtrs();
488 EXPECT_FALSE(ptr.WasInvalidated());
489}
490
Nicolas Ouellet-payeurff1eab62018-07-19 18:41:50491TEST(WeakPtrTest, MaybeValidOnSameSequence) {
492 int data;
493 WeakPtrFactory<int> factory(&data);
494 WeakPtr<int> ptr = factory.GetWeakPtr();
495 EXPECT_TRUE(ptr.MaybeValid());
496 factory.InvalidateWeakPtrs();
497 // Since InvalidateWeakPtrs() ran on this sequence, MaybeValid() should be
498 // false.
499 EXPECT_FALSE(ptr.MaybeValid());
500}
501
502TEST(WeakPtrTest, MaybeValidOnOtherSequence) {
503 int data;
504 WeakPtrFactory<int> factory(&data);
505 WeakPtr<int> ptr = factory.GetWeakPtr();
506 EXPECT_TRUE(ptr.MaybeValid());
507
508 base::Thread other_thread("other_thread");
509 other_thread.StartAndWaitForTesting();
510 other_thread.task_runner()->PostTask(
511 FROM_HERE,
512 base::BindOnce(
513 [](WeakPtr<int> ptr) {
514 // Check that MaybeValid() _eventually_ returns false.
515 const TimeDelta timeout = TestTimeouts::tiny_timeout();
516 const TimeTicks begin = TimeTicks::Now();
Peter Kasting134ef9af2024-12-28 02:30:09517 while (ptr.MaybeValid() && (TimeTicks::Now() - begin) < timeout) {
Nicolas Ouellet-payeurff1eab62018-07-19 18:41:50518 PlatformThread::YieldCurrentThread();
Peter Kasting134ef9af2024-12-28 02:30:09519 }
Nicolas Ouellet-payeurff1eab62018-07-19 18:41:50520 EXPECT_FALSE(ptr.MaybeValid());
521 },
522 ptr));
523 factory.InvalidateWeakPtrs();
524 // |other_thread|'s destructor will join, ensuring we wait for the task to be
525 // run.
526}
527
[email protected]59326aac2009-09-25 23:34:34528TEST(WeakPtrTest, HasWeakPtrs) {
529 int data;
530 WeakPtrFactory<int> factory(&data);
531 {
532 WeakPtr<int> ptr = factory.GetWeakPtr();
533 EXPECT_TRUE(factory.HasWeakPtrs());
534 }
535 EXPECT_FALSE(factory.HasWeakPtrs());
[email protected]3125d6462009-09-01 20:50:17536}
537
[email protected]5d6688f2012-07-11 21:39:03538TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
539 // Test that it is OK to create an object that supports WeakPtr on one thread,
540 // but use it on another. This tests that we do not trip runtime checks that
541 // ensure that a WeakPtr is not used by multiple threads.
dcheng093de9b2016-04-04 21:25:51542 std::unique_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
[email protected]5d6688f2012-07-11 21:39:03543 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
544 EXPECT_EQ(target.get(), weak_ptr.get());
[email protected]3125d6462009-09-01 20:50:17545}
546
[email protected]5d6688f2012-07-11 21:39:03547TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
548 // Test that it is OK to create an object that has a WeakPtr member on one
[email protected]856581a2012-07-04 01:02:14549 // thread, but use it on another. This tests that we do not trip runtime
[email protected]5d6688f2012-07-11 21:39:03550 // checks that ensure that a WeakPtr is not used by multiple threads.
dcheng093de9b2016-04-04 21:25:51551 std::unique_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
[email protected]5d6688f2012-07-11 21:39:03552 Target target;
553 arrow->target = target.AsWeakPtr();
554 EXPECT_EQ(&target, arrow->target.get());
[email protected]856581a2012-07-04 01:02:14555}
556
[email protected]5d6688f2012-07-11 21:39:03557TEST(WeakPtrTest, MoveOwnershipImplicitly) {
558 // Move object ownership to another thread by releasing all weak pointers
559 // on the original thread first, and then establish WeakPtr on a different
560 // thread.
561 BackgroundThread background;
562 background.Start();
563
564 Target* target = new Target();
[email protected]1edefc42011-08-26 17:32:29565 {
[email protected]5d6688f2012-07-11 21:39:03566 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
567 // Main thread deletes the WeakPtr, then the thread ownership of the
568 // object can be implicitly moved.
[email protected]1edefc42011-08-26 17:32:29569 }
[email protected]5d6688f2012-07-11 21:39:03570 Arrow* arrow;
571
572 // Background thread creates WeakPtr(and implicitly owns the object).
573 background.CreateArrowFromTarget(&arrow, target);
574 EXPECT_EQ(background.DeRef(arrow), target);
575
576 {
577 // Main thread creates another WeakPtr, but this does not trigger implicitly
578 // thread ownership move.
Dave Tapuska0b98e5c2019-09-04 13:05:46579 Arrow scoped_arrow;
580 scoped_arrow.target = target->AsWeakPtr();
[email protected]5d6688f2012-07-11 21:39:03581
582 // The new WeakPtr is owned by background thread.
Dave Tapuska0b98e5c2019-09-04 13:05:46583 EXPECT_EQ(target, background.DeRef(&scoped_arrow));
[email protected]5d6688f2012-07-11 21:39:03584 }
585
586 // Target can only be deleted on background thread.
587 background.DeleteTarget(target);
588 background.DeleteArrow(arrow);
[email protected]1edefc42011-08-26 17:32:29589}
590
[email protected]7e530912013-08-03 03:13:52591TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) {
[email protected]5d6688f2012-07-11 21:39:03592 BackgroundThread background;
593 background.Start();
594
595 Arrow* arrow;
596 {
597 Target target;
[email protected]7e530912013-08-03 03:13:52598 // Background thread creates WeakPtr.
[email protected]5d6688f2012-07-11 21:39:03599 background.CreateArrowFromTarget(&arrow, &target);
[email protected]7e530912013-08-03 03:13:52600
601 // Bind to background thread.
[email protected]5d6688f2012-07-11 21:39:03602 EXPECT_EQ(&target, background.DeRef(arrow));
603
[email protected]7e530912013-08-03 03:13:52604 // Release the only WeakPtr.
Wezcaf863b992018-05-01 11:03:29605 arrow->target.reset();
[email protected]7e530912013-08-03 03:13:52606
607 // Now we should be able to create a new reference from this thread.
608 arrow->target = target.AsWeakPtr();
[email protected]5d6688f2012-07-11 21:39:03609
610 // Re-bind to main thread.
611 EXPECT_EQ(&target, arrow->target.get());
612
[email protected]7e530912013-08-03 03:13:52613 // And the main thread can now delete the target.
[email protected]5d6688f2012-07-11 21:39:03614 }
615
[email protected]7e530912013-08-03 03:13:52616 delete arrow;
617}
618
619TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
620 BackgroundThread background;
621 background.Start();
622
623 Arrow arrow;
dcheng093de9b2016-04-04 21:25:51624 std::unique_ptr<TargetWithFactory> target(new TargetWithFactory);
[email protected]7e530912013-08-03 03:13:52625
626 // Bind to main thread.
627 arrow.target = target->factory.GetWeakPtr();
628 EXPECT_EQ(target.get(), arrow.target.get());
629
630 target->factory.InvalidateWeakPtrs();
dchengefeb19b2016-04-05 20:07:40631 EXPECT_EQ(nullptr, arrow.target.get());
[email protected]7e530912013-08-03 03:13:52632
633 arrow.target = target->factory.GetWeakPtr();
634 // Re-bind to background thread.
635 EXPECT_EQ(target.get(), background.DeRef(&arrow));
636
637 // And the background thread can now delete the target.
638 background.DeleteTarget(target.release());
[email protected]5d6688f2012-07-11 21:39:03639}
640
641TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
[email protected]1edefc42011-08-26 17:32:29642 // Originating thread has a WeakPtr that outlives others.
[email protected]5d6688f2012-07-11 21:39:03643 // - Main thread creates a WeakPtr
644 // - Background thread creates a WeakPtr copy from the one in main thread
645 // - Destruct the WeakPtr on background thread
646 // - Destruct the WeakPtr on main thread
647 BackgroundThread background;
648 background.Start();
649
650 Target target;
651 Arrow arrow;
652 arrow.target = target.AsWeakPtr();
653
654 Arrow* arrow_copy;
655 background.CreateArrowFromArrow(&arrow_copy, &arrow);
[email protected]1653d322013-06-04 17:35:13656 EXPECT_EQ(arrow_copy->target.get(), &target);
[email protected]5d6688f2012-07-11 21:39:03657 background.DeleteArrow(arrow_copy);
[email protected]1edefc42011-08-26 17:32:29658}
659
[email protected]5d6688f2012-07-11 21:39:03660TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
[email protected]1edefc42011-08-26 17:32:29661 // Originating thread drops all references before another thread.
[email protected]5d6688f2012-07-11 21:39:03662 // - Main thread creates a WeakPtr and passes copy to background thread
663 // - Destruct the pointer on main thread
664 // - Destruct the pointer on background thread
665 BackgroundThread background;
666 background.Start();
667
668 Target target;
669 Arrow* arrow_copy;
[email protected]1edefc42011-08-26 17:32:29670 {
[email protected]5d6688f2012-07-11 21:39:03671 Arrow arrow;
672 arrow.target = target.AsWeakPtr();
673 background.CreateArrowFromArrow(&arrow_copy, &arrow);
[email protected]1edefc42011-08-26 17:32:29674 }
[email protected]1653d322013-06-04 17:35:13675 EXPECT_EQ(arrow_copy->target.get(), &target);
[email protected]5d6688f2012-07-11 21:39:03676 background.DeleteArrow(arrow_copy);
[email protected]1edefc42011-08-26 17:32:29677}
678
679TEST(WeakPtrTest, OwnerThreadDeletesObject) {
680 // Originating thread invalidates WeakPtrs while its held by other thread.
[email protected]5d6688f2012-07-11 21:39:03681 // - Main thread creates WeakPtr and passes Copy to background thread
682 // - Object gets destroyed on main thread
683 // (invalidates WeakPtr on background thread)
[email protected]1edefc42011-08-26 17:32:29684 // - WeakPtr gets destroyed on Thread B
[email protected]5d6688f2012-07-11 21:39:03685 BackgroundThread background;
686 background.Start();
687 Arrow* arrow_copy;
[email protected]1edefc42011-08-26 17:32:29688 {
[email protected]5d6688f2012-07-11 21:39:03689 Target target;
690 Arrow arrow;
691 arrow.target = target.AsWeakPtr();
692 background.CreateArrowFromArrow(&arrow_copy, &arrow);
[email protected]1edefc42011-08-26 17:32:29693 }
dchengefeb19b2016-04-05 20:07:40694 EXPECT_EQ(nullptr, arrow_copy->target.get());
[email protected]5d6688f2012-07-11 21:39:03695 background.DeleteArrow(arrow_copy);
[email protected]1edefc42011-08-26 17:32:29696}
697
[email protected]c33acdb2013-03-02 02:31:45698TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
699 // Main thread creates a Target object.
700 Target target;
701 // Main thread creates an arrow referencing the Target.
Peter Kasting134ef9af2024-12-28 02:30:09702 Arrow* arrow = new Arrow();
[email protected]144e1ce2013-06-10 23:46:15703 arrow->target = target.AsWeakPtr();
704
[email protected]c33acdb2013-03-02 02:31:45705 // Background can copy and assign arrow (as well as the WeakPtr inside).
706 BackgroundThread background;
707 background.Start();
708 background.CopyAndAssignArrow(arrow);
[email protected]144e1ce2013-06-10 23:46:15709 background.DeleteArrow(arrow);
[email protected]c33acdb2013-03-02 02:31:45710}
711
712TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
713 // Main thread creates a Target object.
714 Target target;
715 // Main thread creates an arrow referencing the Target.
Peter Kasting134ef9af2024-12-28 02:30:09716 Arrow* arrow = new Arrow();
[email protected]144e1ce2013-06-10 23:46:15717 arrow->target = target.AsWeakPtr();
718
[email protected]c33acdb2013-03-02 02:31:45719 // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
720 BackgroundThread background;
721 background.Start();
722 background.CopyAndAssignArrowBase(arrow);
[email protected]144e1ce2013-06-10 23:46:15723 background.DeleteArrow(arrow);
[email protected]c33acdb2013-03-02 02:31:45724}
725
[email protected]5d6688f2012-07-11 21:39:03726TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
727 // Main thread creates a Target object.
728 Target target;
729 // Main thread creates an arrow referencing the Target.
730 Arrow* arrow = new Arrow();
731 arrow->target = target.AsWeakPtr();
732
733 // Background can delete arrow (as well as the WeakPtr inside).
734 BackgroundThread background;
735 background.Start();
736 background.DeleteArrow(arrow);
[email protected]7f18b7c42012-02-24 09:13:09737}
738
Alan Cutter4252ed22022-10-05 09:04:19739TEST(WeakPtrTest, ConstUpCast) {
740 Target target;
Alan Cutter6e972c82022-10-07 05:03:45741
742 // WeakPtrs can upcast from non-const T to const T.
Alan Cutter4252ed22022-10-05 09:04:19743 WeakPtr<const Target> const_weak_ptr = target.AsWeakPtr();
Alan Cutter6e972c82022-10-07 05:03:45744
745 // WeakPtrs don't enable conversion from const T to nonconst T.
746 static_assert(
747 !std::is_constructible_v<WeakPtr<Target>, WeakPtr<const Target>>);
Alan Cutter4252ed22022-10-05 09:04:19748}
749
Alan Cutterc2d2c472022-10-20 02:14:43750TEST(WeakPtrTest, ConstGetWeakPtr) {
751 struct TestTarget {
752 const char* Method() const { return "const method"; }
753 const char* Method() { return "non-const method"; }
754
755 WeakPtrFactory<TestTarget> weak_ptr_factory{this};
756 } non_const_test_target;
757
758 const TestTarget& const_test_target = non_const_test_target;
759
760 EXPECT_EQ(const_test_target.weak_ptr_factory.GetWeakPtr()->Method(),
761 "const method");
762 EXPECT_EQ(non_const_test_target.weak_ptr_factory.GetWeakPtr()->Method(),
763 "non-const method");
764 EXPECT_EQ(const_test_target.weak_ptr_factory.GetMutableWeakPtr()->Method(),
765 "non-const method");
766}
767
Alan Cutter4252ed22022-10-05 09:04:19768TEST(WeakPtrTest, GetMutableWeakPtr) {
769 struct TestStruct {
770 int member = 0;
771 WeakPtrFactory<TestStruct> weak_ptr_factory{this};
772 };
773 TestStruct test_struct;
774 EXPECT_EQ(test_struct.member, 0);
775
776 // GetMutableWeakPtr() grants non-const access to T.
777 const TestStruct& const_test_struct = test_struct;
778 WeakPtr<TestStruct> weak_ptr =
779 const_test_struct.weak_ptr_factory.GetMutableWeakPtr();
780 weak_ptr->member = 1;
781 EXPECT_EQ(test_struct.member, 1);
782}
783
Joe Mason0f6f6112024-02-08 17:48:10784TEST(WeakPtrDeathTest, BindToCurrentSequence) {
785 BackgroundThread background;
786 background.Start();
787
788 TargetWithFactory target_with_factory;
789 Arrow arrow{
790 .target = target_with_factory.factory.GetWeakPtr(),
791 };
792
793 // WeakPtr can be accessed on main thread.
794 EXPECT_TRUE(arrow.target.get());
795
796 background.BindToCurrentSequence(&target_with_factory);
797
798 // Now WeakPtr can be accessed on background thread.
799 EXPECT_TRUE(background.DeRef(&arrow));
800
801 // WeakPtr can no longer be accessed on main thread.
802 EXPECT_DCHECK_DEATH(arrow.target.get());
803}
804
[email protected]5d6688f2012-07-11 21:39:03805TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
806 // The default style "fast" does not support multi-threaded tests
807 // (introduces deadlock on Linux).
Daniel Cheng4ef1552f2023-12-05 02:55:54808 GTEST_FLAG_SET(death_test_style, "threadsafe");
[email protected]5d6688f2012-07-11 21:39:03809
810 BackgroundThread background;
811 background.Start();
812
813 // Main thread creates a Target object.
814 Target target;
815 // Main thread creates an arrow referencing the Target.
816 Arrow arrow;
817 arrow.target = target.AsWeakPtr();
818
819 // Background copies the WeakPtr.
820 Arrow* arrow_copy;
821 background.CreateArrowFromArrow(&arrow_copy, &arrow);
822
823 // The copy is still bound to main thread so I can deref.
824 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
825
826 // Although background thread created the copy, it can not deref the copied
827 // WeakPtr.
gab5e69cff2016-08-05 03:25:40828 ASSERT_DCHECK_DEATH(background.DeRef(arrow_copy));
[email protected]5d6688f2012-07-11 21:39:03829
830 background.DeleteArrow(arrow_copy);
831}
832
[email protected]ed3f67342013-05-29 08:04:32833TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) {
[email protected]5d6688f2012-07-11 21:39:03834 // The default style "fast" does not support multi-threaded tests
835 // (introduces deadlock on Linux).
Daniel Cheng4ef1552f2023-12-05 02:55:54836 GTEST_FLAG_SET(death_test_style, "threadsafe");
[email protected]5d6688f2012-07-11 21:39:03837
838 // Main thread creates a Target object.
839 Target target;
840
841 // Main thread creates an arrow referencing the Target (so target's
842 // thread ownership can not be implicitly moved).
843 Arrow arrow;
844 arrow.target = target.AsWeakPtr();
[email protected]ed3f67342013-05-29 08:04:32845 arrow.target.get();
[email protected]5d6688f2012-07-11 21:39:03846
847 // Background thread tries to deref target, which violates thread ownership.
848 BackgroundThread background;
849 background.Start();
gab5e69cff2016-08-05 03:25:40850 ASSERT_DCHECK_DEATH(background.DeRef(&arrow));
[email protected]5d6688f2012-07-11 21:39:03851}
852
[email protected]ed3f67342013-05-29 08:04:32853TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) {
[email protected]5d6688f2012-07-11 21:39:03854 // The default style "fast" does not support multi-threaded tests
855 // (introduces deadlock on Linux).
Daniel Cheng4ef1552f2023-12-05 02:55:54856 GTEST_FLAG_SET(death_test_style, "threadsafe");
[email protected]5d6688f2012-07-11 21:39:03857
dcheng093de9b2016-04-04 21:25:51858 std::unique_ptr<Target> target(new Target());
[email protected]ed3f67342013-05-29 08:04:32859
860 // Main thread creates an arrow referencing the Target.
[email protected]5d6688f2012-07-11 21:39:03861 Arrow arrow;
862 arrow.target = target->AsWeakPtr();
863
[email protected]ed3f67342013-05-29 08:04:32864 // Background thread tries to deref target, binding it to the thread.
865 BackgroundThread background;
866 background.Start();
867 background.DeRef(&arrow);
868
869 // Main thread deletes Target, violating thread binding.
gab5e69cff2016-08-05 03:25:40870 ASSERT_DCHECK_DEATH(target.reset());
[email protected]ca8c0342013-06-01 01:19:39871
872 // |target.reset()| died so |target| still holds the object, so we
873 // must pass it to the background thread to teardown.
874 background.DeleteTarget(target.release());
[email protected]ed3f67342013-05-29 08:04:32875}
876
877TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) {
878 // The default style "fast" does not support multi-threaded tests
879 // (introduces deadlock on Linux).
Daniel Cheng4ef1552f2023-12-05 02:55:54880 GTEST_FLAG_SET(death_test_style, "threadsafe");
[email protected]ed3f67342013-05-29 08:04:32881
dcheng093de9b2016-04-04 21:25:51882 std::unique_ptr<Target> target(new Target());
[email protected]ed3f67342013-05-29 08:04:32883
884 // Main thread creates an arrow referencing the Target, and references it, so
885 // that it becomes bound to the thread.
886 Arrow arrow;
887 arrow.target = target->AsWeakPtr();
888 arrow.target.get();
889
890 // Background thread tries to delete target, volating thread binding.
[email protected]5d6688f2012-07-11 21:39:03891 BackgroundThread background;
892 background.Start();
gab5e69cff2016-08-05 03:25:40893 ASSERT_DCHECK_DEATH(background.DeleteTarget(target.release()));
[email protected]5d6688f2012-07-11 21:39:03894}
895
[email protected]ed3f67342013-05-29 08:04:32896TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
897 // The default style "fast" does not support multi-threaded tests
898 // (introduces deadlock on Linux).
Daniel Cheng4ef1552f2023-12-05 02:55:54899 GTEST_FLAG_SET(death_test_style, "threadsafe");
[email protected]ed3f67342013-05-29 08:04:32900
dcheng093de9b2016-04-04 21:25:51901 std::unique_ptr<Target> target(new Target());
[email protected]ed3f67342013-05-29 08:04:32902
903 // Main thread creates an arrow referencing the Target.
904 Arrow arrow;
905 arrow.target = target->AsWeakPtr();
906
907 // Background thread tries to delete target, binding the object to the thread.
908 BackgroundThread background;
909 background.Start();
910 background.DeleteTarget(target.release());
911
912 // Main thread attempts to dereference the target, violating thread binding.
gab5e69cff2016-08-05 03:25:40913 ASSERT_DCHECK_DEATH(arrow.target.get());
[email protected]ed3f67342013-05-29 08:04:32914}
915
Daniel Cheng0b308a02020-10-13 19:17:03916TEST(WeakPtrDeathTest, ArrowOperatorChecksOnBadDereference) {
917 // The default style "fast" does not support multi-threaded tests
918 // (introduces deadlock on Linux).
Daniel Cheng4ef1552f2023-12-05 02:55:54919 GTEST_FLAG_SET(death_test_style, "threadsafe");
Daniel Cheng0b308a02020-10-13 19:17:03920
921 auto target = std::make_unique<Target>();
922 WeakPtr<Target> weak = target->AsWeakPtr();
923 target.reset();
924 EXPECT_CHECK_DEATH(weak->AsWeakPtr());
925}
926
927TEST(WeakPtrDeathTest, StarOperatorChecksOnBadDereference) {
928 // The default style "fast" does not support multi-threaded tests
929 // (introduces deadlock on Linux).
Daniel Cheng4ef1552f2023-12-05 02:55:54930 GTEST_FLAG_SET(death_test_style, "threadsafe");
Daniel Cheng0b308a02020-10-13 19:17:03931
932 auto target = std::make_unique<Target>();
933 WeakPtr<Target> weak = target->AsWeakPtr();
934 target.reset();
935 EXPECT_CHECK_DEATH((*weak).AsWeakPtr());
936}
937
[email protected]3125d6462009-09-01 20:50:17938} // namespace base