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 11namespace base { 12namespace { 13 14template <class T> 15class 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 35struct Base {}; 36struct Derived : Base {}; 37 38struct Producer : SupportsWeakPtr<Producer> {}; 39struct Consumer { WeakPtr<Producer> producer; }; 40 41} // namespace 42 43TEST(WeakPtrTest, Basic) { 44 int data; 45 WeakPtrFactory<int> factory(&data); 46 WeakPtr<int> ptr = factory.GetWeakPtr(); 47 EXPECT_EQ(&data, ptr.get()); 48} 49 50TEST(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 58TEST(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 69TEST(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 83TEST(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 91TEST(WeakPtrTest, SupportsWeakPtr) { 92 Producer f; 93 WeakPtr<Producer> ptr = f.AsWeakPtr(); 94 EXPECT_EQ(&f, ptr.get()); 95} 96 97TEST(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 108TEST(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 118TEST(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 127TEST(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