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 ~BackgroundThread() override { Stop(); }
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());
279 // Test that the factory can create new weak pointers after a
280 // InvalidateWeakPtrs call, and they remain valid until the next
281 // InvalidateWeakPtrs call.
282 WeakPtr<int> ptr2 = factory.GetWeakPtr();
283 EXPECT_EQ(&data, ptr2.get());
284 EXPECT_TRUE(factory.HasWeakPtrs());
285 factory.InvalidateWeakPtrs();
286 EXPECT_EQ(NULL, ptr2.get());
287 EXPECT_FALSE(factory.HasWeakPtrs());
290 TEST(WeakPtrTest, HasWeakPtrs) {
292 WeakPtrFactory<int> factory(&data);
294 WeakPtr<int> ptr = factory.GetWeakPtr();
295 EXPECT_TRUE(factory.HasWeakPtrs());
297 EXPECT_FALSE(factory.HasWeakPtrs());
300 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
301 // Test that it is OK to create an object that supports WeakPtr on one thread,
302 // but use it on another. This tests that we do not trip runtime checks that
303 // ensure that a WeakPtr is not used by multiple threads.
304 scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
305 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
306 EXPECT_EQ(target.get(), weak_ptr.get());
309 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
310 // Test that it is OK to create an object that has a WeakPtr member on one
311 // thread, but use it on another. This tests that we do not trip runtime
312 // checks that ensure that a WeakPtr is not used by multiple threads.
313 scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
315 arrow->target = target.AsWeakPtr();
316 EXPECT_EQ(&target, arrow->target.get());
319 TEST(WeakPtrTest, MoveOwnershipImplicitly) {
320 // Move object ownership to another thread by releasing all weak pointers
321 // on the original thread first, and then establish WeakPtr on a different
323 BackgroundThread background;
326 Target* target = new Target();
328 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
329 // Main thread deletes the WeakPtr, then the thread ownership of the
330 // object can be implicitly moved.
334 // Background thread creates WeakPtr(and implicitly owns the object).
335 background.CreateArrowFromTarget(&arrow, target);
336 EXPECT_EQ(background.DeRef(arrow), target);
339 // Main thread creates another WeakPtr, but this does not trigger implicitly
340 // thread ownership move.
342 arrow.target = target->AsWeakPtr();
344 // The new WeakPtr is owned by background thread.
345 EXPECT_EQ(target, background.DeRef(&arrow));
348 // Target can only be deleted on background thread.
349 background.DeleteTarget(target);
350 background.DeleteArrow(arrow);
353 TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) {
354 BackgroundThread background;
360 // Background thread creates WeakPtr.
361 background.CreateArrowFromTarget(&arrow, &target);
363 // Bind to background thread.
364 EXPECT_EQ(&target, background.DeRef(arrow));
366 // Release the only WeakPtr.
367 arrow->target.reset();
369 // Now we should be able to create a new reference from this thread.
370 arrow->target = target.AsWeakPtr();
372 // Re-bind to main thread.
373 EXPECT_EQ(&target, arrow->target.get());
375 // And the main thread can now delete the target.
381 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
382 BackgroundThread background;
386 scoped_ptr<TargetWithFactory> target(new TargetWithFactory);
388 // Bind to main thread.
389 arrow.target = target->factory.GetWeakPtr();
390 EXPECT_EQ(target.get(), arrow.target.get());
392 target->factory.InvalidateWeakPtrs();
393 EXPECT_EQ(NULL, arrow.target.get());
395 arrow.target = target->factory.GetWeakPtr();
396 // Re-bind to background thread.
397 EXPECT_EQ(target.get(), background.DeRef(&arrow));
399 // And the background thread can now delete the target.
400 background.DeleteTarget(target.release());
403 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
404 // Originating thread has a WeakPtr that outlives others.
405 // - Main thread creates a WeakPtr
406 // - Background thread creates a WeakPtr copy from the one in main thread
407 // - Destruct the WeakPtr on background thread
408 // - Destruct the WeakPtr on main thread
409 BackgroundThread background;
414 arrow.target = target.AsWeakPtr();
417 background.CreateArrowFromArrow(&arrow_copy, &arrow);
418 EXPECT_EQ(arrow_copy->target.get(), &target);
419 background.DeleteArrow(arrow_copy);
422 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
423 // Originating thread drops all references before another thread.
424 // - Main thread creates a WeakPtr and passes copy to background thread
425 // - Destruct the pointer on main thread
426 // - Destruct the pointer on background thread
427 BackgroundThread background;
434 arrow.target = target.AsWeakPtr();
435 background.CreateArrowFromArrow(&arrow_copy, &arrow);
437 EXPECT_EQ(arrow_copy->target.get(), &target);
438 background.DeleteArrow(arrow_copy);
441 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
442 // Originating thread invalidates WeakPtrs while its held by other thread.
443 // - Main thread creates WeakPtr and passes Copy to background thread
444 // - Object gets destroyed on main thread
445 // (invalidates WeakPtr on background thread)
446 // - WeakPtr gets destroyed on Thread B
447 BackgroundThread background;
453 arrow.target = target.AsWeakPtr();
454 background.CreateArrowFromArrow(&arrow_copy, &arrow);
456 EXPECT_EQ(NULL, arrow_copy->target.get());
457 background.DeleteArrow(arrow_copy);
460 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
461 // Main thread creates a Target object.
463 // Main thread creates an arrow referencing the Target.
464 Arrow *arrow = new Arrow();
465 arrow->target = target.AsWeakPtr();
467 // Background can copy and assign arrow (as well as the WeakPtr inside).
468 BackgroundThread background;
470 background.CopyAndAssignArrow(arrow);
471 background.DeleteArrow(arrow);
474 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
475 // Main thread creates a Target object.
477 // Main thread creates an arrow referencing the Target.
478 Arrow *arrow = new Arrow();
479 arrow->target = target.AsWeakPtr();
481 // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
482 BackgroundThread background;
484 background.CopyAndAssignArrowBase(arrow);
485 background.DeleteArrow(arrow);
488 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
489 // Main thread creates a Target object.
491 // Main thread creates an arrow referencing the Target.
492 Arrow* arrow = new Arrow();
493 arrow->target = target.AsWeakPtr();
495 // Background can delete arrow (as well as the WeakPtr inside).
496 BackgroundThread background;
498 background.DeleteArrow(arrow);
501 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
503 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
504 // The default style "fast" does not support multi-threaded tests
505 // (introduces deadlock on Linux).
506 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
508 BackgroundThread background;
511 // Main thread creates a Target object.
513 // Main thread creates an arrow referencing the Target.
515 arrow.target = target.AsWeakPtr();
517 // Background copies the WeakPtr.
519 background.CreateArrowFromArrow(&arrow_copy, &arrow);
521 // The copy is still bound to main thread so I can deref.
522 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
524 // Although background thread created the copy, it can not deref the copied
526 ASSERT_DEATH(background.DeRef(arrow_copy), "");
528 background.DeleteArrow(arrow_copy);
531 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) {
532 // The default style "fast" does not support multi-threaded tests
533 // (introduces deadlock on Linux).
534 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
536 // Main thread creates a Target object.
539 // Main thread creates an arrow referencing the Target (so target's
540 // thread ownership can not be implicitly moved).
542 arrow.target = target.AsWeakPtr();
545 // Background thread tries to deref target, which violates thread ownership.
546 BackgroundThread background;
548 ASSERT_DEATH(background.DeRef(&arrow), "");
551 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) {
552 // The default style "fast" does not support multi-threaded tests
553 // (introduces deadlock on Linux).
554 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
556 scoped_ptr<Target> target(new Target());
558 // Main thread creates an arrow referencing the Target.
560 arrow.target = target->AsWeakPtr();
562 // Background thread tries to deref target, binding it to the thread.
563 BackgroundThread background;
565 background.DeRef(&arrow);
567 // Main thread deletes Target, violating thread binding.
568 ASSERT_DEATH(target.reset(), "");
570 // |target.reset()| died so |target| still holds the object, so we
571 // must pass it to the background thread to teardown.
572 background.DeleteTarget(target.release());
575 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) {
576 // The default style "fast" does not support multi-threaded tests
577 // (introduces deadlock on Linux).
578 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
580 scoped_ptr<Target> target(new Target());
582 // Main thread creates an arrow referencing the Target, and references it, so
583 // that it becomes bound to the thread.
585 arrow.target = target->AsWeakPtr();
588 // Background thread tries to delete target, volating thread binding.
589 BackgroundThread background;
591 ASSERT_DEATH(background.DeleteTarget(target.release()), "");
594 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
595 // The default style "fast" does not support multi-threaded tests
596 // (introduces deadlock on Linux).
597 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
599 scoped_ptr<Target> target(new Target());
601 // Main thread creates an arrow referencing the Target.
603 arrow.target = target->AsWeakPtr();
605 // Background thread tries to delete target, binding the object to the thread.
606 BackgroundThread background;
608 background.DeleteTarget(target.release());
610 // Main thread attempts to dereference the target, violating thread binding.
611 ASSERT_DEATH(arrow.target.get(), "");