1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include "base/at_exit.h"
8*635a8641SAndroid Build Coastguard Worker #include "base/memory/singleton.h"
9*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
10*635a8641SAndroid Build Coastguard Worker
11*635a8641SAndroid Build Coastguard Worker namespace base {
12*635a8641SAndroid Build Coastguard Worker namespace {
13*635a8641SAndroid Build Coastguard Worker
14*635a8641SAndroid Build Coastguard Worker static_assert(DefaultSingletonTraits<int>::kRegisterAtExit == true,
15*635a8641SAndroid Build Coastguard Worker "object must be deleted on process exit");
16*635a8641SAndroid Build Coastguard Worker
17*635a8641SAndroid Build Coastguard Worker typedef void (*CallbackFunc)();
18*635a8641SAndroid Build Coastguard Worker
19*635a8641SAndroid Build Coastguard Worker template <size_t alignment>
20*635a8641SAndroid Build Coastguard Worker class AlignedData {
21*635a8641SAndroid Build Coastguard Worker public:
22*635a8641SAndroid Build Coastguard Worker AlignedData() = default;
23*635a8641SAndroid Build Coastguard Worker ~AlignedData() = default;
24*635a8641SAndroid Build Coastguard Worker alignas(alignment) char data_[alignment];
25*635a8641SAndroid Build Coastguard Worker };
26*635a8641SAndroid Build Coastguard Worker
27*635a8641SAndroid Build Coastguard Worker class IntSingleton {
28*635a8641SAndroid Build Coastguard Worker public:
GetInstance()29*635a8641SAndroid Build Coastguard Worker static IntSingleton* GetInstance() {
30*635a8641SAndroid Build Coastguard Worker return Singleton<IntSingleton>::get();
31*635a8641SAndroid Build Coastguard Worker }
32*635a8641SAndroid Build Coastguard Worker
33*635a8641SAndroid Build Coastguard Worker int value_;
34*635a8641SAndroid Build Coastguard Worker };
35*635a8641SAndroid Build Coastguard Worker
36*635a8641SAndroid Build Coastguard Worker class Init5Singleton {
37*635a8641SAndroid Build Coastguard Worker public:
38*635a8641SAndroid Build Coastguard Worker struct Trait;
39*635a8641SAndroid Build Coastguard Worker
GetInstance()40*635a8641SAndroid Build Coastguard Worker static Init5Singleton* GetInstance() {
41*635a8641SAndroid Build Coastguard Worker return Singleton<Init5Singleton, Trait>::get();
42*635a8641SAndroid Build Coastguard Worker }
43*635a8641SAndroid Build Coastguard Worker
44*635a8641SAndroid Build Coastguard Worker int value_;
45*635a8641SAndroid Build Coastguard Worker };
46*635a8641SAndroid Build Coastguard Worker
47*635a8641SAndroid Build Coastguard Worker struct Init5Singleton::Trait : public DefaultSingletonTraits<Init5Singleton> {
Newbase::__anon51cb60830111::Init5Singleton::Trait48*635a8641SAndroid Build Coastguard Worker static Init5Singleton* New() {
49*635a8641SAndroid Build Coastguard Worker Init5Singleton* instance = new Init5Singleton();
50*635a8641SAndroid Build Coastguard Worker instance->value_ = 5;
51*635a8641SAndroid Build Coastguard Worker return instance;
52*635a8641SAndroid Build Coastguard Worker }
53*635a8641SAndroid Build Coastguard Worker };
54*635a8641SAndroid Build Coastguard Worker
SingletonInt()55*635a8641SAndroid Build Coastguard Worker int* SingletonInt() {
56*635a8641SAndroid Build Coastguard Worker return &IntSingleton::GetInstance()->value_;
57*635a8641SAndroid Build Coastguard Worker }
58*635a8641SAndroid Build Coastguard Worker
SingletonInt5()59*635a8641SAndroid Build Coastguard Worker int* SingletonInt5() {
60*635a8641SAndroid Build Coastguard Worker return &Init5Singleton::GetInstance()->value_;
61*635a8641SAndroid Build Coastguard Worker }
62*635a8641SAndroid Build Coastguard Worker
63*635a8641SAndroid Build Coastguard Worker template <typename Type>
64*635a8641SAndroid Build Coastguard Worker struct CallbackTrait : public DefaultSingletonTraits<Type> {
Deletebase::__anon51cb60830111::CallbackTrait65*635a8641SAndroid Build Coastguard Worker static void Delete(Type* instance) {
66*635a8641SAndroid Build Coastguard Worker if (instance->callback_)
67*635a8641SAndroid Build Coastguard Worker (instance->callback_)();
68*635a8641SAndroid Build Coastguard Worker DefaultSingletonTraits<Type>::Delete(instance);
69*635a8641SAndroid Build Coastguard Worker }
70*635a8641SAndroid Build Coastguard Worker };
71*635a8641SAndroid Build Coastguard Worker
72*635a8641SAndroid Build Coastguard Worker class CallbackSingleton {
73*635a8641SAndroid Build Coastguard Worker public:
CallbackSingleton()74*635a8641SAndroid Build Coastguard Worker CallbackSingleton() : callback_(nullptr) {}
75*635a8641SAndroid Build Coastguard Worker CallbackFunc callback_;
76*635a8641SAndroid Build Coastguard Worker };
77*635a8641SAndroid Build Coastguard Worker
78*635a8641SAndroid Build Coastguard Worker class CallbackSingletonWithNoLeakTrait : public CallbackSingleton {
79*635a8641SAndroid Build Coastguard Worker public:
80*635a8641SAndroid Build Coastguard Worker struct Trait : public CallbackTrait<CallbackSingletonWithNoLeakTrait> { };
81*635a8641SAndroid Build Coastguard Worker
CallbackSingletonWithNoLeakTrait()82*635a8641SAndroid Build Coastguard Worker CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { }
83*635a8641SAndroid Build Coastguard Worker
GetInstance()84*635a8641SAndroid Build Coastguard Worker static CallbackSingletonWithNoLeakTrait* GetInstance() {
85*635a8641SAndroid Build Coastguard Worker return Singleton<CallbackSingletonWithNoLeakTrait, Trait>::get();
86*635a8641SAndroid Build Coastguard Worker }
87*635a8641SAndroid Build Coastguard Worker };
88*635a8641SAndroid Build Coastguard Worker
89*635a8641SAndroid Build Coastguard Worker class CallbackSingletonWithLeakTrait : public CallbackSingleton {
90*635a8641SAndroid Build Coastguard Worker public:
91*635a8641SAndroid Build Coastguard Worker struct Trait : public CallbackTrait<CallbackSingletonWithLeakTrait> {
92*635a8641SAndroid Build Coastguard Worker static const bool kRegisterAtExit = false;
93*635a8641SAndroid Build Coastguard Worker };
94*635a8641SAndroid Build Coastguard Worker
CallbackSingletonWithLeakTrait()95*635a8641SAndroid Build Coastguard Worker CallbackSingletonWithLeakTrait() : CallbackSingleton() { }
96*635a8641SAndroid Build Coastguard Worker
GetInstance()97*635a8641SAndroid Build Coastguard Worker static CallbackSingletonWithLeakTrait* GetInstance() {
98*635a8641SAndroid Build Coastguard Worker return Singleton<CallbackSingletonWithLeakTrait, Trait>::get();
99*635a8641SAndroid Build Coastguard Worker }
100*635a8641SAndroid Build Coastguard Worker };
101*635a8641SAndroid Build Coastguard Worker
102*635a8641SAndroid Build Coastguard Worker class CallbackSingletonWithStaticTrait : public CallbackSingleton {
103*635a8641SAndroid Build Coastguard Worker public:
104*635a8641SAndroid Build Coastguard Worker struct Trait;
105*635a8641SAndroid Build Coastguard Worker
CallbackSingletonWithStaticTrait()106*635a8641SAndroid Build Coastguard Worker CallbackSingletonWithStaticTrait() : CallbackSingleton() { }
107*635a8641SAndroid Build Coastguard Worker
GetInstance()108*635a8641SAndroid Build Coastguard Worker static CallbackSingletonWithStaticTrait* GetInstance() {
109*635a8641SAndroid Build Coastguard Worker return Singleton<CallbackSingletonWithStaticTrait, Trait>::get();
110*635a8641SAndroid Build Coastguard Worker }
111*635a8641SAndroid Build Coastguard Worker };
112*635a8641SAndroid Build Coastguard Worker
113*635a8641SAndroid Build Coastguard Worker struct CallbackSingletonWithStaticTrait::Trait
114*635a8641SAndroid Build Coastguard Worker : public StaticMemorySingletonTraits<CallbackSingletonWithStaticTrait> {
Deletebase::__anon51cb60830111::CallbackSingletonWithStaticTrait::Trait115*635a8641SAndroid Build Coastguard Worker static void Delete(CallbackSingletonWithStaticTrait* instance) {
116*635a8641SAndroid Build Coastguard Worker if (instance->callback_)
117*635a8641SAndroid Build Coastguard Worker (instance->callback_)();
118*635a8641SAndroid Build Coastguard Worker StaticMemorySingletonTraits<CallbackSingletonWithStaticTrait>::Delete(
119*635a8641SAndroid Build Coastguard Worker instance);
120*635a8641SAndroid Build Coastguard Worker }
121*635a8641SAndroid Build Coastguard Worker };
122*635a8641SAndroid Build Coastguard Worker
123*635a8641SAndroid Build Coastguard Worker template <class Type>
124*635a8641SAndroid Build Coastguard Worker class AlignedTestSingleton {
125*635a8641SAndroid Build Coastguard Worker public:
126*635a8641SAndroid Build Coastguard Worker AlignedTestSingleton() = default;
127*635a8641SAndroid Build Coastguard Worker ~AlignedTestSingleton() = default;
GetInstance()128*635a8641SAndroid Build Coastguard Worker static AlignedTestSingleton* GetInstance() {
129*635a8641SAndroid Build Coastguard Worker return Singleton<AlignedTestSingleton,
130*635a8641SAndroid Build Coastguard Worker StaticMemorySingletonTraits<AlignedTestSingleton>>::get();
131*635a8641SAndroid Build Coastguard Worker }
132*635a8641SAndroid Build Coastguard Worker
133*635a8641SAndroid Build Coastguard Worker Type type_;
134*635a8641SAndroid Build Coastguard Worker };
135*635a8641SAndroid Build Coastguard Worker
136*635a8641SAndroid Build Coastguard Worker
SingletonNoLeak(CallbackFunc CallOnQuit)137*635a8641SAndroid Build Coastguard Worker void SingletonNoLeak(CallbackFunc CallOnQuit) {
138*635a8641SAndroid Build Coastguard Worker CallbackSingletonWithNoLeakTrait::GetInstance()->callback_ = CallOnQuit;
139*635a8641SAndroid Build Coastguard Worker }
140*635a8641SAndroid Build Coastguard Worker
SingletonLeak(CallbackFunc CallOnQuit)141*635a8641SAndroid Build Coastguard Worker void SingletonLeak(CallbackFunc CallOnQuit) {
142*635a8641SAndroid Build Coastguard Worker CallbackSingletonWithLeakTrait::GetInstance()->callback_ = CallOnQuit;
143*635a8641SAndroid Build Coastguard Worker }
144*635a8641SAndroid Build Coastguard Worker
GetLeakySingleton()145*635a8641SAndroid Build Coastguard Worker CallbackFunc* GetLeakySingleton() {
146*635a8641SAndroid Build Coastguard Worker return &CallbackSingletonWithLeakTrait::GetInstance()->callback_;
147*635a8641SAndroid Build Coastguard Worker }
148*635a8641SAndroid Build Coastguard Worker
DeleteLeakySingleton()149*635a8641SAndroid Build Coastguard Worker void DeleteLeakySingleton() {
150*635a8641SAndroid Build Coastguard Worker DefaultSingletonTraits<CallbackSingletonWithLeakTrait>::Delete(
151*635a8641SAndroid Build Coastguard Worker CallbackSingletonWithLeakTrait::GetInstance());
152*635a8641SAndroid Build Coastguard Worker }
153*635a8641SAndroid Build Coastguard Worker
SingletonStatic(CallbackFunc CallOnQuit)154*635a8641SAndroid Build Coastguard Worker void SingletonStatic(CallbackFunc CallOnQuit) {
155*635a8641SAndroid Build Coastguard Worker CallbackSingletonWithStaticTrait::GetInstance()->callback_ = CallOnQuit;
156*635a8641SAndroid Build Coastguard Worker }
157*635a8641SAndroid Build Coastguard Worker
GetStaticSingleton()158*635a8641SAndroid Build Coastguard Worker CallbackFunc* GetStaticSingleton() {
159*635a8641SAndroid Build Coastguard Worker return &CallbackSingletonWithStaticTrait::GetInstance()->callback_;
160*635a8641SAndroid Build Coastguard Worker }
161*635a8641SAndroid Build Coastguard Worker
162*635a8641SAndroid Build Coastguard Worker
163*635a8641SAndroid Build Coastguard Worker class SingletonTest : public testing::Test {
164*635a8641SAndroid Build Coastguard Worker public:
165*635a8641SAndroid Build Coastguard Worker SingletonTest() = default;
166*635a8641SAndroid Build Coastguard Worker
SetUp()167*635a8641SAndroid Build Coastguard Worker void SetUp() override {
168*635a8641SAndroid Build Coastguard Worker non_leak_called_ = false;
169*635a8641SAndroid Build Coastguard Worker leaky_called_ = false;
170*635a8641SAndroid Build Coastguard Worker static_called_ = false;
171*635a8641SAndroid Build Coastguard Worker }
172*635a8641SAndroid Build Coastguard Worker
173*635a8641SAndroid Build Coastguard Worker protected:
VerifiesCallbacks()174*635a8641SAndroid Build Coastguard Worker void VerifiesCallbacks() {
175*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(non_leak_called_);
176*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(leaky_called_);
177*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(static_called_);
178*635a8641SAndroid Build Coastguard Worker non_leak_called_ = false;
179*635a8641SAndroid Build Coastguard Worker leaky_called_ = false;
180*635a8641SAndroid Build Coastguard Worker static_called_ = false;
181*635a8641SAndroid Build Coastguard Worker }
182*635a8641SAndroid Build Coastguard Worker
VerifiesCallbacksNotCalled()183*635a8641SAndroid Build Coastguard Worker void VerifiesCallbacksNotCalled() {
184*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(non_leak_called_);
185*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(leaky_called_);
186*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(static_called_);
187*635a8641SAndroid Build Coastguard Worker non_leak_called_ = false;
188*635a8641SAndroid Build Coastguard Worker leaky_called_ = false;
189*635a8641SAndroid Build Coastguard Worker static_called_ = false;
190*635a8641SAndroid Build Coastguard Worker }
191*635a8641SAndroid Build Coastguard Worker
CallbackNoLeak()192*635a8641SAndroid Build Coastguard Worker static void CallbackNoLeak() {
193*635a8641SAndroid Build Coastguard Worker non_leak_called_ = true;
194*635a8641SAndroid Build Coastguard Worker }
195*635a8641SAndroid Build Coastguard Worker
CallbackLeak()196*635a8641SAndroid Build Coastguard Worker static void CallbackLeak() {
197*635a8641SAndroid Build Coastguard Worker leaky_called_ = true;
198*635a8641SAndroid Build Coastguard Worker }
199*635a8641SAndroid Build Coastguard Worker
CallbackStatic()200*635a8641SAndroid Build Coastguard Worker static void CallbackStatic() {
201*635a8641SAndroid Build Coastguard Worker static_called_ = true;
202*635a8641SAndroid Build Coastguard Worker }
203*635a8641SAndroid Build Coastguard Worker
204*635a8641SAndroid Build Coastguard Worker private:
205*635a8641SAndroid Build Coastguard Worker static bool non_leak_called_;
206*635a8641SAndroid Build Coastguard Worker static bool leaky_called_;
207*635a8641SAndroid Build Coastguard Worker static bool static_called_;
208*635a8641SAndroid Build Coastguard Worker };
209*635a8641SAndroid Build Coastguard Worker
210*635a8641SAndroid Build Coastguard Worker bool SingletonTest::non_leak_called_ = false;
211*635a8641SAndroid Build Coastguard Worker bool SingletonTest::leaky_called_ = false;
212*635a8641SAndroid Build Coastguard Worker bool SingletonTest::static_called_ = false;
213*635a8641SAndroid Build Coastguard Worker
TEST_F(SingletonTest,Basic)214*635a8641SAndroid Build Coastguard Worker TEST_F(SingletonTest, Basic) {
215*635a8641SAndroid Build Coastguard Worker int* singleton_int;
216*635a8641SAndroid Build Coastguard Worker int* singleton_int_5;
217*635a8641SAndroid Build Coastguard Worker CallbackFunc* leaky_singleton;
218*635a8641SAndroid Build Coastguard Worker CallbackFunc* static_singleton;
219*635a8641SAndroid Build Coastguard Worker
220*635a8641SAndroid Build Coastguard Worker {
221*635a8641SAndroid Build Coastguard Worker ShadowingAtExitManager sem;
222*635a8641SAndroid Build Coastguard Worker {
223*635a8641SAndroid Build Coastguard Worker singleton_int = SingletonInt();
224*635a8641SAndroid Build Coastguard Worker }
225*635a8641SAndroid Build Coastguard Worker // Ensure POD type initialization.
226*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(*singleton_int, 0);
227*635a8641SAndroid Build Coastguard Worker *singleton_int = 1;
228*635a8641SAndroid Build Coastguard Worker
229*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(singleton_int, SingletonInt());
230*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(*singleton_int, 1);
231*635a8641SAndroid Build Coastguard Worker
232*635a8641SAndroid Build Coastguard Worker {
233*635a8641SAndroid Build Coastguard Worker singleton_int_5 = SingletonInt5();
234*635a8641SAndroid Build Coastguard Worker }
235*635a8641SAndroid Build Coastguard Worker // Is default initialized to 5.
236*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(*singleton_int_5, 5);
237*635a8641SAndroid Build Coastguard Worker
238*635a8641SAndroid Build Coastguard Worker SingletonNoLeak(&CallbackNoLeak);
239*635a8641SAndroid Build Coastguard Worker SingletonLeak(&CallbackLeak);
240*635a8641SAndroid Build Coastguard Worker SingletonStatic(&CallbackStatic);
241*635a8641SAndroid Build Coastguard Worker static_singleton = GetStaticSingleton();
242*635a8641SAndroid Build Coastguard Worker leaky_singleton = GetLeakySingleton();
243*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(leaky_singleton);
244*635a8641SAndroid Build Coastguard Worker }
245*635a8641SAndroid Build Coastguard Worker
246*635a8641SAndroid Build Coastguard Worker // Verify that only the expected callback has been called.
247*635a8641SAndroid Build Coastguard Worker VerifiesCallbacks();
248*635a8641SAndroid Build Coastguard Worker // Delete the leaky singleton.
249*635a8641SAndroid Build Coastguard Worker DeleteLeakySingleton();
250*635a8641SAndroid Build Coastguard Worker
251*635a8641SAndroid Build Coastguard Worker // The static singleton can't be acquired post-atexit.
252*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(nullptr, GetStaticSingleton());
253*635a8641SAndroid Build Coastguard Worker
254*635a8641SAndroid Build Coastguard Worker {
255*635a8641SAndroid Build Coastguard Worker ShadowingAtExitManager sem;
256*635a8641SAndroid Build Coastguard Worker // Verifiy that the variables were reset.
257*635a8641SAndroid Build Coastguard Worker {
258*635a8641SAndroid Build Coastguard Worker singleton_int = SingletonInt();
259*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(*singleton_int, 0);
260*635a8641SAndroid Build Coastguard Worker }
261*635a8641SAndroid Build Coastguard Worker {
262*635a8641SAndroid Build Coastguard Worker singleton_int_5 = SingletonInt5();
263*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(*singleton_int_5, 5);
264*635a8641SAndroid Build Coastguard Worker }
265*635a8641SAndroid Build Coastguard Worker {
266*635a8641SAndroid Build Coastguard Worker // Resurrect the static singleton, and assert that it
267*635a8641SAndroid Build Coastguard Worker // still points to the same (static) memory.
268*635a8641SAndroid Build Coastguard Worker CallbackSingletonWithStaticTrait::Trait::ResurrectForTesting();
269*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(GetStaticSingleton(), static_singleton);
270*635a8641SAndroid Build Coastguard Worker }
271*635a8641SAndroid Build Coastguard Worker }
272*635a8641SAndroid Build Coastguard Worker // The leaky singleton shouldn't leak since SingletonLeak has not been called.
273*635a8641SAndroid Build Coastguard Worker VerifiesCallbacksNotCalled();
274*635a8641SAndroid Build Coastguard Worker }
275*635a8641SAndroid Build Coastguard Worker
276*635a8641SAndroid Build Coastguard Worker #define EXPECT_ALIGNED(ptr, align) \
277*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
278*635a8641SAndroid Build Coastguard Worker
TEST_F(SingletonTest,Alignment)279*635a8641SAndroid Build Coastguard Worker TEST_F(SingletonTest, Alignment) {
280*635a8641SAndroid Build Coastguard Worker // Create some static singletons with increasing sizes and alignment
281*635a8641SAndroid Build Coastguard Worker // requirements. By ordering this way, the linker will need to do some work to
282*635a8641SAndroid Build Coastguard Worker // ensure proper alignment of the static data.
283*635a8641SAndroid Build Coastguard Worker AlignedTestSingleton<int32_t>* align4 =
284*635a8641SAndroid Build Coastguard Worker AlignedTestSingleton<int32_t>::GetInstance();
285*635a8641SAndroid Build Coastguard Worker AlignedTestSingleton<AlignedData<32>>* align32 =
286*635a8641SAndroid Build Coastguard Worker AlignedTestSingleton<AlignedData<32>>::GetInstance();
287*635a8641SAndroid Build Coastguard Worker AlignedTestSingleton<AlignedData<128>>* align128 =
288*635a8641SAndroid Build Coastguard Worker AlignedTestSingleton<AlignedData<128>>::GetInstance();
289*635a8641SAndroid Build Coastguard Worker AlignedTestSingleton<AlignedData<4096>>* align4096 =
290*635a8641SAndroid Build Coastguard Worker AlignedTestSingleton<AlignedData<4096>>::GetInstance();
291*635a8641SAndroid Build Coastguard Worker
292*635a8641SAndroid Build Coastguard Worker EXPECT_ALIGNED(align4, 4);
293*635a8641SAndroid Build Coastguard Worker EXPECT_ALIGNED(align32, 32);
294*635a8641SAndroid Build Coastguard Worker EXPECT_ALIGNED(align128, 128);
295*635a8641SAndroid Build Coastguard Worker EXPECT_ALIGNED(align4096, 4096);
296*635a8641SAndroid Build Coastguard Worker }
297*635a8641SAndroid Build Coastguard Worker
298*635a8641SAndroid Build Coastguard Worker } // namespace
299*635a8641SAndroid Build Coastguard Worker } // namespace base
300