1 // 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. 4 5 #include "base/at_exit.h" 6 #include "base/file_util.h" 7 #include "base/path_service.h" 8 #include "base/singleton.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 11 namespace { 12 13 COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a); 14 15 template<typename Type> 16 struct LockTrait : public DefaultSingletonTraits<Type> { 17 }; 18 19 struct Init5Trait : public DefaultSingletonTraits<int> { 20 static int* New() { 21 return new int(5); 22 } 23 }; 24 25 typedef void (*CallbackFunc)(); 26 27 struct CallbackTrait : public DefaultSingletonTraits<CallbackFunc> { 28 static void Delete(CallbackFunc* p) { 29 if (*p) 30 (*p)(); 31 DefaultSingletonTraits<CallbackFunc>::Delete(p); 32 } 33 }; 34 35 struct NoLeakTrait : public CallbackTrait { 36 }; 37 38 struct LeakTrait : public CallbackTrait { 39 static const bool kRegisterAtExit = false; 40 }; 41 42 int* SingletonInt1() { 43 return Singleton<int>::get(); 44 } 45 46 int* SingletonInt2() { 47 // Force to use a different singleton than SingletonInt1. 48 return Singleton<int, DefaultSingletonTraits<int> >::get(); 49 } 50 51 class DummyDifferentiatingClass { 52 }; 53 54 int* SingletonInt3() { 55 // Force to use a different singleton than SingletonInt1 and SingletonInt2. 56 // Note that any type can be used; int, float, std::wstring... 57 return Singleton<int, DefaultSingletonTraits<int>, 58 DummyDifferentiatingClass>::get(); 59 } 60 61 int* SingletonInt4() { 62 return Singleton<int, LockTrait<int> >::get(); 63 } 64 65 int* SingletonInt5() { 66 return Singleton<int, Init5Trait>::get(); 67 } 68 69 void SingletonNoLeak(CallbackFunc CallOnQuit) { 70 *Singleton<CallbackFunc, NoLeakTrait>::get() = CallOnQuit; 71 } 72 73 void SingletonLeak(CallbackFunc CallOnQuit) { 74 *Singleton<CallbackFunc, LeakTrait>::get() = CallOnQuit; 75 } 76 77 CallbackFunc* GetLeakySingleton() { 78 return Singleton<CallbackFunc, LeakTrait>::get(); 79 } 80 81 } // namespace 82 83 class SingletonTest : public testing::Test { 84 public: 85 SingletonTest() { } 86 87 virtual void SetUp() { 88 non_leak_called_ = false; 89 leaky_called_ = false; 90 } 91 92 protected: 93 void VerifiesCallbacks() { 94 EXPECT_TRUE(non_leak_called_); 95 EXPECT_FALSE(leaky_called_); 96 non_leak_called_ = false; 97 leaky_called_ = false; 98 } 99 100 void VerifiesCallbacksNotCalled() { 101 EXPECT_FALSE(non_leak_called_); 102 EXPECT_FALSE(leaky_called_); 103 non_leak_called_ = false; 104 leaky_called_ = false; 105 } 106 107 static void CallbackNoLeak() { 108 non_leak_called_ = true; 109 } 110 111 static void CallbackLeak() { 112 leaky_called_ = true; 113 } 114 115 private: 116 static bool non_leak_called_; 117 static bool leaky_called_; 118 }; 119 120 bool SingletonTest::non_leak_called_ = false; 121 bool SingletonTest::leaky_called_ = false; 122 123 TEST_F(SingletonTest, Basic) { 124 int* singleton_int_1; 125 int* singleton_int_2; 126 int* singleton_int_3; 127 int* singleton_int_4; 128 int* singleton_int_5; 129 CallbackFunc* leaky_singleton; 130 131 { 132 base::ShadowingAtExitManager sem; 133 { 134 singleton_int_1 = SingletonInt1(); 135 } 136 // Ensure POD type initialization. 137 EXPECT_EQ(*singleton_int_1, 0); 138 *singleton_int_1 = 1; 139 140 EXPECT_EQ(singleton_int_1, SingletonInt1()); 141 EXPECT_EQ(*singleton_int_1, 1); 142 143 { 144 singleton_int_2 = SingletonInt2(); 145 } 146 // Same instance that 1. 147 EXPECT_EQ(*singleton_int_2, 1); 148 EXPECT_EQ(singleton_int_1, singleton_int_2); 149 150 { 151 singleton_int_3 = SingletonInt3(); 152 } 153 // Different instance than 1 and 2. 154 EXPECT_EQ(*singleton_int_3, 0); 155 EXPECT_NE(singleton_int_1, singleton_int_3); 156 *singleton_int_3 = 3; 157 EXPECT_EQ(*singleton_int_1, 1); 158 EXPECT_EQ(*singleton_int_2, 1); 159 160 { 161 singleton_int_4 = SingletonInt4(); 162 } 163 // Use a lock for creation. Not really tested at length. 164 EXPECT_EQ(*singleton_int_4, 0); 165 *singleton_int_4 = 4; 166 EXPECT_NE(singleton_int_1, singleton_int_4); 167 EXPECT_NE(singleton_int_3, singleton_int_4); 168 169 { 170 singleton_int_5 = SingletonInt5(); 171 } 172 // Is default initialized to 5. 173 EXPECT_EQ(*singleton_int_5, 5); 174 EXPECT_NE(singleton_int_1, singleton_int_5); 175 EXPECT_NE(singleton_int_3, singleton_int_5); 176 EXPECT_NE(singleton_int_4, singleton_int_5); 177 178 SingletonNoLeak(&CallbackNoLeak); 179 SingletonLeak(&CallbackLeak); 180 leaky_singleton = GetLeakySingleton(); 181 EXPECT_TRUE(leaky_singleton); 182 } 183 184 // Verify that only the expected callback has been called. 185 VerifiesCallbacks(); 186 // Delete the leaky singleton. It is interesting to note that Purify does 187 // *not* detect the leak when this call is commented out. :( 188 DefaultSingletonTraits<CallbackFunc>::Delete(leaky_singleton); 189 190 { 191 base::ShadowingAtExitManager sem; 192 // Verifiy that the variables were reset. 193 { 194 singleton_int_1 = SingletonInt1(); 195 EXPECT_EQ(*singleton_int_1, 0); 196 } 197 { 198 singleton_int_5 = SingletonInt5(); 199 EXPECT_EQ(*singleton_int_5, 5); 200 } 201 } 202 // The leaky singleton shouldn't leak since SingletonLeak has not been called. 203 VerifiesCallbacksNotCalled(); 204 } 205