/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * SingletonUnitTest.cpp * * Created on: Mar 11, 2010 * Author: crueger */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "SingletonUnitTest.hpp" #include #include #include #include #include "CodePatterns/Singleton.hpp" #include "CodePatterns/Singleton_impl.hpp" #ifdef HAVE_TESTRUNNER #include "UnitTestMain.hpp" #endif /*HAVE_TESTRUNNER*/ CPPUNIT_TEST_SUITE_REGISTRATION( SingletonTest ); // some necessary stubs class SingletonStub1 : public Singleton { friend class Singleton; private: SingletonStub1(){ count1++; } // explicit copy constructor to catch if this is ever called SingletonStub1(const SingletonStub1&){ CPPUNIT_FAIL ( "Copy constructor of Singleton called" ); } virtual ~SingletonStub1(){ count2++; } public: static int count1; static int count2; }; int SingletonStub1::count1 = 0; int SingletonStub1::count2 = 0; CONSTRUCT_SINGLETON(SingletonStub1); class SingletonStub2 : public Singleton{ friend class Singleton; private: SingletonStub2(){ count1++; } // explicit copy constructor to catch if this is ever called SingletonStub2(const SingletonStub2&){ CPPUNIT_FAIL ( "Copy constructor of Singleton called" ); } virtual ~SingletonStub2(){ count2++; } public: static int count1; static int count2; }; int SingletonStub2::count1 = 0; int SingletonStub2::count2 = 0; CONSTRUCT_SINGLETON(SingletonStub2); void SingletonTest::setUp() { ASSERT_DO(Assert::Throw); } void SingletonTest::tearDown(){} void SingletonTest::ConstructionTest(){ void *ptr_1_1 = reinterpret_cast(SingletonStub1::getPointer()); void *ptr_1_2 = reinterpret_cast(SingletonStub1::getPointer()); void *ptr_1_3 = reinterpret_cast(&(SingletonStub1::getInstance())); // test if we always get the same instance of our singleton CPPUNIT_ASSERT_EQUAL(ptr_1_1,ptr_1_2); CPPUNIT_ASSERT_EQUAL(ptr_1_1,ptr_1_3); void *ptr_2_1 = reinterpret_cast(SingletonStub2::getPointer()); void *ptr_2_2 = reinterpret_cast(SingletonStub2::getPointer()); void *ptr_2_3 = reinterpret_cast(&(SingletonStub2::getInstance())); // same as above but for a different singleton CPPUNIT_ASSERT_EQUAL(ptr_2_1,ptr_2_2); CPPUNIT_ASSERT_EQUAL(ptr_2_1,ptr_2_3); // see if the two singletons actually differ CPPUNIT_ASSERT(ptr_1_1!=ptr_2_1); // see if each constructor was called exactly once CPPUNIT_ASSERT_EQUAL(1,SingletonStub1::count1); CPPUNIT_ASSERT_EQUAL(1,SingletonStub2::count1); // no calls to the destructor should have occured so far CPPUNIT_ASSERT_EQUAL(0,SingletonStub1::count2); CPPUNIT_ASSERT_EQUAL(0,SingletonStub2::count2); SingletonStub1::purgeInstance(); void *ptr_3_1 = reinterpret_cast(SingletonStub1::getPointer()); void *ptr_3_2 = reinterpret_cast(SingletonStub1::getPointer()); // now the constructor should have been called twice CPPUNIT_ASSERT_EQUAL(2,SingletonStub1::count1); // the destructor should have been called once CPPUNIT_ASSERT_EQUAL(1,SingletonStub1::count2); // see if the singleton Assumption holds CPPUNIT_ASSERT_EQUAL(ptr_3_1,ptr_3_2); // Some esoteric thing might cause our pointer to lay at the position of Singleton2 now // See that those two objects still differ CPPUNIT_ASSERT(ptr_3_1!=ptr_2_1); // don't test for pointer difference between first and second singleton here, // because they might be constructed in the same place SingletonStub2::resetInstance(); // now the constructor should have been called twice CPPUNIT_ASSERT_EQUAL(2,SingletonStub2::count1); // the destructor should have been called once CPPUNIT_ASSERT_EQUAL(1,SingletonStub2::count2); void *ptr_4_1 = reinterpret_cast(SingletonStub2::getPointer()); void *ptr_4_2 = reinterpret_cast(SingletonStub2::getPointer()); // Still only two calls to the constructor, one call to destructor CPPUNIT_ASSERT_EQUAL(2,SingletonStub2::count1); CPPUNIT_ASSERT_EQUAL(1,SingletonStub2::count2); // test if Singleton assumption can be broken by reset CPPUNIT_ASSERT_EQUAL(ptr_4_1,ptr_4_2); // and again test if we actually have a object seperate from anything else CPPUNIT_ASSERT(ptr_4_1!=ptr_3_1); // we don't purge our singletons here. Purging should be done automatically by the Singleton // mechanism. Check with Valgrind to see if memory-leak occurs std::cout << "Not purging Singleton!\n Check with Valgrind to see if automatic purgins is working!" << std::endl; } void SingletonTest::LockedTest(){ const AtomicInstance ptr_1_1(SingletonStub1::getLockedInstance()); const SingletonStub1 &test_1 = *ptr_1_1; // this deadlocks // AtomicInstance ptr_1_2(SingletonStub1::getLockedInstance()); AtomicInstance ptr_2_1(SingletonStub2::getLockedInstance()); SingletonStub2 &test_2 = *ptr_2_1; // this deadlocks // AtomicInstance ptr_2_2(SingletonStub2::getLockedInstance()); }