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(), "");