1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/memory/weak_ptr.h"
6
7 #include <memory>
8 #include <string>
9
10 #include "base/debug/leak_annotations.h"
11 #include "base/functional/bind.h"
12 #include "base/location.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/task/single_thread_task_runner.h"
15 #include "base/test/gtest_util.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/threading/thread.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace base {
21
22 namespace subtle {
23
24 class BindWeakPtrFactoryForTesting {
25 public:
26 template <typename T>
BindToCurrentSequence(WeakPtrFactory<T> & factory)27 static void BindToCurrentSequence(WeakPtrFactory<T>& factory) {
28 factory.BindToCurrentSequence(BindWeakPtrFactoryPassKey());
29 }
30 };
31
32 } // namespace subtle
33
34 namespace {
35
PassThru(WeakPtr<int> ptr)36 WeakPtr<int> PassThru(WeakPtr<int> ptr) {
37 return ptr;
38 }
39
40 template <class T>
41 class OffThreadObjectCreator {
42 public:
NewObject()43 static T* NewObject() {
44 T* result;
45 {
46 Thread creator_thread("creator_thread");
47 creator_thread.Start();
48 creator_thread.task_runner()->PostTask(
49 FROM_HERE,
50 base::BindOnce(OffThreadObjectCreator::CreateObject, &result));
51 }
52 DCHECK(result); // We synchronized on thread destruction above.
53 return result;
54 }
55 private:
CreateObject(T ** result)56 static void CreateObject(T** result) {
57 *result = new T;
58 }
59 };
60
61 struct Base {
62 std::string member;
63 };
64 struct Derived : public Base {};
65
66 struct TargetBase {};
67
68 struct Target : public TargetBase {
69 virtual ~Target() = default;
AsWeakPtrbase::__anon45defd890111::Target70 WeakPtr<Target> AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
71
72 private:
73 WeakPtrFactory<Target> weak_ptr_factory_{this};
74 };
75
76 struct DerivedTarget : public Target {};
77
78 // A class inheriting from Target and defining a nested type called 'Base'.
79 // To guard against strange compilation errors.
80 struct DerivedTargetWithNestedBase : public Target {
81 using Base = void;
82 };
83
84 // A struct with a virtual destructor.
85 struct VirtualDestructor {
86 virtual ~VirtualDestructor() = default;
87 };
88
89 // A class inheriting from Target where Target is not the first base, and where
90 // the first base has a virtual method table. This creates a structure where the
91 // Target base is not positioned at the beginning of
92 // DerivedTargetMultipleInheritance.
93 struct DerivedTargetMultipleInheritance : public VirtualDestructor,
94 public Target {};
95
96 struct Arrow {
97 WeakPtr<Target> target;
98 };
99 struct TargetWithFactory : public Target {
100 TargetWithFactory() = default;
101 WeakPtrFactory<Target> factory{this};
102 };
103
104 // Helper class to create and destroy weak pointer copies
105 // and delete objects on a background thread.
106 class BackgroundThread : public Thread {
107 public:
BackgroundThread()108 BackgroundThread() : Thread("owner_thread") {}
109
~BackgroundThread()110 ~BackgroundThread() override { Stop(); }
111
CreateArrowFromTarget(Arrow ** arrow,Target * target)112 void CreateArrowFromTarget(Arrow** arrow, Target* target) {
113 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
114 WaitableEvent::InitialState::NOT_SIGNALED);
115 task_runner()->PostTask(
116 FROM_HERE, base::BindOnce(&BackgroundThread::DoCreateArrowFromTarget,
117 arrow, target, &completion));
118 completion.Wait();
119 }
120
CreateArrowFromArrow(Arrow ** arrow,const Arrow * other)121 void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
122 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
123 WaitableEvent::InitialState::NOT_SIGNALED);
124 task_runner()->PostTask(
125 FROM_HERE, base::BindOnce(&BackgroundThread::DoCreateArrowFromArrow,
126 arrow, other, &completion));
127 completion.Wait();
128 }
129
DeleteTarget(Target * object)130 void DeleteTarget(Target* object) {
131 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
132 WaitableEvent::InitialState::NOT_SIGNALED);
133 task_runner()->PostTask(
134 FROM_HERE,
135 base::BindOnce(&BackgroundThread::DoDeleteTarget, object, &completion));
136 completion.Wait();
137 }
138
CopyAndAssignArrow(Arrow * object)139 void CopyAndAssignArrow(Arrow* object) {
140 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
141 WaitableEvent::InitialState::NOT_SIGNALED);
142 task_runner()->PostTask(
143 FROM_HERE, base::BindOnce(&BackgroundThread::DoCopyAndAssignArrow,
144 object, &completion));
145 completion.Wait();
146 }
147
CopyAndAssignArrowBase(Arrow * object)148 void CopyAndAssignArrowBase(Arrow* object) {
149 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
150 WaitableEvent::InitialState::NOT_SIGNALED);
151 task_runner()->PostTask(
152 FROM_HERE, base::BindOnce(&BackgroundThread::DoCopyAndAssignArrowBase,
153 object, &completion));
154 completion.Wait();
155 }
156
DeleteArrow(Arrow * object)157 void DeleteArrow(Arrow* object) {
158 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
159 WaitableEvent::InitialState::NOT_SIGNALED);
160 task_runner()->PostTask(
161 FROM_HERE,
162 base::BindOnce(&BackgroundThread::DoDeleteArrow, object, &completion));
163 completion.Wait();
164 }
165
DeRef(const Arrow * arrow)166 Target* DeRef(const Arrow* arrow) {
167 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
168 WaitableEvent::InitialState::NOT_SIGNALED);
169 Target* result = nullptr;
170 task_runner()->PostTask(
171 FROM_HERE, base::BindOnce(&BackgroundThread::DoDeRef, arrow, &result,
172 &completion));
173 completion.Wait();
174 return result;
175 }
176
BindToCurrentSequence(TargetWithFactory * target_with_factory)177 void BindToCurrentSequence(TargetWithFactory* target_with_factory) {
178 WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
179 WaitableEvent::InitialState::NOT_SIGNALED);
180 task_runner()->PostTask(
181 FROM_HERE, base::BindOnce(&BackgroundThread::DoBindToCurrentSequence,
182 target_with_factory, &completion));
183 completion.Wait();
184 }
185
186 protected:
DoCreateArrowFromArrow(Arrow ** arrow,const Arrow * other,WaitableEvent * completion)187 static void DoCreateArrowFromArrow(Arrow** arrow,
188 const Arrow* other,
189 WaitableEvent* completion) {
190 *arrow = new Arrow;
191 **arrow = *other;
192 completion->Signal();
193 }
194
DoCreateArrowFromTarget(Arrow ** arrow,Target * target,WaitableEvent * completion)195 static void DoCreateArrowFromTarget(Arrow** arrow,
196 Target* target,
197 WaitableEvent* completion) {
198 *arrow = new Arrow;
199 (*arrow)->target = target->AsWeakPtr();
200 completion->Signal();
201 }
202
DoDeRef(const Arrow * arrow,Target ** result,WaitableEvent * completion)203 static void DoDeRef(const Arrow* arrow,
204 Target** result,
205 WaitableEvent* completion) {
206 *result = arrow->target.get();
207 completion->Signal();
208 }
209
DoDeleteTarget(Target * object,WaitableEvent * completion)210 static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
211 delete object;
212 completion->Signal();
213 }
214
DoCopyAndAssignArrow(Arrow * object,WaitableEvent * completion)215 static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) {
216 // Copy constructor.
217 Arrow a = *object;
218 // Assignment operator.
219 *object = a;
220 completion->Signal();
221 }
222
DoCopyAndAssignArrowBase(Arrow * object,WaitableEvent * completion)223 static void DoCopyAndAssignArrowBase(
224 Arrow* object,
225 WaitableEvent* completion) {
226 // Copy constructor.
227 WeakPtr<TargetBase> b = object->target;
228 // Assignment operator.
229 WeakPtr<TargetBase> c;
230 c = object->target;
231 completion->Signal();
232 }
233
DoDeleteArrow(Arrow * object,WaitableEvent * completion)234 static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
235 delete object;
236 completion->Signal();
237 }
238
DoBindToCurrentSequence(TargetWithFactory * target_with_factory,WaitableEvent * completion)239 static void DoBindToCurrentSequence(TargetWithFactory* target_with_factory,
240 WaitableEvent* completion) {
241 subtle::BindWeakPtrFactoryForTesting::BindToCurrentSequence(
242 target_with_factory->factory);
243 completion->Signal();
244 }
245 };
246
247 } // namespace
248
TEST(WeakPtrFactoryTest,Basic)249 TEST(WeakPtrFactoryTest, Basic) {
250 int data;
251 WeakPtrFactory<int> factory(&data);
252 WeakPtr<int> ptr = factory.GetWeakPtr();
253 EXPECT_EQ(&data, ptr.get());
254 }
255
TEST(WeakPtrFactoryTest,Comparison)256 TEST(WeakPtrFactoryTest, Comparison) {
257 int data;
258 WeakPtrFactory<int> factory(&data);
259 WeakPtr<int> ptr = factory.GetWeakPtr();
260 WeakPtr<int> ptr2 = ptr;
261 EXPECT_EQ(ptr.get(), ptr2.get());
262 }
263
TEST(WeakPtrFactoryTest,Move)264 TEST(WeakPtrFactoryTest, Move) {
265 int data;
266 WeakPtrFactory<int> factory(&data);
267 WeakPtr<int> ptr = factory.GetWeakPtr();
268 WeakPtr<int> ptr2 = factory.GetWeakPtr();
269 WeakPtr<int> ptr3 = std::move(ptr2);
270 EXPECT_NE(ptr.get(), ptr2.get());
271 EXPECT_EQ(ptr.get(), ptr3.get());
272 }
273
TEST(WeakPtrFactoryTest,OutOfScope)274 TEST(WeakPtrFactoryTest, OutOfScope) {
275 WeakPtr<int> ptr;
276 EXPECT_EQ(nullptr, ptr.get());
277 {
278 int data;
279 WeakPtrFactory<int> factory(&data);
280 ptr = factory.GetWeakPtr();
281 }
282 EXPECT_EQ(nullptr, ptr.get());
283 }
284
TEST(WeakPtrFactoryTest,Multiple)285 TEST(WeakPtrFactoryTest, Multiple) {
286 WeakPtr<int> a, b;
287 {
288 int data;
289 WeakPtrFactory<int> factory(&data);
290 a = factory.GetWeakPtr();
291 b = factory.GetWeakPtr();
292 EXPECT_EQ(&data, a.get());
293 EXPECT_EQ(&data, b.get());
294 }
295 EXPECT_EQ(nullptr, a.get());
296 EXPECT_EQ(nullptr, b.get());
297 }
298
TEST(WeakPtrFactoryTest,MultipleStaged)299 TEST(WeakPtrFactoryTest, MultipleStaged) {
300 WeakPtr<int> a;
301 {
302 int data;
303 WeakPtrFactory<int> factory(&data);
304 a = factory.GetWeakPtr();
305 {
306 WeakPtr<int> b = factory.GetWeakPtr();
307 }
308 EXPECT_NE(nullptr, a.get());
309 }
310 EXPECT_EQ(nullptr, a.get());
311 }
312
TEST(WeakPtrFactoryTest,Dereference)313 TEST(WeakPtrFactoryTest, Dereference) {
314 Base data;
315 data.member = "123456";
316 WeakPtrFactory<Base> factory(&data);
317 WeakPtr<Base> ptr = factory.GetWeakPtr();
318 EXPECT_EQ(&data, ptr.get());
319 EXPECT_EQ(data.member, (*ptr).member);
320 EXPECT_EQ(data.member, ptr->member);
321 }
322
TEST(WeakPtrFactoryTest,UpCast)323 TEST(WeakPtrFactoryTest, UpCast) {
324 Derived data;
325 WeakPtrFactory<Derived> factory(&data);
326 WeakPtr<Base> ptr = factory.GetWeakPtr();
327 ptr = factory.GetWeakPtr();
328 EXPECT_EQ(ptr.get(), &data);
329 }
330
TEST(WeakPtrTest,ConstructFromNullptr)331 TEST(WeakPtrTest, ConstructFromNullptr) {
332 WeakPtr<int> ptr = PassThru(nullptr);
333 EXPECT_EQ(nullptr, ptr.get());
334 }
335
TEST(WeakPtrFactoryTest,BooleanTesting)336 TEST(WeakPtrFactoryTest, BooleanTesting) {
337 int data;
338 WeakPtrFactory<int> factory(&data);
339
340 WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
341 EXPECT_TRUE(ptr_to_an_instance);
342 EXPECT_FALSE(!ptr_to_an_instance);
343
344 if (ptr_to_an_instance) {
345 } else {
346 ADD_FAILURE() << "Pointer to an instance should result in true.";
347 }
348
349 if (!ptr_to_an_instance) { // check for operator!().
350 ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
351 }
352
353 WeakPtr<int> null_ptr;
354 EXPECT_FALSE(null_ptr);
355 EXPECT_TRUE(!null_ptr);
356
357 if (null_ptr) {
358 ADD_FAILURE() << "Null pointer should result in false.";
359 }
360
361 if (!null_ptr) { // check for operator!().
362 } else {
363 ADD_FAILURE() << "Null pointer should result in !x being true.";
364 }
365 }
366
TEST(WeakPtrFactoryTest,ComparisonToNull)367 TEST(WeakPtrFactoryTest, ComparisonToNull) {
368 int data;
369 WeakPtrFactory<int> factory(&data);
370
371 WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
372 EXPECT_NE(nullptr, ptr_to_an_instance);
373 EXPECT_NE(ptr_to_an_instance, nullptr);
374
375 WeakPtr<int> null_ptr;
376 EXPECT_EQ(null_ptr, nullptr);
377 EXPECT_EQ(nullptr, null_ptr);
378 }
379
380 struct ReallyBaseClass {};
381 struct BaseClass : ReallyBaseClass {
382 virtual ~BaseClass() = default;
VirtualMethodbase::BaseClass383 void VirtualMethod() {}
384 };
385 struct OtherBaseClass {
386 virtual ~OtherBaseClass() = default;
VirtualMethodbase::OtherBaseClass387 virtual void VirtualMethod() {}
388 };
389 struct WithWeak final : BaseClass, OtherBaseClass {
390 WeakPtrFactory<WithWeak> factory{this};
391 };
392
TEST(WeakPtrTest,ConversionOffsetsPointer)393 TEST(WeakPtrTest, ConversionOffsetsPointer) {
394 WithWeak with;
395 WeakPtr<WithWeak> ptr(with.factory.GetWeakPtr());
396 {
397 // Copy construction.
398 WeakPtr<OtherBaseClass> base_ptr(ptr);
399 EXPECT_EQ(static_cast<WithWeak*>(&*base_ptr), &with);
400 }
401 {
402 // Move construction.
403 WeakPtr<OtherBaseClass> base_ptr(std::move(ptr));
404 EXPECT_EQ(static_cast<WithWeak*>(&*base_ptr), &with);
405 }
406
407 // WeakPtr doesn't have conversion operators for assignment.
408 }
409
TEST(WeakPtrTest,InvalidateWeakPtrs)410 TEST(WeakPtrTest, InvalidateWeakPtrs) {
411 int data;
412 WeakPtrFactory<int> factory(&data);
413 WeakPtr<int> ptr = factory.GetWeakPtr();
414 EXPECT_EQ(&data, ptr.get());
415 EXPECT_TRUE(factory.HasWeakPtrs());
416 factory.InvalidateWeakPtrs();
417 EXPECT_EQ(nullptr, ptr.get());
418 EXPECT_FALSE(factory.HasWeakPtrs());
419
420 // Test that the factory can create new weak pointers after a
421 // InvalidateWeakPtrs call, and they remain valid until the next
422 // InvalidateWeakPtrs call.
423 WeakPtr<int> ptr2 = factory.GetWeakPtr();
424 EXPECT_EQ(&data, ptr2.get());
425 EXPECT_TRUE(factory.HasWeakPtrs());
426 factory.InvalidateWeakPtrs();
427 EXPECT_EQ(nullptr, ptr2.get());
428 EXPECT_FALSE(factory.HasWeakPtrs());
429 }
430
431 // Tests that WasInvalidated() is true only for invalidated WeakPtrs (not
432 // nullptr) and doesn't DCHECK (e.g. because of a dereference attempt).
TEST(WeakPtrTest,WasInvalidatedByFactoryDestruction)433 TEST(WeakPtrTest, WasInvalidatedByFactoryDestruction) {
434 WeakPtr<int> ptr;
435 EXPECT_FALSE(ptr.WasInvalidated());
436
437 // Test |data| destroyed. That is, the typical pattern when |data| (and its
438 // associated factory) go out of scope.
439 {
440 int data = 0;
441 WeakPtrFactory<int> factory(&data);
442 ptr = factory.GetWeakPtr();
443
444 // Verify that a live WeakPtr is not reported as Invalidated.
445 EXPECT_FALSE(ptr.WasInvalidated());
446 }
447
448 // Checking validity shouldn't read beyond the stack frame.
449 EXPECT_TRUE(ptr.WasInvalidated());
450 ptr = nullptr;
451 EXPECT_FALSE(ptr.WasInvalidated());
452 }
453
454 // As above, but testing InvalidateWeakPtrs().
TEST(WeakPtrTest,WasInvalidatedByInvalidateWeakPtrs)455 TEST(WeakPtrTest, WasInvalidatedByInvalidateWeakPtrs) {
456 int data = 0;
457 WeakPtrFactory<int> factory(&data);
458 WeakPtr<int> ptr = factory.GetWeakPtr();
459 EXPECT_FALSE(ptr.WasInvalidated());
460 factory.InvalidateWeakPtrs();
461 EXPECT_TRUE(ptr.WasInvalidated());
462 ptr = nullptr;
463 EXPECT_FALSE(ptr.WasInvalidated());
464 }
465
466 // A WeakPtr should not be reported as 'invalidated' if nullptr was assigned to
467 // it.
TEST(WeakPtrTest,WasInvalidatedWhilstNull)468 TEST(WeakPtrTest, WasInvalidatedWhilstNull) {
469 int data = 0;
470 WeakPtrFactory<int> factory(&data);
471 WeakPtr<int> ptr = factory.GetWeakPtr();
472 EXPECT_FALSE(ptr.WasInvalidated());
473 ptr = nullptr;
474 EXPECT_FALSE(ptr.WasInvalidated());
475 factory.InvalidateWeakPtrs();
476 EXPECT_FALSE(ptr.WasInvalidated());
477 }
478
TEST(WeakPtrTest,MaybeValidOnSameSequence)479 TEST(WeakPtrTest, MaybeValidOnSameSequence) {
480 int data;
481 WeakPtrFactory<int> factory(&data);
482 WeakPtr<int> ptr = factory.GetWeakPtr();
483 EXPECT_TRUE(ptr.MaybeValid());
484 factory.InvalidateWeakPtrs();
485 // Since InvalidateWeakPtrs() ran on this sequence, MaybeValid() should be
486 // false.
487 EXPECT_FALSE(ptr.MaybeValid());
488 }
489
TEST(WeakPtrTest,MaybeValidOnOtherSequence)490 TEST(WeakPtrTest, MaybeValidOnOtherSequence) {
491 int data;
492 WeakPtrFactory<int> factory(&data);
493 WeakPtr<int> ptr = factory.GetWeakPtr();
494 EXPECT_TRUE(ptr.MaybeValid());
495
496 base::Thread other_thread("other_thread");
497 other_thread.StartAndWaitForTesting();
498 other_thread.task_runner()->PostTask(
499 FROM_HERE,
500 base::BindOnce(
501 [](WeakPtr<int> ptr) {
502 // Check that MaybeValid() _eventually_ returns false.
503 const TimeDelta timeout = TestTimeouts::tiny_timeout();
504 const TimeTicks begin = TimeTicks::Now();
505 while (ptr.MaybeValid() && (TimeTicks::Now() - begin) < timeout)
506 PlatformThread::YieldCurrentThread();
507 EXPECT_FALSE(ptr.MaybeValid());
508 },
509 ptr));
510 factory.InvalidateWeakPtrs();
511 // |other_thread|'s destructor will join, ensuring we wait for the task to be
512 // run.
513 }
514
TEST(WeakPtrTest,HasWeakPtrs)515 TEST(WeakPtrTest, HasWeakPtrs) {
516 int data;
517 WeakPtrFactory<int> factory(&data);
518 {
519 WeakPtr<int> ptr = factory.GetWeakPtr();
520 EXPECT_TRUE(factory.HasWeakPtrs());
521 }
522 EXPECT_FALSE(factory.HasWeakPtrs());
523 }
524
TEST(WeakPtrTest,ObjectAndWeakPtrOnDifferentThreads)525 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
526 // Test that it is OK to create an object that supports WeakPtr on one thread,
527 // but use it on another. This tests that we do not trip runtime checks that
528 // ensure that a WeakPtr is not used by multiple threads.
529 std::unique_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
530 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
531 EXPECT_EQ(target.get(), weak_ptr.get());
532 }
533
TEST(WeakPtrTest,WeakPtrInitiateAndUseOnDifferentThreads)534 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
535 // Test that it is OK to create an object that has a WeakPtr member on one
536 // thread, but use it on another. This tests that we do not trip runtime
537 // checks that ensure that a WeakPtr is not used by multiple threads.
538 std::unique_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
539 Target target;
540 arrow->target = target.AsWeakPtr();
541 EXPECT_EQ(&target, arrow->target.get());
542 }
543
TEST(WeakPtrTest,MoveOwnershipImplicitly)544 TEST(WeakPtrTest, MoveOwnershipImplicitly) {
545 // Move object ownership to another thread by releasing all weak pointers
546 // on the original thread first, and then establish WeakPtr on a different
547 // thread.
548 BackgroundThread background;
549 background.Start();
550
551 Target* target = new Target();
552 {
553 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
554 // Main thread deletes the WeakPtr, then the thread ownership of the
555 // object can be implicitly moved.
556 }
557 Arrow* arrow;
558
559 // Background thread creates WeakPtr(and implicitly owns the object).
560 background.CreateArrowFromTarget(&arrow, target);
561 EXPECT_EQ(background.DeRef(arrow), target);
562
563 {
564 // Main thread creates another WeakPtr, but this does not trigger implicitly
565 // thread ownership move.
566 Arrow scoped_arrow;
567 scoped_arrow.target = target->AsWeakPtr();
568
569 // The new WeakPtr is owned by background thread.
570 EXPECT_EQ(target, background.DeRef(&scoped_arrow));
571 }
572
573 // Target can only be deleted on background thread.
574 background.DeleteTarget(target);
575 background.DeleteArrow(arrow);
576 }
577
TEST(WeakPtrTest,MoveOwnershipOfUnreferencedObject)578 TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) {
579 BackgroundThread background;
580 background.Start();
581
582 Arrow* arrow;
583 {
584 Target target;
585 // Background thread creates WeakPtr.
586 background.CreateArrowFromTarget(&arrow, &target);
587
588 // Bind to background thread.
589 EXPECT_EQ(&target, background.DeRef(arrow));
590
591 // Release the only WeakPtr.
592 arrow->target.reset();
593
594 // Now we should be able to create a new reference from this thread.
595 arrow->target = target.AsWeakPtr();
596
597 // Re-bind to main thread.
598 EXPECT_EQ(&target, arrow->target.get());
599
600 // And the main thread can now delete the target.
601 }
602
603 delete arrow;
604 }
605
TEST(WeakPtrTest,MoveOwnershipAfterInvalidate)606 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
607 BackgroundThread background;
608 background.Start();
609
610 Arrow arrow;
611 std::unique_ptr<TargetWithFactory> target(new TargetWithFactory);
612
613 // Bind to main thread.
614 arrow.target = target->factory.GetWeakPtr();
615 EXPECT_EQ(target.get(), arrow.target.get());
616
617 target->factory.InvalidateWeakPtrs();
618 EXPECT_EQ(nullptr, arrow.target.get());
619
620 arrow.target = target->factory.GetWeakPtr();
621 // Re-bind to background thread.
622 EXPECT_EQ(target.get(), background.DeRef(&arrow));
623
624 // And the background thread can now delete the target.
625 background.DeleteTarget(target.release());
626 }
627
TEST(WeakPtrTest,MainThreadRefOutlivesBackgroundThreadRef)628 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
629 // Originating thread has a WeakPtr that outlives others.
630 // - Main thread creates a WeakPtr
631 // - Background thread creates a WeakPtr copy from the one in main thread
632 // - Destruct the WeakPtr on background thread
633 // - Destruct the WeakPtr on main thread
634 BackgroundThread background;
635 background.Start();
636
637 Target target;
638 Arrow arrow;
639 arrow.target = target.AsWeakPtr();
640
641 Arrow* arrow_copy;
642 background.CreateArrowFromArrow(&arrow_copy, &arrow);
643 EXPECT_EQ(arrow_copy->target.get(), &target);
644 background.DeleteArrow(arrow_copy);
645 }
646
TEST(WeakPtrTest,BackgroundThreadRefOutlivesMainThreadRef)647 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
648 // Originating thread drops all references before another thread.
649 // - Main thread creates a WeakPtr and passes copy to background thread
650 // - Destruct the pointer on main thread
651 // - Destruct the pointer on background thread
652 BackgroundThread background;
653 background.Start();
654
655 Target target;
656 Arrow* arrow_copy;
657 {
658 Arrow arrow;
659 arrow.target = target.AsWeakPtr();
660 background.CreateArrowFromArrow(&arrow_copy, &arrow);
661 }
662 EXPECT_EQ(arrow_copy->target.get(), &target);
663 background.DeleteArrow(arrow_copy);
664 }
665
TEST(WeakPtrTest,OwnerThreadDeletesObject)666 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
667 // Originating thread invalidates WeakPtrs while its held by other thread.
668 // - Main thread creates WeakPtr and passes Copy to background thread
669 // - Object gets destroyed on main thread
670 // (invalidates WeakPtr on background thread)
671 // - WeakPtr gets destroyed on Thread B
672 BackgroundThread background;
673 background.Start();
674 Arrow* arrow_copy;
675 {
676 Target target;
677 Arrow arrow;
678 arrow.target = target.AsWeakPtr();
679 background.CreateArrowFromArrow(&arrow_copy, &arrow);
680 }
681 EXPECT_EQ(nullptr, arrow_copy->target.get());
682 background.DeleteArrow(arrow_copy);
683 }
684
TEST(WeakPtrTest,NonOwnerThreadCanCopyAndAssignWeakPtr)685 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
686 // Main thread creates a Target object.
687 Target target;
688 // Main thread creates an arrow referencing the Target.
689 Arrow *arrow = new Arrow();
690 arrow->target = target.AsWeakPtr();
691
692 // Background can copy and assign arrow (as well as the WeakPtr inside).
693 BackgroundThread background;
694 background.Start();
695 background.CopyAndAssignArrow(arrow);
696 background.DeleteArrow(arrow);
697 }
698
TEST(WeakPtrTest,NonOwnerThreadCanCopyAndAssignWeakPtrBase)699 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
700 // Main thread creates a Target object.
701 Target target;
702 // Main thread creates an arrow referencing the Target.
703 Arrow *arrow = new Arrow();
704 arrow->target = target.AsWeakPtr();
705
706 // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
707 BackgroundThread background;
708 background.Start();
709 background.CopyAndAssignArrowBase(arrow);
710 background.DeleteArrow(arrow);
711 }
712
TEST(WeakPtrTest,NonOwnerThreadCanDeleteWeakPtr)713 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
714 // Main thread creates a Target object.
715 Target target;
716 // Main thread creates an arrow referencing the Target.
717 Arrow* arrow = new Arrow();
718 arrow->target = target.AsWeakPtr();
719
720 // Background can delete arrow (as well as the WeakPtr inside).
721 BackgroundThread background;
722 background.Start();
723 background.DeleteArrow(arrow);
724 }
725
TEST(WeakPtrTest,ConstUpCast)726 TEST(WeakPtrTest, ConstUpCast) {
727 Target target;
728
729 // WeakPtrs can upcast from non-const T to const T.
730 WeakPtr<const Target> const_weak_ptr = target.AsWeakPtr();
731
732 // WeakPtrs don't enable conversion from const T to nonconst T.
733 static_assert(
734 !std::is_constructible_v<WeakPtr<Target>, WeakPtr<const Target>>);
735 }
736
TEST(WeakPtrTest,ConstGetWeakPtr)737 TEST(WeakPtrTest, ConstGetWeakPtr) {
738 struct TestTarget {
739 const char* Method() const { return "const method"; }
740 const char* Method() { return "non-const method"; }
741
742 WeakPtrFactory<TestTarget> weak_ptr_factory{this};
743 } non_const_test_target;
744
745 const TestTarget& const_test_target = non_const_test_target;
746
747 EXPECT_EQ(const_test_target.weak_ptr_factory.GetWeakPtr()->Method(),
748 "const method");
749 EXPECT_EQ(non_const_test_target.weak_ptr_factory.GetWeakPtr()->Method(),
750 "non-const method");
751 EXPECT_EQ(const_test_target.weak_ptr_factory.GetMutableWeakPtr()->Method(),
752 "non-const method");
753 }
754
TEST(WeakPtrTest,GetMutableWeakPtr)755 TEST(WeakPtrTest, GetMutableWeakPtr) {
756 struct TestStruct {
757 int member = 0;
758 WeakPtrFactory<TestStruct> weak_ptr_factory{this};
759 };
760 TestStruct test_struct;
761 EXPECT_EQ(test_struct.member, 0);
762
763 // GetMutableWeakPtr() grants non-const access to T.
764 const TestStruct& const_test_struct = test_struct;
765 WeakPtr<TestStruct> weak_ptr =
766 const_test_struct.weak_ptr_factory.GetMutableWeakPtr();
767 weak_ptr->member = 1;
768 EXPECT_EQ(test_struct.member, 1);
769 }
770
TEST(WeakPtrDeathTest,BindToCurrentSequence)771 TEST(WeakPtrDeathTest, BindToCurrentSequence) {
772 BackgroundThread background;
773 background.Start();
774
775 TargetWithFactory target_with_factory;
776 Arrow arrow{
777 .target = target_with_factory.factory.GetWeakPtr(),
778 };
779
780 // WeakPtr can be accessed on main thread.
781 EXPECT_TRUE(arrow.target.get());
782
783 background.BindToCurrentSequence(&target_with_factory);
784
785 // Now WeakPtr can be accessed on background thread.
786 EXPECT_TRUE(background.DeRef(&arrow));
787
788 // WeakPtr can no longer be accessed on main thread.
789 EXPECT_DCHECK_DEATH(arrow.target.get());
790 }
791
TEST(WeakPtrDeathTest,WeakPtrCopyDoesNotChangeThreadBinding)792 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
793 // The default style "fast" does not support multi-threaded tests
794 // (introduces deadlock on Linux).
795 GTEST_FLAG_SET(death_test_style, "threadsafe");
796
797 BackgroundThread background;
798 background.Start();
799
800 // Main thread creates a Target object.
801 Target target;
802 // Main thread creates an arrow referencing the Target.
803 Arrow arrow;
804 arrow.target = target.AsWeakPtr();
805
806 // Background copies the WeakPtr.
807 Arrow* arrow_copy;
808 background.CreateArrowFromArrow(&arrow_copy, &arrow);
809
810 // The copy is still bound to main thread so I can deref.
811 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
812
813 // Although background thread created the copy, it can not deref the copied
814 // WeakPtr.
815 ASSERT_DCHECK_DEATH(background.DeRef(arrow_copy));
816
817 background.DeleteArrow(arrow_copy);
818 }
819
TEST(WeakPtrDeathTest,NonOwnerThreadDereferencesWeakPtrAfterReference)820 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) {
821 // The default style "fast" does not support multi-threaded tests
822 // (introduces deadlock on Linux).
823 GTEST_FLAG_SET(death_test_style, "threadsafe");
824
825 // Main thread creates a Target object.
826 Target target;
827
828 // Main thread creates an arrow referencing the Target (so target's
829 // thread ownership can not be implicitly moved).
830 Arrow arrow;
831 arrow.target = target.AsWeakPtr();
832 arrow.target.get();
833
834 // Background thread tries to deref target, which violates thread ownership.
835 BackgroundThread background;
836 background.Start();
837 ASSERT_DCHECK_DEATH(background.DeRef(&arrow));
838 }
839
TEST(WeakPtrDeathTest,NonOwnerThreadDeletesWeakPtrAfterReference)840 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) {
841 // The default style "fast" does not support multi-threaded tests
842 // (introduces deadlock on Linux).
843 GTEST_FLAG_SET(death_test_style, "threadsafe");
844
845 std::unique_ptr<Target> target(new Target());
846
847 // Main thread creates an arrow referencing the Target.
848 Arrow arrow;
849 arrow.target = target->AsWeakPtr();
850
851 // Background thread tries to deref target, binding it to the thread.
852 BackgroundThread background;
853 background.Start();
854 background.DeRef(&arrow);
855
856 // Main thread deletes Target, violating thread binding.
857 ASSERT_DCHECK_DEATH(target.reset());
858
859 // |target.reset()| died so |target| still holds the object, so we
860 // must pass it to the background thread to teardown.
861 background.DeleteTarget(target.release());
862 }
863
TEST(WeakPtrDeathTest,NonOwnerThreadDeletesObjectAfterReference)864 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) {
865 // The default style "fast" does not support multi-threaded tests
866 // (introduces deadlock on Linux).
867 GTEST_FLAG_SET(death_test_style, "threadsafe");
868
869 std::unique_ptr<Target> target(new Target());
870
871 // Main thread creates an arrow referencing the Target, and references it, so
872 // that it becomes bound to the thread.
873 Arrow arrow;
874 arrow.target = target->AsWeakPtr();
875 arrow.target.get();
876
877 // Background thread tries to delete target, volating thread binding.
878 BackgroundThread background;
879 background.Start();
880 ASSERT_DCHECK_DEATH(background.DeleteTarget(target.release()));
881 }
882
TEST(WeakPtrDeathTest,NonOwnerThreadReferencesObjectAfterDeletion)883 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
884 // The default style "fast" does not support multi-threaded tests
885 // (introduces deadlock on Linux).
886 GTEST_FLAG_SET(death_test_style, "threadsafe");
887
888 std::unique_ptr<Target> target(new Target());
889
890 // Main thread creates an arrow referencing the Target.
891 Arrow arrow;
892 arrow.target = target->AsWeakPtr();
893
894 // Background thread tries to delete target, binding the object to the thread.
895 BackgroundThread background;
896 background.Start();
897 background.DeleteTarget(target.release());
898
899 // Main thread attempts to dereference the target, violating thread binding.
900 ASSERT_DCHECK_DEATH(arrow.target.get());
901 }
902
TEST(WeakPtrDeathTest,ArrowOperatorChecksOnBadDereference)903 TEST(WeakPtrDeathTest, ArrowOperatorChecksOnBadDereference) {
904 // The default style "fast" does not support multi-threaded tests
905 // (introduces deadlock on Linux).
906 GTEST_FLAG_SET(death_test_style, "threadsafe");
907
908 auto target = std::make_unique<Target>();
909 WeakPtr<Target> weak = target->AsWeakPtr();
910 target.reset();
911 EXPECT_CHECK_DEATH(weak->AsWeakPtr());
912 }
913
TEST(WeakPtrDeathTest,StarOperatorChecksOnBadDereference)914 TEST(WeakPtrDeathTest, StarOperatorChecksOnBadDereference) {
915 // The default style "fast" does not support multi-threaded tests
916 // (introduces deadlock on Linux).
917 GTEST_FLAG_SET(death_test_style, "threadsafe");
918
919 auto target = std::make_unique<Target>();
920 WeakPtr<Target> weak = target->AsWeakPtr();
921 target.reset();
922 EXPECT_CHECK_DEATH((*weak).AsWeakPtr());
923 }
924
925 } // namespace base
926