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