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