diff options
author | levin@chromium.org <levin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-28 01:54:15 +0000 |
---|---|---|
committer | levin@chromium.org <levin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-28 01:54:15 +0000 |
commit | 3b63f8f451afcf414a59c529f627c620e4d449d9 (patch) | |
tree | 2dcbab1c060b29a260c29bb19b67bf97a8293ca3 /base/memory/singleton_unittest.cc | |
parent | 9174a108509c2aafe513da68e6e63fbc7df38c85 (diff) | |
download | chromium_src-3b63f8f451afcf414a59c529f627c620e4d449d9.zip chromium_src-3b63f8f451afcf414a59c529f627c620e4d449d9.tar.gz chromium_src-3b63f8f451afcf414a59c529f627c620e4d449d9.tar.bz2 |
Move some files from base to base/memory.
raw_scoped_refptr_mismatch_checker.h
ref_counted.cc
ref_counted.h
ref_counted_memory.cc
ref_counted_memory.h
ref_counted_unittest.cc
scoped_callback_factory.h
scoped_comptr_win.h
scoped_handle.h
scoped_native_library.cc
scoped_native_library.h
scoped_native_library_unittest.cc
scoped_nsobject.h
scoped_open_process.h
scoped_ptr.h
scoped_ptr_unittest.cc
scoped_temp_dir.cc
scoped_temp_dir.h
scoped_temp_dir_unittest.cc
scoped_vector.h
singleton.h
singleton_objc.h
singleton_unittest.cc
linked_ptr.h
linked_ptr_unittest.cc
weak_ptr.cc
weak_ptr.h
weak_ptr_unittest.cc
BUG=None
TEST=Compile
Review URL: http://codereview.chromium.org/6714032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79524 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/memory/singleton_unittest.cc')
-rw-r--r-- | base/memory/singleton_unittest.cc | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/base/memory/singleton_unittest.cc b/base/memory/singleton_unittest.cc new file mode 100644 index 0000000..a605885 --- /dev/null +++ b/base/memory/singleton_unittest.cc @@ -0,0 +1,256 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/at_exit.h" +#include "base/file_util.h" +#include "base/memory/singleton.h" +#include "base/path_service.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a); + +typedef void (*CallbackFunc)(); + +class IntSingleton { + public: + static IntSingleton* GetInstance() { + return Singleton<IntSingleton>::get(); + } + + int value_; +}; + +class Init5Singleton { + public: + struct Trait; + + static Init5Singleton* GetInstance() { + return Singleton<Init5Singleton, Trait>::get(); + } + + int value_; +}; + +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_; +} + +template <typename Type> +struct CallbackTrait : public DefaultSingletonTraits<Type> { + static void Delete(Type* instance) { + if (instance->callback_) + (instance->callback_)(); + DefaultSingletonTraits<Type>::Delete(instance); + } +}; + +class CallbackSingleton { + public: + CallbackSingleton() : callback_(NULL) { } + CallbackFunc callback_; +}; + +class CallbackSingletonWithNoLeakTrait : public CallbackSingleton { + public: + struct Trait : public CallbackTrait<CallbackSingletonWithNoLeakTrait> { }; + + CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { } + + static CallbackSingletonWithNoLeakTrait* GetInstance() { + return Singleton<CallbackSingletonWithNoLeakTrait, Trait>::get(); + } +}; + +class CallbackSingletonWithLeakTrait : public CallbackSingleton { + public: + struct Trait : public CallbackTrait<CallbackSingletonWithLeakTrait> { + static const bool kRegisterAtExit = false; + }; + + 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); + } +}; + + +void SingletonNoLeak(CallbackFunc CallOnQuit) { + CallbackSingletonWithNoLeakTrait::GetInstance()->callback_ = CallOnQuit; +} + +void SingletonLeak(CallbackFunc CallOnQuit) { + CallbackSingletonWithLeakTrait::GetInstance()->callback_ = CallOnQuit; +} + +CallbackFunc* GetLeakySingleton() { + return &CallbackSingletonWithLeakTrait::GetInstance()->callback_; +} + +void DeleteLeakySingleton() { + DefaultSingletonTraits<CallbackSingletonWithLeakTrait>::Delete( + CallbackSingletonWithLeakTrait::GetInstance()); +} + +void SingletonStatic(CallbackFunc CallOnQuit) { + CallbackSingletonWithStaticTrait::GetInstance()->callback_ = CallOnQuit; +} + +CallbackFunc* GetStaticSingleton() { + return &CallbackSingletonWithStaticTrait::GetInstance()->callback_; +} + +void ResurrectStaticSingleton() { +} + +} // namespace + +class SingletonTest : public testing::Test { + public: + SingletonTest() { } + + virtual void SetUp() { + non_leak_called_ = false; + leaky_called_ = false; + static_called_ = false; + } + + protected: + void VerifiesCallbacks() { + EXPECT_TRUE(non_leak_called_); + EXPECT_FALSE(leaky_called_); + EXPECT_TRUE(static_called_); + non_leak_called_ = false; + leaky_called_ = false; + static_called_ = false; + } + + void VerifiesCallbacksNotCalled() { + EXPECT_FALSE(non_leak_called_); + EXPECT_FALSE(leaky_called_); + EXPECT_FALSE(static_called_); + non_leak_called_ = false; + leaky_called_ = false; + static_called_ = false; + } + + static void CallbackNoLeak() { + non_leak_called_ = true; + } + + static void CallbackLeak() { + leaky_called_ = true; + } + + static void CallbackStatic() { + static_called_ = true; + } + + private: + static bool non_leak_called_; + static bool leaky_called_; + static bool static_called_; +}; + +bool SingletonTest::non_leak_called_ = false; +bool SingletonTest::leaky_called_ = false; +bool SingletonTest::static_called_ = false; + +TEST_F(SingletonTest, Basic) { + int* singleton_int; + int* singleton_int_5; + CallbackFunc* leaky_singleton; + CallbackFunc* static_singleton; + + { + base::ShadowingAtExitManager sem; + { + singleton_int = SingletonInt(); + } + // Ensure POD type initialization. + EXPECT_EQ(*singleton_int, 0); + *singleton_int = 1; + + 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); + + SingletonNoLeak(&CallbackNoLeak); + SingletonLeak(&CallbackLeak); + SingletonStatic(&CallbackStatic); + static_singleton = GetStaticSingleton(); + leaky_singleton = GetLeakySingleton(); + EXPECT_TRUE(leaky_singleton); + } + + // Verify that only the expected callback has been called. + VerifiesCallbacks(); + // Delete the leaky singleton. It is interesting to note that Purify does + // *not* detect the leak when this call is commented out. :( + DeleteLeakySingleton(); + + // The static singleton can't be acquired post-atexit. + EXPECT_EQ(NULL, GetStaticSingleton()); + + { + base::ShadowingAtExitManager sem; + // Verifiy that the variables were reset. + { + singleton_int = SingletonInt(); + EXPECT_EQ(*singleton_int, 0); + } + { + singleton_int_5 = SingletonInt5(); + EXPECT_EQ(*singleton_int_5, 5); + } + { + // Resurrect the static singleton, and assert that it + // still points to the same (static) memory. + CallbackSingletonWithStaticTrait::Trait::Resurrect(); + EXPECT_EQ(GetStaticSingleton(), static_singleton); + } + } + // The leaky singleton shouldn't leak since SingletonLeak has not been called. + VerifiesCallbacksNotCalled(); +} |