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