Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / base / memory / singleton_unittest.cc
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.
4
5 #include "base/at_exit.h"
6 #include "base/memory/singleton.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8
9 namespace {
10
11 COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a);
12
13 typedef void (*CallbackFunc)();
14
15 class IntSingleton {
16  public:
17   static IntSingleton* GetInstance() {
18     return Singleton<IntSingleton>::get();
19   }
20
21   int value_;
22 };
23
24 class Init5Singleton {
25  public:
26   struct Trait;
27
28   static Init5Singleton* GetInstance() {
29     return Singleton<Init5Singleton, Trait>::get();
30   }
31
32   int value_;
33 };
34
35 struct Init5Singleton::Trait : public DefaultSingletonTraits<Init5Singleton> {
36   static Init5Singleton* New() {
37     Init5Singleton* instance = new Init5Singleton();
38     instance->value_ = 5;
39     return instance;
40   }
41 };
42
43 int* SingletonInt() {
44   return &IntSingleton::GetInstance()->value_;
45 }
46
47 int* SingletonInt5() {
48   return &Init5Singleton::GetInstance()->value_;
49 }
50
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);
57   }
58 };
59
60 class CallbackSingleton {
61  public:
62   CallbackSingleton() : callback_(NULL) { }
63   CallbackFunc callback_;
64 };
65
66 class CallbackSingletonWithNoLeakTrait : public CallbackSingleton {
67  public:
68   struct Trait : public CallbackTrait<CallbackSingletonWithNoLeakTrait> { };
69
70   CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { }
71
72   static CallbackSingletonWithNoLeakTrait* GetInstance() {
73     return Singleton<CallbackSingletonWithNoLeakTrait, Trait>::get();
74   }
75 };
76
77 class CallbackSingletonWithLeakTrait : public CallbackSingleton {
78  public:
79   struct Trait : public CallbackTrait<CallbackSingletonWithLeakTrait> {
80     static const bool kRegisterAtExit = false;
81   };
82
83   CallbackSingletonWithLeakTrait() : CallbackSingleton() { }
84
85   static CallbackSingletonWithLeakTrait* GetInstance() {
86     return Singleton<CallbackSingletonWithLeakTrait, Trait>::get();
87   }
88 };
89
90 class CallbackSingletonWithStaticTrait : public CallbackSingleton {
91  public:
92   struct Trait;
93
94   CallbackSingletonWithStaticTrait() : CallbackSingleton() { }
95
96   static CallbackSingletonWithStaticTrait* GetInstance() {
97     return Singleton<CallbackSingletonWithStaticTrait, Trait>::get();
98   }
99 };
100
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(
107         instance);
108   }
109 };
110
111 template <class Type>
112 class AlignedTestSingleton {
113  public:
114   AlignedTestSingleton() {}
115   ~AlignedTestSingleton() {}
116   static AlignedTestSingleton* GetInstance() {
117     return Singleton<AlignedTestSingleton,
118         StaticMemorySingletonTraits<AlignedTestSingleton> >::get();
119   }
120
121   Type type_;
122 };
123
124
125 void SingletonNoLeak(CallbackFunc CallOnQuit) {
126   CallbackSingletonWithNoLeakTrait::GetInstance()->callback_ = CallOnQuit;
127 }
128
129 void SingletonLeak(CallbackFunc CallOnQuit) {
130   CallbackSingletonWithLeakTrait::GetInstance()->callback_ = CallOnQuit;
131 }
132
133 CallbackFunc* GetLeakySingleton() {
134   return &CallbackSingletonWithLeakTrait::GetInstance()->callback_;
135 }
136
137 void DeleteLeakySingleton() {
138   DefaultSingletonTraits<CallbackSingletonWithLeakTrait>::Delete(
139       CallbackSingletonWithLeakTrait::GetInstance());
140 }
141
142 void SingletonStatic(CallbackFunc CallOnQuit) {
143   CallbackSingletonWithStaticTrait::GetInstance()->callback_ = CallOnQuit;
144 }
145
146 CallbackFunc* GetStaticSingleton() {
147   return &CallbackSingletonWithStaticTrait::GetInstance()->callback_;
148 }
149
150 }  // namespace
151
152 class SingletonTest : public testing::Test {
153  public:
154   SingletonTest() {}
155
156   virtual void SetUp() override {
157     non_leak_called_ = false;
158     leaky_called_ = false;
159     static_called_ = false;
160   }
161
162  protected:
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;
170   }
171
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;
179   }
180
181   static void CallbackNoLeak() {
182     non_leak_called_ = true;
183   }
184
185   static void CallbackLeak() {
186     leaky_called_ = true;
187   }
188
189   static void CallbackStatic() {
190     static_called_ = true;
191   }
192
193  private:
194   static bool non_leak_called_;
195   static bool leaky_called_;
196   static bool static_called_;
197 };
198
199 bool SingletonTest::non_leak_called_ = false;
200 bool SingletonTest::leaky_called_ = false;
201 bool SingletonTest::static_called_ = false;
202
203 TEST_F(SingletonTest, Basic) {
204   int* singleton_int;
205   int* singleton_int_5;
206   CallbackFunc* leaky_singleton;
207   CallbackFunc* static_singleton;
208
209   {
210     base::ShadowingAtExitManager sem;
211     {
212       singleton_int = SingletonInt();
213     }
214     // Ensure POD type initialization.
215     EXPECT_EQ(*singleton_int, 0);
216     *singleton_int = 1;
217
218     EXPECT_EQ(singleton_int, SingletonInt());
219     EXPECT_EQ(*singleton_int, 1);
220
221     {
222       singleton_int_5 = SingletonInt5();
223     }
224     // Is default initialized to 5.
225     EXPECT_EQ(*singleton_int_5, 5);
226
227     SingletonNoLeak(&CallbackNoLeak);
228     SingletonLeak(&CallbackLeak);
229     SingletonStatic(&CallbackStatic);
230     static_singleton = GetStaticSingleton();
231     leaky_singleton = GetLeakySingleton();
232     EXPECT_TRUE(leaky_singleton);
233   }
234
235   // Verify that only the expected callback has been called.
236   VerifiesCallbacks();
237   // Delete the leaky singleton.
238   DeleteLeakySingleton();
239
240   // The static singleton can't be acquired post-atexit.
241   EXPECT_EQ(NULL, GetStaticSingleton());
242
243   {
244     base::ShadowingAtExitManager sem;
245     // Verifiy that the variables were reset.
246     {
247       singleton_int = SingletonInt();
248       EXPECT_EQ(*singleton_int, 0);
249     }
250     {
251       singleton_int_5 = SingletonInt5();
252       EXPECT_EQ(*singleton_int_5, 5);
253     }
254     {
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);
259     }
260   }
261   // The leaky singleton shouldn't leak since SingletonLeak has not been called.
262   VerifiesCallbacksNotCalled();
263 }
264
265 #define EXPECT_ALIGNED(ptr, align) \
266     EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
267
268 TEST_F(SingletonTest, Alignment) {
269   using base::AlignedMemory;
270
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();
282
283   EXPECT_ALIGNED(align4, 4);
284   EXPECT_ALIGNED(align32, 32);
285   EXPECT_ALIGNED(align128, 128);
286   EXPECT_ALIGNED(align4096, 4096);
287 }