blob: acb1247d96d09ba3f9b18929d419996f3a0baf1c [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commitd7cae122008-07-26 21:49:384
[email protected]4ac8f672008-08-11 14:02:065#include "base/at_exit.h"
initial.commitd7cae122008-07-26 21:49:386#include "base/file_util.h"
7#include "base/path_service.h"
[email protected]4ac8f672008-08-11 14:02:068#include "base/singleton.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11namespace {
12
[email protected]4ac8f672008-08-11 14:02:0613COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a);
14
15template<typename Type>
16struct LockTrait : public DefaultSingletonTraits<Type> {
17};
18
[email protected]5820d2f02010-12-11 10:23:3719struct Init5Trait : public DefaultSingletonTraits<int> {
20 static int* New() {
21 return new int(5);
22 }
23};
24
[email protected]4ac8f672008-08-11 14:02:0625typedef void (*CallbackFunc)();
26
[email protected]5820d2f02010-12-11 10:23:3727struct CallbackTrait : public DefaultSingletonTraits<CallbackFunc> {
28 static void Delete(CallbackFunc* p) {
29 if (*p)
30 (*p)();
31 DefaultSingletonTraits<CallbackFunc>::Delete(p);
32 }
33};
[email protected]49ab5562010-12-11 09:13:5434
[email protected]5820d2f02010-12-11 10:23:3735struct StaticCallbackTrait : public StaticMemorySingletonTraits<CallbackFunc> {
36 static void Delete(CallbackFunc* p) {
37 if (*p)
38 (*p)();
39 StaticMemorySingletonTraits<CallbackFunc>::Delete(p);
40 }
41};
[email protected]49ab5562010-12-11 09:13:5442
[email protected]297d0e52010-05-07 15:24:4943
[email protected]5820d2f02010-12-11 10:23:3744struct NoLeakTrait : public CallbackTrait {
45};
46
47struct LeakTrait : public CallbackTrait {
48 static const bool kRegisterAtExit = false;
[email protected]4ac8f672008-08-11 14:02:0649};
50
51int* SingletonInt1() {
[email protected]5820d2f02010-12-11 10:23:3752 return Singleton<int>::get();
[email protected]4ac8f672008-08-11 14:02:0653}
54
55int* SingletonInt2() {
56 // Force to use a different singleton than SingletonInt1.
[email protected]5820d2f02010-12-11 10:23:3757 return Singleton<int, DefaultSingletonTraits<int> >::get();
[email protected]4ac8f672008-08-11 14:02:0658}
59
[email protected]5820d2f02010-12-11 10:23:3760class DummyDifferentiatingClass {
61};
62
[email protected]4ac8f672008-08-11 14:02:0663int* SingletonInt3() {
64 // Force to use a different singleton than SingletonInt1 and SingletonInt2.
[email protected]5820d2f02010-12-11 10:23:3765 // Note that any type can be used; int, float, std::wstring...
66 return Singleton<int, DefaultSingletonTraits<int>,
67 DummyDifferentiatingClass>::get();
[email protected]4ac8f672008-08-11 14:02:0668}
69
70int* SingletonInt4() {
[email protected]5820d2f02010-12-11 10:23:3771 return Singleton<int, LockTrait<int> >::get();
[email protected]4ac8f672008-08-11 14:02:0672}
73
74int* SingletonInt5() {
[email protected]5820d2f02010-12-11 10:23:3775 return Singleton<int, Init5Trait>::get();
[email protected]4ac8f672008-08-11 14:02:0676}
77
78void SingletonNoLeak(CallbackFunc CallOnQuit) {
[email protected]5820d2f02010-12-11 10:23:3779 *Singleton<CallbackFunc, NoLeakTrait>::get() = CallOnQuit;
[email protected]4ac8f672008-08-11 14:02:0680}
81
82void SingletonLeak(CallbackFunc CallOnQuit) {
[email protected]5820d2f02010-12-11 10:23:3783 *Singleton<CallbackFunc, LeakTrait>::get() = CallOnQuit;
[email protected]4ac8f672008-08-11 14:02:0684}
85
86CallbackFunc* GetLeakySingleton() {
[email protected]5820d2f02010-12-11 10:23:3787 return Singleton<CallbackFunc, LeakTrait>::get();
[email protected]4ac8f672008-08-11 14:02:0688}
89
[email protected]297d0e52010-05-07 15:24:4990void SingletonStatic(CallbackFunc CallOnQuit) {
[email protected]5820d2f02010-12-11 10:23:3791 *Singleton<CallbackFunc, StaticCallbackTrait>::get() = CallOnQuit;
[email protected]297d0e52010-05-07 15:24:4992}
93
94CallbackFunc* GetStaticSingleton() {
[email protected]5820d2f02010-12-11 10:23:3795 return Singleton<CallbackFunc, StaticCallbackTrait>::get();
[email protected]297d0e52010-05-07 15:24:4996}
97
[email protected]4ac8f672008-08-11 14:02:0698} // namespace
initial.commitd7cae122008-07-26 21:49:3899
100class SingletonTest : public testing::Test {
101 public:
[email protected]4ac8f672008-08-11 14:02:06102 SingletonTest() { }
initial.commitd7cae122008-07-26 21:49:38103
104 virtual void SetUp() {
initial.commitd7cae122008-07-26 21:49:38105 non_leak_called_ = false;
106 leaky_called_ = false;
[email protected]297d0e52010-05-07 15:24:49107 static_called_ = false;
initial.commitd7cae122008-07-26 21:49:38108 }
109
initial.commitd7cae122008-07-26 21:49:38110 protected:
initial.commitd7cae122008-07-26 21:49:38111 void VerifiesCallbacks() {
112 EXPECT_TRUE(non_leak_called_);
113 EXPECT_FALSE(leaky_called_);
[email protected]297d0e52010-05-07 15:24:49114 EXPECT_TRUE(static_called_);
initial.commitd7cae122008-07-26 21:49:38115 non_leak_called_ = false;
116 leaky_called_ = false;
[email protected]297d0e52010-05-07 15:24:49117 static_called_ = false;
initial.commitd7cae122008-07-26 21:49:38118 }
119
120 void VerifiesCallbacksNotCalled() {
121 EXPECT_FALSE(non_leak_called_);
122 EXPECT_FALSE(leaky_called_);
[email protected]297d0e52010-05-07 15:24:49123 EXPECT_FALSE(static_called_);
initial.commitd7cae122008-07-26 21:49:38124 non_leak_called_ = false;
125 leaky_called_ = false;
[email protected]297d0e52010-05-07 15:24:49126 static_called_ = false;
initial.commitd7cae122008-07-26 21:49:38127 }
128
[email protected]4ac8f672008-08-11 14:02:06129 static void CallbackNoLeak() {
initial.commitd7cae122008-07-26 21:49:38130 non_leak_called_ = true;
131 }
132
[email protected]4ac8f672008-08-11 14:02:06133 static void CallbackLeak() {
initial.commitd7cae122008-07-26 21:49:38134 leaky_called_ = true;
135 }
136
[email protected]297d0e52010-05-07 15:24:49137 static void CallbackStatic() {
138 static_called_ = true;
139 }
140
initial.commitd7cae122008-07-26 21:49:38141 private:
initial.commitd7cae122008-07-26 21:49:38142 static bool non_leak_called_;
143 static bool leaky_called_;
[email protected]297d0e52010-05-07 15:24:49144 static bool static_called_;
initial.commitd7cae122008-07-26 21:49:38145};
146
147bool SingletonTest::non_leak_called_ = false;
148bool SingletonTest::leaky_called_ = false;
[email protected]297d0e52010-05-07 15:24:49149bool SingletonTest::static_called_ = false;
initial.commitd7cae122008-07-26 21:49:38150
initial.commitd7cae122008-07-26 21:49:38151TEST_F(SingletonTest, Basic) {
initial.commitd7cae122008-07-26 21:49:38152 int* singleton_int_1;
153 int* singleton_int_2;
154 int* singleton_int_3;
155 int* singleton_int_4;
156 int* singleton_int_5;
[email protected]4ac8f672008-08-11 14:02:06157 CallbackFunc* leaky_singleton;
[email protected]297d0e52010-05-07 15:24:49158 CallbackFunc* static_singleton;
initial.commitd7cae122008-07-26 21:49:38159
initial.commitd7cae122008-07-26 21:49:38160 {
[email protected]4ea927b2009-11-19 09:11:39161 base::ShadowingAtExitManager sem;
initial.commitd7cae122008-07-26 21:49:38162 {
[email protected]4ac8f672008-08-11 14:02:06163 singleton_int_1 = SingletonInt1();
initial.commitd7cae122008-07-26 21:49:38164 }
165 // Ensure POD type initialization.
166 EXPECT_EQ(*singleton_int_1, 0);
167 *singleton_int_1 = 1;
168
[email protected]4ac8f672008-08-11 14:02:06169 EXPECT_EQ(singleton_int_1, SingletonInt1());
initial.commitd7cae122008-07-26 21:49:38170 EXPECT_EQ(*singleton_int_1, 1);
171
172 {
[email protected]4ac8f672008-08-11 14:02:06173 singleton_int_2 = SingletonInt2();
initial.commitd7cae122008-07-26 21:49:38174 }
175 // Same instance that 1.
176 EXPECT_EQ(*singleton_int_2, 1);
177 EXPECT_EQ(singleton_int_1, singleton_int_2);
178
179 {
[email protected]4ac8f672008-08-11 14:02:06180 singleton_int_3 = SingletonInt3();
initial.commitd7cae122008-07-26 21:49:38181 }
182 // Different instance than 1 and 2.
183 EXPECT_EQ(*singleton_int_3, 0);
184 EXPECT_NE(singleton_int_1, singleton_int_3);
185 *singleton_int_3 = 3;
186 EXPECT_EQ(*singleton_int_1, 1);
187 EXPECT_EQ(*singleton_int_2, 1);
188
189 {
[email protected]4ac8f672008-08-11 14:02:06190 singleton_int_4 = SingletonInt4();
initial.commitd7cae122008-07-26 21:49:38191 }
192 // Use a lock for creation. Not really tested at length.
193 EXPECT_EQ(*singleton_int_4, 0);
194 *singleton_int_4 = 4;
195 EXPECT_NE(singleton_int_1, singleton_int_4);
196 EXPECT_NE(singleton_int_3, singleton_int_4);
197
198 {
[email protected]4ac8f672008-08-11 14:02:06199 singleton_int_5 = SingletonInt5();
initial.commitd7cae122008-07-26 21:49:38200 }
201 // Is default initialized to 5.
202 EXPECT_EQ(*singleton_int_5, 5);
203 EXPECT_NE(singleton_int_1, singleton_int_5);
204 EXPECT_NE(singleton_int_3, singleton_int_5);
205 EXPECT_NE(singleton_int_4, singleton_int_5);
initial.commitd7cae122008-07-26 21:49:38206
[email protected]4ac8f672008-08-11 14:02:06207 SingletonNoLeak(&CallbackNoLeak);
208 SingletonLeak(&CallbackLeak);
[email protected]297d0e52010-05-07 15:24:49209 SingletonStatic(&CallbackStatic);
210 static_singleton = GetStaticSingleton();
[email protected]4ac8f672008-08-11 14:02:06211 leaky_singleton = GetLeakySingleton();
initial.commitd7cae122008-07-26 21:49:38212 EXPECT_TRUE(leaky_singleton);
213 }
initial.commitd7cae122008-07-26 21:49:38214
215 // Verify that only the expected callback has been called.
216 VerifiesCallbacks();
217 // Delete the leaky singleton. It is interesting to note that Purify does
218 // *not* detect the leak when this call is commented out. :(
[email protected]4ac8f672008-08-11 14:02:06219 DefaultSingletonTraits<CallbackFunc>::Delete(leaky_singleton);
initial.commitd7cae122008-07-26 21:49:38220
[email protected]297d0e52010-05-07 15:24:49221 // The static singleton can't be acquired post-atexit.
222 EXPECT_EQ(NULL, GetStaticSingleton());
223
initial.commitd7cae122008-07-26 21:49:38224 {
[email protected]4ea927b2009-11-19 09:11:39225 base::ShadowingAtExitManager sem;
initial.commitd7cae122008-07-26 21:49:38226 // Verifiy that the variables were reset.
227 {
[email protected]4ac8f672008-08-11 14:02:06228 singleton_int_1 = SingletonInt1();
initial.commitd7cae122008-07-26 21:49:38229 EXPECT_EQ(*singleton_int_1, 0);
230 }
231 {
[email protected]4ac8f672008-08-11 14:02:06232 singleton_int_5 = SingletonInt5();
initial.commitd7cae122008-07-26 21:49:38233 EXPECT_EQ(*singleton_int_5, 5);
234 }
[email protected]297d0e52010-05-07 15:24:49235 {
236 // Resurrect the static singleton, and assert that it
237 // still points to the same (static) memory.
[email protected]5820d2f02010-12-11 10:23:37238 StaticMemorySingletonTraits<CallbackFunc>::Resurrect();
[email protected]297d0e52010-05-07 15:24:49239 EXPECT_EQ(GetStaticSingleton(), static_singleton);
240 }
initial.commitd7cae122008-07-26 21:49:38241 }
242 // The leaky singleton shouldn't leak since SingletonLeak has not been called.
initial.commitd7cae122008-07-26 21:49:38243 VerifiesCallbacksNotCalled();
244}