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 "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_
;
152 class SingletonTest
: public testing::Test
{
156 void SetUp() override
{
157 non_leak_called_
= false;
158 leaky_called_
= false;
159 static_called_
= false;
163 void VerifiesCallbacks() {
164 EXPECT_TRUE(non_leak_called_
);
165 EXPECT_FALSE(leaky_called_
);
166 EXPECT_TRUE(static_called_
);
167 non_leak_called_
= false;
168 leaky_called_
= false;
169 static_called_
= false;
172 void VerifiesCallbacksNotCalled() {
173 EXPECT_FALSE(non_leak_called_
);
174 EXPECT_FALSE(leaky_called_
);
175 EXPECT_FALSE(static_called_
);
176 non_leak_called_
= false;
177 leaky_called_
= false;
178 static_called_
= false;
181 static void CallbackNoLeak() {
182 non_leak_called_
= true;
185 static void CallbackLeak() {
186 leaky_called_
= true;
189 static void CallbackStatic() {
190 static_called_
= true;
194 static bool non_leak_called_
;
195 static bool leaky_called_
;
196 static bool static_called_
;
199 bool SingletonTest::non_leak_called_
= false;
200 bool SingletonTest::leaky_called_
= false;
201 bool SingletonTest::static_called_
= false;
203 TEST_F(SingletonTest
, Basic
) {
205 int* singleton_int_5
;
206 CallbackFunc
* leaky_singleton
;
207 CallbackFunc
* static_singleton
;
210 ShadowingAtExitManager sem
;
212 singleton_int
= SingletonInt();
214 // Ensure POD type initialization.
215 EXPECT_EQ(*singleton_int
, 0);
218 EXPECT_EQ(singleton_int
, SingletonInt());
219 EXPECT_EQ(*singleton_int
, 1);
222 singleton_int_5
= SingletonInt5();
224 // Is default initialized to 5.
225 EXPECT_EQ(*singleton_int_5
, 5);
227 SingletonNoLeak(&CallbackNoLeak
);
228 SingletonLeak(&CallbackLeak
);
229 SingletonStatic(&CallbackStatic
);
230 static_singleton
= GetStaticSingleton();
231 leaky_singleton
= GetLeakySingleton();
232 EXPECT_TRUE(leaky_singleton
);
235 // Verify that only the expected callback has been called.
237 // Delete the leaky singleton.
238 DeleteLeakySingleton();
240 // The static singleton can't be acquired post-atexit.
241 EXPECT_EQ(NULL
, GetStaticSingleton());
244 ShadowingAtExitManager sem
;
245 // Verifiy that the variables were reset.
247 singleton_int
= SingletonInt();
248 EXPECT_EQ(*singleton_int
, 0);
251 singleton_int_5
= SingletonInt5();
252 EXPECT_EQ(*singleton_int_5
, 5);
255 // Resurrect the static singleton, and assert that it
256 // still points to the same (static) memory.
257 CallbackSingletonWithStaticTrait::Trait::Resurrect();
258 EXPECT_EQ(GetStaticSingleton(), static_singleton
);
261 // The leaky singleton shouldn't leak since SingletonLeak has not been called.
262 VerifiesCallbacksNotCalled();
265 #define EXPECT_ALIGNED(ptr, align) \
266 EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
268 TEST_F(SingletonTest
, Alignment
) {
269 using base::AlignedMemory
;
271 // Create some static singletons with increasing sizes and alignment
272 // requirements. By ordering this way, the linker will need to do some work to
273 // ensure proper alignment of the static data.
274 AlignedTestSingleton
<int32
>* align4
=
275 AlignedTestSingleton
<int32
>::GetInstance();
276 AlignedTestSingleton
<AlignedMemory
<32, 32> >* align32
=
277 AlignedTestSingleton
<AlignedMemory
<32, 32> >::GetInstance();
278 AlignedTestSingleton
<AlignedMemory
<128, 128> >* align128
=
279 AlignedTestSingleton
<AlignedMemory
<128, 128> >::GetInstance();
280 AlignedTestSingleton
<AlignedMemory
<4096, 4096> >* align4096
=
281 AlignedTestSingleton
<AlignedMemory
<4096, 4096> >::GetInstance();
283 EXPECT_ALIGNED(align4
, 4);
284 EXPECT_ALIGNED(align32
, 32);
285 EXPECT_ALIGNED(align128
, 128);
286 EXPECT_ALIGNED(align4096
, 4096);