diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index ac6ba0b..f501db5 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -4,7 +4,7 @@ project (CPP_UTILS_LIB) set(CMAKE_CXX_COMPILER "/usr/lib/colorgcc/bin/g++") set (CXX_FLAGS "-Wall -Wextra -pedantic -Weffc++ -Wshadow " - "-ggdb -fprofile-arcs -ftest-coverage") + "-ggdb -fprofile-arcs -ftest-coverage -std=c++0x") add_definitions( ${CXX_FLAGS} ) include_directories (../include) diff --git a/include/ConcurrentDeque.hpp b/include/ConcurrentDeque.hpp new file mode 100644 index 0000000..a5908f7 --- /dev/null +++ b/include/ConcurrentDeque.hpp @@ -0,0 +1,134 @@ +#ifndef CONCURRENTQUEUE_HPP +#define CONCURRENTQUEUE_HPP + +#include +#include +#include + +#include "Mutex.hpp" +#include "ConditionVariable.hpp" +#include "ScopedLock.hpp" +#include "Common.hpp" + + + +class CancelledException {}; + + +template +class ConcurrentDeque +{ +public: + + ConcurrentDeque() + : m_queue() + , m_cancelled(false) + , m_mutex() + , m_condVar(m_mutex) + { + TRACE; + } + + ~ConcurrentDeque() + { + TRACE; + freeDeque(); + } + + + void push(const T value) + { + TRACE; + ScopedLock sl(m_mutex); + if (m_cancelled) throw CancelledException(); + m_queue.push_back( value ); + m_condVar.signal(); + } + + + bool tryPop(T &popped_value) + { + TRACE; + ScopedLock sl(m_mutex); + if (m_cancelled) throw CancelledException(); + if ( m_queue.empty() ) return false; + + popped_value = m_queue.front(); + m_queue.pop_front(); + return true; + } + + + T waitAndPop() + { + TRACE; + ScopedLock sl(m_mutex); + + while ( m_queue.empty() and not m_cancelled) { + m_condVar.wait(); + } + if (m_cancelled) throw CancelledException(); + + T retVal = m_queue.front(); // cctor + m_queue.pop_front(); + return retVal; + } + + + bool empty() const + { + TRACE; + ScopedLock sl(m_mutex); + if (m_cancelled) throw CancelledException(); + return m_queue.empty(); + } + + void cancel() + { + TRACE; + ScopedLock sl(m_mutex); + m_cancelled = true; + m_condVar.broadcast(); + freeDeque(); + } + + template + typename std::enable_if< std::is_pointer::value >::type + freeDeque() + { + TRACE; + typename std::deque::iterator it; + for ( it = m_queue.begin(); it != m_queue.end(); ++it ) + delete *it; + + m_queue.clear(); + } + + template + typename std::enable_if< !(std::is_pointer::value) >::type + freeDeque() + { + TRACE; + m_queue.clear(); + } + + bool cancelled() + { + TRACE; + return m_cancelled; + } + +private: + + + ConcurrentDeque& operator=( const ConcurrentDeque& ); + ConcurrentDeque( const ConcurrentDeque& ); + + std::deque m_queue; + bool m_cancelled; + mutable Mutex m_mutex; + ConditionVariable m_condVar; + +}; + +#endif // CONCURRENTQUEUE_HPP diff --git a/include/ConcurrentQueue.hpp b/include/ConcurrentQueue.hpp deleted file mode 100644 index 437cbc7..0000000 --- a/include/ConcurrentQueue.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef CONCURRENTQUEUE_HPP -#define CONCURRENTQUEUE_HPP - -#include - -#include "Mutex.hpp" -#include "ConditionVariable.hpp" -#include "ScopedLock.hpp" -#include "Common.hpp" - - - -class CancelledException {}; - - -template -class ConcurrentQueue { - - public: - - - ConcurrentQueue() - : m_queue() - , m_cancelled(false) - , m_mutex() - , m_condVar(m_mutex) - { - TRACE; - } - - ~ConcurrentQueue() - { - TRACE; - } - - - void push(const T task) - { - TRACE; - ScopedLock sl(m_mutex); - if (m_cancelled) throw CancelledException(); - m_queue.push( task ); - m_condVar.signal(); - } - - - bool tryPop(T &popped_value) - { - TRACE; - ScopedLock sl(m_mutex); - if (m_cancelled) throw CancelledException(); - if ( m_queue.empty() ) return false; - - popped_value = m_queue.front(); - m_queue.pop(); - return true; - } - - - T waitAndPop() - { - TRACE; - ScopedLock sl(m_mutex); - - while ( m_queue.empty() and not m_cancelled) { - m_condVar.wait(); - } - if (m_cancelled) throw CancelledException(); - - T retVal = m_queue.front(); // cctor - m_queue.pop(); - return retVal; - } - - - bool empty() const - { - TRACE; - ScopedLock sl(m_mutex); - if (m_cancelled) throw CancelledException(); - return m_queue.empty(); - } - - - void cancel() - { - TRACE; - ScopedLock sl(m_mutex); - m_cancelled = true; - m_condVar.broadcast(); - } - - private: - - ConcurrentQueue& operator=( const ConcurrentQueue& ); - ConcurrentQueue( const ConcurrentQueue& ); - - std::queue m_queue; - bool m_cancelled; - mutable Mutex m_mutex; - ConditionVariable m_condVar; - -}; - -#endif // CONCURRENTQUEUE_HPP diff --git a/include/MysqlConnectionPool.hpp b/include/MysqlConnectionPool.hpp new file mode 100644 index 0000000..668b6ac --- /dev/null +++ b/include/MysqlConnectionPool.hpp @@ -0,0 +1,35 @@ +#ifndef MYSQL_CONNECTION_POOL_HPP +#define MYSQL_CONNECTION_POOL_HPP + +#include "ObjectPool.hpp" +#include "MysqlClient.hpp" + + +class MysqlConnectionPool : public ObjectPool +{ +public: + + MysqlConnectionPool( const char *host = NULL, + const char *user = NULL, + const char *passwd = NULL, + const char *db = NULL ); + ~MysqlConnectionPool(); + + void create(); + + void clear(); + +private: + + MysqlConnectionPool(const MysqlConnectionPool&); + MysqlConnectionPool& operator=(const MysqlConnectionPool&); + + const char *m_host; + const char *m_user; + const char *m_passwd; + const char *m_db; + +}; + + +#endif // MYSQL_CONNECTION_POOL_HPP diff --git a/include/ObjectPool.hpp b/include/ObjectPool.hpp new file mode 100644 index 0000000..1fb092a --- /dev/null +++ b/include/ObjectPool.hpp @@ -0,0 +1,81 @@ +#ifndef OBJECT_POOL_HPP +#define OBJECT_POOL_HPP + +#include "ConcurrentDeque.hpp" +#include "Logger.hpp" + +template +class ObjectPool +{ +public: + + ObjectPool() + : m_pool() + , m_numberOfUsedObjects(0) + { + TRACE; + } + + virtual ~ObjectPool() + { + TRACE; + } + + void add(const T object) // throws CancelledException + { + TRACE; + m_pool.push(object); + } + + + T acquire() // throws CancelledException + { + TRACE; + T tmp = m_pool.waitAndPop(); + m_numberOfUsedObjects++; + return tmp; + } + + template + typename std::enable_if< std::is_pointer::value >::type + release(T object) + { + TRACE; + if ( m_pool.cancelled() ) { + m_numberOfUsedObjects--; + delete object; + return; + } + + m_pool.push(object); + m_numberOfUsedObjects--; + } + + template + typename std::enable_if< !(std::is_pointer::value) >::type + release(T object) + { + TRACE; + if ( m_pool.cancelled() ) { + m_numberOfUsedObjects--; + return; + } + + m_pool.push(object); + m_numberOfUsedObjects--; + } + + void clear() + { + TRACE; + m_pool.cancel(); + } + + +private: + + ConcurrentDeque m_pool; + int m_numberOfUsedObjects; +}; + +#endif // OBJECT_POOL_HPP diff --git a/include/Singleton_DCLP.hpp b/include/Singleton_DCLP.hpp index 07ead7f..55da169 100644 --- a/include/Singleton_DCLP.hpp +++ b/include/Singleton_DCLP.hpp @@ -39,6 +39,11 @@ public: return m_instance; } + static void destroy() + { + delete m_instance; + } + private: diff --git a/include/Singleton_call_once.hpp b/include/Singleton_call_once.hpp index 117a913..3d8de36 100644 --- a/include/Singleton_call_once.hpp +++ b/include/Singleton_call_once.hpp @@ -24,6 +24,11 @@ public: return m_instance; } + static void destroy() + { + delete m_instance; + } + private: static void do_init() diff --git a/include/Thread.hpp b/include/Thread.hpp index bb9957b..592d212 100644 --- a/include/Thread.hpp +++ b/include/Thread.hpp @@ -17,17 +17,15 @@ public: void sendSignal( const int nSignal ) const; bool isRunning() const; -private: - - virtual void* run() = 0; - static void* threadStarter( void* pData ); - protected: bool m_isRunning; private: + virtual void* run() = 0; + static void* threadStarter( void* pData ); + pthread_t m_threadHandler; }; diff --git a/include/ThreadPool.hpp b/include/ThreadPool.hpp index f88ac26..300b117 100644 --- a/include/ThreadPool.hpp +++ b/include/ThreadPool.hpp @@ -3,7 +3,7 @@ #include -#include "ConcurrentQueue.hpp" +#include "ConcurrentDeque.hpp" #include "Task.hpp" #include "Thread.hpp" #include "Mutex.hpp" @@ -32,7 +32,7 @@ class ThreadPool ThreadPool& operator=( const ThreadPool& ); std::vector m_threads; - ConcurrentQueue m_tasks; + ConcurrentDeque m_tasks; }; diff --git a/other/mysqlclient_main.cpp b/other/mysqlclient_main.cpp index 49d4445..dae693b 100644 --- a/other/mysqlclient_main.cpp +++ b/other/mysqlclient_main.cpp @@ -1,12 +1,13 @@ -// gpp mysqlclient_main.cpp ../src/Logger.cpp ../src/MysqlClient.cpp ../src/ArgParse.cpp -I../include -lmysqlclient -o mysqlclient +// g++ mysqlclient_main.cpp src/Logger.cpp src/MysqlClient.cpp src/ArgParse.cpp -I./include -lmysqlclient -// ./mysqlclient -u USER -db MYSQL_DB -p PASS #include "Logger.hpp" #include "Common.hpp" #include "ArgParse.hpp" #include "MysqlClient.hpp" +#include "MysqlConnectionPool.hpp" + #include #include @@ -20,33 +21,24 @@ void setUpArgs(ArgParse &argParse) argParse.addArgument("--host", "Hostname/IP", - ArgParse::STRING ); + ArgParse::STRING, + ArgParse::REQUIRED ); argParse.addArgument("-u, --user", "Username", ArgParse::STRING, - ArgParse::REQUIRED, ArgParse::REQUIRED ); + ArgParse::REQUIRED ); argParse.addArgument("-db, --database", "Database", ArgParse::STRING, - ArgParse::REQUIRED, ArgParse::REQUIRED ); + ArgParse::REQUIRED ); argParse.addArgument("-p, --password", "Password", ArgParse::STRING, - ArgParse::REQUIRED, ArgParse::REQUIRED ); - argParse.addArgument("-port", - "Port", - ArgParse::INT ); - argParse.addArgument("-s, --unix-socket", - "Unix socket", - ArgParse::STRING ); - argParse.addArgument("-f, --client-flags", - "Client flags", - ArgParse::INT ); - argParse.addArgument("-r, --max-reconnect", - "Maximum number of retries if connection is lost. " - "Default is 5.", - ArgParse::INT, ArgParse::REQUIRED ); + + argParse.addArgument("-n, --number-of-connections", + "Number of connections. Default is 5", + ArgParse::INT ); } @@ -56,10 +48,7 @@ void getArgs( int argc, char* argv[], std::string &user, std::string &db, std::string &pass, - std::string &unixsocket, - int &port, - int &clientflags, - int &retry ) + int &numberOfConnections ) { TRACE_STATIC; @@ -69,10 +58,42 @@ void getArgs( int argc, char* argv[], argParse.argAsString("-u, --user", user); argParse.argAsString("-db, --database", db); argParse.argAsString("-p, --password", pass); - argParse.argAsInt("-port", port); - argParse.argAsString("-s, --unix-socket", unixsocket); - argParse.argAsInt("-f, --client-flags", clientflags); - argParse.argAsInt("-r, --max-reconnect", retry); + + argParse.argAsInt("-n, --number-of-connections", numberOfConnections); +} + + +bool checkArgs( int argc, char* argv[], + ArgParse &argParse, + std::string &host, + std::string &user, + std::string &db, + std::string &pass, + int &numberOfConnections ) +{ + TRACE_STATIC; + + try { + getArgs( argc, argv, + argParse, + host, user, db, pass, + numberOfConnections ); + } catch (std::runtime_error e) { + if ( argParse.foundArg("-h, --help") ) { + std::cout << argParse.usage() << std::endl; + return false; + } + std::cerr << e.what() << std::endl + << "Check usage: " << argv[0] << " --help" << std::endl; + return false; + } + + if ( argParse.foundArg("-h, --help") ) { + std::cout << argParse.usage() << std::endl; + return false; + } + + return true; } @@ -97,79 +118,43 @@ int main(int argc, char* argv[] ) Logger::init(std::cout); Logger::setLogLevel(Logger::FINEST); + + // args ArgParse argParse("Simple MySQL client", "Report bugs to: denes.matetelki@gmail.com"); - setUpArgs(argParse); - std::string host, user, db, pass, unixsocket; - int port, clientflags, retry; - - try { - getArgs( argc, argv, - argParse, - host, user, db, pass, unixsocket, - port, clientflags, retry ); - } catch (std::runtime_error e) { - if ( argParse.foundArg("-h, --help") ) { - std::cout << argParse.usage() << std::endl; - return 1; - } - std::cerr << e.what() << std::endl - << "Check usage: " << argv[0] << " --help" << std::endl; - return 1; - } - + std::string host, user, db, pass; + int numberOfConnections(5); - if ( argParse.foundArg("-h, --help") ) { - std::cout << argParse.usage() << std::endl; + if ( !checkArgs(argc, argv, argParse, + host, user, db, pass, numberOfConnections ) ) return 1; - } + // init init_client_errs(); + MysqlConnectionPool cp ( + argParse.foundArg("--host") ? host.c_str() : NULL, + argParse.foundArg("-u, --user") ? user.c_str() : NULL, + argParse.foundArg("-p, --password") ? pass.c_str() : NULL, + argParse.foundArg("-db, --database") ? db .c_str() : NULL ); - MysqlClient mysqlClient ( - argParse.foundArg("--host") ? host.c_str() : NULL, - argParse.foundArg("-u, --user") ? user.c_str() : NULL, - argParse.foundArg("-p, --password") ? pass.c_str() : NULL, - argParse.foundArg("-db, --database") ? db .c_str() : NULL, - argParse.foundArg("-port") ? port : 0, - argParse.foundArg("-s, --unix-socket") ? unixsocket.c_str() : NULL, - argParse.foundArg("-f, --client-flags") ? clientflags : 0, - argParse.foundArg("-r, --max-reconnect") ? retry : 5 ); - - if ( !mysqlClient.connect() && !mysqlClient.reconnect() ) { - finish_client_errs(); - Logger::destroy(); - return 0; - } - - std::string queryMsg("SELECT * FROM seats"); - MYSQL_RES *queryResult; - if ( !mysqlClient.querty(queryMsg.c_str(), queryMsg.length(), &queryResult) ) { - LOG( Logger::ERR, "Could not execute query." ); - if ( !mysqlClient.reconnect() ) { - LOG( Logger::ERR, "Reconnect failed, exiting." ); - finish_client_errs(); - Logger::destroy(); - return 0; - } - - LOG( Logger::ERR, "Trying query again." ); - if ( !mysqlClient.querty(queryMsg.c_str(), queryMsg.length(), &queryResult) ) { - LOG( Logger::ERR, "Query failed again, exiting." ); - finish_client_errs(); - Logger::destroy(); - return 0; - } - } + for ( int i = 0; i < numberOfConnections; ++i ) + cp.create(); + // work std::list results; - MysqlClient::queryResultToStringList(queryResult, results); - printResults(results); + MysqlClient *c = cp.acquire(); + if ( !c->querty("SELECT * FROM seats", results) ) { + LOG ( Logger::ERR, "Could not execute query." ); + } else { + printResults(results); + } + cp.release(c); - mysql_free_result(queryResult); + // end + cp.clear(); finish_client_errs(); Logger::destroy(); return 0; diff --git a/test/test_TimerThreadMultimap.hpp b/other/test_TimerThreadMultimap.hpp similarity index 100% rename from test/test_TimerThreadMultimap.hpp rename to other/test_TimerThreadMultimap.hpp diff --git a/src/MysqlConnectionPool.cpp b/src/MysqlConnectionPool.cpp new file mode 100644 index 0000000..315901f --- /dev/null +++ b/src/MysqlConnectionPool.cpp @@ -0,0 +1,31 @@ +#include "MysqlConnectionPool.hpp" + +#include "Logger.hpp" + + +MysqlConnectionPool::MysqlConnectionPool( const char *host, + const char *user, + const char *passwd, + const char *db ) + : m_host(host) + , m_user(user) + , m_passwd(passwd) + , m_db(db) +{ + TRACE; +} + +MysqlConnectionPool::~MysqlConnectionPool() +{ + TRACE; +} + + +void MysqlConnectionPool::create() +{ + TRACE; + + MysqlClient *client = new MysqlClient ( m_host, m_user, m_passwd, m_db ); + client->connect(); + add(client); +} diff --git a/src/Thread.cpp b/src/Thread.cpp index 2f735d0..f4c6f75 100644 --- a/src/Thread.cpp +++ b/src/Thread.cpp @@ -33,6 +33,9 @@ void Thread::start() void* Thread::join() const { TRACE; + if ( !m_isRunning ) + return 0; + void* retVal; pthread_join( m_threadHandler, &retVal ); return retVal; diff --git a/src/ThreadPool.cpp b/src/ThreadPool.cpp index 5cbb74a..2df53f1 100644 --- a/src/ThreadPool.cpp +++ b/src/ThreadPool.cpp @@ -61,7 +61,8 @@ void ThreadPool::stop() (*it)->stop(); } - m_tasks.cancel(); + /// @todo solve this! +// m_tasks.cancel( ); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0b0bfe3..b76249b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -19,19 +19,20 @@ if(CXXTEST_FOUND) Fixture.hpp # test_ArgParse.hpp -# test_Singelton_call_once.hpp -# test_Singleton.hpp -# test_Singleton_meyers.hpp -# test_Singleton_DCLP.hpp +# test_Common.hpp +# test_ConditionalVariable.hpp +# test_Multiton.hpp # test_Mutex.hpp + test_ObjectPool.hpp # test_ScopedLock.hpp -# test_ConditionalVariable.hpp - test_Thread.hpp -# test_ThreadPool.hpp # test_Semaphore.hpp -# test_Timer.hpp -# test_Common.hpp -# test_TimerThreadMultimap.hpp +# test_Singleton_DCLP.hpp +# test_Singleton_call_once.hpp +# # test_Singleton.hpp Cannot test private member, Ficture.hpp loads it +# test_Singleton_meyers.hpp +# test_Thread.hpp +# test_ThreadPool.hpp +# # test_Timer.hpp Takes too much time&buggy ) target_link_libraries(testCppUtils CppUtils gcov) endif() diff --git a/test/run_test.sh b/test/run_test.sh index 1d4b474..2322f5b 100755 --- a/test/run_test.sh +++ b/test/run_test.sh @@ -65,8 +65,7 @@ valgrind \ $test | tee $test.out; retval=$PIPESTATUS # NOTE to gen suppressions run: -# valgrind --leak-check=full --show-reachable=yes --show-below-main=no --track-origins=yes --num-callers=30 --malloc-fill=0xaa --free-fill=0xdd --gen-suppressions=yes ./test - +# valgrind --leak-check=full --show-reachable=yes --show-below-main=no --track-origins=yes --num-callers=30 --malloc-fill=0xaa --free-fill=0xdd --suppressions=valgrind.supp --gen-suppressions=yes ./testCppUtils # retval is 0 on success # or the number of failed cases diff --git a/test/test_ObjectPool.hpp b/test/test_ObjectPool.hpp new file mode 100644 index 0000000..b0bb51a --- /dev/null +++ b/test/test_ObjectPool.hpp @@ -0,0 +1,134 @@ +#include + +#include "Common.hpp" +#include "Fixture.hpp" + +#include "ObjectPool.hpp" +#include "Thread.hpp" + +class TestObjectPool : public CxxTest::TestSuite +{ + +public: + + void testBasic( void ) + { + TEST_HEADER; + + ObjectPool op; + + int a(1); + op.add(a); + + TS_ASSERT_EQUALS( op.acquire(), a ); + } + + void testPointers( void ) + { + TEST_HEADER; + + ObjectPool op; + + int *a = new int(1); + int *b = new int(2); + op.add(a); + op.add(b); + + int *tmp_a = op.acquire(); + int *tmp_b = op.acquire(); + + TS_ASSERT_EQUALS( *tmp_a, *a ); + TS_ASSERT_EQUALS( *tmp_b, *b ); + + // release will delete them + op.release(tmp_a); + op.release(tmp_b); + } + + +private: + + class ObjecPoolUserThread : public Thread + { + public: + ObjecPoolUserThread( ObjectPool &objectPool + ) + : m_objectPool(objectPool) + { + TRACE; + } + + private: + void* run() + { + TRACE; + int *a; + try { + a = m_objectPool.acquire(); + LOG( Logger::DEBUG, std::string("Acquired int: "). + append(TToStr(*a)).c_str() ); + } catch ( CancelledException ex ) { + LOG( Logger::DEBUG, "Cancelled while acquiring" ); + } + + sleep(1); + + try { + m_objectPool.release(a); + } catch ( CancelledException ex ) { + LOG( Logger::DEBUG, "Cancelled while releasing" ); + } + return 0; + } + + ObjectPool &m_objectPool; + }; + +public: + + void testCompetingThreads( void ) + { + TEST_HEADER; + + ObjectPool op; + + ObjecPoolUserThread t1(op); + ObjecPoolUserThread t2(op); + + int *a = new int(27); + op.add(a); + + t1.start(); + t2.start(); + + t1.join(); + t2.join(); + + // no need to delete "a", dtor of the ConqurrentDeque takes care of it + } + + +public: + + void testCleanUp( void ) + { + TEST_HEADER; + + ObjectPool cop; + int *a = new int(12); + int *b = new int(13); + int *c = new int(14); + cop.add(a); + cop.add(b); + cop.add(c); + +// ObjecPoolUserThread t1(cop); +// ObjecPoolUserThread t2(cop); + +// t1.start(); +// t2.start(); + + cop.clear(); + } + +}; diff --git a/test/test_PThreadWrappers.hpp b/test/test_PThreadWrappers.hpp deleted file mode 100644 index 471e30b..0000000 --- a/test/test_PThreadWrappers.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#include - -#define private public // need to reach private variables - -#include "Common.hpp" -#include "Fixture.hpp" -#include "Mutex.hpp" - -class TestPThreadWrappers : public CxxTest::TestSuite -{ - - -public: - - void testMutexBasic( void ) - { - TEST_HEADER; - Mutex m; - m.lock(); - TS_ASSERT_EQUALS ( m.tryLock(0), 0 ); - m.unlock(); - } - - void testMutexCreate( void ) - { - TEST_HEADER; - Mutex m(PTHREAD_MUTEX_ERRORCHECK); - m.lock(); - TS_ASSERT_EQUALS ( m.lock(), 1 ); - - m.unlock(); - } - - -}; diff --git a/test/test_Semaphore.hpp b/test/test_Semaphore.hpp index 36c8933..c8d39b0 100644 --- a/test/test_Semaphore.hpp +++ b/test/test_Semaphore.hpp @@ -34,6 +34,7 @@ private: { TRACE; } + ~ThreadClassWithSemaphore() { TRACE; } @@ -94,6 +95,8 @@ public: TS_ASSERT_EQUALS( t2->release(), true ); TS_ASSERT_EQUALS( semaphore.getCount(), 1 ); + + // t2 releases instead of the using t1 TS_ASSERT_EQUALS( t2->release(), true ); TS_ASSERT_EQUALS( semaphore.getCount(), 2 ); TS_ASSERT_EQUALS( t2->release(), false ); @@ -102,6 +105,7 @@ public: t2->stop(); t1->join(); t2->join(); + delete t1; delete t2; } diff --git a/test/test_Singelton_DCLP.hpp b/test/test_Singelton_DCLP.hpp deleted file mode 100644 index d5089b3..0000000 --- a/test/test_Singelton_DCLP.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#include - -#define private public // need to reach Singleton's private m_instance - -#include "Common.hpp" -#include "Fixture.hpp" -#include "Singleton_DCLP.hpp" - - -class TestSingletonDCLPSuite : public CxxTest::TestSuite -{ - -private: - - class BasicSingleton : public Singleton_DCLP - { - public: - int getSeven() - { - TRACE; - return 7; - } - }; - -public: - - void testBasic( void ) - { - TEST_HEADER; - - TS_ASSERT_EQUALS( BasicSingleton::getInstance()->getSeven(), 7 ); - } - - -}; diff --git a/test/test_Singleton_DCLP.hpp b/test/test_Singleton_DCLP.hpp index d5089b3..8c1fb20 100644 --- a/test/test_Singleton_DCLP.hpp +++ b/test/test_Singleton_DCLP.hpp @@ -29,6 +29,7 @@ public: TEST_HEADER; TS_ASSERT_EQUALS( BasicSingleton::getInstance()->getSeven(), 7 ); + BasicSingleton::destroy(); } diff --git a/test/test_Singelton_call_once.hpp b/test/test_Singleton_call_once.hpp similarity index 94% rename from test/test_Singelton_call_once.hpp rename to test/test_Singleton_call_once.hpp index 873530a..9da22fa 100644 --- a/test/test_Singelton_call_once.hpp +++ b/test/test_Singleton_call_once.hpp @@ -29,6 +29,7 @@ public: TEST_HEADER; TS_ASSERT_EQUALS( BasicSingleton::getInstance()->getSeven(), 7 ); + BasicSingleton::destroy(); } diff --git a/test/test_Thread.hpp b/test/test_Thread.hpp index 7b2a00f..a5fc5fc 100644 --- a/test/test_Thread.hpp +++ b/test/test_Thread.hpp @@ -34,18 +34,14 @@ public: void testBasic( void ) { TEST_HEADER; - ThreadClass *m = new ThreadClass; - m->start(); + ThreadClass m; + m.start(); - void *retVal = m->join(); + void *retVal = m.join(); TS_ASSERT_EQUALS ( *((int*)retVal) , 14 ); free(retVal); - delete m; } -/** - * @note send a signal to a thread - */ private: @@ -62,7 +58,6 @@ private: TRACE; } - private: void* run( void ) { @@ -73,10 +68,9 @@ private: */ sleep(665); -// void* retVal = malloc(sizeof(int)); -// *((int*)retVal) = 15; -// return retVal; - return 0; + void* retVal = malloc(sizeof(int)); + *((int*)retVal) = 15; + return retVal; } static void signal_handler(int sig) @@ -97,18 +91,17 @@ public: void testSignalSend( void ) { TEST_HEADER; - ThreadClassWithSignal *m2 = new ThreadClassWithSignal; - m2->start(); + ThreadClassWithSignal m2 ; + m2.start(); sleep(1); - m2->sendSignal(SIGINT); + m2.sendSignal(SIGINT); - void *retVal = m2->join(); + void *retVal = m2.join(); TS_ASSERT(retVal); if (retVal != 0 ) { TS_ASSERT_EQUALS ( *((int*)retVal) , 16 ); free((int*)retVal); } - delete m2; } @@ -127,7 +120,7 @@ private: public: - void testEmpty( void ) + void eetestEmpty( void ) { TEST_HEADER; @@ -138,4 +131,17 @@ public: void *retVal = e.join(); TS_ASSERT_EQUALS ( retVal , (void *)0 ); } + + void testJoiningNotStartedThread( void ) + { + TEST_HEADER; + + EmptyThreadClass e; + + e.stop(); + e.join(); + void *retVal = e.join(); + TS_ASSERT_EQUALS ( retVal , (void *)0 ); + } + }; diff --git a/test/valgrind.supp b/test/valgrind.supp index 77628ba..edd82f0 100644 --- a/test/valgrind.supp +++ b/test/valgrind.supp @@ -69,7 +69,18 @@ Memcheck:Leak fun:calloc fun:_dl_allocate_tls - fun:pthread_create@@GLIBC_*.*.* + fun:pthread_create@@GLIBC_* + ... + fun:main +} + +{ + create thread2 + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls + fun:pthread_create@@GLIBC_* ... fun:main }