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.
5 #include "base/memory/weak_ptr.h"
10 #include "base/debug/leak_annotations.h"
11 #include "base/location.h"
12 #include "base/memory/scoped_ptr.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"
22 class OffThreadObjectCreator
{
24 static T
* NewObject() {
27 Thread
creator_thread("creator_thread");
28 creator_thread
.Start();
29 creator_thread
.task_runner()->PostTask(
30 FROM_HERE
, base::Bind(OffThreadObjectCreator::CreateObject
, &result
));
32 DCHECK(result
); // We synchronized on thread destruction above.
36 static void CreateObject(T
** result
) {
44 struct Derived
: public Base
{};
47 struct Target
: public TargetBase
, public SupportsWeakPtr
<Target
> {
50 struct DerivedTarget
: public Target
{};
52 WeakPtr
<Target
> target
;
54 struct TargetWithFactory
: public Target
{
55 TargetWithFactory() : factory(this) {}
56 WeakPtrFactory
<Target
> factory
;
59 // Helper class to create and destroy weak pointer copies
60 // and delete objects on a background thread.
61 class BackgroundThread
: public Thread
{
63 BackgroundThread() : Thread("owner_thread") {}
65 ~BackgroundThread() override
{ Stop(); }
67 void CreateArrowFromTarget(Arrow
** arrow
, Target
* target
) {
68 WaitableEvent
completion(true, false);
69 task_runner()->PostTask(
70 FROM_HERE
, base::Bind(&BackgroundThread::DoCreateArrowFromTarget
, arrow
,
71 target
, &completion
));
75 void CreateArrowFromArrow(Arrow
** arrow
, const Arrow
* other
) {
76 WaitableEvent
completion(true, false);
77 task_runner()->PostTask(
78 FROM_HERE
, base::Bind(&BackgroundThread::DoCreateArrowFromArrow
, arrow
,
83 void DeleteTarget(Target
* object
) {
84 WaitableEvent
completion(true, false);
85 task_runner()->PostTask(
87 base::Bind(&BackgroundThread::DoDeleteTarget
, object
, &completion
));
91 void CopyAndAssignArrow(Arrow
* object
) {
92 WaitableEvent
completion(true, false);
93 task_runner()->PostTask(
94 FROM_HERE
, base::Bind(&BackgroundThread::DoCopyAndAssignArrow
, object
,
99 void CopyAndAssignArrowBase(Arrow
* object
) {
100 WaitableEvent
completion(true, false);
101 task_runner()->PostTask(
102 FROM_HERE
, base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase
,
103 object
, &completion
));
107 void DeleteArrow(Arrow
* object
) {
108 WaitableEvent
completion(true, false);
109 task_runner()->PostTask(
111 base::Bind(&BackgroundThread::DoDeleteArrow
, object
, &completion
));
115 Target
* DeRef(const Arrow
* arrow
) {
116 WaitableEvent
completion(true, false);
117 Target
* result
= NULL
;
118 task_runner()->PostTask(FROM_HERE
, base::Bind(&BackgroundThread::DoDeRef
,
119 arrow
, &result
, &completion
));
125 static void DoCreateArrowFromArrow(Arrow
** arrow
,
127 WaitableEvent
* completion
) {
130 completion
->Signal();
133 static void DoCreateArrowFromTarget(Arrow
** arrow
,
135 WaitableEvent
* completion
) {
137 (*arrow
)->target
= target
->AsWeakPtr();
138 completion
->Signal();
141 static void DoDeRef(const Arrow
* arrow
,
143 WaitableEvent
* completion
) {
144 *result
= arrow
->target
.get();
145 completion
->Signal();
148 static void DoDeleteTarget(Target
* object
, WaitableEvent
* completion
) {
150 completion
->Signal();
153 static void DoCopyAndAssignArrow(Arrow
* object
, WaitableEvent
* completion
) {
156 // Assignment operator.
158 completion
->Signal();
161 static void DoCopyAndAssignArrowBase(
163 WaitableEvent
* completion
) {
165 WeakPtr
<TargetBase
> b
= object
->target
;
166 // Assignment operator.
167 WeakPtr
<TargetBase
> c
;
169 completion
->Signal();
172 static void DoDeleteArrow(Arrow
* object
, WaitableEvent
* completion
) {
174 completion
->Signal();
180 TEST(WeakPtrFactoryTest
, Basic
) {
182 WeakPtrFactory
<int> factory(&data
);
183 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
184 EXPECT_EQ(&data
, ptr
.get());
187 TEST(WeakPtrFactoryTest
, Comparison
) {
189 WeakPtrFactory
<int> factory(&data
);
190 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
191 WeakPtr
<int> ptr2
= ptr
;
192 EXPECT_EQ(ptr
.get(), ptr2
.get());
195 TEST(WeakPtrFactoryTest
, OutOfScope
) {
197 EXPECT_EQ(NULL
, ptr
.get());
200 WeakPtrFactory
<int> factory(&data
);
201 ptr
= factory
.GetWeakPtr();
203 EXPECT_EQ(NULL
, ptr
.get());
206 TEST(WeakPtrFactoryTest
, Multiple
) {
210 WeakPtrFactory
<int> factory(&data
);
211 a
= factory
.GetWeakPtr();
212 b
= factory
.GetWeakPtr();
213 EXPECT_EQ(&data
, a
.get());
214 EXPECT_EQ(&data
, b
.get());
216 EXPECT_EQ(NULL
, a
.get());
217 EXPECT_EQ(NULL
, b
.get());
220 TEST(WeakPtrFactoryTest
, MultipleStaged
) {
224 WeakPtrFactory
<int> factory(&data
);
225 a
= factory
.GetWeakPtr();
227 WeakPtr
<int> b
= factory
.GetWeakPtr();
229 EXPECT_TRUE(NULL
!= a
.get());
231 EXPECT_EQ(NULL
, a
.get());
234 TEST(WeakPtrFactoryTest
, Dereference
) {
236 data
.member
= "123456";
237 WeakPtrFactory
<Base
> factory(&data
);
238 WeakPtr
<Base
> ptr
= factory
.GetWeakPtr();
239 EXPECT_EQ(&data
, ptr
.get());
240 EXPECT_EQ(data
.member
, (*ptr
).member
);
241 EXPECT_EQ(data
.member
, ptr
->member
);
244 TEST(WeakPtrFactoryTest
, UpCast
) {
246 WeakPtrFactory
<Derived
> factory(&data
);
247 WeakPtr
<Base
> ptr
= factory
.GetWeakPtr();
248 ptr
= factory
.GetWeakPtr();
249 EXPECT_EQ(ptr
.get(), &data
);
252 TEST(WeakPtrTest
, SupportsWeakPtr
) {
254 WeakPtr
<Target
> ptr
= target
.AsWeakPtr();
255 EXPECT_EQ(&target
, ptr
.get());
258 TEST(WeakPtrTest
, DerivedTarget
) {
259 DerivedTarget target
;
260 WeakPtr
<DerivedTarget
> ptr
= AsWeakPtr(&target
);
261 EXPECT_EQ(&target
, ptr
.get());
264 TEST(WeakPtrTest
, InvalidateWeakPtrs
) {
266 WeakPtrFactory
<int> factory(&data
);
267 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
268 EXPECT_EQ(&data
, ptr
.get());
269 EXPECT_TRUE(factory
.HasWeakPtrs());
270 factory
.InvalidateWeakPtrs();
271 EXPECT_EQ(NULL
, ptr
.get());
272 EXPECT_FALSE(factory
.HasWeakPtrs());
274 // Test that the factory can create new weak pointers after a
275 // InvalidateWeakPtrs call, and they remain valid until the next
276 // InvalidateWeakPtrs call.
277 WeakPtr
<int> ptr2
= factory
.GetWeakPtr();
278 EXPECT_EQ(&data
, ptr2
.get());
279 EXPECT_TRUE(factory
.HasWeakPtrs());
280 factory
.InvalidateWeakPtrs();
281 EXPECT_EQ(NULL
, ptr2
.get());
282 EXPECT_FALSE(factory
.HasWeakPtrs());
285 TEST(WeakPtrTest
, HasWeakPtrs
) {
287 WeakPtrFactory
<int> factory(&data
);
289 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
290 EXPECT_TRUE(factory
.HasWeakPtrs());
292 EXPECT_FALSE(factory
.HasWeakPtrs());
295 TEST(WeakPtrTest
, ObjectAndWeakPtrOnDifferentThreads
) {
296 // Test that it is OK to create an object that supports WeakPtr on one thread,
297 // but use it on another. This tests that we do not trip runtime checks that
298 // ensure that a WeakPtr is not used by multiple threads.
299 scoped_ptr
<Target
> target(OffThreadObjectCreator
<Target
>::NewObject());
300 WeakPtr
<Target
> weak_ptr
= target
->AsWeakPtr();
301 EXPECT_EQ(target
.get(), weak_ptr
.get());
304 TEST(WeakPtrTest
, WeakPtrInitiateAndUseOnDifferentThreads
) {
305 // Test that it is OK to create an object that has a WeakPtr member on one
306 // thread, but use it on another. This tests that we do not trip runtime
307 // checks that ensure that a WeakPtr is not used by multiple threads.
308 scoped_ptr
<Arrow
> arrow(OffThreadObjectCreator
<Arrow
>::NewObject());
310 arrow
->target
= target
.AsWeakPtr();
311 EXPECT_EQ(&target
, arrow
->target
.get());
314 TEST(WeakPtrTest
, MoveOwnershipImplicitly
) {
315 // Move object ownership to another thread by releasing all weak pointers
316 // on the original thread first, and then establish WeakPtr on a different
318 BackgroundThread background
;
321 Target
* target
= new Target();
323 WeakPtr
<Target
> weak_ptr
= target
->AsWeakPtr();
324 // Main thread deletes the WeakPtr, then the thread ownership of the
325 // object can be implicitly moved.
329 // Background thread creates WeakPtr(and implicitly owns the object).
330 background
.CreateArrowFromTarget(&arrow
, target
);
331 EXPECT_EQ(background
.DeRef(arrow
), target
);
334 // Main thread creates another WeakPtr, but this does not trigger implicitly
335 // thread ownership move.
337 arrow
.target
= target
->AsWeakPtr();
339 // The new WeakPtr is owned by background thread.
340 EXPECT_EQ(target
, background
.DeRef(&arrow
));
343 // Target can only be deleted on background thread.
344 background
.DeleteTarget(target
);
345 background
.DeleteArrow(arrow
);
348 TEST(WeakPtrTest
, MoveOwnershipOfUnreferencedObject
) {
349 BackgroundThread background
;
355 // Background thread creates WeakPtr.
356 background
.CreateArrowFromTarget(&arrow
, &target
);
358 // Bind to background thread.
359 EXPECT_EQ(&target
, background
.DeRef(arrow
));
361 // Release the only WeakPtr.
362 arrow
->target
.reset();
364 // Now we should be able to create a new reference from this thread.
365 arrow
->target
= target
.AsWeakPtr();
367 // Re-bind to main thread.
368 EXPECT_EQ(&target
, arrow
->target
.get());
370 // And the main thread can now delete the target.
376 TEST(WeakPtrTest
, MoveOwnershipAfterInvalidate
) {
377 BackgroundThread background
;
381 scoped_ptr
<TargetWithFactory
> target(new TargetWithFactory
);
383 // Bind to main thread.
384 arrow
.target
= target
->factory
.GetWeakPtr();
385 EXPECT_EQ(target
.get(), arrow
.target
.get());
387 target
->factory
.InvalidateWeakPtrs();
388 EXPECT_EQ(NULL
, arrow
.target
.get());
390 arrow
.target
= target
->factory
.GetWeakPtr();
391 // Re-bind to background thread.
392 EXPECT_EQ(target
.get(), background
.DeRef(&arrow
));
394 // And the background thread can now delete the target.
395 background
.DeleteTarget(target
.release());
398 TEST(WeakPtrTest
, MainThreadRefOutlivesBackgroundThreadRef
) {
399 // Originating thread has a WeakPtr that outlives others.
400 // - Main thread creates a WeakPtr
401 // - Background thread creates a WeakPtr copy from the one in main thread
402 // - Destruct the WeakPtr on background thread
403 // - Destruct the WeakPtr on main thread
404 BackgroundThread background
;
409 arrow
.target
= target
.AsWeakPtr();
412 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
413 EXPECT_EQ(arrow_copy
->target
.get(), &target
);
414 background
.DeleteArrow(arrow_copy
);
417 TEST(WeakPtrTest
, BackgroundThreadRefOutlivesMainThreadRef
) {
418 // Originating thread drops all references before another thread.
419 // - Main thread creates a WeakPtr and passes copy to background thread
420 // - Destruct the pointer on main thread
421 // - Destruct the pointer on background thread
422 BackgroundThread background
;
429 arrow
.target
= target
.AsWeakPtr();
430 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
432 EXPECT_EQ(arrow_copy
->target
.get(), &target
);
433 background
.DeleteArrow(arrow_copy
);
436 TEST(WeakPtrTest
, OwnerThreadDeletesObject
) {
437 // Originating thread invalidates WeakPtrs while its held by other thread.
438 // - Main thread creates WeakPtr and passes Copy to background thread
439 // - Object gets destroyed on main thread
440 // (invalidates WeakPtr on background thread)
441 // - WeakPtr gets destroyed on Thread B
442 BackgroundThread background
;
448 arrow
.target
= target
.AsWeakPtr();
449 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
451 EXPECT_EQ(NULL
, arrow_copy
->target
.get());
452 background
.DeleteArrow(arrow_copy
);
455 TEST(WeakPtrTest
, NonOwnerThreadCanCopyAndAssignWeakPtr
) {
456 // Main thread creates a Target object.
458 // Main thread creates an arrow referencing the Target.
459 Arrow
*arrow
= new Arrow();
460 arrow
->target
= target
.AsWeakPtr();
462 // Background can copy and assign arrow (as well as the WeakPtr inside).
463 BackgroundThread background
;
465 background
.CopyAndAssignArrow(arrow
);
466 background
.DeleteArrow(arrow
);
469 TEST(WeakPtrTest
, NonOwnerThreadCanCopyAndAssignWeakPtrBase
) {
470 // Main thread creates a Target object.
472 // Main thread creates an arrow referencing the Target.
473 Arrow
*arrow
= new Arrow();
474 arrow
->target
= target
.AsWeakPtr();
476 // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
477 BackgroundThread background
;
479 background
.CopyAndAssignArrowBase(arrow
);
480 background
.DeleteArrow(arrow
);
483 TEST(WeakPtrTest
, NonOwnerThreadCanDeleteWeakPtr
) {
484 // Main thread creates a Target object.
486 // Main thread creates an arrow referencing the Target.
487 Arrow
* arrow
= new Arrow();
488 arrow
->target
= target
.AsWeakPtr();
490 // Background can delete arrow (as well as the WeakPtr inside).
491 BackgroundThread background
;
493 background
.DeleteArrow(arrow
);
496 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
498 TEST(WeakPtrDeathTest
, WeakPtrCopyDoesNotChangeThreadBinding
) {
499 // The default style "fast" does not support multi-threaded tests
500 // (introduces deadlock on Linux).
501 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
503 BackgroundThread background
;
506 // Main thread creates a Target object.
508 // Main thread creates an arrow referencing the Target.
510 arrow
.target
= target
.AsWeakPtr();
512 // Background copies the WeakPtr.
514 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
516 // The copy is still bound to main thread so I can deref.
517 EXPECT_EQ(arrow
.target
.get(), arrow_copy
->target
.get());
519 // Although background thread created the copy, it can not deref the copied
521 ASSERT_DEATH(background
.DeRef(arrow_copy
), "");
523 background
.DeleteArrow(arrow_copy
);
526 TEST(WeakPtrDeathTest
, NonOwnerThreadDereferencesWeakPtrAfterReference
) {
527 // The default style "fast" does not support multi-threaded tests
528 // (introduces deadlock on Linux).
529 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
531 // Main thread creates a Target object.
534 // Main thread creates an arrow referencing the Target (so target's
535 // thread ownership can not be implicitly moved).
537 arrow
.target
= target
.AsWeakPtr();
540 // Background thread tries to deref target, which violates thread ownership.
541 BackgroundThread background
;
543 ASSERT_DEATH(background
.DeRef(&arrow
), "");
546 TEST(WeakPtrDeathTest
, NonOwnerThreadDeletesWeakPtrAfterReference
) {
547 // The default style "fast" does not support multi-threaded tests
548 // (introduces deadlock on Linux).
549 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
551 scoped_ptr
<Target
> target(new Target());
553 // Main thread creates an arrow referencing the Target.
555 arrow
.target
= target
->AsWeakPtr();
557 // Background thread tries to deref target, binding it to the thread.
558 BackgroundThread background
;
560 background
.DeRef(&arrow
);
562 // Main thread deletes Target, violating thread binding.
563 ASSERT_DEATH(target
.reset(), "");
565 // |target.reset()| died so |target| still holds the object, so we
566 // must pass it to the background thread to teardown.
567 background
.DeleteTarget(target
.release());
570 TEST(WeakPtrDeathTest
, NonOwnerThreadDeletesObjectAfterReference
) {
571 // The default style "fast" does not support multi-threaded tests
572 // (introduces deadlock on Linux).
573 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
575 scoped_ptr
<Target
> target(new Target());
577 // Main thread creates an arrow referencing the Target, and references it, so
578 // that it becomes bound to the thread.
580 arrow
.target
= target
->AsWeakPtr();
583 // Background thread tries to delete target, volating thread binding.
584 BackgroundThread background
;
586 ASSERT_DEATH(background
.DeleteTarget(target
.release()), "");
589 TEST(WeakPtrDeathTest
, NonOwnerThreadReferencesObjectAfterDeletion
) {
590 // The default style "fast" does not support multi-threaded tests
591 // (introduces deadlock on Linux).
592 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
594 scoped_ptr
<Target
> target(new Target());
596 // Main thread creates an arrow referencing the Target.
598 arrow
.target
= target
->AsWeakPtr();
600 // Background thread tries to delete target, binding the object to the thread.
601 BackgroundThread background
;
603 background
.DeleteTarget(target
.release());
605 // Main thread attempts to dereference the target, violating thread binding.
606 ASSERT_DEATH(arrow
.target
.get(), "");