| Index: base/singleton_unittest.cc
|
| diff --git a/base/singleton_unittest.cc b/base/singleton_unittest.cc
|
| index acb1247d96d09ba3f9b18929d419996f3a0baf1c..3d7e7e60d10d5f47e801d5b379aa9dd99be45ffc 100644
|
| --- a/base/singleton_unittest.cc
|
| +++ b/base/singleton_unittest.cc
|
| @@ -12,87 +12,131 @@ namespace {
|
|
|
| COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a);
|
|
|
| -template<typename Type>
|
| -struct LockTrait : public DefaultSingletonTraits<Type> {
|
| -};
|
| +typedef void (*CallbackFunc)();
|
|
|
| -struct Init5Trait : public DefaultSingletonTraits<int> {
|
| - static int* New() {
|
| - return new int(5);
|
| +class IntSingleton {
|
| + public:
|
| + static IntSingleton* GetInstance() {
|
| + return Singleton<IntSingleton>::get();
|
| }
|
| +
|
| + int value_;
|
| };
|
|
|
| -typedef void (*CallbackFunc)();
|
| +class Init5Singleton {
|
| + public:
|
| + struct Trait;
|
|
|
| -struct CallbackTrait : public DefaultSingletonTraits<CallbackFunc> {
|
| - static void Delete(CallbackFunc* p) {
|
| - if (*p)
|
| - (*p)();
|
| - DefaultSingletonTraits<CallbackFunc>::Delete(p);
|
| + static Init5Singleton* GetInstance() {
|
| + return Singleton<Init5Singleton, Trait>::get();
|
| }
|
| +
|
| + int value_;
|
| };
|
|
|
| -struct StaticCallbackTrait : public StaticMemorySingletonTraits<CallbackFunc> {
|
| - static void Delete(CallbackFunc* p) {
|
| - if (*p)
|
| - (*p)();
|
| - StaticMemorySingletonTraits<CallbackFunc>::Delete(p);
|
| +struct Init5Singleton::Trait : public DefaultSingletonTraits<Init5Singleton> {
|
| + static Init5Singleton* New() {
|
| + Init5Singleton* instance = new Init5Singleton();
|
| + instance->value_ = 5;
|
| + return instance;
|
| }
|
| };
|
|
|
| +int* SingletonInt() {
|
| + return &IntSingleton::GetInstance()->value_;
|
| +}
|
| +
|
| +int* SingletonInt5() {
|
| + return &Init5Singleton::GetInstance()->value_;
|
| +}
|
|
|
| -struct NoLeakTrait : public CallbackTrait {
|
| +template <typename Type>
|
| +struct CallbackTrait : public DefaultSingletonTraits<Type> {
|
| + static void Delete(Type* instance) {
|
| + if (instance->callback_)
|
| + (instance->callback_)();
|
| + DefaultSingletonTraits<Type>::Delete(instance);
|
| + }
|
| };
|
|
|
| -struct LeakTrait : public CallbackTrait {
|
| - static const bool kRegisterAtExit = false;
|
| +class CallbackSingleton {
|
| + public:
|
| + CallbackSingleton() : callback_(NULL) { }
|
| + CallbackFunc callback_;
|
| };
|
|
|
| -int* SingletonInt1() {
|
| - return Singleton<int>::get();
|
| -}
|
| +class CallbackSingletonWithNoLeakTrait : public CallbackSingleton {
|
| + public:
|
| + struct Trait : public CallbackTrait<CallbackSingletonWithNoLeakTrait> { };
|
|
|
| -int* SingletonInt2() {
|
| - // Force to use a different singleton than SingletonInt1.
|
| - return Singleton<int, DefaultSingletonTraits<int> >::get();
|
| -}
|
| + CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { }
|
|
|
| -class DummyDifferentiatingClass {
|
| + static CallbackSingletonWithNoLeakTrait* GetInstance() {
|
| + return Singleton<CallbackSingletonWithNoLeakTrait, Trait>::get();
|
| + }
|
| };
|
|
|
| -int* SingletonInt3() {
|
| - // Force to use a different singleton than SingletonInt1 and SingletonInt2.
|
| - // Note that any type can be used; int, float, std::wstring...
|
| - return Singleton<int, DefaultSingletonTraits<int>,
|
| - DummyDifferentiatingClass>::get();
|
| -}
|
| +class CallbackSingletonWithLeakTrait : public CallbackSingleton {
|
| + public:
|
| + struct Trait : public CallbackTrait<CallbackSingletonWithLeakTrait> {
|
| + static const bool kRegisterAtExit = false;
|
| + };
|
|
|
| -int* SingletonInt4() {
|
| - return Singleton<int, LockTrait<int> >::get();
|
| -}
|
| + CallbackSingletonWithLeakTrait() : CallbackSingleton() { }
|
| +
|
| + static CallbackSingletonWithLeakTrait* GetInstance() {
|
| + return Singleton<CallbackSingletonWithLeakTrait, Trait>::get();
|
| + }
|
| +};
|
| +
|
| +class CallbackSingletonWithStaticTrait : public CallbackSingleton {
|
| + public:
|
| + struct Trait;
|
| +
|
| + CallbackSingletonWithStaticTrait() : CallbackSingleton() { }
|
| +
|
| + static CallbackSingletonWithStaticTrait* GetInstance() {
|
| + return Singleton<CallbackSingletonWithStaticTrait, Trait>::get();
|
| + }
|
| +};
|
| +
|
| +struct CallbackSingletonWithStaticTrait::Trait
|
| + : public StaticMemorySingletonTraits<CallbackSingletonWithStaticTrait> {
|
| + static void Delete(CallbackSingletonWithStaticTrait* instance) {
|
| + if (instance->callback_)
|
| + (instance->callback_)();
|
| + StaticMemorySingletonTraits<CallbackSingletonWithStaticTrait>::Delete(
|
| + instance);
|
| + }
|
| +};
|
|
|
| -int* SingletonInt5() {
|
| - return Singleton<int, Init5Trait>::get();
|
| -}
|
|
|
| void SingletonNoLeak(CallbackFunc CallOnQuit) {
|
| - *Singleton<CallbackFunc, NoLeakTrait>::get() = CallOnQuit;
|
| + CallbackSingletonWithNoLeakTrait::GetInstance()->callback_ = CallOnQuit;
|
| }
|
|
|
| void SingletonLeak(CallbackFunc CallOnQuit) {
|
| - *Singleton<CallbackFunc, LeakTrait>::get() = CallOnQuit;
|
| + CallbackSingletonWithLeakTrait::GetInstance()->callback_ = CallOnQuit;
|
| }
|
|
|
| CallbackFunc* GetLeakySingleton() {
|
| - return Singleton<CallbackFunc, LeakTrait>::get();
|
| + return &CallbackSingletonWithLeakTrait::GetInstance()->callback_;
|
| +}
|
| +
|
| +void DeleteLeakySingleton() {
|
| + DefaultSingletonTraits<CallbackSingletonWithLeakTrait>::Delete(
|
| + CallbackSingletonWithLeakTrait::GetInstance());
|
| }
|
|
|
| void SingletonStatic(CallbackFunc CallOnQuit) {
|
| - *Singleton<CallbackFunc, StaticCallbackTrait>::get() = CallOnQuit;
|
| + CallbackSingletonWithStaticTrait::GetInstance()->callback_ = CallOnQuit;
|
| }
|
|
|
| CallbackFunc* GetStaticSingleton() {
|
| - return Singleton<CallbackFunc, StaticCallbackTrait>::get();
|
| + return &CallbackSingletonWithStaticTrait::GetInstance()->callback_;
|
| +}
|
| +
|
| +void ResurrectStaticSingleton() {
|
| }
|
|
|
| } // namespace
|
| @@ -149,10 +193,7 @@ bool SingletonTest::leaky_called_ = false;
|
| bool SingletonTest::static_called_ = false;
|
|
|
| TEST_F(SingletonTest, Basic) {
|
| - int* singleton_int_1;
|
| - int* singleton_int_2;
|
| - int* singleton_int_3;
|
| - int* singleton_int_4;
|
| + int* singleton_int;
|
| int* singleton_int_5;
|
| CallbackFunc* leaky_singleton;
|
| CallbackFunc* static_singleton;
|
| @@ -160,49 +201,20 @@ TEST_F(SingletonTest, Basic) {
|
| {
|
| base::ShadowingAtExitManager sem;
|
| {
|
| - singleton_int_1 = SingletonInt1();
|
| + singleton_int = SingletonInt();
|
| }
|
| // Ensure POD type initialization.
|
| - EXPECT_EQ(*singleton_int_1, 0);
|
| - *singleton_int_1 = 1;
|
| -
|
| - EXPECT_EQ(singleton_int_1, SingletonInt1());
|
| - EXPECT_EQ(*singleton_int_1, 1);
|
| -
|
| - {
|
| - singleton_int_2 = SingletonInt2();
|
| - }
|
| - // Same instance that 1.
|
| - EXPECT_EQ(*singleton_int_2, 1);
|
| - EXPECT_EQ(singleton_int_1, singleton_int_2);
|
| + EXPECT_EQ(*singleton_int, 0);
|
| + *singleton_int = 1;
|
|
|
| - {
|
| - singleton_int_3 = SingletonInt3();
|
| - }
|
| - // Different instance than 1 and 2.
|
| - EXPECT_EQ(*singleton_int_3, 0);
|
| - EXPECT_NE(singleton_int_1, singleton_int_3);
|
| - *singleton_int_3 = 3;
|
| - EXPECT_EQ(*singleton_int_1, 1);
|
| - EXPECT_EQ(*singleton_int_2, 1);
|
| -
|
| - {
|
| - singleton_int_4 = SingletonInt4();
|
| - }
|
| - // Use a lock for creation. Not really tested at length.
|
| - EXPECT_EQ(*singleton_int_4, 0);
|
| - *singleton_int_4 = 4;
|
| - EXPECT_NE(singleton_int_1, singleton_int_4);
|
| - EXPECT_NE(singleton_int_3, singleton_int_4);
|
| + EXPECT_EQ(singleton_int, SingletonInt());
|
| + EXPECT_EQ(*singleton_int, 1);
|
|
|
| {
|
| singleton_int_5 = SingletonInt5();
|
| }
|
| // Is default initialized to 5.
|
| EXPECT_EQ(*singleton_int_5, 5);
|
| - EXPECT_NE(singleton_int_1, singleton_int_5);
|
| - EXPECT_NE(singleton_int_3, singleton_int_5);
|
| - EXPECT_NE(singleton_int_4, singleton_int_5);
|
|
|
| SingletonNoLeak(&CallbackNoLeak);
|
| SingletonLeak(&CallbackLeak);
|
| @@ -216,7 +228,7 @@ TEST_F(SingletonTest, Basic) {
|
| VerifiesCallbacks();
|
| // Delete the leaky singleton. It is interesting to note that Purify does
|
| // *not* detect the leak when this call is commented out. :(
|
| - DefaultSingletonTraits<CallbackFunc>::Delete(leaky_singleton);
|
| + DeleteLeakySingleton();
|
|
|
| // The static singleton can't be acquired post-atexit.
|
| EXPECT_EQ(NULL, GetStaticSingleton());
|
| @@ -225,8 +237,8 @@ TEST_F(SingletonTest, Basic) {
|
| base::ShadowingAtExitManager sem;
|
| // Verifiy that the variables were reset.
|
| {
|
| - singleton_int_1 = SingletonInt1();
|
| - EXPECT_EQ(*singleton_int_1, 0);
|
| + singleton_int = SingletonInt();
|
| + EXPECT_EQ(*singleton_int, 0);
|
| }
|
| {
|
| singleton_int_5 = SingletonInt5();
|
| @@ -235,7 +247,7 @@ TEST_F(SingletonTest, Basic) {
|
| {
|
| // Resurrect the static singleton, and assert that it
|
| // still points to the same (static) memory.
|
| - StaticMemorySingletonTraits<CallbackFunc>::Resurrect();
|
| + CallbackSingletonWithStaticTrait::Trait::Resurrect();
|
| EXPECT_EQ(GetStaticSingleton(), static_singleton);
|
| }
|
| }
|
|
|