1 // Copyright (c) 2006-2008 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/at_exit.h"
6 #include "base/file_util.h"
7 #include "base/path_service.h"
8 #include "base/singleton.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace {
12
13 COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a);
14
15 template<typename Type>
16 struct LockTrait : public DefaultSingletonTraits<Type> {
17 };
18
19 struct Init5Trait : public DefaultSingletonTraits<int> {
New__anon80d48fbe0111::Init5Trait20 static int* New() {
21 return new int(5);
22 }
23 };
24
25 typedef void (*CallbackFunc)();
26
27 struct CallbackTrait : public DefaultSingletonTraits<CallbackFunc> {
Delete__anon80d48fbe0111::CallbackTrait28 static void Delete(CallbackFunc* p) {
29 if (*p)
30 (*p)();
31 DefaultSingletonTraits<CallbackFunc>::Delete(p);
32 }
33 };
34
35 struct NoLeakTrait : public CallbackTrait {
36 };
37
38 struct LeakTrait : public CallbackTrait {
39 static const bool kRegisterAtExit = false;
40 };
41
SingletonInt1()42 int* SingletonInt1() {
43 return Singleton<int>::get();
44 }
45
SingletonInt2()46 int* SingletonInt2() {
47 // Force to use a different singleton than SingletonInt1.
48 return Singleton<int, DefaultSingletonTraits<int> >::get();
49 }
50
51 class DummyDifferentiatingClass {
52 };
53
SingletonInt3()54 int* SingletonInt3() {
55 // Force to use a different singleton than SingletonInt1 and SingletonInt2.
56 // Note that any type can be used; int, float, std::wstring...
57 return Singleton<int, DefaultSingletonTraits<int>,
58 DummyDifferentiatingClass>::get();
59 }
60
SingletonInt4()61 int* SingletonInt4() {
62 return Singleton<int, LockTrait<int> >::get();
63 }
64
SingletonInt5()65 int* SingletonInt5() {
66 return Singleton<int, Init5Trait>::get();
67 }
68
SingletonNoLeak(CallbackFunc CallOnQuit)69 void SingletonNoLeak(CallbackFunc CallOnQuit) {
70 *Singleton<CallbackFunc, NoLeakTrait>::get() = CallOnQuit;
71 }
72
SingletonLeak(CallbackFunc CallOnQuit)73 void SingletonLeak(CallbackFunc CallOnQuit) {
74 *Singleton<CallbackFunc, LeakTrait>::get() = CallOnQuit;
75 }
76
GetLeakySingleton()77 CallbackFunc* GetLeakySingleton() {
78 return Singleton<CallbackFunc, LeakTrait>::get();
79 }
80
81 } // namespace
82
83 class SingletonTest : public testing::Test {
84 public:
SingletonTest()85 SingletonTest() { }
86
SetUp()87 virtual void SetUp() {
88 non_leak_called_ = false;
89 leaky_called_ = false;
90 }
91
92 protected:
VerifiesCallbacks()93 void VerifiesCallbacks() {
94 EXPECT_TRUE(non_leak_called_);
95 EXPECT_FALSE(leaky_called_);
96 non_leak_called_ = false;
97 leaky_called_ = false;
98 }
99
VerifiesCallbacksNotCalled()100 void VerifiesCallbacksNotCalled() {
101 EXPECT_FALSE(non_leak_called_);
102 EXPECT_FALSE(leaky_called_);
103 non_leak_called_ = false;
104 leaky_called_ = false;
105 }
106
CallbackNoLeak()107 static void CallbackNoLeak() {
108 non_leak_called_ = true;
109 }
110
CallbackLeak()111 static void CallbackLeak() {
112 leaky_called_ = true;
113 }
114
115 private:
116 static bool non_leak_called_;
117 static bool leaky_called_;
118 };
119
120 bool SingletonTest::non_leak_called_ = false;
121 bool SingletonTest::leaky_called_ = false;
122
TEST_F(SingletonTest,Basic)123 TEST_F(SingletonTest, Basic) {
124 int* singleton_int_1;
125 int* singleton_int_2;
126 int* singleton_int_3;
127 int* singleton_int_4;
128 int* singleton_int_5;
129 CallbackFunc* leaky_singleton;
130
131 {
132 base::ShadowingAtExitManager sem;
133 {
134 singleton_int_1 = SingletonInt1();
135 }
136 // Ensure POD type initialization.
137 EXPECT_EQ(*singleton_int_1, 0);
138 *singleton_int_1 = 1;
139
140 EXPECT_EQ(singleton_int_1, SingletonInt1());
141 EXPECT_EQ(*singleton_int_1, 1);
142
143 {
144 singleton_int_2 = SingletonInt2();
145 }
146 // Same instance that 1.
147 EXPECT_EQ(*singleton_int_2, 1);
148 EXPECT_EQ(singleton_int_1, singleton_int_2);
149
150 {
151 singleton_int_3 = SingletonInt3();
152 }
153 // Different instance than 1 and 2.
154 EXPECT_EQ(*singleton_int_3, 0);
155 EXPECT_NE(singleton_int_1, singleton_int_3);
156 *singleton_int_3 = 3;
157 EXPECT_EQ(*singleton_int_1, 1);
158 EXPECT_EQ(*singleton_int_2, 1);
159
160 {
161 singleton_int_4 = SingletonInt4();
162 }
163 // Use a lock for creation. Not really tested at length.
164 EXPECT_EQ(*singleton_int_4, 0);
165 *singleton_int_4 = 4;
166 EXPECT_NE(singleton_int_1, singleton_int_4);
167 EXPECT_NE(singleton_int_3, singleton_int_4);
168
169 {
170 singleton_int_5 = SingletonInt5();
171 }
172 // Is default initialized to 5.
173 EXPECT_EQ(*singleton_int_5, 5);
174 EXPECT_NE(singleton_int_1, singleton_int_5);
175 EXPECT_NE(singleton_int_3, singleton_int_5);
176 EXPECT_NE(singleton_int_4, singleton_int_5);
177
178 SingletonNoLeak(&CallbackNoLeak);
179 SingletonLeak(&CallbackLeak);
180 leaky_singleton = GetLeakySingleton();
181 EXPECT_TRUE(leaky_singleton);
182 }
183
184 // Verify that only the expected callback has been called.
185 VerifiesCallbacks();
186 // Delete the leaky singleton. It is interesting to note that Purify does
187 // *not* detect the leak when this call is commented out. :(
188 DefaultSingletonTraits<CallbackFunc>::Delete(leaky_singleton);
189
190 {
191 base::ShadowingAtExitManager sem;
192 // Verifiy that the variables were reset.
193 {
194 singleton_int_1 = SingletonInt1();
195 EXPECT_EQ(*singleton_int_1, 0);
196 }
197 {
198 singleton_int_5 = SingletonInt5();
199 EXPECT_EQ(*singleton_int_5, 5);
200 }
201 }
202 // The leaky singleton shouldn't leak since SingletonLeak has not been called.
203 VerifiesCallbacksNotCalled();
204 }
205