1 // Copyright (c) 2012 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/memory/singleton.h"
8 #include "base/path_service.h"
9 #include "testing/gtest/include/gtest/gtest.h"
13 COMPILE_ASSERT(DefaultSingletonTraits
<int>::kRegisterAtExit
== true, a
);
15 typedef void (*CallbackFunc
)();
19 static IntSingleton
* GetInstance() {
20 return Singleton
<IntSingleton
>::get();
26 class Init5Singleton
{
30 static Init5Singleton
* GetInstance() {
31 return Singleton
<Init5Singleton
, Trait
>::get();
37 struct Init5Singleton::Trait
: public DefaultSingletonTraits
<Init5Singleton
> {
38 static Init5Singleton
* New() {
39 Init5Singleton
* instance
= new Init5Singleton();
46 return &IntSingleton::GetInstance()->value_
;
49 int* SingletonInt5() {
50 return &Init5Singleton::GetInstance()->value_
;
53 template <typename Type
>
54 struct CallbackTrait
: public DefaultSingletonTraits
<Type
> {
55 static void Delete(Type
* instance
) {
56 if (instance
->callback_
)
57 (instance
->callback_
)();
58 DefaultSingletonTraits
<Type
>::Delete(instance
);
62 class CallbackSingleton
{
64 CallbackSingleton() : callback_(NULL
) { }
65 CallbackFunc callback_
;
68 class CallbackSingletonWithNoLeakTrait
: public CallbackSingleton
{
70 struct Trait
: public CallbackTrait
<CallbackSingletonWithNoLeakTrait
> { };
72 CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { }
74 static CallbackSingletonWithNoLeakTrait
* GetInstance() {
75 return Singleton
<CallbackSingletonWithNoLeakTrait
, Trait
>::get();
79 class CallbackSingletonWithLeakTrait
: public CallbackSingleton
{
81 struct Trait
: public CallbackTrait
<CallbackSingletonWithLeakTrait
> {
82 static const bool kRegisterAtExit
= false;
85 CallbackSingletonWithLeakTrait() : CallbackSingleton() { }
87 static CallbackSingletonWithLeakTrait
* GetInstance() {
88 return Singleton
<CallbackSingletonWithLeakTrait
, Trait
>::get();
92 class CallbackSingletonWithStaticTrait
: public CallbackSingleton
{
96 CallbackSingletonWithStaticTrait() : CallbackSingleton() { }
98 static CallbackSingletonWithStaticTrait
* GetInstance() {
99 return Singleton
<CallbackSingletonWithStaticTrait
, Trait
>::get();
103 struct CallbackSingletonWithStaticTrait::Trait
104 : public StaticMemorySingletonTraits
<CallbackSingletonWithStaticTrait
> {
105 static void Delete(CallbackSingletonWithStaticTrait
* instance
) {
106 if (instance
->callback_
)
107 (instance
->callback_
)();
108 StaticMemorySingletonTraits
<CallbackSingletonWithStaticTrait
>::Delete(
113 template <class Type
>
114 class AlignedTestSingleton
{
116 AlignedTestSingleton() {}
117 ~AlignedTestSingleton() {}
118 static AlignedTestSingleton
* GetInstance() {
119 return Singleton
<AlignedTestSingleton
,
120 StaticMemorySingletonTraits
<AlignedTestSingleton
> >::get();
127 void SingletonNoLeak(CallbackFunc CallOnQuit
) {
128 CallbackSingletonWithNoLeakTrait::GetInstance()->callback_
= CallOnQuit
;
131 void SingletonLeak(CallbackFunc CallOnQuit
) {
132 CallbackSingletonWithLeakTrait::GetInstance()->callback_
= CallOnQuit
;
135 CallbackFunc
* GetLeakySingleton() {
136 return &CallbackSingletonWithLeakTrait::GetInstance()->callback_
;
139 void DeleteLeakySingleton() {
140 DefaultSingletonTraits
<CallbackSingletonWithLeakTrait
>::Delete(
141 CallbackSingletonWithLeakTrait::GetInstance());
144 void SingletonStatic(CallbackFunc CallOnQuit
) {
145 CallbackSingletonWithStaticTrait::GetInstance()->callback_
= CallOnQuit
;
148 CallbackFunc
* GetStaticSingleton() {
149 return &CallbackSingletonWithStaticTrait::GetInstance()->callback_
;
154 class SingletonTest
: public testing::Test
{
158 virtual void SetUp() OVERRIDE
{
159 non_leak_called_
= false;
160 leaky_called_
= false;
161 static_called_
= false;
165 void VerifiesCallbacks() {
166 EXPECT_TRUE(non_leak_called_
);
167 EXPECT_FALSE(leaky_called_
);
168 EXPECT_TRUE(static_called_
);
169 non_leak_called_
= false;
170 leaky_called_
= false;
171 static_called_
= false;
174 void VerifiesCallbacksNotCalled() {
175 EXPECT_FALSE(non_leak_called_
);
176 EXPECT_FALSE(leaky_called_
);
177 EXPECT_FALSE(static_called_
);
178 non_leak_called_
= false;
179 leaky_called_
= false;
180 static_called_
= false;
183 static void CallbackNoLeak() {
184 non_leak_called_
= true;
187 static void CallbackLeak() {
188 leaky_called_
= true;
191 static void CallbackStatic() {
192 static_called_
= true;
196 static bool non_leak_called_
;
197 static bool leaky_called_
;
198 static bool static_called_
;
201 bool SingletonTest::non_leak_called_
= false;
202 bool SingletonTest::leaky_called_
= false;
203 bool SingletonTest::static_called_
= false;
205 TEST_F(SingletonTest
, Basic
) {
207 int* singleton_int_5
;
208 CallbackFunc
* leaky_singleton
;
209 CallbackFunc
* static_singleton
;
212 base::ShadowingAtExitManager sem
;
214 singleton_int
= SingletonInt();
216 // Ensure POD type initialization.
217 EXPECT_EQ(*singleton_int
, 0);
220 EXPECT_EQ(singleton_int
, SingletonInt());
221 EXPECT_EQ(*singleton_int
, 1);
224 singleton_int_5
= SingletonInt5();
226 // Is default initialized to 5.
227 EXPECT_EQ(*singleton_int_5
, 5);
229 SingletonNoLeak(&CallbackNoLeak
);
230 SingletonLeak(&CallbackLeak
);
231 SingletonStatic(&CallbackStatic
);
232 static_singleton
= GetStaticSingleton();
233 leaky_singleton
= GetLeakySingleton();
234 EXPECT_TRUE(leaky_singleton
);
237 // Verify that only the expected callback has been called.
239 // Delete the leaky singleton.
240 DeleteLeakySingleton();
242 // The static singleton can't be acquired post-atexit.
243 EXPECT_EQ(NULL
, GetStaticSingleton());
246 base::ShadowingAtExitManager sem
;
247 // Verifiy that the variables were reset.
249 singleton_int
= SingletonInt();
250 EXPECT_EQ(*singleton_int
, 0);
253 singleton_int_5
= SingletonInt5();
254 EXPECT_EQ(*singleton_int_5
, 5);
257 // Resurrect the static singleton, and assert that it
258 // still points to the same (static) memory.
259 CallbackSingletonWithStaticTrait::Trait::Resurrect();
260 EXPECT_EQ(GetStaticSingleton(), static_singleton
);
263 // The leaky singleton shouldn't leak since SingletonLeak has not been called.
264 VerifiesCallbacksNotCalled();
267 #define EXPECT_ALIGNED(ptr, align) \
268 EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
270 TEST_F(SingletonTest
, Alignment
) {
271 using base::AlignedMemory
;
273 // Create some static singletons with increasing sizes and alignment
274 // requirements. By ordering this way, the linker will need to do some work to
275 // ensure proper alignment of the static data.
276 AlignedTestSingleton
<int32
>* align4
=
277 AlignedTestSingleton
<int32
>::GetInstance();
278 AlignedTestSingleton
<AlignedMemory
<32, 32> >* align32
=
279 AlignedTestSingleton
<AlignedMemory
<32, 32> >::GetInstance();
280 AlignedTestSingleton
<AlignedMemory
<128, 128> >* align128
=
281 AlignedTestSingleton
<AlignedMemory
<128, 128> >::GetInstance();
282 AlignedTestSingleton
<AlignedMemory
<4096, 4096> >* align4096
=
283 AlignedTestSingleton
<AlignedMemory
<4096, 4096> >::GetInstance();
285 EXPECT_ALIGNED(align4
, 4);
286 EXPECT_ALIGNED(align32
, 32);
287 EXPECT_ALIGNED(align128
, 128);
288 EXPECT_ALIGNED(align4096
, 4096);