| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/at_exit.h" | 5 #include "base/at_exit.h" |
| 6 #include "base/file_util.h" | 6 #include "base/file_util.h" |
| 7 #include "base/path_service.h" | 7 #include "base/path_service.h" |
| 8 #include "base/singleton.h" | 8 #include "base/singleton.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 | 10 |
| 11 namespace { | 11 namespace { |
| 12 | 12 |
| 13 COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a); | 13 COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a); |
| 14 | 14 |
| 15 template<typename Type> | 15 template<typename Type> |
| 16 struct LockTrait : public DefaultSingletonTraits<Type> { | 16 struct LockTrait : public DefaultSingletonTraits<Type> { |
| 17 }; | 17 }; |
| 18 | 18 |
| 19 struct Init5Trait : public DefaultSingletonTraits<int> { | |
| 20 static int* New() { | |
| 21 return new int(5); | |
| 22 } | |
| 23 }; | |
| 24 | |
| 25 typedef void (*CallbackFunc)(); | 19 typedef void (*CallbackFunc)(); |
| 26 | 20 |
| 27 struct CallbackTrait : public DefaultSingletonTraits<CallbackFunc> { | 21 class IntSingleton { |
| 28 static void Delete(CallbackFunc* p) { | 22 public: |
| 29 if (*p) | 23 class DummyDifferentiatingClass { |
| 30 (*p)(); | 24 }; |
| 31 DefaultSingletonTraits<CallbackFunc>::Delete(p); | 25 |
| 26 struct Init5Trait : public DefaultSingletonTraits<IntSingleton> { |
| 27 static IntSingleton* New() { |
| 28 IntSingleton* instance = new IntSingleton(); |
| 29 instance->value_ = 5; |
| 30 return instance; |
| 31 } |
| 32 }; |
| 33 |
| 34 static IntSingleton* GetInstance() { |
| 35 return Singleton<IntSingleton>::get(); |
| 32 } | 36 } |
| 33 }; | 37 static IntSingleton* GetInstanceWithDefaultTraits() { |
| 38 return Singleton<IntSingleton, |
| 39 DefaultSingletonTraits<IntSingleton> >::get(); |
| 40 } |
| 41 static IntSingleton* GetInstanceWithDifferentiatingClass() { |
| 42 return Singleton<IntSingleton, |
| 43 DefaultSingletonTraits<IntSingleton>, |
| 44 DummyDifferentiatingClass>::get(); |
| 45 } |
| 46 static IntSingleton* GetInstanceWithLockTrait() { |
| 47 return Singleton<IntSingleton, LockTrait<IntSingleton> >::get(); |
| 48 } |
| 49 static IntSingleton* GetInstanceWithInit5Trait() { |
| 50 return Singleton<IntSingleton, Init5Trait>::get(); |
| 51 } |
| 34 | 52 |
| 35 struct StaticCallbackTrait : public StaticMemorySingletonTraits<CallbackFunc> { | 53 int value_; |
| 36 static void Delete(CallbackFunc* p) { | |
| 37 if (*p) | |
| 38 (*p)(); | |
| 39 StaticMemorySingletonTraits<CallbackFunc>::Delete(p); | |
| 40 } | |
| 41 }; | |
| 42 | |
| 43 | |
| 44 struct NoLeakTrait : public CallbackTrait { | |
| 45 }; | |
| 46 | |
| 47 struct LeakTrait : public CallbackTrait { | |
| 48 static const bool kRegisterAtExit = false; | |
| 49 }; | 54 }; |
| 50 | 55 |
| 51 int* SingletonInt1() { | 56 int* SingletonInt1() { |
| 52 return Singleton<int>::get(); | 57 return &IntSingleton::GetInstance()->value_; |
| 53 } | 58 } |
| 54 | 59 |
| 55 int* SingletonInt2() { | 60 int* SingletonInt2() { |
| 56 // Force to use a different singleton than SingletonInt1. | 61 // Force to use a different singleton than SingletonInt1. |
| 57 return Singleton<int, DefaultSingletonTraits<int> >::get(); | 62 return &IntSingleton::GetInstanceWithDefaultTraits()->value_; |
| 58 } | 63 } |
| 59 | 64 |
| 60 class DummyDifferentiatingClass { | |
| 61 }; | |
| 62 | |
| 63 int* SingletonInt3() { | 65 int* SingletonInt3() { |
| 64 // Force to use a different singleton than SingletonInt1 and SingletonInt2. | 66 // Force to use a different singleton than SingletonInt1 and SingletonInt2. |
| 65 // Note that any type can be used; int, float, std::wstring... | 67 return &IntSingleton::GetInstanceWithDifferentiatingClass()->value_; |
| 66 return Singleton<int, DefaultSingletonTraits<int>, | |
| 67 DummyDifferentiatingClass>::get(); | |
| 68 } | 68 } |
| 69 | 69 |
| 70 int* SingletonInt4() { | 70 int* SingletonInt4() { |
| 71 return Singleton<int, LockTrait<int> >::get(); | 71 return &IntSingleton::GetInstanceWithLockTrait()->value_; |
| 72 } | 72 } |
| 73 | 73 |
| 74 int* SingletonInt5() { | 74 int* SingletonInt5() { |
| 75 return Singleton<int, Init5Trait>::get(); | 75 return &IntSingleton::GetInstanceWithInit5Trait()->value_; |
| 76 } |
| 77 |
| 78 class CallbackSingleton { |
| 79 public: |
| 80 struct CallbackTrait : public DefaultSingletonTraits<CallbackSingleton> { |
| 81 static void Delete(CallbackSingleton* instance) { |
| 82 if (instance->callback_) |
| 83 (instance->callback_)(); |
| 84 DefaultSingletonTraits<CallbackSingleton>::Delete(instance); |
| 85 } |
| 86 }; |
| 87 |
| 88 struct NoLeakTrait : public CallbackTrait { |
| 89 }; |
| 90 |
| 91 struct LeakTrait : public CallbackTrait { |
| 92 static const bool kRegisterAtExit = false; |
| 93 }; |
| 94 |
| 95 CallbackSingleton() : callback_(NULL) { |
| 96 } |
| 97 |
| 98 static CallbackSingleton* GetInstanceWithNoLeakTrait() { |
| 99 return Singleton<CallbackSingleton, NoLeakTrait>::get(); |
| 100 } |
| 101 static CallbackSingleton* GetInstanceWithLeakTrait() { |
| 102 return Singleton<CallbackSingleton, LeakTrait>::get(); |
| 103 } |
| 104 static CallbackSingleton* GetInstanceWithStaticTrait(); |
| 105 |
| 106 CallbackFunc callback_; |
| 107 }; |
| 108 |
| 109 struct StaticCallbackTrait |
| 110 : public StaticMemorySingletonTraits<CallbackSingleton> { |
| 111 static void Delete(CallbackSingleton* instance) { |
| 112 if (instance->callback_) |
| 113 (instance->callback_)(); |
| 114 StaticMemorySingletonTraits<CallbackSingleton>::Delete(instance); |
| 115 } |
| 116 }; |
| 117 |
| 118 CallbackSingleton* CallbackSingleton::GetInstanceWithStaticTrait() { |
| 119 return Singleton<CallbackSingleton, StaticCallbackTrait>::get(); |
| 76 } | 120 } |
| 77 | 121 |
| 78 void SingletonNoLeak(CallbackFunc CallOnQuit) { | 122 void SingletonNoLeak(CallbackFunc CallOnQuit) { |
| 79 *Singleton<CallbackFunc, NoLeakTrait>::get() = CallOnQuit; | 123 CallbackSingleton::GetInstanceWithNoLeakTrait()->callback_ = CallOnQuit; |
| 80 } | 124 } |
| 81 | 125 |
| 82 void SingletonLeak(CallbackFunc CallOnQuit) { | 126 void SingletonLeak(CallbackFunc CallOnQuit) { |
| 83 *Singleton<CallbackFunc, LeakTrait>::get() = CallOnQuit; | 127 CallbackSingleton::GetInstanceWithLeakTrait()->callback_ = CallOnQuit; |
| 84 } | 128 } |
| 85 | 129 |
| 86 CallbackFunc* GetLeakySingleton() { | 130 CallbackFunc* GetLeakySingleton() { |
| 87 return Singleton<CallbackFunc, LeakTrait>::get(); | 131 return &CallbackSingleton::GetInstanceWithLeakTrait()->callback_; |
| 88 } | 132 } |
| 89 | 133 |
| 90 void SingletonStatic(CallbackFunc CallOnQuit) { | 134 void SingletonStatic(CallbackFunc CallOnQuit) { |
| 91 *Singleton<CallbackFunc, StaticCallbackTrait>::get() = CallOnQuit; | 135 CallbackSingleton::GetInstanceWithStaticTrait()->callback_ = CallOnQuit; |
| 92 } | 136 } |
| 93 | 137 |
| 94 CallbackFunc* GetStaticSingleton() { | 138 CallbackFunc* GetStaticSingleton() { |
| 95 return Singleton<CallbackFunc, StaticCallbackTrait>::get(); | 139 return &CallbackSingleton::GetInstanceWithStaticTrait()->callback_; |
| 96 } | 140 } |
| 97 | 141 |
| 98 } // namespace | 142 } // namespace |
| 99 | 143 |
| 100 class SingletonTest : public testing::Test { | 144 class SingletonTest : public testing::Test { |
| 101 public: | 145 public: |
| 102 SingletonTest() { } | 146 SingletonTest() { } |
| 103 | 147 |
| 104 virtual void SetUp() { | 148 virtual void SetUp() { |
| 105 non_leak_called_ = false; | 149 non_leak_called_ = false; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 singleton_int_1 = SingletonInt1(); | 272 singleton_int_1 = SingletonInt1(); |
| 229 EXPECT_EQ(*singleton_int_1, 0); | 273 EXPECT_EQ(*singleton_int_1, 0); |
| 230 } | 274 } |
| 231 { | 275 { |
| 232 singleton_int_5 = SingletonInt5(); | 276 singleton_int_5 = SingletonInt5(); |
| 233 EXPECT_EQ(*singleton_int_5, 5); | 277 EXPECT_EQ(*singleton_int_5, 5); |
| 234 } | 278 } |
| 235 { | 279 { |
| 236 // Resurrect the static singleton, and assert that it | 280 // Resurrect the static singleton, and assert that it |
| 237 // still points to the same (static) memory. | 281 // still points to the same (static) memory. |
| 238 StaticMemorySingletonTraits<CallbackFunc>::Resurrect(); | 282 StaticMemorySingletonTraits<CallbackSingleton>::Resurrect(); |
| 239 EXPECT_EQ(GetStaticSingleton(), static_singleton); | 283 EXPECT_EQ(GetStaticSingleton(), static_singleton); |
| 240 } | 284 } |
| 241 } | 285 } |
| 242 // The leaky singleton shouldn't leak since SingletonLeak has not been called. | 286 // The leaky singleton shouldn't leak since SingletonLeak has not been called. |
| 243 VerifiesCallbacksNotCalled(); | 287 VerifiesCallbacksNotCalled(); |
| 244 } | 288 } |
| OLD | NEW |