summaryrefslogtreecommitdiffstats
path: root/base/singleton_unittest.cc
diff options
context:
space:
mode:
authordeanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-11 14:02:06 +0000
committerdeanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-11 14:02:06 +0000
commit4ac8f670af190931c88542ae57295da97e2971ce (patch)
treec53779e5876223856392e291d340c20088ab339e /base/singleton_unittest.cc
parent663fe3c5c9327b3b604fe7f2c7fd3f4d5cccc4e4 (diff)
downloadchromium_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.cc187
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();
}