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