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
> {};
48 struct DerivedTarget
: public Target
{};
50 WeakPtr
<Target
> target
;
52 struct TargetWithFactory
: public Target
{
53 TargetWithFactory() : factory(this) {}
54 WeakPtrFactory
<Target
> factory
;
57 // Helper class to create and destroy weak pointer copies
58 // and delete objects on a background thread.
59 class BackgroundThread
: public Thread
{
61 BackgroundThread() : Thread("owner_thread") {}
63 virtual ~BackgroundThread() {
67 void CreateArrowFromTarget(Arrow
** arrow
, Target
* target
) {
68 WaitableEvent
completion(true, false);
69 message_loop()->PostTask(
71 base::Bind(&BackgroundThread::DoCreateArrowFromTarget
,
72 arrow
, target
, &completion
));
76 void CreateArrowFromArrow(Arrow
** arrow
, const Arrow
* other
) {
77 WaitableEvent
completion(true, false);
78 message_loop()->PostTask(
80 base::Bind(&BackgroundThread::DoCreateArrowFromArrow
,
81 arrow
, other
, &completion
));
85 void DeleteTarget(Target
* object
) {
86 WaitableEvent
completion(true, false);
87 message_loop()->PostTask(
89 base::Bind(&BackgroundThread::DoDeleteTarget
, object
, &completion
));
93 void CopyAndAssignArrow(Arrow
* object
) {
94 WaitableEvent
completion(true, false);
95 message_loop()->PostTask(
97 base::Bind(&BackgroundThread::DoCopyAndAssignArrow
,
98 object
, &completion
));
102 void CopyAndAssignArrowBase(Arrow
* object
) {
103 WaitableEvent
completion(true, false);
104 message_loop()->PostTask(
106 base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase
,
107 object
, &completion
));
111 void DeleteArrow(Arrow
* object
) {
112 WaitableEvent
completion(true, false);
113 message_loop()->PostTask(
115 base::Bind(&BackgroundThread::DoDeleteArrow
, object
, &completion
));
119 Target
* DeRef(const Arrow
* arrow
) {
120 WaitableEvent
completion(true, false);
121 Target
* result
= NULL
;
122 message_loop()->PostTask(
124 base::Bind(&BackgroundThread::DoDeRef
, arrow
, &result
, &completion
));
130 static void DoCreateArrowFromArrow(Arrow
** arrow
,
132 WaitableEvent
* completion
) {
135 completion
->Signal();
138 static void DoCreateArrowFromTarget(Arrow
** arrow
,
140 WaitableEvent
* completion
) {
142 (*arrow
)->target
= target
->AsWeakPtr();
143 completion
->Signal();
146 static void DoDeRef(const Arrow
* arrow
,
148 WaitableEvent
* completion
) {
149 *result
= arrow
->target
.get();
150 completion
->Signal();
153 static void DoDeleteTarget(Target
* object
, WaitableEvent
* completion
) {
155 completion
->Signal();
158 static void DoCopyAndAssignArrow(Arrow
* object
, WaitableEvent
* completion
) {
161 // Assignment operator.
163 completion
->Signal();
166 static void DoCopyAndAssignArrowBase(
168 WaitableEvent
* completion
) {
170 WeakPtr
<TargetBase
> b
= object
->target
;
171 // Assignment operator.
172 WeakPtr
<TargetBase
> c
;
174 completion
->Signal();
177 static void DoDeleteArrow(Arrow
* object
, WaitableEvent
* completion
) {
179 completion
->Signal();
185 TEST(WeakPtrFactoryTest
, Basic
) {
187 WeakPtrFactory
<int> factory(&data
);
188 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
189 EXPECT_EQ(&data
, ptr
.get());
192 TEST(WeakPtrFactoryTest
, Comparison
) {
194 WeakPtrFactory
<int> factory(&data
);
195 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
196 WeakPtr
<int> ptr2
= ptr
;
197 EXPECT_EQ(ptr
.get(), ptr2
.get());
200 TEST(WeakPtrFactoryTest
, OutOfScope
) {
202 EXPECT_EQ(NULL
, ptr
.get());
205 WeakPtrFactory
<int> factory(&data
);
206 ptr
= factory
.GetWeakPtr();
208 EXPECT_EQ(NULL
, ptr
.get());
211 TEST(WeakPtrFactoryTest
, Multiple
) {
215 WeakPtrFactory
<int> factory(&data
);
216 a
= factory
.GetWeakPtr();
217 b
= factory
.GetWeakPtr();
218 EXPECT_EQ(&data
, a
.get());
219 EXPECT_EQ(&data
, b
.get());
221 EXPECT_EQ(NULL
, a
.get());
222 EXPECT_EQ(NULL
, b
.get());
225 TEST(WeakPtrFactoryTest
, MultipleStaged
) {
229 WeakPtrFactory
<int> factory(&data
);
230 a
= factory
.GetWeakPtr();
232 WeakPtr
<int> b
= factory
.GetWeakPtr();
234 EXPECT_TRUE(NULL
!= a
.get());
236 EXPECT_EQ(NULL
, a
.get());
239 TEST(WeakPtrFactoryTest
, Dereference
) {
241 data
.member
= "123456";
242 WeakPtrFactory
<Base
> factory(&data
);
243 WeakPtr
<Base
> ptr
= factory
.GetWeakPtr();
244 EXPECT_EQ(&data
, ptr
.get());
245 EXPECT_EQ(data
.member
, (*ptr
).member
);
246 EXPECT_EQ(data
.member
, ptr
->member
);
249 TEST(WeakPtrFactoryTest
, UpCast
) {
251 WeakPtrFactory
<Derived
> factory(&data
);
252 WeakPtr
<Base
> ptr
= factory
.GetWeakPtr();
253 ptr
= factory
.GetWeakPtr();
254 EXPECT_EQ(ptr
.get(), &data
);
257 TEST(WeakPtrTest
, SupportsWeakPtr
) {
259 WeakPtr
<Target
> ptr
= target
.AsWeakPtr();
260 EXPECT_EQ(&target
, ptr
.get());
263 TEST(WeakPtrTest
, DerivedTarget
) {
264 DerivedTarget target
;
265 WeakPtr
<DerivedTarget
> ptr
= AsWeakPtr(&target
);
266 EXPECT_EQ(&target
, ptr
.get());
269 TEST(WeakPtrTest
, InvalidateWeakPtrs
) {
271 WeakPtrFactory
<int> factory(&data
);
272 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
273 EXPECT_EQ(&data
, ptr
.get());
274 EXPECT_TRUE(factory
.HasWeakPtrs());
275 factory
.InvalidateWeakPtrs();
276 EXPECT_EQ(NULL
, ptr
.get());
277 EXPECT_FALSE(factory
.HasWeakPtrs());
280 TEST(WeakPtrTest
, HasWeakPtrs
) {
282 WeakPtrFactory
<int> factory(&data
);
284 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
285 EXPECT_TRUE(factory
.HasWeakPtrs());
287 EXPECT_FALSE(factory
.HasWeakPtrs());
290 TEST(WeakPtrTest
, ObjectAndWeakPtrOnDifferentThreads
) {
291 // Test that it is OK to create an object that supports WeakPtr on one thread,
292 // but use it on another. This tests that we do not trip runtime checks that
293 // ensure that a WeakPtr is not used by multiple threads.
294 scoped_ptr
<Target
> target(OffThreadObjectCreator
<Target
>::NewObject());
295 WeakPtr
<Target
> weak_ptr
= target
->AsWeakPtr();
296 EXPECT_EQ(target
.get(), weak_ptr
.get());
299 TEST(WeakPtrTest
, WeakPtrInitiateAndUseOnDifferentThreads
) {
300 // Test that it is OK to create an object that has a WeakPtr member on one
301 // thread, but use it on another. This tests that we do not trip runtime
302 // checks that ensure that a WeakPtr is not used by multiple threads.
303 scoped_ptr
<Arrow
> arrow(OffThreadObjectCreator
<Arrow
>::NewObject());
305 arrow
->target
= target
.AsWeakPtr();
306 EXPECT_EQ(&target
, arrow
->target
.get());
309 TEST(WeakPtrTest
, MoveOwnershipImplicitly
) {
310 // Move object ownership to another thread by releasing all weak pointers
311 // on the original thread first, and then establish WeakPtr on a different
313 BackgroundThread background
;
316 Target
* target
= new Target();
318 WeakPtr
<Target
> weak_ptr
= target
->AsWeakPtr();
319 // Main thread deletes the WeakPtr, then the thread ownership of the
320 // object can be implicitly moved.
324 // Background thread creates WeakPtr(and implicitly owns the object).
325 background
.CreateArrowFromTarget(&arrow
, target
);
326 EXPECT_EQ(background
.DeRef(arrow
), target
);
329 // Main thread creates another WeakPtr, but this does not trigger implicitly
330 // thread ownership move.
332 arrow
.target
= target
->AsWeakPtr();
334 // The new WeakPtr is owned by background thread.
335 EXPECT_EQ(target
, background
.DeRef(&arrow
));
338 // Target can only be deleted on background thread.
339 background
.DeleteTarget(target
);
340 background
.DeleteArrow(arrow
);
343 TEST(WeakPtrTest
, MoveOwnershipOfUnreferencedObject
) {
344 BackgroundThread background
;
350 // Background thread creates WeakPtr.
351 background
.CreateArrowFromTarget(&arrow
, &target
);
353 // Bind to background thread.
354 EXPECT_EQ(&target
, background
.DeRef(arrow
));
356 // Release the only WeakPtr.
357 arrow
->target
.reset();
359 // Now we should be able to create a new reference from this thread.
360 arrow
->target
= target
.AsWeakPtr();
362 // Re-bind to main thread.
363 EXPECT_EQ(&target
, arrow
->target
.get());
365 // And the main thread can now delete the target.
371 TEST(WeakPtrTest
, MoveOwnershipAfterInvalidate
) {
372 BackgroundThread background
;
376 scoped_ptr
<TargetWithFactory
> target(new TargetWithFactory
);
378 // Bind to main thread.
379 arrow
.target
= target
->factory
.GetWeakPtr();
380 EXPECT_EQ(target
.get(), arrow
.target
.get());
382 target
->factory
.InvalidateWeakPtrs();
383 EXPECT_EQ(NULL
, arrow
.target
.get());
385 arrow
.target
= target
->factory
.GetWeakPtr();
386 // Re-bind to background thread.
387 EXPECT_EQ(target
.get(), background
.DeRef(&arrow
));
389 // And the background thread can now delete the target.
390 background
.DeleteTarget(target
.release());
393 TEST(WeakPtrTest
, MainThreadRefOutlivesBackgroundThreadRef
) {
394 // Originating thread has a WeakPtr that outlives others.
395 // - Main thread creates a WeakPtr
396 // - Background thread creates a WeakPtr copy from the one in main thread
397 // - Destruct the WeakPtr on background thread
398 // - Destruct the WeakPtr on main thread
399 BackgroundThread background
;
404 arrow
.target
= target
.AsWeakPtr();
407 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
408 EXPECT_EQ(arrow_copy
->target
.get(), &target
);
409 background
.DeleteArrow(arrow_copy
);
412 TEST(WeakPtrTest
, BackgroundThreadRefOutlivesMainThreadRef
) {
413 // Originating thread drops all references before another thread.
414 // - Main thread creates a WeakPtr and passes copy to background thread
415 // - Destruct the pointer on main thread
416 // - Destruct the pointer on background thread
417 BackgroundThread background
;
424 arrow
.target
= target
.AsWeakPtr();
425 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
427 EXPECT_EQ(arrow_copy
->target
.get(), &target
);
428 background
.DeleteArrow(arrow_copy
);
431 TEST(WeakPtrTest
, OwnerThreadDeletesObject
) {
432 // Originating thread invalidates WeakPtrs while its held by other thread.
433 // - Main thread creates WeakPtr and passes Copy to background thread
434 // - Object gets destroyed on main thread
435 // (invalidates WeakPtr on background thread)
436 // - WeakPtr gets destroyed on Thread B
437 BackgroundThread background
;
443 arrow
.target
= target
.AsWeakPtr();
444 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
446 EXPECT_EQ(NULL
, arrow_copy
->target
.get());
447 background
.DeleteArrow(arrow_copy
);
450 TEST(WeakPtrTest
, NonOwnerThreadCanCopyAndAssignWeakPtr
) {
451 // Main thread creates a Target object.
453 // Main thread creates an arrow referencing the Target.
454 Arrow
*arrow
= new Arrow();
455 arrow
->target
= target
.AsWeakPtr();
457 // Background can copy and assign arrow (as well as the WeakPtr inside).
458 BackgroundThread background
;
460 background
.CopyAndAssignArrow(arrow
);
461 background
.DeleteArrow(arrow
);
464 TEST(WeakPtrTest
, NonOwnerThreadCanCopyAndAssignWeakPtrBase
) {
465 // Main thread creates a Target object.
467 // Main thread creates an arrow referencing the Target.
468 Arrow
*arrow
= new Arrow();
469 arrow
->target
= target
.AsWeakPtr();
471 // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
472 BackgroundThread background
;
474 background
.CopyAndAssignArrowBase(arrow
);
475 background
.DeleteArrow(arrow
);
478 TEST(WeakPtrTest
, NonOwnerThreadCanDeleteWeakPtr
) {
479 // Main thread creates a Target object.
481 // Main thread creates an arrow referencing the Target.
482 Arrow
* arrow
= new Arrow();
483 arrow
->target
= target
.AsWeakPtr();
485 // Background can delete arrow (as well as the WeakPtr inside).
486 BackgroundThread background
;
488 background
.DeleteArrow(arrow
);
491 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
493 TEST(WeakPtrDeathTest
, WeakPtrCopyDoesNotChangeThreadBinding
) {
494 // The default style "fast" does not support multi-threaded tests
495 // (introduces deadlock on Linux).
496 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
498 BackgroundThread background
;
501 // Main thread creates a Target object.
503 // Main thread creates an arrow referencing the Target.
505 arrow
.target
= target
.AsWeakPtr();
507 // Background copies the WeakPtr.
509 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
511 // The copy is still bound to main thread so I can deref.
512 EXPECT_EQ(arrow
.target
.get(), arrow_copy
->target
.get());
514 // Although background thread created the copy, it can not deref the copied
516 ASSERT_DEATH(background
.DeRef(arrow_copy
), "");
518 background
.DeleteArrow(arrow_copy
);
521 TEST(WeakPtrDeathTest
, NonOwnerThreadDereferencesWeakPtrAfterReference
) {
522 // The default style "fast" does not support multi-threaded tests
523 // (introduces deadlock on Linux).
524 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
526 // Main thread creates a Target object.
529 // Main thread creates an arrow referencing the Target (so target's
530 // thread ownership can not be implicitly moved).
532 arrow
.target
= target
.AsWeakPtr();
535 // Background thread tries to deref target, which violates thread ownership.
536 BackgroundThread background
;
538 ASSERT_DEATH(background
.DeRef(&arrow
), "");
541 TEST(WeakPtrDeathTest
, NonOwnerThreadDeletesWeakPtrAfterReference
) {
542 // The default style "fast" does not support multi-threaded tests
543 // (introduces deadlock on Linux).
544 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
546 scoped_ptr
<Target
> target(new Target());
548 // Main thread creates an arrow referencing the Target.
550 arrow
.target
= target
->AsWeakPtr();
552 // Background thread tries to deref target, binding it to the thread.
553 BackgroundThread background
;
555 background
.DeRef(&arrow
);
557 // Main thread deletes Target, violating thread binding.
558 ASSERT_DEATH(target
.reset(), "");
560 // |target.reset()| died so |target| still holds the object, so we
561 // must pass it to the background thread to teardown.
562 background
.DeleteTarget(target
.release());
565 TEST(WeakPtrDeathTest
, NonOwnerThreadDeletesObjectAfterReference
) {
566 // The default style "fast" does not support multi-threaded tests
567 // (introduces deadlock on Linux).
568 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
570 scoped_ptr
<Target
> target(new Target());
572 // Main thread creates an arrow referencing the Target, and references it, so
573 // that it becomes bound to the thread.
575 arrow
.target
= target
->AsWeakPtr();
578 // Background thread tries to delete target, volating thread binding.
579 BackgroundThread background
;
581 ASSERT_DEATH(background
.DeleteTarget(target
.release()), "");
584 TEST(WeakPtrDeathTest
, NonOwnerThreadReferencesObjectAfterDeletion
) {
585 // The default style "fast" does not support multi-threaded tests
586 // (introduces deadlock on Linux).
587 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
589 scoped_ptr
<Target
> target(new Target());
591 // Main thread creates an arrow referencing the Target.
593 arrow
.target
= target
->AsWeakPtr();
595 // Background thread tries to delete target, binding the object to the thread.
596 BackgroundThread background
;
598 background
.DeleteTarget(target
.release());
600 // Main thread attempts to dereference the target, violating thread binding.
601 ASSERT_DEATH(arrow
.target
.get(), "");