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/memory/singleton.h"
7 #include "base/path_service.h"
8 #include "testing/gtest/include/gtest/gtest.h"
12 COMPILE_ASSERT(DefaultSingletonTraits
<int>::kRegisterAtExit
== true, a
);
14 typedef void (*CallbackFunc
)();
18 static IntSingleton
* GetInstance() {
19 return Singleton
<IntSingleton
>::get();
25 class Init5Singleton
{
29 static Init5Singleton
* GetInstance() {
30 return Singleton
<Init5Singleton
, Trait
>::get();
36 struct Init5Singleton::Trait
: public DefaultSingletonTraits
<Init5Singleton
> {
37 static Init5Singleton
* New() {
38 Init5Singleton
* instance
= new Init5Singleton();
45 return &IntSingleton::GetInstance()->value_
;
48 int* SingletonInt5() {
49 return &Init5Singleton::GetInstance()->value_
;
52 template <typename Type
>
53 struct CallbackTrait
: public DefaultSingletonTraits
<Type
> {
54 static void Delete(Type
* instance
) {
55 if (instance
->callback_
)
56 (instance
->callback_
)();
57 DefaultSingletonTraits
<Type
>::Delete(instance
);
61 class CallbackSingleton
{
63 CallbackSingleton() : callback_(NULL
) { }
64 CallbackFunc callback_
;
67 class CallbackSingletonWithNoLeakTrait
: public CallbackSingleton
{
69 struct Trait
: public CallbackTrait
<CallbackSingletonWithNoLeakTrait
> { };
71 CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { }
73 static CallbackSingletonWithNoLeakTrait
* GetInstance() {
74 return Singleton
<CallbackSingletonWithNoLeakTrait
, Trait
>::get();
78 class CallbackSingletonWithLeakTrait
: public CallbackSingleton
{
80 struct Trait
: public CallbackTrait
<CallbackSingletonWithLeakTrait
> {
81 static const bool kRegisterAtExit
= false;
84 CallbackSingletonWithLeakTrait() : CallbackSingleton() { }
86 static CallbackSingletonWithLeakTrait
* GetInstance() {
87 return Singleton
<CallbackSingletonWithLeakTrait
, Trait
>::get();
91 class CallbackSingletonWithStaticTrait
: public CallbackSingleton
{
95 CallbackSingletonWithStaticTrait() : CallbackSingleton() { }
97 static CallbackSingletonWithStaticTrait
* GetInstance() {
98 return Singleton
<CallbackSingletonWithStaticTrait
, Trait
>::get();
102 struct CallbackSingletonWithStaticTrait::Trait
103 : public StaticMemorySingletonTraits
<CallbackSingletonWithStaticTrait
> {
104 static void Delete(CallbackSingletonWithStaticTrait
* instance
) {
105 if (instance
->callback_
)
106 (instance
->callback_
)();
107 StaticMemorySingletonTraits
<CallbackSingletonWithStaticTrait
>::Delete(
112 template <class Type
>
113 class AlignedTestSingleton
{
115 AlignedTestSingleton() {}
116 ~AlignedTestSingleton() {}
117 static AlignedTestSingleton
* GetInstance() {
118 return Singleton
<AlignedTestSingleton
,
119 StaticMemorySingletonTraits
<AlignedTestSingleton
> >::get();
126 void SingletonNoLeak(CallbackFunc CallOnQuit
) {
127 CallbackSingletonWithNoLeakTrait::GetInstance()->callback_
= CallOnQuit
;
130 void SingletonLeak(CallbackFunc CallOnQuit
) {
131 CallbackSingletonWithLeakTrait::GetInstance()->callback_
= CallOnQuit
;
134 CallbackFunc
* GetLeakySingleton() {
135 return &CallbackSingletonWithLeakTrait::GetInstance()->callback_
;
138 void DeleteLeakySingleton() {
139 DefaultSingletonTraits
<CallbackSingletonWithLeakTrait
>::Delete(
140 CallbackSingletonWithLeakTrait::GetInstance());
143 void SingletonStatic(CallbackFunc CallOnQuit
) {
144 CallbackSingletonWithStaticTrait::GetInstance()->callback_
= CallOnQuit
;
147 CallbackFunc
* GetStaticSingleton() {
148 return &CallbackSingletonWithStaticTrait::GetInstance()->callback_
;
153 class SingletonTest
: public testing::Test
{
157 virtual void SetUp() override
{
158 non_leak_called_
= false;
159 leaky_called_
= false;
160 static_called_
= false;
164 void VerifiesCallbacks() {
165 EXPECT_TRUE(non_leak_called_
);
166 EXPECT_FALSE(leaky_called_
);
167 EXPECT_TRUE(static_called_
);
168 non_leak_called_
= false;
169 leaky_called_
= false;
170 static_called_
= false;
173 void VerifiesCallbacksNotCalled() {
174 EXPECT_FALSE(non_leak_called_
);
175 EXPECT_FALSE(leaky_called_
);
176 EXPECT_FALSE(static_called_
);
177 non_leak_called_
= false;
178 leaky_called_
= false;
179 static_called_
= false;
182 static void CallbackNoLeak() {
183 non_leak_called_
= true;
186 static void CallbackLeak() {
187 leaky_called_
= true;
190 static void CallbackStatic() {
191 static_called_
= true;
195 static bool non_leak_called_
;
196 static bool leaky_called_
;
197 static bool static_called_
;
200 bool SingletonTest::non_leak_called_
= false;
201 bool SingletonTest::leaky_called_
= false;
202 bool SingletonTest::static_called_
= false;
204 TEST_F(SingletonTest
, Basic
) {
206 int* singleton_int_5
;
207 CallbackFunc
* leaky_singleton
;
208 CallbackFunc
* static_singleton
;
211 base::ShadowingAtExitManager sem
;
213 singleton_int
= SingletonInt();
215 // Ensure POD type initialization.
216 EXPECT_EQ(*singleton_int
, 0);
219 EXPECT_EQ(singleton_int
, SingletonInt());
220 EXPECT_EQ(*singleton_int
, 1);
223 singleton_int_5
= SingletonInt5();
225 // Is default initialized to 5.
226 EXPECT_EQ(*singleton_int_5
, 5);
228 SingletonNoLeak(&CallbackNoLeak
);
229 SingletonLeak(&CallbackLeak
);
230 SingletonStatic(&CallbackStatic
);
231 static_singleton
= GetStaticSingleton();
232 leaky_singleton
= GetLeakySingleton();
233 EXPECT_TRUE(leaky_singleton
);
236 // Verify that only the expected callback has been called.
238 // Delete the leaky singleton.
239 DeleteLeakySingleton();
241 // The static singleton can't be acquired post-atexit.
242 EXPECT_EQ(NULL
, GetStaticSingleton());
245 base::ShadowingAtExitManager sem
;
246 // Verifiy that the variables were reset.
248 singleton_int
= SingletonInt();
249 EXPECT_EQ(*singleton_int
, 0);
252 singleton_int_5
= SingletonInt5();
253 EXPECT_EQ(*singleton_int_5
, 5);
256 // Resurrect the static singleton, and assert that it
257 // still points to the same (static) memory.
258 CallbackSingletonWithStaticTrait::Trait::Resurrect();
259 EXPECT_EQ(GetStaticSingleton(), static_singleton
);
262 // The leaky singleton shouldn't leak since SingletonLeak has not been called.
263 VerifiesCallbacksNotCalled();
266 #define EXPECT_ALIGNED(ptr, align) \
267 EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
269 TEST_F(SingletonTest
, Alignment
) {
270 using base::AlignedMemory
;
272 // Create some static singletons with increasing sizes and alignment
273 // requirements. By ordering this way, the linker will need to do some work to
274 // ensure proper alignment of the static data.
275 AlignedTestSingleton
<int32
>* align4
=
276 AlignedTestSingleton
<int32
>::GetInstance();
277 AlignedTestSingleton
<AlignedMemory
<32, 32> >* align32
=
278 AlignedTestSingleton
<AlignedMemory
<32, 32> >::GetInstance();
279 AlignedTestSingleton
<AlignedMemory
<128, 128> >* align128
=
280 AlignedTestSingleton
<AlignedMemory
<128, 128> >::GetInstance();
281 AlignedTestSingleton
<AlignedMemory
<4096, 4096> >* align4096
=
282 AlignedTestSingleton
<AlignedMemory
<4096, 4096> >::GetInstance();
284 EXPECT_ALIGNED(align4
, 4);
285 EXPECT_ALIGNED(align32
, 32);
286 EXPECT_ALIGNED(align128
, 128);
287 EXPECT_ALIGNED(align4096
, 4096);