Add git cl format presubmit warning for extension and apps.
[chromium-blink-merge.git] / base / memory / weak_ptr_unittest.cc
blobe7e12a272d33570885a01ffa738ea19b29ae0424
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"
7 #include <string>
9 #include "base/bind.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"
17 namespace base {
18 namespace {
20 template <class T>
21 class OffThreadObjectCreator {
22 public:
23 static T* NewObject() {
24 T* result;
26 Thread creator_thread("creator_thread");
27 creator_thread.Start();
28 creator_thread.message_loop()->PostTask(
29 FROM_HERE,
30 base::Bind(OffThreadObjectCreator::CreateObject, &result));
32 DCHECK(result); // We synchronized on thread destruction above.
33 return result;
35 private:
36 static void CreateObject(T** result) {
37 *result = new T;
41 struct Base {
42 std::string member;
44 struct Derived : public Base {};
46 struct TargetBase {};
47 struct Target : public TargetBase, public SupportsWeakPtr<Target> {};
48 struct DerivedTarget : public Target {};
49 struct Arrow {
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 {
60 public:
61 BackgroundThread() : Thread("owner_thread") {}
63 virtual ~BackgroundThread() {
64 Stop();
67 void CreateArrowFromTarget(Arrow** arrow, Target* target) {
68 WaitableEvent completion(true, false);
69 message_loop()->PostTask(
70 FROM_HERE,
71 base::Bind(&BackgroundThread::DoCreateArrowFromTarget,
72 arrow, target, &completion));
73 completion.Wait();
76 void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
77 WaitableEvent completion(true, false);
78 message_loop()->PostTask(
79 FROM_HERE,
80 base::Bind(&BackgroundThread::DoCreateArrowFromArrow,
81 arrow, other, &completion));
82 completion.Wait();
85 void DeleteTarget(Target* object) {
86 WaitableEvent completion(true, false);
87 message_loop()->PostTask(
88 FROM_HERE,
89 base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion));
90 completion.Wait();
93 void CopyAndAssignArrow(Arrow* object) {
94 WaitableEvent completion(true, false);
95 message_loop()->PostTask(
96 FROM_HERE,
97 base::Bind(&BackgroundThread::DoCopyAndAssignArrow,
98 object, &completion));
99 completion.Wait();
102 void CopyAndAssignArrowBase(Arrow* object) {
103 WaitableEvent completion(true, false);
104 message_loop()->PostTask(
105 FROM_HERE,
106 base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase,
107 object, &completion));
108 completion.Wait();
111 void DeleteArrow(Arrow* object) {
112 WaitableEvent completion(true, false);
113 message_loop()->PostTask(
114 FROM_HERE,
115 base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion));
116 completion.Wait();
119 Target* DeRef(const Arrow* arrow) {
120 WaitableEvent completion(true, false);
121 Target* result = NULL;
122 message_loop()->PostTask(
123 FROM_HERE,
124 base::Bind(&BackgroundThread::DoDeRef, arrow, &result, &completion));
125 completion.Wait();
126 return result;
129 protected:
130 static void DoCreateArrowFromArrow(Arrow** arrow,
131 const Arrow* other,
132 WaitableEvent* completion) {
133 *arrow = new Arrow;
134 **arrow = *other;
135 completion->Signal();
138 static void DoCreateArrowFromTarget(Arrow** arrow,
139 Target* target,
140 WaitableEvent* completion) {
141 *arrow = new Arrow;
142 (*arrow)->target = target->AsWeakPtr();
143 completion->Signal();
146 static void DoDeRef(const Arrow* arrow,
147 Target** result,
148 WaitableEvent* completion) {
149 *result = arrow->target.get();
150 completion->Signal();
153 static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
154 delete object;
155 completion->Signal();
158 static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) {
159 // Copy constructor.
160 Arrow a = *object;
161 // Assignment operator.
162 *object = a;
163 completion->Signal();
166 static void DoCopyAndAssignArrowBase(
167 Arrow* object,
168 WaitableEvent* completion) {
169 // Copy constructor.
170 WeakPtr<TargetBase> b = object->target;
171 // Assignment operator.
172 WeakPtr<TargetBase> c;
173 c = object->target;
174 completion->Signal();
177 static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
178 delete object;
179 completion->Signal();
183 } // namespace
185 TEST(WeakPtrFactoryTest, Basic) {
186 int data;
187 WeakPtrFactory<int> factory(&data);
188 WeakPtr<int> ptr = factory.GetWeakPtr();
189 EXPECT_EQ(&data, ptr.get());
192 TEST(WeakPtrFactoryTest, Comparison) {
193 int data;
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) {
201 WeakPtr<int> ptr;
202 EXPECT_EQ(NULL, ptr.get());
204 int data;
205 WeakPtrFactory<int> factory(&data);
206 ptr = factory.GetWeakPtr();
208 EXPECT_EQ(NULL, ptr.get());
211 TEST(WeakPtrFactoryTest, Multiple) {
212 WeakPtr<int> a, b;
214 int data;
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) {
226 WeakPtr<int> a;
228 int data;
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) {
240 Base data;
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) {
250 Derived data;
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) {
258 Target target;
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) {
270 int data;
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) {
281 int data;
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());
304 Target target;
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
312 // thread.
313 BackgroundThread background;
314 background.Start();
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.
322 Arrow* arrow;
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.
331 Arrow arrow;
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;
345 background.Start();
347 Arrow* arrow;
349 Target target;
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.
368 delete arrow;
371 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
372 BackgroundThread background;
373 background.Start();
375 Arrow arrow;
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;
400 background.Start();
402 Target target;
403 Arrow arrow;
404 arrow.target = target.AsWeakPtr();
406 Arrow* arrow_copy;
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;
418 background.Start();
420 Target target;
421 Arrow* arrow_copy;
423 Arrow arrow;
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;
438 background.Start();
439 Arrow* arrow_copy;
441 Target target;
442 Arrow arrow;
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.
452 Target target;
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;
459 background.Start();
460 background.CopyAndAssignArrow(arrow);
461 background.DeleteArrow(arrow);
464 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
465 // Main thread creates a Target object.
466 Target target;
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;
473 background.Start();
474 background.CopyAndAssignArrowBase(arrow);
475 background.DeleteArrow(arrow);
478 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
479 // Main thread creates a Target object.
480 Target target;
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;
487 background.Start();
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;
499 background.Start();
501 // Main thread creates a Target object.
502 Target target;
503 // Main thread creates an arrow referencing the Target.
504 Arrow arrow;
505 arrow.target = target.AsWeakPtr();
507 // Background copies the WeakPtr.
508 Arrow* arrow_copy;
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
515 // WeakPtr.
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.
527 Target target;
529 // Main thread creates an arrow referencing the Target (so target's
530 // thread ownership can not be implicitly moved).
531 Arrow arrow;
532 arrow.target = target.AsWeakPtr();
533 arrow.target.get();
535 // Background thread tries to deref target, which violates thread ownership.
536 BackgroundThread background;
537 background.Start();
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.
549 Arrow arrow;
550 arrow.target = target->AsWeakPtr();
552 // Background thread tries to deref target, binding it to the thread.
553 BackgroundThread background;
554 background.Start();
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.
574 Arrow arrow;
575 arrow.target = target->AsWeakPtr();
576 arrow.target.get();
578 // Background thread tries to delete target, volating thread binding.
579 BackgroundThread background;
580 background.Start();
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.
592 Arrow arrow;
593 arrow.target = target->AsWeakPtr();
595 // Background thread tries to delete target, binding the object to the thread.
596 BackgroundThread background;
597 background.Start();
598 background.DeleteTarget(target.release());
600 // Main thread attempts to dereference the target, violating thread binding.
601 ASSERT_DEATH(arrow.target.get(), "");
604 #endif
606 } // namespace base