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"
11 COMPILE_ASSERT(DefaultSingletonTraits
<int>::kRegisterAtExit
== true, a
);
13 typedef void (*CallbackFunc
)();
17 static IntSingleton
* GetInstance() {
18 return Singleton
<IntSingleton
>::get();
24 class Init5Singleton
{
28 static Init5Singleton
* GetInstance() {
29 return Singleton
<Init5Singleton
, Trait
>::get();
35 struct Init5Singleton::Trait
: public DefaultSingletonTraits
<Init5Singleton
> {
36 static Init5Singleton
* New() {
37 Init5Singleton
* instance
= new Init5Singleton();
44 return &IntSingleton::GetInstance()->value_
;
47 int* SingletonInt5() {
48 return &Init5Singleton::GetInstance()->value_
;
51 template <typename Type
>
52 struct CallbackTrait
: public DefaultSingletonTraits
<Type
> {
53 static void Delete(Type
* instance
) {
54 if (instance
->callback_
)
55 (instance
->callback_
)();
56 DefaultSingletonTraits
<Type
>::Delete(instance
);
60 class CallbackSingleton
{
62 CallbackSingleton() : callback_(NULL
) { }
63 CallbackFunc callback_
;
66 class CallbackSingletonWithNoLeakTrait
: public CallbackSingleton
{
68 struct Trait
: public CallbackTrait
<CallbackSingletonWithNoLeakTrait
> { };
70 CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { }
72 static CallbackSingletonWithNoLeakTrait
* GetInstance() {
73 return Singleton
<CallbackSingletonWithNoLeakTrait
, Trait
>::get();
77 class CallbackSingletonWithLeakTrait
: public CallbackSingleton
{
79 struct Trait
: public CallbackTrait
<CallbackSingletonWithLeakTrait
> {
80 static const bool kRegisterAtExit
= false;
83 CallbackSingletonWithLeakTrait() : CallbackSingleton() { }
85 static CallbackSingletonWithLeakTrait
* GetInstance() {
86 return Singleton
<CallbackSingletonWithLeakTrait
, Trait
>::get();
90 class CallbackSingletonWithStaticTrait
: public CallbackSingleton
{
94 CallbackSingletonWithStaticTrait() : CallbackSingleton() { }
96 static CallbackSingletonWithStaticTrait
* GetInstance() {
97 return Singleton
<CallbackSingletonWithStaticTrait
, Trait
>::get();
101 struct CallbackSingletonWithStaticTrait::Trait
102 : public StaticMemorySingletonTraits
<CallbackSingletonWithStaticTrait
> {
103 static void Delete(CallbackSingletonWithStaticTrait
* instance
) {
104 if (instance
->callback_
)
105 (instance
->callback_
)();
106 StaticMemorySingletonTraits
<CallbackSingletonWithStaticTrait
>::Delete(
111 template <class Type
>
112 class AlignedTestSingleton
{
114 AlignedTestSingleton() {}
115 ~AlignedTestSingleton() {}
116 static AlignedTestSingleton
* GetInstance() {
117 return Singleton
<AlignedTestSingleton
,
118 StaticMemorySingletonTraits
<AlignedTestSingleton
> >::get();
125 void SingletonNoLeak(CallbackFunc CallOnQuit
) {
126 CallbackSingletonWithNoLeakTrait::GetInstance()->callback_
= CallOnQuit
;
129 void SingletonLeak(CallbackFunc CallOnQuit
) {
130 CallbackSingletonWithLeakTrait::GetInstance()->callback_
= CallOnQuit
;
133 CallbackFunc
* GetLeakySingleton() {
134 return &CallbackSingletonWithLeakTrait::GetInstance()->callback_
;
137 void DeleteLeakySingleton() {
138 DefaultSingletonTraits
<CallbackSingletonWithLeakTrait
>::Delete(
139 CallbackSingletonWithLeakTrait::GetInstance());
142 void SingletonStatic(CallbackFunc CallOnQuit
) {
143 CallbackSingletonWithStaticTrait::GetInstance()->callback_
= CallOnQuit
;
146 CallbackFunc
* GetStaticSingleton() {
147 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 base::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 base::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);