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.
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"
13 COMPILE_ASSERT(DefaultSingletonTraits
<int>::kRegisterAtExit
== true, a
);
15 template<typename Type
>
16 struct LockTrait
: public DefaultSingletonTraits
<Type
> {
19 struct Init5Trait
: public DefaultSingletonTraits
<int> {
25 typedef void (*CallbackFunc
)();
27 struct CallbackTrait
: public DefaultSingletonTraits
<CallbackFunc
> {
28 static void Delete(CallbackFunc
* p
) {
31 DefaultSingletonTraits
<CallbackFunc
>::Delete(p
);
35 struct NoLeakTrait
: public CallbackTrait
{
38 struct LeakTrait
: public CallbackTrait
{
39 static const bool kRegisterAtExit
= false;
42 int* SingletonInt1() {
43 return Singleton
<int>::get();
46 int* SingletonInt2() {
47 // Force to use a different singleton than SingletonInt1.
48 return Singleton
<int, DefaultSingletonTraits
<int> >::get();
51 class DummyDifferentiatingClass
{
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();
61 int* SingletonInt4() {
62 return Singleton
<int, LockTrait
<int> >::get();
65 int* SingletonInt5() {
66 return Singleton
<int, Init5Trait
>::get();
69 void SingletonNoLeak(CallbackFunc CallOnQuit
) {
70 *Singleton
<CallbackFunc
, NoLeakTrait
>::get() = CallOnQuit
;
73 void SingletonLeak(CallbackFunc CallOnQuit
) {
74 *Singleton
<CallbackFunc
, LeakTrait
>::get() = CallOnQuit
;
77 CallbackFunc
* GetLeakySingleton() {
78 return Singleton
<CallbackFunc
, LeakTrait
>::get();
83 class SingletonTest
: public testing::Test
{
87 virtual void SetUp() {
88 non_leak_called_
= false;
89 leaky_called_
= false;
93 void VerifiesCallbacks() {
94 EXPECT_TRUE(non_leak_called_
);
95 EXPECT_FALSE(leaky_called_
);
96 non_leak_called_
= false;
97 leaky_called_
= false;
100 void VerifiesCallbacksNotCalled() {
101 EXPECT_FALSE(non_leak_called_
);
102 EXPECT_FALSE(leaky_called_
);
103 non_leak_called_
= false;
104 leaky_called_
= false;
107 static void CallbackNoLeak() {
108 non_leak_called_
= true;
111 static void CallbackLeak() {
112 leaky_called_
= true;
116 static bool non_leak_called_
;
117 static bool leaky_called_
;
120 bool SingletonTest::non_leak_called_
= false;
121 bool SingletonTest::leaky_called_
= false;
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
;
132 base::ShadowingAtExitManager sem
;
134 singleton_int_1
= SingletonInt1();
136 // Ensure POD type initialization.
137 EXPECT_EQ(*singleton_int_1
, 0);
138 *singleton_int_1
= 1;
140 EXPECT_EQ(singleton_int_1
, SingletonInt1());
141 EXPECT_EQ(*singleton_int_1
, 1);
144 singleton_int_2
= SingletonInt2();
146 // Same instance that 1.
147 EXPECT_EQ(*singleton_int_2
, 1);
148 EXPECT_EQ(singleton_int_1
, singleton_int_2
);
151 singleton_int_3
= SingletonInt3();
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);
161 singleton_int_4
= SingletonInt4();
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
);
170 singleton_int_5
= SingletonInt5();
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
);
178 SingletonNoLeak(&CallbackNoLeak
);
179 SingletonLeak(&CallbackLeak
);
180 leaky_singleton
= GetLeakySingleton();
181 EXPECT_TRUE(leaky_singleton
);
184 // Verify that only the expected callback has been called.
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
);
191 base::ShadowingAtExitManager sem
;
192 // Verifiy that the variables were reset.
194 singleton_int_1
= SingletonInt1();
195 EXPECT_EQ(*singleton_int_1
, 0);
198 singleton_int_5
= SingletonInt5();
199 EXPECT_EQ(*singleton_int_5
, 5);
202 // The leaky singleton shouldn't leak since SingletonLeak has not been called.
203 VerifiesCallbacksNotCalled();