Update .DEPS.git
[chromium-blink-merge.git] / base / memory / singleton_unittest.cc
blobd9892cba482f6df5c48798398e9347204637a332
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"
11 namespace {
13 COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a);
15 typedef void (*CallbackFunc)();
17 class IntSingleton {
18 public:
19 static IntSingleton* GetInstance() {
20 return Singleton<IntSingleton>::get();
23 int value_;
26 class Init5Singleton {
27 public:
28 struct Trait;
30 static Init5Singleton* GetInstance() {
31 return Singleton<Init5Singleton, Trait>::get();
34 int value_;
37 struct Init5Singleton::Trait : public DefaultSingletonTraits<Init5Singleton> {
38 static Init5Singleton* New() {
39 Init5Singleton* instance = new Init5Singleton();
40 instance->value_ = 5;
41 return instance;
45 int* SingletonInt() {
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 {
63 public:
64 CallbackSingleton() : callback_(NULL) { }
65 CallbackFunc callback_;
68 class CallbackSingletonWithNoLeakTrait : public CallbackSingleton {
69 public:
70 struct Trait : public CallbackTrait<CallbackSingletonWithNoLeakTrait> { };
72 CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { }
74 static CallbackSingletonWithNoLeakTrait* GetInstance() {
75 return Singleton<CallbackSingletonWithNoLeakTrait, Trait>::get();
79 class CallbackSingletonWithLeakTrait : public CallbackSingleton {
80 public:
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 {
93 public:
94 struct Trait;
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(
109 instance);
113 template <class Type>
114 class AlignedTestSingleton {
115 public:
116 AlignedTestSingleton() {}
117 ~AlignedTestSingleton() {}
118 static AlignedTestSingleton* GetInstance() {
119 return Singleton<AlignedTestSingleton,
120 StaticMemorySingletonTraits<AlignedTestSingleton> >::get();
123 Type type_;
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_;
152 } // namespace
154 class SingletonTest : public testing::Test {
155 public:
156 SingletonTest() {}
158 virtual void SetUp() OVERRIDE {
159 non_leak_called_ = false;
160 leaky_called_ = false;
161 static_called_ = false;
164 protected:
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;
195 private:
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) {
206 int* singleton_int;
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);
218 *singleton_int = 1;
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.
238 VerifiesCallbacks();
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);