Notify network properties changed for IPConfig updates
[chromium-blink-merge.git] / base / memory / weak_ptr_unittest.cc
blobd79e8d4d41c49d32d4643e24511c139a65d97d2e
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 virtual ~Target() {}
50 struct DerivedTarget : public Target {};
51 struct Arrow {
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 {
62 public:
63 BackgroundThread() : Thread("owner_thread") {}
65 virtual ~BackgroundThread() {
66 Stop();
69 void CreateArrowFromTarget(Arrow** arrow, Target* target) {
70 WaitableEvent completion(true, false);
71 message_loop()->PostTask(
72 FROM_HERE,
73 base::Bind(&BackgroundThread::DoCreateArrowFromTarget,
74 arrow, target, &completion));
75 completion.Wait();
78 void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
79 WaitableEvent completion(true, false);
80 message_loop()->PostTask(
81 FROM_HERE,
82 base::Bind(&BackgroundThread::DoCreateArrowFromArrow,
83 arrow, other, &completion));
84 completion.Wait();
87 void DeleteTarget(Target* object) {
88 WaitableEvent completion(true, false);
89 message_loop()->PostTask(
90 FROM_HERE,
91 base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion));
92 completion.Wait();
95 void CopyAndAssignArrow(Arrow* object) {
96 WaitableEvent completion(true, false);
97 message_loop()->PostTask(
98 FROM_HERE,
99 base::Bind(&BackgroundThread::DoCopyAndAssignArrow,
100 object, &completion));
101 completion.Wait();
104 void CopyAndAssignArrowBase(Arrow* object) {
105 WaitableEvent completion(true, false);
106 message_loop()->PostTask(
107 FROM_HERE,
108 base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase,
109 object, &completion));
110 completion.Wait();
113 void DeleteArrow(Arrow* object) {
114 WaitableEvent completion(true, false);
115 message_loop()->PostTask(
116 FROM_HERE,
117 base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion));
118 completion.Wait();
121 Target* DeRef(const Arrow* arrow) {
122 WaitableEvent completion(true, false);
123 Target* result = NULL;
124 message_loop()->PostTask(
125 FROM_HERE,
126 base::Bind(&BackgroundThread::DoDeRef, arrow, &result, &completion));
127 completion.Wait();
128 return result;
131 protected:
132 static void DoCreateArrowFromArrow(Arrow** arrow,
133 const Arrow* other,
134 WaitableEvent* completion) {
135 *arrow = new Arrow;
136 **arrow = *other;
137 completion->Signal();
140 static void DoCreateArrowFromTarget(Arrow** arrow,
141 Target* target,
142 WaitableEvent* completion) {
143 *arrow = new Arrow;
144 (*arrow)->target = target->AsWeakPtr();
145 completion->Signal();
148 static void DoDeRef(const Arrow* arrow,
149 Target** result,
150 WaitableEvent* completion) {
151 *result = arrow->target.get();
152 completion->Signal();
155 static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
156 delete object;
157 completion->Signal();
160 static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) {
161 // Copy constructor.
162 Arrow a = *object;
163 // Assignment operator.
164 *object = a;
165 completion->Signal();
168 static void DoCopyAndAssignArrowBase(
169 Arrow* object,
170 WaitableEvent* completion) {
171 // Copy constructor.
172 WeakPtr<TargetBase> b = object->target;
173 // Assignment operator.
174 WeakPtr<TargetBase> c;
175 c = object->target;
176 completion->Signal();
179 static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
180 delete object;
181 completion->Signal();
185 } // namespace
187 TEST(WeakPtrFactoryTest, Basic) {
188 int data;
189 WeakPtrFactory<int> factory(&data);
190 WeakPtr<int> ptr = factory.GetWeakPtr();
191 EXPECT_EQ(&data, ptr.get());
194 TEST(WeakPtrFactoryTest, Comparison) {
195 int data;
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) {
203 WeakPtr<int> ptr;
204 EXPECT_EQ(NULL, ptr.get());
206 int data;
207 WeakPtrFactory<int> factory(&data);
208 ptr = factory.GetWeakPtr();
210 EXPECT_EQ(NULL, ptr.get());
213 TEST(WeakPtrFactoryTest, Multiple) {
214 WeakPtr<int> a, b;
216 int data;
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) {
228 WeakPtr<int> a;
230 int data;
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) {
242 Base data;
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) {
252 Derived data;
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) {
260 Target target;
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) {
272 int data;
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) {
293 int data;
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());
316 Target target;
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
324 // thread.
325 BackgroundThread background;
326 background.Start();
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.
334 Arrow* arrow;
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.
343 Arrow arrow;
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;
357 background.Start();
359 Arrow* arrow;
361 Target target;
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.
380 delete arrow;
383 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
384 BackgroundThread background;
385 background.Start();
387 Arrow arrow;
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;
412 background.Start();
414 Target target;
415 Arrow arrow;
416 arrow.target = target.AsWeakPtr();
418 Arrow* arrow_copy;
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;
430 background.Start();
432 Target target;
433 Arrow* arrow_copy;
435 Arrow arrow;
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;
450 background.Start();
451 Arrow* arrow_copy;
453 Target target;
454 Arrow arrow;
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.
464 Target target;
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;
471 background.Start();
472 background.CopyAndAssignArrow(arrow);
473 background.DeleteArrow(arrow);
476 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
477 // Main thread creates a Target object.
478 Target target;
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;
485 background.Start();
486 background.CopyAndAssignArrowBase(arrow);
487 background.DeleteArrow(arrow);
490 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
491 // Main thread creates a Target object.
492 Target target;
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;
499 background.Start();
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;
511 background.Start();
513 // Main thread creates a Target object.
514 Target target;
515 // Main thread creates an arrow referencing the Target.
516 Arrow arrow;
517 arrow.target = target.AsWeakPtr();
519 // Background copies the WeakPtr.
520 Arrow* arrow_copy;
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
527 // WeakPtr.
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.
539 Target target;
541 // Main thread creates an arrow referencing the Target (so target's
542 // thread ownership can not be implicitly moved).
543 Arrow arrow;
544 arrow.target = target.AsWeakPtr();
545 arrow.target.get();
547 // Background thread tries to deref target, which violates thread ownership.
548 BackgroundThread background;
549 background.Start();
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.
561 Arrow arrow;
562 arrow.target = target->AsWeakPtr();
564 // Background thread tries to deref target, binding it to the thread.
565 BackgroundThread background;
566 background.Start();
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.
586 Arrow arrow;
587 arrow.target = target->AsWeakPtr();
588 arrow.target.get();
590 // Background thread tries to delete target, volating thread binding.
591 BackgroundThread background;
592 background.Start();
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.
604 Arrow arrow;
605 arrow.target = target->AsWeakPtr();
607 // Background thread tries to delete target, binding the object to the thread.
608 BackgroundThread background;
609 background.Start();
610 background.DeleteTarget(target.release());
612 // Main thread attempts to dereference the target, violating thread binding.
613 ASSERT_DEATH(arrow.target.get(), "");
616 #endif
618 } // namespace base