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/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/threading/thread.h"
15 #include "testing/gtest/include/gtest/gtest.h"
21 class OffThreadObjectCreator
{
23 static T
* NewObject() {
26 Thread
creator_thread("creator_thread");
27 creator_thread
.Start();
28 creator_thread
.message_loop()->PostTask(
30 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 virtual ~BackgroundThread() {
69 void CreateArrowFromTarget(Arrow
** arrow
, Target
* target
) {
70 WaitableEvent
completion(true, false);
71 message_loop()->PostTask(
73 base::Bind(&BackgroundThread::DoCreateArrowFromTarget
,
74 arrow
, target
, &completion
));
78 void CreateArrowFromArrow(Arrow
** arrow
, const Arrow
* other
) {
79 WaitableEvent
completion(true, false);
80 message_loop()->PostTask(
82 base::Bind(&BackgroundThread::DoCreateArrowFromArrow
,
83 arrow
, other
, &completion
));
87 void DeleteTarget(Target
* object
) {
88 WaitableEvent
completion(true, false);
89 message_loop()->PostTask(
91 base::Bind(&BackgroundThread::DoDeleteTarget
, object
, &completion
));
95 void CopyAndAssignArrow(Arrow
* object
) {
96 WaitableEvent
completion(true, false);
97 message_loop()->PostTask(
99 base::Bind(&BackgroundThread::DoCopyAndAssignArrow
,
100 object
, &completion
));
104 void CopyAndAssignArrowBase(Arrow
* object
) {
105 WaitableEvent
completion(true, false);
106 message_loop()->PostTask(
108 base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase
,
109 object
, &completion
));
113 void DeleteArrow(Arrow
* object
) {
114 WaitableEvent
completion(true, false);
115 message_loop()->PostTask(
117 base::Bind(&BackgroundThread::DoDeleteArrow
, object
, &completion
));
121 Target
* DeRef(const Arrow
* arrow
) {
122 WaitableEvent
completion(true, false);
123 Target
* result
= NULL
;
124 message_loop()->PostTask(
126 base::Bind(&BackgroundThread::DoDeRef
, arrow
, &result
, &completion
));
132 static void DoCreateArrowFromArrow(Arrow
** arrow
,
134 WaitableEvent
* completion
) {
137 completion
->Signal();
140 static void DoCreateArrowFromTarget(Arrow
** arrow
,
142 WaitableEvent
* completion
) {
144 (*arrow
)->target
= target
->AsWeakPtr();
145 completion
->Signal();
148 static void DoDeRef(const Arrow
* arrow
,
150 WaitableEvent
* completion
) {
151 *result
= arrow
->target
.get();
152 completion
->Signal();
155 static void DoDeleteTarget(Target
* object
, WaitableEvent
* completion
) {
157 completion
->Signal();
160 static void DoCopyAndAssignArrow(Arrow
* object
, WaitableEvent
* completion
) {
163 // Assignment operator.
165 completion
->Signal();
168 static void DoCopyAndAssignArrowBase(
170 WaitableEvent
* completion
) {
172 WeakPtr
<TargetBase
> b
= object
->target
;
173 // Assignment operator.
174 WeakPtr
<TargetBase
> c
;
176 completion
->Signal();
179 static void DoDeleteArrow(Arrow
* object
, WaitableEvent
* completion
) {
181 completion
->Signal();
187 TEST(WeakPtrFactoryTest
, Basic
) {
189 WeakPtrFactory
<int> factory(&data
);
190 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
191 EXPECT_EQ(&data
, ptr
.get());
194 TEST(WeakPtrFactoryTest
, Comparison
) {
196 WeakPtrFactory
<int> factory(&data
);
197 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
198 WeakPtr
<int> ptr2
= ptr
;
199 EXPECT_EQ(ptr
.get(), ptr2
.get());
202 TEST(WeakPtrFactoryTest
, OutOfScope
) {
204 EXPECT_EQ(NULL
, ptr
.get());
207 WeakPtrFactory
<int> factory(&data
);
208 ptr
= factory
.GetWeakPtr();
210 EXPECT_EQ(NULL
, ptr
.get());
213 TEST(WeakPtrFactoryTest
, Multiple
) {
217 WeakPtrFactory
<int> factory(&data
);
218 a
= factory
.GetWeakPtr();
219 b
= factory
.GetWeakPtr();
220 EXPECT_EQ(&data
, a
.get());
221 EXPECT_EQ(&data
, b
.get());
223 EXPECT_EQ(NULL
, a
.get());
224 EXPECT_EQ(NULL
, b
.get());
227 TEST(WeakPtrFactoryTest
, MultipleStaged
) {
231 WeakPtrFactory
<int> factory(&data
);
232 a
= factory
.GetWeakPtr();
234 WeakPtr
<int> b
= factory
.GetWeakPtr();
236 EXPECT_TRUE(NULL
!= a
.get());
238 EXPECT_EQ(NULL
, a
.get());
241 TEST(WeakPtrFactoryTest
, Dereference
) {
243 data
.member
= "123456";
244 WeakPtrFactory
<Base
> factory(&data
);
245 WeakPtr
<Base
> ptr
= factory
.GetWeakPtr();
246 EXPECT_EQ(&data
, ptr
.get());
247 EXPECT_EQ(data
.member
, (*ptr
).member
);
248 EXPECT_EQ(data
.member
, ptr
->member
);
251 TEST(WeakPtrFactoryTest
, UpCast
) {
253 WeakPtrFactory
<Derived
> factory(&data
);
254 WeakPtr
<Base
> ptr
= factory
.GetWeakPtr();
255 ptr
= factory
.GetWeakPtr();
256 EXPECT_EQ(ptr
.get(), &data
);
259 TEST(WeakPtrTest
, SupportsWeakPtr
) {
261 WeakPtr
<Target
> ptr
= target
.AsWeakPtr();
262 EXPECT_EQ(&target
, ptr
.get());
265 TEST(WeakPtrTest
, DerivedTarget
) {
266 DerivedTarget target
;
267 WeakPtr
<DerivedTarget
> ptr
= AsWeakPtr(&target
);
268 EXPECT_EQ(&target
, ptr
.get());
271 TEST(WeakPtrTest
, InvalidateWeakPtrs
) {
273 WeakPtrFactory
<int> factory(&data
);
274 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
275 EXPECT_EQ(&data
, ptr
.get());
276 EXPECT_TRUE(factory
.HasWeakPtrs());
277 factory
.InvalidateWeakPtrs();
278 EXPECT_EQ(NULL
, ptr
.get());
279 EXPECT_FALSE(factory
.HasWeakPtrs());
281 // Test that the factory can create new weak pointers after a
282 // InvalidateWeakPtrs call, and they remain valid until the next
283 // InvalidateWeakPtrs call.
284 WeakPtr
<int> ptr2
= factory
.GetWeakPtr();
285 EXPECT_EQ(&data
, ptr2
.get());
286 EXPECT_TRUE(factory
.HasWeakPtrs());
287 factory
.InvalidateWeakPtrs();
288 EXPECT_EQ(NULL
, ptr2
.get());
289 EXPECT_FALSE(factory
.HasWeakPtrs());
292 TEST(WeakPtrTest
, HasWeakPtrs
) {
294 WeakPtrFactory
<int> factory(&data
);
296 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
297 EXPECT_TRUE(factory
.HasWeakPtrs());
299 EXPECT_FALSE(factory
.HasWeakPtrs());
302 TEST(WeakPtrTest
, ObjectAndWeakPtrOnDifferentThreads
) {
303 // Test that it is OK to create an object that supports WeakPtr on one thread,
304 // but use it on another. This tests that we do not trip runtime checks that
305 // ensure that a WeakPtr is not used by multiple threads.
306 scoped_ptr
<Target
> target(OffThreadObjectCreator
<Target
>::NewObject());
307 WeakPtr
<Target
> weak_ptr
= target
->AsWeakPtr();
308 EXPECT_EQ(target
.get(), weak_ptr
.get());
311 TEST(WeakPtrTest
, WeakPtrInitiateAndUseOnDifferentThreads
) {
312 // Test that it is OK to create an object that has a WeakPtr member on one
313 // thread, but use it on another. This tests that we do not trip runtime
314 // checks that ensure that a WeakPtr is not used by multiple threads.
315 scoped_ptr
<Arrow
> arrow(OffThreadObjectCreator
<Arrow
>::NewObject());
317 arrow
->target
= target
.AsWeakPtr();
318 EXPECT_EQ(&target
, arrow
->target
.get());
321 TEST(WeakPtrTest
, MoveOwnershipImplicitly
) {
322 // Move object ownership to another thread by releasing all weak pointers
323 // on the original thread first, and then establish WeakPtr on a different
325 BackgroundThread background
;
328 Target
* target
= new Target();
330 WeakPtr
<Target
> weak_ptr
= target
->AsWeakPtr();
331 // Main thread deletes the WeakPtr, then the thread ownership of the
332 // object can be implicitly moved.
336 // Background thread creates WeakPtr(and implicitly owns the object).
337 background
.CreateArrowFromTarget(&arrow
, target
);
338 EXPECT_EQ(background
.DeRef(arrow
), target
);
341 // Main thread creates another WeakPtr, but this does not trigger implicitly
342 // thread ownership move.
344 arrow
.target
= target
->AsWeakPtr();
346 // The new WeakPtr is owned by background thread.
347 EXPECT_EQ(target
, background
.DeRef(&arrow
));
350 // Target can only be deleted on background thread.
351 background
.DeleteTarget(target
);
352 background
.DeleteArrow(arrow
);
355 TEST(WeakPtrTest
, MoveOwnershipOfUnreferencedObject
) {
356 BackgroundThread background
;
362 // Background thread creates WeakPtr.
363 background
.CreateArrowFromTarget(&arrow
, &target
);
365 // Bind to background thread.
366 EXPECT_EQ(&target
, background
.DeRef(arrow
));
368 // Release the only WeakPtr.
369 arrow
->target
.reset();
371 // Now we should be able to create a new reference from this thread.
372 arrow
->target
= target
.AsWeakPtr();
374 // Re-bind to main thread.
375 EXPECT_EQ(&target
, arrow
->target
.get());
377 // And the main thread can now delete the target.
383 TEST(WeakPtrTest
, MoveOwnershipAfterInvalidate
) {
384 BackgroundThread background
;
388 scoped_ptr
<TargetWithFactory
> target(new TargetWithFactory
);
390 // Bind to main thread.
391 arrow
.target
= target
->factory
.GetWeakPtr();
392 EXPECT_EQ(target
.get(), arrow
.target
.get());
394 target
->factory
.InvalidateWeakPtrs();
395 EXPECT_EQ(NULL
, arrow
.target
.get());
397 arrow
.target
= target
->factory
.GetWeakPtr();
398 // Re-bind to background thread.
399 EXPECT_EQ(target
.get(), background
.DeRef(&arrow
));
401 // And the background thread can now delete the target.
402 background
.DeleteTarget(target
.release());
405 TEST(WeakPtrTest
, MainThreadRefOutlivesBackgroundThreadRef
) {
406 // Originating thread has a WeakPtr that outlives others.
407 // - Main thread creates a WeakPtr
408 // - Background thread creates a WeakPtr copy from the one in main thread
409 // - Destruct the WeakPtr on background thread
410 // - Destruct the WeakPtr on main thread
411 BackgroundThread background
;
416 arrow
.target
= target
.AsWeakPtr();
419 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
420 EXPECT_EQ(arrow_copy
->target
.get(), &target
);
421 background
.DeleteArrow(arrow_copy
);
424 TEST(WeakPtrTest
, BackgroundThreadRefOutlivesMainThreadRef
) {
425 // Originating thread drops all references before another thread.
426 // - Main thread creates a WeakPtr and passes copy to background thread
427 // - Destruct the pointer on main thread
428 // - Destruct the pointer on background thread
429 BackgroundThread background
;
436 arrow
.target
= target
.AsWeakPtr();
437 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
439 EXPECT_EQ(arrow_copy
->target
.get(), &target
);
440 background
.DeleteArrow(arrow_copy
);
443 TEST(WeakPtrTest
, OwnerThreadDeletesObject
) {
444 // Originating thread invalidates WeakPtrs while its held by other thread.
445 // - Main thread creates WeakPtr and passes Copy to background thread
446 // - Object gets destroyed on main thread
447 // (invalidates WeakPtr on background thread)
448 // - WeakPtr gets destroyed on Thread B
449 BackgroundThread background
;
455 arrow
.target
= target
.AsWeakPtr();
456 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
458 EXPECT_EQ(NULL
, arrow_copy
->target
.get());
459 background
.DeleteArrow(arrow_copy
);
462 TEST(WeakPtrTest
, NonOwnerThreadCanCopyAndAssignWeakPtr
) {
463 // Main thread creates a Target object.
465 // Main thread creates an arrow referencing the Target.
466 Arrow
*arrow
= new Arrow();
467 arrow
->target
= target
.AsWeakPtr();
469 // Background can copy and assign arrow (as well as the WeakPtr inside).
470 BackgroundThread background
;
472 background
.CopyAndAssignArrow(arrow
);
473 background
.DeleteArrow(arrow
);
476 TEST(WeakPtrTest
, NonOwnerThreadCanCopyAndAssignWeakPtrBase
) {
477 // Main thread creates a Target object.
479 // Main thread creates an arrow referencing the Target.
480 Arrow
*arrow
= new Arrow();
481 arrow
->target
= target
.AsWeakPtr();
483 // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
484 BackgroundThread background
;
486 background
.CopyAndAssignArrowBase(arrow
);
487 background
.DeleteArrow(arrow
);
490 TEST(WeakPtrTest
, NonOwnerThreadCanDeleteWeakPtr
) {
491 // Main thread creates a Target object.
493 // Main thread creates an arrow referencing the Target.
494 Arrow
* arrow
= new Arrow();
495 arrow
->target
= target
.AsWeakPtr();
497 // Background can delete arrow (as well as the WeakPtr inside).
498 BackgroundThread background
;
500 background
.DeleteArrow(arrow
);
503 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
505 TEST(WeakPtrDeathTest
, WeakPtrCopyDoesNotChangeThreadBinding
) {
506 // The default style "fast" does not support multi-threaded tests
507 // (introduces deadlock on Linux).
508 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
510 BackgroundThread background
;
513 // Main thread creates a Target object.
515 // Main thread creates an arrow referencing the Target.
517 arrow
.target
= target
.AsWeakPtr();
519 // Background copies the WeakPtr.
521 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
523 // The copy is still bound to main thread so I can deref.
524 EXPECT_EQ(arrow
.target
.get(), arrow_copy
->target
.get());
526 // Although background thread created the copy, it can not deref the copied
528 ASSERT_DEATH(background
.DeRef(arrow_copy
), "");
530 background
.DeleteArrow(arrow_copy
);
533 TEST(WeakPtrDeathTest
, NonOwnerThreadDereferencesWeakPtrAfterReference
) {
534 // The default style "fast" does not support multi-threaded tests
535 // (introduces deadlock on Linux).
536 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
538 // Main thread creates a Target object.
541 // Main thread creates an arrow referencing the Target (so target's
542 // thread ownership can not be implicitly moved).
544 arrow
.target
= target
.AsWeakPtr();
547 // Background thread tries to deref target, which violates thread ownership.
548 BackgroundThread background
;
550 ASSERT_DEATH(background
.DeRef(&arrow
), "");
553 TEST(WeakPtrDeathTest
, NonOwnerThreadDeletesWeakPtrAfterReference
) {
554 // The default style "fast" does not support multi-threaded tests
555 // (introduces deadlock on Linux).
556 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
558 scoped_ptr
<Target
> target(new Target());
560 // Main thread creates an arrow referencing the Target.
562 arrow
.target
= target
->AsWeakPtr();
564 // Background thread tries to deref target, binding it to the thread.
565 BackgroundThread background
;
567 background
.DeRef(&arrow
);
569 // Main thread deletes Target, violating thread binding.
570 ASSERT_DEATH(target
.reset(), "");
572 // |target.reset()| died so |target| still holds the object, so we
573 // must pass it to the background thread to teardown.
574 background
.DeleteTarget(target
.release());
577 TEST(WeakPtrDeathTest
, NonOwnerThreadDeletesObjectAfterReference
) {
578 // The default style "fast" does not support multi-threaded tests
579 // (introduces deadlock on Linux).
580 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
582 scoped_ptr
<Target
> target(new Target());
584 // Main thread creates an arrow referencing the Target, and references it, so
585 // that it becomes bound to the thread.
587 arrow
.target
= target
->AsWeakPtr();
590 // Background thread tries to delete target, volating thread binding.
591 BackgroundThread background
;
593 ASSERT_DEATH(background
.DeleteTarget(target
.release()), "");
596 TEST(WeakPtrDeathTest
, NonOwnerThreadReferencesObjectAfterDeletion
) {
597 // The default style "fast" does not support multi-threaded tests
598 // (introduces deadlock on Linux).
599 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
601 scoped_ptr
<Target
> target(new Target());
603 // Main thread creates an arrow referencing the Target.
605 arrow
.target
= target
->AsWeakPtr();
607 // Background thread tries to delete target, binding the object to the thread.
608 BackgroundThread background
;
610 background
.DeleteTarget(target
.release());
612 // Main thread attempts to dereference the target, violating thread binding.
613 ASSERT_DEATH(arrow
.target
.get(), "");