• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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