• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
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/bind.h"
11 #include "base/debug/leak_annotations.h"
12 #include "base/location.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/test/gtest_util.h"
16 #include "base/threading/thread.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 namespace base {
20 namespace {
21 
PassThru(WeakPtr<int> ptr)22 WeakPtr<int> PassThru(WeakPtr<int> ptr) {
23   return ptr;
24 }
25 
26 template <class T>
27 class OffThreadObjectCreator {
28  public:
NewObject()29   static T* NewObject() {
30     T* result;
31     {
32       Thread creator_thread("creator_thread");
33       creator_thread.Start();
34       creator_thread.task_runner()->PostTask(
35           FROM_HERE,
36           base::BindOnce(OffThreadObjectCreator::CreateObject, &result));
37     }
38     DCHECK(result);  // We synchronized on thread destruction above.
39     return result;
40   }
41  private:
CreateObject(T ** result)42   static void CreateObject(T** result) {
43     *result = new T;
44   }
45 };
46 
47 struct Base {
48   std::string member;
49 };
50 struct Derived : public Base {};
51 
52 struct TargetBase {};
53 struct Target : public TargetBase, public SupportsWeakPtr<Target> {
54   virtual ~Target() = default;
55 };
56 
57 struct DerivedTarget : public Target {};
58 
59 // A class inheriting from Target and defining a nested type called 'Base'.
60 // To guard against strange compilation errors.
61 struct DerivedTargetWithNestedBase : public Target {
62   using Base = void;
63 };
64 
65 // A struct with a virtual destructor.
66 struct VirtualDestructor {
67   virtual ~VirtualDestructor() = default;
68 };
69 
70 // A class inheriting from Target where Target is not the first base, and where
71 // the first base has a virtual method table. This creates a structure where the
72 // Target base is not positioned at the beginning of
73 // DerivedTargetMultipleInheritance.
74 struct DerivedTargetMultipleInheritance : public VirtualDestructor,
75                                           public Target {};
76 
77 struct Arrow {
78   WeakPtr<Target> target;
79 };
80 struct TargetWithFactory : public Target {
TargetWithFactorybase::__anon14485c400111::TargetWithFactory81   TargetWithFactory() : factory(this) {}
82   WeakPtrFactory<Target> factory;
83 };
84 
85 // Helper class to create and destroy weak pointer copies
86 // and delete objects on a background thread.
87 class BackgroundThread : public Thread {
88  public:
BackgroundThread()89   BackgroundThread() : Thread("owner_thread") {}
90 
~BackgroundThread()91   ~BackgroundThread() override { Stop(); }
92 
CreateArrowFromTarget(Arrow ** arrow,Target * target)93   void CreateArrowFromTarget(Arrow** arrow, Target* target) {
94     WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
95                              WaitableEvent::InitialState::NOT_SIGNALED);
96     task_runner()->PostTask(
97         FROM_HERE, base::BindOnce(&BackgroundThread::DoCreateArrowFromTarget,
98                                   arrow, target, &completion));
99     completion.Wait();
100   }
101 
CreateArrowFromArrow(Arrow ** arrow,const Arrow * other)102   void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
103     WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
104                              WaitableEvent::InitialState::NOT_SIGNALED);
105     task_runner()->PostTask(
106         FROM_HERE, base::BindOnce(&BackgroundThread::DoCreateArrowFromArrow,
107                                   arrow, other, &completion));
108     completion.Wait();
109   }
110 
DeleteTarget(Target * object)111   void DeleteTarget(Target* object) {
112     WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
113                              WaitableEvent::InitialState::NOT_SIGNALED);
114     task_runner()->PostTask(
115         FROM_HERE,
116         base::BindOnce(&BackgroundThread::DoDeleteTarget, object, &completion));
117     completion.Wait();
118   }
119 
CopyAndAssignArrow(Arrow * object)120   void CopyAndAssignArrow(Arrow* object) {
121     WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
122                              WaitableEvent::InitialState::NOT_SIGNALED);
123     task_runner()->PostTask(
124         FROM_HERE, base::BindOnce(&BackgroundThread::DoCopyAndAssignArrow,
125                                   object, &completion));
126     completion.Wait();
127   }
128 
CopyAndAssignArrowBase(Arrow * object)129   void CopyAndAssignArrowBase(Arrow* object) {
130     WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
131                              WaitableEvent::InitialState::NOT_SIGNALED);
132     task_runner()->PostTask(
133         FROM_HERE, base::BindOnce(&BackgroundThread::DoCopyAndAssignArrowBase,
134                                   object, &completion));
135     completion.Wait();
136   }
137 
DeleteArrow(Arrow * object)138   void DeleteArrow(Arrow* object) {
139     WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
140                              WaitableEvent::InitialState::NOT_SIGNALED);
141     task_runner()->PostTask(
142         FROM_HERE,
143         base::BindOnce(&BackgroundThread::DoDeleteArrow, object, &completion));
144     completion.Wait();
145   }
146 
DeRef(const Arrow * arrow)147   Target* DeRef(const Arrow* arrow) {
148     WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
149                              WaitableEvent::InitialState::NOT_SIGNALED);
150     Target* result = nullptr;
151     task_runner()->PostTask(
152         FROM_HERE, base::BindOnce(&BackgroundThread::DoDeRef, arrow, &result,
153                                   &completion));
154     completion.Wait();
155     return result;
156   }
157 
158  protected:
DoCreateArrowFromArrow(Arrow ** arrow,const Arrow * other,WaitableEvent * completion)159   static void DoCreateArrowFromArrow(Arrow** arrow,
160                                      const Arrow* other,
161                                      WaitableEvent* completion) {
162     *arrow = new Arrow;
163     **arrow = *other;
164     completion->Signal();
165   }
166 
DoCreateArrowFromTarget(Arrow ** arrow,Target * target,WaitableEvent * completion)167   static void DoCreateArrowFromTarget(Arrow** arrow,
168                                       Target* target,
169                                       WaitableEvent* completion) {
170     *arrow = new Arrow;
171     (*arrow)->target = target->AsWeakPtr();
172     completion->Signal();
173   }
174 
DoDeRef(const Arrow * arrow,Target ** result,WaitableEvent * completion)175   static void DoDeRef(const Arrow* arrow,
176                       Target** result,
177                       WaitableEvent* completion) {
178     *result = arrow->target.get();
179     completion->Signal();
180   }
181 
DoDeleteTarget(Target * object,WaitableEvent * completion)182   static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
183     delete object;
184     completion->Signal();
185   }
186 
DoCopyAndAssignArrow(Arrow * object,WaitableEvent * completion)187   static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) {
188     // Copy constructor.
189     Arrow a = *object;
190     // Assignment operator.
191     *object = a;
192     completion->Signal();
193   }
194 
DoCopyAndAssignArrowBase(Arrow * object,WaitableEvent * completion)195   static void DoCopyAndAssignArrowBase(
196       Arrow* object,
197       WaitableEvent* completion) {
198     // Copy constructor.
199     WeakPtr<TargetBase> b = object->target;
200     // Assignment operator.
201     WeakPtr<TargetBase> c;
202     c = object->target;
203     completion->Signal();
204   }
205 
DoDeleteArrow(Arrow * object,WaitableEvent * completion)206   static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
207     delete object;
208     completion->Signal();
209   }
210 };
211 
212 }  // namespace
213 
TEST(WeakPtrFactoryTest,Basic)214 TEST(WeakPtrFactoryTest, Basic) {
215   int data;
216   WeakPtrFactory<int> factory(&data);
217   WeakPtr<int> ptr = factory.GetWeakPtr();
218   EXPECT_EQ(&data, ptr.get());
219 }
220 
TEST(WeakPtrFactoryTest,Comparison)221 TEST(WeakPtrFactoryTest, Comparison) {
222   int data;
223   WeakPtrFactory<int> factory(&data);
224   WeakPtr<int> ptr = factory.GetWeakPtr();
225   WeakPtr<int> ptr2 = ptr;
226   EXPECT_EQ(ptr.get(), ptr2.get());
227 }
228 
TEST(WeakPtrFactoryTest,Move)229 TEST(WeakPtrFactoryTest, Move) {
230   int data;
231   WeakPtrFactory<int> factory(&data);
232   WeakPtr<int> ptr = factory.GetWeakPtr();
233   WeakPtr<int> ptr2 = factory.GetWeakPtr();
234   WeakPtr<int> ptr3 = std::move(ptr2);
235   EXPECT_NE(ptr.get(), ptr2.get());
236   EXPECT_EQ(ptr.get(), ptr3.get());
237 }
238 
TEST(WeakPtrFactoryTest,OutOfScope)239 TEST(WeakPtrFactoryTest, OutOfScope) {
240   WeakPtr<int> ptr;
241   EXPECT_EQ(nullptr, ptr.get());
242   {
243     int data;
244     WeakPtrFactory<int> factory(&data);
245     ptr = factory.GetWeakPtr();
246   }
247   EXPECT_EQ(nullptr, ptr.get());
248 }
249 
TEST(WeakPtrFactoryTest,Multiple)250 TEST(WeakPtrFactoryTest, Multiple) {
251   WeakPtr<int> a, b;
252   {
253     int data;
254     WeakPtrFactory<int> factory(&data);
255     a = factory.GetWeakPtr();
256     b = factory.GetWeakPtr();
257     EXPECT_EQ(&data, a.get());
258     EXPECT_EQ(&data, b.get());
259   }
260   EXPECT_EQ(nullptr, a.get());
261   EXPECT_EQ(nullptr, b.get());
262 }
263 
TEST(WeakPtrFactoryTest,MultipleStaged)264 TEST(WeakPtrFactoryTest, MultipleStaged) {
265   WeakPtr<int> a;
266   {
267     int data;
268     WeakPtrFactory<int> factory(&data);
269     a = factory.GetWeakPtr();
270     {
271       WeakPtr<int> b = factory.GetWeakPtr();
272     }
273     EXPECT_NE(nullptr, a.get());
274   }
275   EXPECT_EQ(nullptr, a.get());
276 }
277 
TEST(WeakPtrFactoryTest,Dereference)278 TEST(WeakPtrFactoryTest, Dereference) {
279   Base data;
280   data.member = "123456";
281   WeakPtrFactory<Base> factory(&data);
282   WeakPtr<Base> ptr = factory.GetWeakPtr();
283   EXPECT_EQ(&data, ptr.get());
284   EXPECT_EQ(data.member, (*ptr).member);
285   EXPECT_EQ(data.member, ptr->member);
286 }
287 
TEST(WeakPtrFactoryTest,UpCast)288 TEST(WeakPtrFactoryTest, UpCast) {
289   Derived data;
290   WeakPtrFactory<Derived> factory(&data);
291   WeakPtr<Base> ptr = factory.GetWeakPtr();
292   ptr = factory.GetWeakPtr();
293   EXPECT_EQ(ptr.get(), &data);
294 }
295 
TEST(WeakPtrTest,ConstructFromNullptr)296 TEST(WeakPtrTest, ConstructFromNullptr) {
297   WeakPtr<int> ptr = PassThru(nullptr);
298   EXPECT_EQ(nullptr, ptr.get());
299 }
300 
TEST(WeakPtrTest,SupportsWeakPtr)301 TEST(WeakPtrTest, SupportsWeakPtr) {
302   Target target;
303   WeakPtr<Target> ptr = target.AsWeakPtr();
304   EXPECT_EQ(&target, ptr.get());
305 }
306 
TEST(WeakPtrTest,DerivedTarget)307 TEST(WeakPtrTest, DerivedTarget) {
308   DerivedTarget target;
309   WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target);
310   EXPECT_EQ(&target, ptr.get());
311 }
312 
TEST(WeakPtrTest,DerivedTargetWithNestedBase)313 TEST(WeakPtrTest, DerivedTargetWithNestedBase) {
314   DerivedTargetWithNestedBase target;
315   WeakPtr<DerivedTargetWithNestedBase> ptr = AsWeakPtr(&target);
316   EXPECT_EQ(&target, ptr.get());
317 }
318 
TEST(WeakPtrTest,DerivedTargetMultipleInheritance)319 TEST(WeakPtrTest, DerivedTargetMultipleInheritance) {
320   DerivedTargetMultipleInheritance d;
321   Target& b = d;
322   EXPECT_NE(static_cast<void*>(&d), static_cast<void*>(&b));
323   const WeakPtr<Target> pb = AsWeakPtr(&b);
324   EXPECT_EQ(pb.get(), &b);
325   const WeakPtr<DerivedTargetMultipleInheritance> pd = AsWeakPtr(&d);
326   EXPECT_EQ(pd.get(), &d);
327 }
328 
TEST(WeakPtrFactoryTest,BooleanTesting)329 TEST(WeakPtrFactoryTest, BooleanTesting) {
330   int data;
331   WeakPtrFactory<int> factory(&data);
332 
333   WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
334   EXPECT_TRUE(ptr_to_an_instance);
335   EXPECT_FALSE(!ptr_to_an_instance);
336 
337   if (ptr_to_an_instance) {
338   } else {
339     ADD_FAILURE() << "Pointer to an instance should result in true.";
340   }
341 
342   if (!ptr_to_an_instance) {  // check for operator!().
343     ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
344   }
345 
346   WeakPtr<int> null_ptr;
347   EXPECT_FALSE(null_ptr);
348   EXPECT_TRUE(!null_ptr);
349 
350   if (null_ptr) {
351     ADD_FAILURE() << "Null pointer should result in false.";
352   }
353 
354   if (!null_ptr) {  // check for operator!().
355   } else {
356     ADD_FAILURE() << "Null pointer should result in !x being true.";
357   }
358 }
359 
TEST(WeakPtrFactoryTest,ComparisonToNull)360 TEST(WeakPtrFactoryTest, ComparisonToNull) {
361   int data;
362   WeakPtrFactory<int> factory(&data);
363 
364   WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
365   EXPECT_NE(nullptr, ptr_to_an_instance);
366   EXPECT_NE(ptr_to_an_instance, nullptr);
367 
368   WeakPtr<int> null_ptr;
369   EXPECT_EQ(null_ptr, nullptr);
370   EXPECT_EQ(nullptr, null_ptr);
371 }
372 
TEST(WeakPtrTest,InvalidateWeakPtrs)373 TEST(WeakPtrTest, InvalidateWeakPtrs) {
374   int data;
375   WeakPtrFactory<int> factory(&data);
376   WeakPtr<int> ptr = factory.GetWeakPtr();
377   EXPECT_EQ(&data, ptr.get());
378   EXPECT_TRUE(factory.HasWeakPtrs());
379   factory.InvalidateWeakPtrs();
380   EXPECT_EQ(nullptr, ptr.get());
381   EXPECT_FALSE(factory.HasWeakPtrs());
382 
383   // Test that the factory can create new weak pointers after a
384   // InvalidateWeakPtrs call, and they remain valid until the next
385   // InvalidateWeakPtrs call.
386   WeakPtr<int> ptr2 = factory.GetWeakPtr();
387   EXPECT_EQ(&data, ptr2.get());
388   EXPECT_TRUE(factory.HasWeakPtrs());
389   factory.InvalidateWeakPtrs();
390   EXPECT_EQ(nullptr, ptr2.get());
391   EXPECT_FALSE(factory.HasWeakPtrs());
392 }
393 
TEST(WeakPtrTest,HasWeakPtrs)394 TEST(WeakPtrTest, HasWeakPtrs) {
395   int data;
396   WeakPtrFactory<int> factory(&data);
397   {
398     WeakPtr<int> ptr = factory.GetWeakPtr();
399     EXPECT_TRUE(factory.HasWeakPtrs());
400   }
401   EXPECT_FALSE(factory.HasWeakPtrs());
402 }
403 
TEST(WeakPtrTest,ObjectAndWeakPtrOnDifferentThreads)404 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
405   // Test that it is OK to create an object that supports WeakPtr on one thread,
406   // but use it on another.  This tests that we do not trip runtime checks that
407   // ensure that a WeakPtr is not used by multiple threads.
408   std::unique_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
409   WeakPtr<Target> weak_ptr = target->AsWeakPtr();
410   EXPECT_EQ(target.get(), weak_ptr.get());
411 }
412 
TEST(WeakPtrTest,WeakPtrInitiateAndUseOnDifferentThreads)413 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
414   // Test that it is OK to create an object that has a WeakPtr member on one
415   // thread, but use it on another.  This tests that we do not trip runtime
416   // checks that ensure that a WeakPtr is not used by multiple threads.
417   std::unique_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
418   Target target;
419   arrow->target = target.AsWeakPtr();
420   EXPECT_EQ(&target, arrow->target.get());
421 }
422 
TEST(WeakPtrTest,MoveOwnershipImplicitly)423 TEST(WeakPtrTest, MoveOwnershipImplicitly) {
424   // Move object ownership to another thread by releasing all weak pointers
425   // on the original thread first, and then establish WeakPtr on a different
426   // thread.
427   BackgroundThread background;
428   background.Start();
429 
430   Target* target = new Target();
431   {
432     WeakPtr<Target> weak_ptr = target->AsWeakPtr();
433     // Main thread deletes the WeakPtr, then the thread ownership of the
434     // object can be implicitly moved.
435   }
436   Arrow* arrow;
437 
438   // Background thread creates WeakPtr(and implicitly owns the object).
439   background.CreateArrowFromTarget(&arrow, target);
440   EXPECT_EQ(background.DeRef(arrow), target);
441 
442   {
443     // Main thread creates another WeakPtr, but this does not trigger implicitly
444     // thread ownership move.
445     Arrow arrow;
446     arrow.target = target->AsWeakPtr();
447 
448     // The new WeakPtr is owned by background thread.
449     EXPECT_EQ(target, background.DeRef(&arrow));
450   }
451 
452   // Target can only be deleted on background thread.
453   background.DeleteTarget(target);
454   background.DeleteArrow(arrow);
455 }
456 
TEST(WeakPtrTest,MoveOwnershipOfUnreferencedObject)457 TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) {
458   BackgroundThread background;
459   background.Start();
460 
461   Arrow* arrow;
462   {
463     Target target;
464     // Background thread creates WeakPtr.
465     background.CreateArrowFromTarget(&arrow, &target);
466 
467     // Bind to background thread.
468     EXPECT_EQ(&target, background.DeRef(arrow));
469 
470     // Release the only WeakPtr.
471     arrow->target.reset();
472 
473     // Now we should be able to create a new reference from this thread.
474     arrow->target = target.AsWeakPtr();
475 
476     // Re-bind to main thread.
477     EXPECT_EQ(&target, arrow->target.get());
478 
479     // And the main thread can now delete the target.
480   }
481 
482   delete arrow;
483 }
484 
TEST(WeakPtrTest,MoveOwnershipAfterInvalidate)485 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
486   BackgroundThread background;
487   background.Start();
488 
489   Arrow arrow;
490   std::unique_ptr<TargetWithFactory> target(new TargetWithFactory);
491 
492   // Bind to main thread.
493   arrow.target = target->factory.GetWeakPtr();
494   EXPECT_EQ(target.get(), arrow.target.get());
495 
496   target->factory.InvalidateWeakPtrs();
497   EXPECT_EQ(nullptr, arrow.target.get());
498 
499   arrow.target = target->factory.GetWeakPtr();
500   // Re-bind to background thread.
501   EXPECT_EQ(target.get(), background.DeRef(&arrow));
502 
503   // And the background thread can now delete the target.
504   background.DeleteTarget(target.release());
505 }
506 
TEST(WeakPtrTest,MainThreadRefOutlivesBackgroundThreadRef)507 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
508   // Originating thread has a WeakPtr that outlives others.
509   // - Main thread creates a WeakPtr
510   // - Background thread creates a WeakPtr copy from the one in main thread
511   // - Destruct the WeakPtr on background thread
512   // - Destruct the WeakPtr on main thread
513   BackgroundThread background;
514   background.Start();
515 
516   Target target;
517   Arrow arrow;
518   arrow.target = target.AsWeakPtr();
519 
520   Arrow* arrow_copy;
521   background.CreateArrowFromArrow(&arrow_copy, &arrow);
522   EXPECT_EQ(arrow_copy->target.get(), &target);
523   background.DeleteArrow(arrow_copy);
524 }
525 
TEST(WeakPtrTest,BackgroundThreadRefOutlivesMainThreadRef)526 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
527   // Originating thread drops all references before another thread.
528   // - Main thread creates a WeakPtr and passes copy to background thread
529   // - Destruct the pointer on main thread
530   // - Destruct the pointer on background thread
531   BackgroundThread background;
532   background.Start();
533 
534   Target target;
535   Arrow* arrow_copy;
536   {
537     Arrow arrow;
538     arrow.target = target.AsWeakPtr();
539     background.CreateArrowFromArrow(&arrow_copy, &arrow);
540   }
541   EXPECT_EQ(arrow_copy->target.get(), &target);
542   background.DeleteArrow(arrow_copy);
543 }
544 
TEST(WeakPtrTest,OwnerThreadDeletesObject)545 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
546   // Originating thread invalidates WeakPtrs while its held by other thread.
547   // - Main thread creates WeakPtr and passes Copy to background thread
548   // - Object gets destroyed on main thread
549   //   (invalidates WeakPtr on background thread)
550   // - WeakPtr gets destroyed on Thread B
551   BackgroundThread background;
552   background.Start();
553   Arrow* arrow_copy;
554   {
555     Target target;
556     Arrow arrow;
557     arrow.target = target.AsWeakPtr();
558     background.CreateArrowFromArrow(&arrow_copy, &arrow);
559   }
560   EXPECT_EQ(nullptr, arrow_copy->target.get());
561   background.DeleteArrow(arrow_copy);
562 }
563 
TEST(WeakPtrTest,NonOwnerThreadCanCopyAndAssignWeakPtr)564 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
565   // Main thread creates a Target object.
566   Target target;
567   // Main thread creates an arrow referencing the Target.
568   Arrow *arrow = new Arrow();
569   arrow->target = target.AsWeakPtr();
570 
571   // Background can copy and assign arrow (as well as the WeakPtr inside).
572   BackgroundThread background;
573   background.Start();
574   background.CopyAndAssignArrow(arrow);
575   background.DeleteArrow(arrow);
576 }
577 
TEST(WeakPtrTest,NonOwnerThreadCanCopyAndAssignWeakPtrBase)578 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
579   // Main thread creates a Target object.
580   Target target;
581   // Main thread creates an arrow referencing the Target.
582   Arrow *arrow = new Arrow();
583   arrow->target = target.AsWeakPtr();
584 
585   // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
586   BackgroundThread background;
587   background.Start();
588   background.CopyAndAssignArrowBase(arrow);
589   background.DeleteArrow(arrow);
590 }
591 
TEST(WeakPtrTest,NonOwnerThreadCanDeleteWeakPtr)592 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
593   // Main thread creates a Target object.
594   Target target;
595   // Main thread creates an arrow referencing the Target.
596   Arrow* arrow = new Arrow();
597   arrow->target = target.AsWeakPtr();
598 
599   // Background can delete arrow (as well as the WeakPtr inside).
600   BackgroundThread background;
601   background.Start();
602   background.DeleteArrow(arrow);
603 }
604 
TEST(WeakPtrDeathTest,WeakPtrCopyDoesNotChangeThreadBinding)605 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
606   // The default style "fast" does not support multi-threaded tests
607   // (introduces deadlock on Linux).
608   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
609 
610   BackgroundThread background;
611   background.Start();
612 
613   // Main thread creates a Target object.
614   Target target;
615   // Main thread creates an arrow referencing the Target.
616   Arrow arrow;
617   arrow.target = target.AsWeakPtr();
618 
619   // Background copies the WeakPtr.
620   Arrow* arrow_copy;
621   background.CreateArrowFromArrow(&arrow_copy, &arrow);
622 
623   // The copy is still bound to main thread so I can deref.
624   EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
625 
626   // Although background thread created the copy, it can not deref the copied
627   // WeakPtr.
628   ASSERT_DCHECK_DEATH(background.DeRef(arrow_copy));
629 
630   background.DeleteArrow(arrow_copy);
631 }
632 
TEST(WeakPtrDeathTest,NonOwnerThreadDereferencesWeakPtrAfterReference)633 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) {
634   // The default style "fast" does not support multi-threaded tests
635   // (introduces deadlock on Linux).
636   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
637 
638   // Main thread creates a Target object.
639   Target target;
640 
641   // Main thread creates an arrow referencing the Target (so target's
642   // thread ownership can not be implicitly moved).
643   Arrow arrow;
644   arrow.target = target.AsWeakPtr();
645   arrow.target.get();
646 
647   // Background thread tries to deref target, which violates thread ownership.
648   BackgroundThread background;
649   background.Start();
650   ASSERT_DCHECK_DEATH(background.DeRef(&arrow));
651 }
652 
TEST(WeakPtrDeathTest,NonOwnerThreadDeletesWeakPtrAfterReference)653 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) {
654   // The default style "fast" does not support multi-threaded tests
655   // (introduces deadlock on Linux).
656   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
657 
658   std::unique_ptr<Target> target(new Target());
659 
660   // Main thread creates an arrow referencing the Target.
661   Arrow arrow;
662   arrow.target = target->AsWeakPtr();
663 
664   // Background thread tries to deref target, binding it to the thread.
665   BackgroundThread background;
666   background.Start();
667   background.DeRef(&arrow);
668 
669   // Main thread deletes Target, violating thread binding.
670   ASSERT_DCHECK_DEATH(target.reset());
671 
672   // |target.reset()| died so |target| still holds the object, so we
673   // must pass it to the background thread to teardown.
674   background.DeleteTarget(target.release());
675 }
676 
TEST(WeakPtrDeathTest,NonOwnerThreadDeletesObjectAfterReference)677 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) {
678   // The default style "fast" does not support multi-threaded tests
679   // (introduces deadlock on Linux).
680   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
681 
682   std::unique_ptr<Target> target(new Target());
683 
684   // Main thread creates an arrow referencing the Target, and references it, so
685   // that it becomes bound to the thread.
686   Arrow arrow;
687   arrow.target = target->AsWeakPtr();
688   arrow.target.get();
689 
690   // Background thread tries to delete target, volating thread binding.
691   BackgroundThread background;
692   background.Start();
693   ASSERT_DCHECK_DEATH(background.DeleteTarget(target.release()));
694 }
695 
TEST(WeakPtrDeathTest,NonOwnerThreadReferencesObjectAfterDeletion)696 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
697   // The default style "fast" does not support multi-threaded tests
698   // (introduces deadlock on Linux).
699   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
700 
701   std::unique_ptr<Target> target(new Target());
702 
703   // Main thread creates an arrow referencing the Target.
704   Arrow arrow;
705   arrow.target = target->AsWeakPtr();
706 
707   // Background thread tries to delete target, binding the object to the thread.
708   BackgroundThread background;
709   background.Start();
710   background.DeleteTarget(target.release());
711 
712   // Main thread attempts to dereference the target, violating thread binding.
713   ASSERT_DCHECK_DEATH(arrow.target.get());
714 }
715 
716 }  // namespace base
717