1 // Copyright (c) 2011 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. 4 5 #include "base/memory/scoped_ptr.h" 6 #include "base/memory/weak_ptr.h" 7 #include "testing/gtest/include/gtest/gtest.h" 8 #include "base/message_loop.h" 9 #include "base/threading/thread.h" 10 11 namespace base { 12 namespace { 13 14 template <class T> 15 class OffThreadObjectCreator { 16 public: 17 static T* NewObject() { 18 T* result; 19 { 20 Thread creator_thread("creator_thread"); 21 creator_thread.Start(); 22 creator_thread.message_loop()->PostTask( 23 FROM_HERE, 24 NewRunnableFunction(OffThreadObjectCreator::CreateObject, &result)); 25 } 26 DCHECK(result); // We synchronized on thread destruction above. 27 return result; 28 } 29 private: 30 static void CreateObject(T** result) { 31 *result = new T; 32 } 33 }; 34 35 struct Base {}; 36 struct Derived : Base {}; 37 38 struct Producer : SupportsWeakPtr<Producer> {}; 39 struct Consumer { WeakPtr<Producer> producer; }; 40 41 } // namespace 42 43 TEST(WeakPtrTest, Basic) { 44 int data; 45 WeakPtrFactory<int> factory(&data); 46 WeakPtr<int> ptr = factory.GetWeakPtr(); 47 EXPECT_EQ(&data, ptr.get()); 48 } 49 50 TEST(WeakPtrTest, Comparison) { 51 int data; 52 WeakPtrFactory<int> factory(&data); 53 WeakPtr<int> ptr = factory.GetWeakPtr(); 54 WeakPtr<int> ptr2 = ptr; 55 EXPECT_TRUE(ptr == ptr2); 56 } 57 58 TEST(WeakPtrTest, OutOfScope) { 59 WeakPtr<int> ptr; 60 EXPECT_TRUE(ptr.get() == NULL); 61 { 62 int data; 63 WeakPtrFactory<int> factory(&data); 64 ptr = factory.GetWeakPtr(); 65 } 66 EXPECT_TRUE(ptr.get() == NULL); 67 } 68 69 TEST(WeakPtrTest, Multiple) { 70 WeakPtr<int> a, b; 71 { 72 int data; 73 WeakPtrFactory<int> factory(&data); 74 a = factory.GetWeakPtr(); 75 b = factory.GetWeakPtr(); 76 EXPECT_EQ(&data, a.get()); 77 EXPECT_EQ(&data, b.get()); 78 } 79 EXPECT_TRUE(a.get() == NULL); 80 EXPECT_TRUE(b.get() == NULL); 81 } 82 83 TEST(WeakPtrTest, UpCast) { 84 Derived data; 85 WeakPtrFactory<Derived> factory(&data); 86 WeakPtr<Base> ptr = factory.GetWeakPtr(); 87 ptr = factory.GetWeakPtr(); 88 EXPECT_EQ(ptr.get(), &data); 89 } 90 91 TEST(WeakPtrTest, SupportsWeakPtr) { 92 Producer f; 93 WeakPtr<Producer> ptr = f.AsWeakPtr(); 94 EXPECT_EQ(&f, ptr.get()); 95 } 96 97 TEST(WeakPtrTest, InvalidateWeakPtrs) { 98 int data; 99 WeakPtrFactory<int> factory(&data); 100 WeakPtr<int> ptr = factory.GetWeakPtr(); 101 EXPECT_EQ(&data, ptr.get()); 102 EXPECT_TRUE(factory.HasWeakPtrs()); 103 factory.InvalidateWeakPtrs(); 104 EXPECT_TRUE(ptr.get() == NULL); 105 EXPECT_FALSE(factory.HasWeakPtrs()); 106 } 107 108 TEST(WeakPtrTest, HasWeakPtrs) { 109 int data; 110 WeakPtrFactory<int> factory(&data); 111 { 112 WeakPtr<int> ptr = factory.GetWeakPtr(); 113 EXPECT_TRUE(factory.HasWeakPtrs()); 114 } 115 EXPECT_FALSE(factory.HasWeakPtrs()); 116 } 117 118 TEST(WeakPtrTest, SingleThreaded1) { 119 // Test that it is OK to create a class that supports weak references on one 120 // thread, but use it on another. This tests that we do not trip runtime 121 // checks that ensure that a weak reference is not used by multiple threads. 122 scoped_ptr<Producer> producer(OffThreadObjectCreator<Producer>::NewObject()); 123 WeakPtr<Producer> weak_producer = producer->AsWeakPtr(); 124 EXPECT_EQ(producer.get(), weak_producer.get()); 125 } 126 127 TEST(WeakPtrTest, SingleThreaded2) { 128 // Test that it is OK to create a class that has a WeakPtr member on one 129 // thread, but use it on another. This tests that we do not trip runtime 130 // checks that ensure that a weak reference is not used by multiple threads. 131 scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject()); 132 Producer producer; 133 consumer->producer = producer.AsWeakPtr(); 134 EXPECT_EQ(&producer, consumer->producer.get()); 135 } 136 137 } // namespace base 138