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