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