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:
NewObject()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:
CreateObject(T ** result)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
TEST(WeakPtrTest,Basic)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
TEST(WeakPtrTest,Comparison)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
TEST(WeakPtrTest,OutOfScope)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
TEST(WeakPtrTest,Multiple)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
TEST(WeakPtrTest,UpCast)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
TEST(WeakPtrTest,SupportsWeakPtr)91 TEST(WeakPtrTest, SupportsWeakPtr) {
92 Producer f;
93 WeakPtr<Producer> ptr = f.AsWeakPtr();
94 EXPECT_EQ(&f, ptr.get());
95 }
96
TEST(WeakPtrTest,InvalidateWeakPtrs)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
TEST(WeakPtrTest,HasWeakPtrs)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
TEST(WeakPtrTest,SingleThreaded1)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
TEST(WeakPtrTest,SingleThreaded2)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