diff options
author | deanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-11 14:02:06 +0000 |
---|---|---|
committer | deanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-11 14:02:06 +0000 |
commit | 4ac8f670af190931c88542ae57295da97e2971ce (patch) | |
tree | c53779e5876223856392e291d340c20088ab339e /base/singleton_unittest.cc | |
parent | 663fe3c5c9327b3b604fe7f2c7fd3f4d5cccc4e4 (diff) | |
download | chromium_src-4ac8f670af190931c88542ae57295da97e2971ce.zip chromium_src-4ac8f670af190931c88542ae57295da97e2971ce.tar.gz chromium_src-4ac8f670af190931c88542ae57295da97e2971ce.tar.bz2 |
Allow multiple AtExitManagers to be chained in a stack, this allows much easier testing for code that is expecting to be run via an AtExitManager. This actually cleaned up a lot of the at exit code.
Clean up singleton_dll_unittest. It is no longer windows specific DLL, and now is much simpler, and builds and runs cross platform.
BUG=1314043
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@646 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/singleton_unittest.cc')
-rw-r--r-- | base/singleton_unittest.cc | 187 |
1 files changed, 97 insertions, 90 deletions
diff --git a/base/singleton_unittest.cc b/base/singleton_unittest.cc index 5d21593..167fa78 100644 --- a/base/singleton_unittest.cc +++ b/base/singleton_unittest.cc @@ -27,54 +27,99 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "testing/gtest/include/gtest/gtest.h" -#include "base/singleton_dll_unittest.h" +#include "base/at_exit.h" #include "base/file_util.h" #include "base/path_service.h" +#include "base/singleton.h" +#include "testing/gtest/include/gtest/gtest.h" -class SingletonTest : public testing::Test { +namespace { + +class ShadowingAtExitManager : public base::AtExitManager { public: - SingletonTest() { - } + ShadowingAtExitManager() : AtExitManager(true) { } +}; - virtual void SetUp() { - module_ = NULL; - non_leak_called_ = false; - leaky_called_ = false; - } +COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a); - virtual void TearDown() { - ASSERT_FALSE(module_); - } +template<typename Type> +struct LockTrait : public DefaultSingletonTraits<Type> { +}; - static bool IsTestCaseDisabled() { - // Check if the dll exists beside the executable. - std::wstring path; - PathService::Get(base::DIR_EXE, &path); - file_util::AppendToPath(&path, kLibrary); - return !file_util::PathExists(path); +struct Init5Trait : public DefaultSingletonTraits<int> { + static int* New() { + return new int(5); } +}; - protected: - void LoadLibrary() { - ASSERT_FALSE(module_); - module_ = ::LoadLibrary(kLibrary); - ASSERT_TRUE(module_ != NULL); - } +typedef void (*CallbackFunc)(); - void FreeLibrary() { - ASSERT_TRUE(module_ != NULL); - ASSERT_TRUE(::FreeLibrary(module_)); - module_ = NULL; +struct CallbackTrait : public DefaultSingletonTraits<CallbackFunc> { + static void Delete(CallbackFunc* p) { + if (*p) + (*p)(); + DefaultSingletonTraits<CallbackFunc>::Delete(p); } +}; + +struct NoLeakTrait : public CallbackTrait { +}; + +struct LeakTrait : public CallbackTrait { + static const bool kRegisterAtExit = false; +}; + +int* SingletonInt1() { + return Singleton<int>::get(); +} + +int* SingletonInt2() { + // Force to use a different singleton than SingletonInt1. + return Singleton<int, DefaultSingletonTraits<int> >::get(); +} + +class DummyDifferentiatingClass { +}; + +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(); +} + +int* SingletonInt4() { + return Singleton<int, LockTrait<int> >::get(); +} + +int* SingletonInt5() { + return Singleton<int, Init5Trait>::get(); +} + +void SingletonNoLeak(CallbackFunc CallOnQuit) { + *Singleton<CallbackFunc, NoLeakTrait>::get() = CallOnQuit; +} + +void SingletonLeak(CallbackFunc CallOnQuit) { + *Singleton<CallbackFunc, LeakTrait>::get() = CallOnQuit; +} + +CallbackFunc* GetLeakySingleton() { + return Singleton<CallbackFunc, LeakTrait>::get(); +} - template<typename T> - void GetProc(const char* function_name, T* function) { - ASSERT_TRUE(module_ != NULL); - *function = reinterpret_cast<T>(GetProcAddress(module_, function_name)); - ASSERT_TRUE(*function); +} // namespace + +class SingletonTest : public testing::Test { + public: + SingletonTest() { } + + virtual void SetUp() { + non_leak_called_ = false; + leaky_called_ = false; } + protected: void VerifiesCallbacks() { EXPECT_TRUE(non_leak_called_); EXPECT_FALSE(leaky_called_); @@ -89,17 +134,15 @@ class SingletonTest : public testing::Test { leaky_called_ = false; } - static void WINAPI CallbackNoLeak() { + static void CallbackNoLeak() { non_leak_called_ = true; } - static void WINAPI CallbackLeak() { + static void CallbackLeak() { leaky_called_ = true; } private: - static const wchar_t* const kLibrary; - HMODULE module_; static bool non_leak_called_; static bool leaky_called_; }; @@ -107,48 +150,35 @@ class SingletonTest : public testing::Test { bool SingletonTest::non_leak_called_ = false; bool SingletonTest::leaky_called_ = false; -const wchar_t* const SingletonTest::kLibrary = L"singleton_dll_unittest.dll"; - TEST_F(SingletonTest, Basic) { - if (IsTestCaseDisabled()) - return; - int* singleton_int_1; int* singleton_int_2; int* singleton_int_3; int* singleton_int_4; int* singleton_int_5; - CallBackFunc* leaky_singleton; + CallbackFunc* leaky_singleton; - LoadLibrary(); { - SingletonIntFunc sut1; - SingletonIntFunc sut2; - SingletonIntFunc sut3; - SingletonIntFunc sut4; - SingletonIntFunc sut5; + ShadowingAtExitManager sem; { - GetProc("SingletonInt1", &sut1); - singleton_int_1 = sut1(); + singleton_int_1 = SingletonInt1(); } // Ensure POD type initialization. EXPECT_EQ(*singleton_int_1, 0); *singleton_int_1 = 1; - EXPECT_EQ(singleton_int_1, sut1()); + EXPECT_EQ(singleton_int_1, SingletonInt1()); EXPECT_EQ(*singleton_int_1, 1); { - GetProc("SingletonInt2", &sut2); - singleton_int_2 = sut2(); + singleton_int_2 = SingletonInt2(); } // Same instance that 1. EXPECT_EQ(*singleton_int_2, 1); EXPECT_EQ(singleton_int_1, singleton_int_2); { - GetProc("SingletonInt3", &sut3); - singleton_int_3 = sut3(); + singleton_int_3 = SingletonInt3(); } // Different instance than 1 and 2. EXPECT_EQ(*singleton_int_3, 0); @@ -158,8 +188,7 @@ TEST_F(SingletonTest, Basic) { EXPECT_EQ(*singleton_int_2, 1); { - GetProc("SingletonInt4", &sut4); - singleton_int_4 = sut4(); + singleton_int_4 = SingletonInt4(); } // Use a lock for creation. Not really tested at length. EXPECT_EQ(*singleton_int_4, 0); @@ -168,60 +197,38 @@ TEST_F(SingletonTest, Basic) { EXPECT_NE(singleton_int_3, singleton_int_4); { - GetProc("SingletonInt5", &sut5); - singleton_int_5 = sut5(); + 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); -#ifdef _DEBUG - // In release, the optimizer may make both exports use exactly the same - // code. - EXPECT_NE(sut1, sut2); -#endif - EXPECT_NE(sut2, sut3); - EXPECT_NE(sut3, sut4); - EXPECT_NE(sut4, sut5); - - LeakySingletonFunc noleak; - GetProc("SingletonNoLeak", &noleak); - noleak(&CallbackNoLeak); - LeakySingletonFunc leak; - GetProc("SingletonLeak", &leak); - leak(&CallbackLeak); - GetLeakySingletonFunc get_leaky; - GetProc("GetLeakySingleton", &get_leaky); - leaky_singleton = get_leaky(); + + SingletonNoLeak(&CallbackNoLeak); + SingletonLeak(&CallbackLeak); + leaky_singleton = GetLeakySingleton(); EXPECT_TRUE(leaky_singleton); } - FreeLibrary(); // 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. :( - EXPECT_TRUE(CustomAllocTrait<CallBackFunc>::Delete(leaky_singleton)); + DefaultSingletonTraits<CallbackFunc>::Delete(leaky_singleton); - LoadLibrary(); { + ShadowingAtExitManager sem; // Verifiy that the variables were reset. { - SingletonIntFunc sut1; - GetProc("SingletonInt1", &sut1); - singleton_int_1 = sut1(); + singleton_int_1 = SingletonInt1(); EXPECT_EQ(*singleton_int_1, 0); } { - SingletonIntFunc sut5; - GetProc("SingletonInt5", &sut5); - singleton_int_5 = sut5(); + singleton_int_5 = SingletonInt5(); EXPECT_EQ(*singleton_int_5, 5); } } // The leaky singleton shouldn't leak since SingletonLeak has not been called. - FreeLibrary(); - VerifiesCallbacksNotCalled(); } |