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