summaryrefslogtreecommitdiffstats
path: root/base/singleton_unittest.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 21:49:38 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 21:49:38 +0000
commitd7cae12696b96500c05dd2d430f6238922c20c96 (patch)
treeecff27b367735535b2a66477f8cd89d3c462a6c0 /base/singleton_unittest.cc
parentee2815e28d408216cf94e874825b6bcf76c69083 (diff)
downloadchromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.zip
chromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.tar.gz
chromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.tar.bz2
Add base to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/singleton_unittest.cc')
-rw-r--r--base/singleton_unittest.cc227
1 files changed, 227 insertions, 0 deletions
diff --git a/base/singleton_unittest.cc b/base/singleton_unittest.cc
new file mode 100644
index 0000000..5d21593
--- /dev/null
+++ b/base/singleton_unittest.cc
@@ -0,0 +1,227 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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/file_util.h"
+#include "base/path_service.h"
+
+class SingletonTest : public testing::Test {
+ public:
+ SingletonTest() {
+ }
+
+ virtual void SetUp() {
+ module_ = NULL;
+ non_leak_called_ = false;
+ leaky_called_ = false;
+ }
+
+ virtual void TearDown() {
+ ASSERT_FALSE(module_);
+ }
+
+ 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);
+ }
+
+ protected:
+ void LoadLibrary() {
+ ASSERT_FALSE(module_);
+ module_ = ::LoadLibrary(kLibrary);
+ ASSERT_TRUE(module_ != NULL);
+ }
+
+ void FreeLibrary() {
+ ASSERT_TRUE(module_ != NULL);
+ ASSERT_TRUE(::FreeLibrary(module_));
+ module_ = NULL;
+ }
+
+ 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);
+ }
+
+ void VerifiesCallbacks() {
+ EXPECT_TRUE(non_leak_called_);
+ EXPECT_FALSE(leaky_called_);
+ non_leak_called_ = false;
+ leaky_called_ = false;
+ }
+
+ void VerifiesCallbacksNotCalled() {
+ EXPECT_FALSE(non_leak_called_);
+ EXPECT_FALSE(leaky_called_);
+ non_leak_called_ = false;
+ leaky_called_ = false;
+ }
+
+ static void WINAPI CallbackNoLeak() {
+ non_leak_called_ = true;
+ }
+
+ static void WINAPI CallbackLeak() {
+ leaky_called_ = true;
+ }
+
+ private:
+ static const wchar_t* const kLibrary;
+ HMODULE module_;
+ static bool non_leak_called_;
+ static bool leaky_called_;
+};
+
+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;
+
+ LoadLibrary();
+ {
+ SingletonIntFunc sut1;
+ SingletonIntFunc sut2;
+ SingletonIntFunc sut3;
+ SingletonIntFunc sut4;
+ SingletonIntFunc sut5;
+ {
+ GetProc("SingletonInt1", &sut1);
+ singleton_int_1 = sut1();
+ }
+ // 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, 1);
+
+ {
+ GetProc("SingletonInt2", &sut2);
+ singleton_int_2 = sut2();
+ }
+ // 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();
+ }
+ // 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);
+
+ {
+ GetProc("SingletonInt4", &sut4);
+ singleton_int_4 = sut4();
+ }
+ // 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);
+
+ {
+ GetProc("SingletonInt5", &sut5);
+ singleton_int_5 = sut5();
+ }
+ // 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();
+ 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));
+
+ LoadLibrary();
+ {
+ // Verifiy that the variables were reset.
+ {
+ SingletonIntFunc sut1;
+ GetProc("SingletonInt1", &sut1);
+ singleton_int_1 = sut1();
+ EXPECT_EQ(*singleton_int_1, 0);
+ }
+ {
+ SingletonIntFunc sut5;
+ GetProc("SingletonInt5", &sut5);
+ singleton_int_5 = sut5();
+ EXPECT_EQ(*singleton_int_5, 5);
+ }
+ }
+ // The leaky singleton shouldn't leak since SingletonLeak has not been called.
+ FreeLibrary();
+
+ VerifiesCallbacksNotCalled();
+}