From 43cbd3a283989da62d2341da923f91fdfbb0cf7b Mon Sep 17 00:00:00 2001 From: "William E. Kempf" Date: Mon, 12 Aug 2002 05:43:10 +0000 Subject: [PATCH] Split up tests into seperate files and switched fully to unit test framework [SVN r14780] --- include/boost/thread/xtime.hpp | 7 + src/thread.cpp | 51 ++-- test/Jamfile | 4 +- test/test.cpp | 20 ++ test/test_condition.cpp | 191 +++++++++++++ test/test_mutex.cpp | 184 +++++++++++++ test/test_once.cpp | 39 +++ test/test_thread.cpp | 489 ++++----------------------------- test/test_tss.cpp | 59 ++++ 9 files changed, 593 insertions(+), 451 deletions(-) create mode 100644 test/test.cpp create mode 100644 test/test_condition.cpp create mode 100644 test/test_mutex.cpp create mode 100644 test/test_once.cpp create mode 100644 test/test_tss.cpp diff --git a/include/boost/thread/xtime.hpp b/include/boost/thread/xtime.hpp index e5d84d36..32a4cdf8 100644 --- a/include/boost/thread/xtime.hpp +++ b/include/boost/thread/xtime.hpp @@ -40,6 +40,13 @@ struct xtime }; int xtime_get(struct xtime* xtp, int clock_type); +inline int xtime_cmp(const xtime& xt1, const xtime& xt2) +{ + int res = (int)(xt1.sec - xt2.sec); + if (res == 0) + res = (int)(xt1.nsec - xt2.nsec); + return res; +} } // namespace boost diff --git a/src/thread.cpp b/src/thread.cpp index b66c1d53..4a8b8654 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -191,37 +191,44 @@ void thread::join() void thread::sleep(const xtime& xt) { + for (;;) + { #if defined(BOOST_HAS_WINTHREADS) - int milliseconds; - to_duration(xt, milliseconds); - Sleep(milliseconds); + int milliseconds; + to_duration(xt, milliseconds); + Sleep(milliseconds); + xtime xt2; + xtime_get(&xt2, TIME_UTC); #elif defined(BOOST_HAS_PTHREADS) # if defined(BOOST_HAS_PTHREAD_DELAY_NP) - timespec ts; - to_timespec_duration(xt, ts); - int res = 0; - res = pthread_delay_np(&ts); - assert(res == 0); + timespec ts; + to_timespec_duration(xt, ts); + int res = 0; + res = pthread_delay_np(&ts); + assert(res == 0); # elif defined(BOOST_HAS_NANOSLEEP) - timespec ts; - to_timespec_duration(xt, ts); + timespec ts; + to_timespec_duration(xt, ts); - // nanosleep takes a timespec that is an offset, not - // an absolute time. - nanosleep(&ts, 0); + // nanosleep takes a timespec that is an offset, not + // an absolute time. + nanosleep(&ts, 0); # else - mutex mx; - mutex::scoped_lock lock(mx); - condition cond; - cond.timed_wait(lock, xt); + mutex mx; + mutex::scoped_lock lock(mx); + condition cond; + cond.timed_wait(lock, xt); # endif #elif defined(BOOST_HAS_MPTASKS) - int microseconds; - to_microduration(xt, microseconds); - Duration lMicroseconds(kDurationMicrosecond * microseconds); - AbsoluteTime sWakeTime(DurationToAbsolute(lMicroseconds)); - threads::mac::detail::safe_delay_until(&sWakeTime); + int microseconds; + to_microduration(xt, microseconds); + Duration lMicroseconds(kDurationMicrosecond * microseconds); + AbsoluteTime sWakeTime(DurationToAbsolute(lMicroseconds)); + threads::mac::detail::safe_delay_until(&sWakeTime); #endif + if (xtime_cmp(xt, xt2) >= 0) + return; + } } void thread::yield() diff --git a/test/Jamfile b/test/Jamfile index 2e605bde..9bf97473 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -26,11 +26,13 @@ subproject libs/thread/test ; SEARCH on threads.jam = $(BOOST_ROOT)/libs/thread/build ; include threads.jam ; +sources = test.cpp test_thread.cpp test_mutex.cpp test_condition.cpp test_tss.cpp test_once.cpp ; + ####################### # Declare the Boost.Threads unit test program test_thread. unit-test test_thread - : test_thread.cpp + : $(sources) ../build/boost_thread ../../test/build/unit_test_framework $(threadmon) diff --git a/test/test.cpp b/test/test.cpp new file mode 100644 index 00000000..77d433b1 --- /dev/null +++ b/test/test.cpp @@ -0,0 +1,20 @@ +#include + +extern boost::unit_test_framework::test_suite* thread_tests(); +extern boost::unit_test_framework::test_suite* mutex_tests(); +extern boost::unit_test_framework::test_suite* condition_tests(); +extern boost::unit_test_framework::test_suite* tss_tests(); +extern boost::unit_test_framework::test_suite* once_tests(); + +boost::unit_test_framework::test_suite* init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE("Boost.Threads test suite"); + + test->add(thread_tests()); + test->add(mutex_tests()); + test->add(condition_tests()); + test->add(tss_tests()); + test->add(once_tests()); + + return test; +} diff --git a/test/test_condition.cpp b/test/test_condition.cpp new file mode 100644 index 00000000..69d9741e --- /dev/null +++ b/test/test_condition.cpp @@ -0,0 +1,191 @@ +#include +#include +#include + +#include + +namespace +{ + struct condition_test_data + { + condition_test_data() : notified(0), awoken(0) { } + + boost::mutex mutex; + boost::condition condition; + int notified; + int awoken; + }; + + void condition_test_thread(void* param) + { + condition_test_data* data = static_cast(param); + boost::mutex::scoped_lock lock(data->mutex); + BOOST_CHECK(lock); + while (!(data->notified > 0)) + data->condition.wait(lock); + BOOST_CHECK(lock); + data->awoken++; + } + + class thread_adapter + { + public: + thread_adapter(void (*func)(void*), void* param) : _func(func), _param(param) { } + void operator()() const { _func(_param); } + private: + void (*_func)(void*); + void* _param; + }; + + struct cond_predicate + { + cond_predicate(int& var, int val) : _var(var), _val(val) { } + + bool operator()() { return _var == _val; } + + int& _var; + int _val; + }; + + void condition_test_waits(void* param) + { + condition_test_data* data = static_cast(param); + + boost::mutex::scoped_lock lock(data->mutex); + BOOST_CHECK(lock); + + // Test wait. + while (data->notified != 1) + data->condition.wait(lock); + BOOST_CHECK(lock); + BOOST_CHECK_EQUAL(data->notified, 1); + data->awoken++; + data->condition.notify_one(); + + // Test predicate wait. + data->condition.wait(lock, cond_predicate(data->notified, 2)); + BOOST_CHECK(lock); + BOOST_CHECK_EQUAL(data->notified, 2); + data->awoken++; + data->condition.notify_one(); + + // Test timed_wait. + boost::xtime xt; + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.nsec += 100000000; + while (data->notified != 3) + data->condition.timed_wait(lock, xt); + BOOST_CHECK(lock); + BOOST_CHECK_EQUAL(data->notified, 3); + data->awoken++; + data->condition.notify_one(); + + // Test predicate timed_wait. + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.sec += 2; + BOOST_CHECK(data->condition.timed_wait(lock, xt, cond_predicate(data->notified, 4))); + BOOST_CHECK(lock); + BOOST_CHECK_EQUAL(data->notified, 4); + data->awoken++; + } +} + +void test_condition_notify_one() +{ + condition_test_data data; + + boost::thread thread(thread_adapter(&condition_test_thread, &data)); + + { + boost::mutex::scoped_lock lock(data.mutex); + BOOST_CHECK(lock); + data.notified++; + data.condition.notify_one(); + } + + thread.join(); + BOOST_CHECK_EQUAL(data.awoken, 1); +} + +void test_condition_notify_all() +{ + const int NUMTHREADS = 5; + boost::thread_group threads; + condition_test_data data; + + for (int i = 0; i < NUMTHREADS; ++i) + threads.create_thread(thread_adapter(&condition_test_thread, &data)); + + { + boost::mutex::scoped_lock lock(data.mutex); + BOOST_CHECK(lock); + data.notified++; + data.condition.notify_all(); + } + + threads.join_all(); + BOOST_CHECK_EQUAL(data.awoken, NUMTHREADS); +} + +void test_condition_waits() +{ + condition_test_data data; + + boost::thread thread(thread_adapter(&condition_test_waits, &data)); + + boost::xtime xt; + + { + boost::mutex::scoped_lock lock(data.mutex); + BOOST_CHECK(lock); + + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.sec += 1; + boost::thread::sleep(xt); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 1) + data.condition.wait(lock); + BOOST_CHECK_EQUAL(data.awoken, 1); + + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.sec += 1; + boost::thread::sleep(xt); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 2) + data.condition.wait(lock); + BOOST_CHECK_EQUAL(data.awoken, 2); + + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.sec += 1; + boost::thread::sleep(xt); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 3) + data.condition.wait(lock); + BOOST_CHECK_EQUAL(data.awoken, 3); + } + + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.sec += 1; + boost::thread::sleep(xt); + data.notified++; + data.condition.notify_one(); + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.sec += 1; + boost::thread::sleep(xt); + thread.join(); + BOOST_CHECK_EQUAL(data.awoken, 4); +} + +boost::unit_test_framework::test_suite* condition_tests() +{ + boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: condition test suite"); + + test->add(BOOST_TEST_CASE(&test_condition_notify_one)); + test->add(BOOST_TEST_CASE(&test_condition_notify_all)); + test->add(BOOST_TEST_CASE(&test_condition_waits)); + + return test; +} \ No newline at end of file diff --git a/test/test_mutex.cpp b/test/test_mutex.cpp new file mode 100644 index 00000000..38ffabf5 --- /dev/null +++ b/test/test_mutex.cpp @@ -0,0 +1,184 @@ +#include +#include +#include +#include + +#include +#include + +template +struct test_lock +{ + typedef M mutex_type; + typedef typename M::scoped_lock lock_type; + + void operator()() + { + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + lock_type lock(mutex, false); + BOOST_CHECK(!lock); + } + lock_type lock(mutex); + BOOST_CHECK(lock); + + // Construct and initialize an xtime for a fast time out. + boost::xtime xt; + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.nsec += 100000000; + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, xt)); + BOOST_CHECK(lock); + + // Test the lock and unlock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock); + } +}; + +template +struct test_trylock +{ + typedef M mutex_type; + typedef typename M::scoped_try_lock try_lock_type; + + void operator()() + { + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + try_lock_type lock(mutex); + BOOST_CHECK(lock); + } + { + try_lock_type lock(mutex, false); + BOOST_CHECK(!lock); + } + try_lock_type lock(mutex, true); + BOOST_CHECK(lock); + + // Construct and initialize an xtime for a fast time out. + boost::xtime xt; + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.nsec += 100000000; + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, xt)); + BOOST_CHECK(lock); + + // Test the lock, unlock and trylock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock); + lock.unlock(); + BOOST_CHECK(!lock); + BOOST_CHECK(lock.try_lock()); + BOOST_CHECK(lock); + } +}; + +template +struct test_timedlock +{ + typedef M mutex_type; + typedef typename M::scoped_timed_lock timed_lock_type; + + void operator()() + { + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + // Construct and initialize an xtime for a fast time out. + boost::xtime xt; + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.nsec += 100000000; + + timed_lock_type lock(mutex, xt); + BOOST_CHECK(lock); + } + { + timed_lock_type lock(mutex, false); + BOOST_CHECK(!lock); + } + timed_lock_type lock(mutex, true); + BOOST_CHECK(lock); + + // Construct and initialize an xtime for a fast time out. + boost::xtime xt; + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.nsec += 100000000; + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, xt)); + BOOST_CHECK(lock); + + // Test the lock, unlock and timedlock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock); + lock.unlock(); + BOOST_CHECK(!lock); + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.nsec += 100000000; + BOOST_CHECK(lock.timed_lock(xt)); + } +}; + +template +struct test_recursive_lock +{ + typedef M mutex; + + void operator()() + { + mutex mx; + mutex::scoped_lock lock1(mx); + mutex::scoped_lock lock2(mx); + } +}; + +boost::unit_test_framework::test_suite* mutex_tests() +{ + boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: mutex test suite"); + + test->add(BOOST_TEST_CASE(test_lock())); + + test->add(BOOST_TEST_CASE(test_lock())); + test->add(BOOST_TEST_CASE(test_trylock())); + + test->add(BOOST_TEST_CASE(test_lock())); + test->add(BOOST_TEST_CASE(test_trylock())); + test->add(BOOST_TEST_CASE(test_timedlock())); + + test->add(BOOST_TEST_CASE(test_lock())); + test->add(BOOST_TEST_CASE(test_recursive_lock())); + + test->add(BOOST_TEST_CASE(test_lock())); + test->add(BOOST_TEST_CASE(test_trylock())); + test->add(BOOST_TEST_CASE(test_recursive_lock())); + + test->add(BOOST_TEST_CASE(test_lock())); + test->add(BOOST_TEST_CASE(test_trylock())); + test->add(BOOST_TEST_CASE(test_timedlock())); + test->add(BOOST_TEST_CASE(test_recursive_lock())); + + return test; +} \ No newline at end of file diff --git a/test/test_once.cpp b/test/test_once.cpp new file mode 100644 index 00000000..14adcfd0 --- /dev/null +++ b/test/test_once.cpp @@ -0,0 +1,39 @@ +#include +#include + +#include + +namespace +{ + int once_value = 0; + boost::once_flag once = BOOST_ONCE_INIT; + + void init_once_value() + { + once_value++; + } + + void test_once_thread() + { + boost::call_once(&init_once_value, once); + } +} + +void test_once() +{ + const int NUMTHREADS=5; + boost::thread_group threads; + for (int i=0; iadd(BOOST_TEST_CASE(&test_once)); + + return test; +} \ No newline at end of file diff --git a/test/test_thread.cpp b/test/test_thread.cpp index 9a8c96f9..96b16069 100644 --- a/test/test_thread.cpp +++ b/test/test_thread.cpp @@ -1,456 +1,89 @@ -#include -#include -#include -#include -#include -#include #include #include -//#define BOOST_INCLUDE_MAIN -//#include #include -#if defined(BOOST_HAS_WINTHREADS) -# include -#endif - -template -void test_lock(M* dummy=0) +namespace { - typedef M mutex_type; - typedef typename M::scoped_lock lock_type; + inline bool xtime_in_range(boost::xtime& xt, int less_seconds, int greater_seconds) + { + boost::xtime cur; + BOOST_CHECK_EQUAL(boost::xtime_get(&cur, boost::TIME_UTC), boost::TIME_UTC); - mutex_type mutex; - boost::condition condition; + boost::xtime less = cur; + less.sec += less_seconds; - // Test the lock's constructors. - { - lock_type lock(mutex, false); - BOOST_CHECK(!lock); - } - lock_type lock(mutex); - BOOST_CHECK(lock); + boost::xtime greater = cur; + greater.sec += greater_seconds; - // Construct and initialize an xtime for a fast time out. - boost::xtime xt; - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.nsec += 100000000; + return (boost::xtime_cmp(xt, less) >= 0) && (boost::xtime_cmp(xt, greater) <= 0); + } - // Test the lock and the mutex with condition variables. - // No one is going to notify this condition variable. We expect to - // time out. - BOOST_CHECK(!condition.timed_wait(lock, xt)); - BOOST_CHECK(lock); + int test_value; - // Test the lock and unlock methods. - lock.unlock(); - BOOST_CHECK(!lock); - lock.lock(); - BOOST_CHECK(lock); + void simple_thread() + { + test_value = 999; + } + + struct thread_adapter + { + thread_adapter(void (*func)(boost::thread& parent), boost::thread& parent) + : func(func), parent(parent) + { + } + + void operator()() + { + (*func)(parent); + } + + void (*func)(boost::thread& parent); + boost::thread& parent; + }; + + void comparison_thread(boost::thread& parent) + { + boost::thread thrd; + BOOST_TEST(thrd != parent); + BOOST_TEST(thrd == boost::thread()); + } } -template -void test_trylock(M* dummy=0) +void test_sleep() { - typedef M mutex_type; - typedef typename M::scoped_try_lock try_lock_type; + boost::xtime xt; + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); + xt.sec += 5; + + boost::thread::sleep(xt); - mutex_type mutex; - boost::condition condition; - - // Test the lock's constructors. - { - try_lock_type lock(mutex); - BOOST_CHECK(lock); - } - { - try_lock_type lock(mutex, false); - BOOST_CHECK(!lock); - } - try_lock_type lock(mutex, true); - BOOST_CHECK(lock); - - // Construct and initialize an xtime for a fast time out. - boost::xtime xt; - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.nsec += 100000000; - - // Test the lock and the mutex with condition variables. - // No one is going to notify this condition variable. We expect to - // time out. - BOOST_CHECK(!condition.timed_wait(lock, xt)); - BOOST_CHECK(lock); - - // Test the lock, unlock and trylock methods. - lock.unlock(); - BOOST_CHECK(!lock); - lock.lock(); - BOOST_CHECK(lock); - lock.unlock(); - BOOST_CHECK(!lock); - BOOST_CHECK(lock.try_lock()); - BOOST_CHECK(lock); + // Insure it's in a range instead of checking actual equality due to time lapse + BOOST_CHECK(xtime_in_range(xt, -1, 1)); } -template -void test_timedlock(M* dummy=0) +void test_creation() { - typedef M mutex_type; - typedef typename M::scoped_timed_lock timed_lock_type; - - mutex_type mutex; - boost::condition condition; - - // Test the lock's constructors. - { - // Construct and initialize an xtime for a fast time out. - boost::xtime xt; - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.nsec += 100000000; - - timed_lock_type lock(mutex, xt); - BOOST_CHECK(lock); - } - { - timed_lock_type lock(mutex, false); - BOOST_CHECK(!lock); - } - timed_lock_type lock(mutex, true); - BOOST_CHECK(lock); - - // Construct and initialize an xtime for a fast time out. - boost::xtime xt; - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.nsec += 100000000; - - // Test the lock and the mutex with condition variables. - // No one is going to notify this condition variable. We expect to - // time out. - BOOST_CHECK(!condition.timed_wait(lock, xt)); - BOOST_CHECK(lock); - - // Test the lock, unlock and timedlock methods. - lock.unlock(); - BOOST_CHECK(!lock); - lock.lock(); - BOOST_CHECK(lock); - lock.unlock(); - BOOST_CHECK(!lock); - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.nsec += 100000000; - BOOST_CHECK(lock.timed_lock(xt)); + test_value = 0; + boost::thread thrd(&simple_thread); + thrd.join(); + BOOST_CHECK_EQUAL(test_value, 999); } -void test_mutex() +void test_comparison() { - typedef boost::mutex mutex; - test_lock(); + boost::thread self; + boost::thread thrd(thread_adapter(&comparison_thread, self)); + thrd.join(); } -void test_try_mutex() +boost::unit_test_framework::test_suite* thread_tests() { - typedef boost::try_mutex mutex; - test_lock(); - test_trylock(); -} + boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: thread test suite"); -void test_timed_mutex() -{ - typedef boost::timed_mutex mutex; - test_lock(); - test_trylock(); - test_timedlock(); -} - -void test_recursive_mutex() -{ - typedef boost::recursive_mutex mutex; - test_lock(); - mutex mx; - mutex::scoped_lock lock1(mx); - mutex::scoped_lock lock2(mx); -} - -void test_recursive_try_mutex() -{ - typedef boost::recursive_try_mutex mutex; - test_lock(); - test_trylock(); - mutex mx; - mutex::scoped_lock lock1(mx); - mutex::scoped_lock lock2(mx); -} - -void test_recursive_timed_mutex() -{ - typedef boost::recursive_timed_mutex mutex; - test_lock(); - test_trylock(); - test_timedlock(); - mutex mx; - mutex::scoped_lock lock1(mx); - mutex::scoped_lock lock2(mx); -} - -struct condition_test_data -{ - condition_test_data() : notified(0), awoken(0) { } - - boost::mutex mutex; - boost::condition condition; - int notified; - int awoken; -}; - -void condition_test_thread(void* param) -{ - condition_test_data* data = static_cast(param); - boost::mutex::scoped_lock lock(data->mutex); - BOOST_CHECK(lock); - while (!(data->notified > 0)) - data->condition.wait(lock); - BOOST_CHECK(lock); - data->awoken++; -} - -class thread_adapter -{ -public: - thread_adapter(void (*func)(void*), void* param) : _func(func), _param(param) { } - void operator()() const { _func(_param); } -private: - void (*_func)(void*); - void* _param; -}; - -void test_condition_notify_one() -{ - condition_test_data data; - - boost::thread thread(thread_adapter(&condition_test_thread, &data)); - - { - boost::mutex::scoped_lock lock(data.mutex); - BOOST_CHECK(lock); - data.notified++; - data.condition.notify_one(); - } - - thread.join(); - BOOST_CHECK_EQUAL(data.awoken, 1); -} - -void test_condition_notify_all() -{ - const int NUMTHREADS = 5; - boost::thread_group threads; - condition_test_data data; - - for (int i = 0; i < NUMTHREADS; ++i) - threads.create_thread(thread_adapter(&condition_test_thread, &data)); - - { - boost::mutex::scoped_lock lock(data.mutex); - BOOST_CHECK(lock); - data.notified++; - data.condition.notify_all(); - } - - threads.join_all(); - BOOST_CHECK_EQUAL(data.awoken, NUMTHREADS); -} - -struct cond_predicate -{ - cond_predicate(int& var, int val) : _var(var), _val(val) { } - - bool operator()() { return _var == _val; } - - int& _var; - int _val; -}; - -void condition_test_waits(void* param) -{ - condition_test_data* data = static_cast(param); - - boost::mutex::scoped_lock lock(data->mutex); - BOOST_CHECK(lock); - - // Test wait. - while (data->notified != 1) - data->condition.wait(lock); - BOOST_CHECK(lock); - BOOST_CHECK_EQUAL(data->notified, 1); - data->awoken++; - data->condition.notify_one(); - - // Test predicate wait. - data->condition.wait(lock, cond_predicate(data->notified, 2)); - BOOST_CHECK(lock); - BOOST_CHECK_EQUAL(data->notified, 2); - data->awoken++; - data->condition.notify_one(); - - // Test timed_wait. - boost::xtime xt; - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.nsec += 100000000; - while (data->notified != 3) - data->condition.timed_wait(lock, xt); - BOOST_CHECK(lock); - BOOST_CHECK_EQUAL(data->notified, 3); - data->awoken++; - data->condition.notify_one(); - - // Test predicate timed_wait. - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.sec += 2; - BOOST_CHECK(data->condition.timed_wait(lock, xt, cond_predicate(data->notified, 4))); - BOOST_CHECK(lock); - BOOST_CHECK_EQUAL(data->notified, 4); - data->awoken++; -} - -void test_condition_waits() -{ - condition_test_data data; - - boost::thread thread(thread_adapter(&condition_test_waits, &data)); - - boost::xtime xt; - - { - boost::mutex::scoped_lock lock(data.mutex); - BOOST_CHECK(lock); - - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.sec += 1; - boost::thread::sleep(xt); - data.notified++; - data.condition.notify_one(); - while (data.awoken != 1) - data.condition.wait(lock); - BOOST_CHECK_EQUAL(data.awoken, 1); - - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.sec += 1; - boost::thread::sleep(xt); - data.notified++; - data.condition.notify_one(); - while (data.awoken != 2) - data.condition.wait(lock); - BOOST_CHECK_EQUAL(data.awoken, 2); - - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.sec += 1; - boost::thread::sleep(xt); - data.notified++; - data.condition.notify_one(); - while (data.awoken != 3) - data.condition.wait(lock); - BOOST_CHECK_EQUAL(data.awoken, 3); - } - - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.sec += 1; - boost::thread::sleep(xt); - data.notified++; - data.condition.notify_one(); - BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), boost::TIME_UTC); - xt.sec += 1; - boost::thread::sleep(xt); - thread.join(); - BOOST_CHECK_EQUAL(data.awoken, 4); -} - -void test_condition() -{ - test_condition_notify_one(); - test_condition_notify_all(); - test_condition_waits(); -} - -boost::mutex tss_mutex; -int tss_instances = 0; - -struct tss_value_t -{ - tss_value_t() - { - boost::mutex::scoped_lock lock(tss_mutex); - ++tss_instances; - value = 0; - } - ~tss_value_t() - { - boost::mutex::scoped_lock lock(tss_mutex); - --tss_instances; - } - int value; -}; - -boost::thread_specific_ptr tss_value; - -void test_tss_thread() -{ - tss_value.reset(new tss_value_t()); - for (int i=0; i<1000; ++i) - { - int& n = tss_value->value; - BOOST_CHECK_EQUAL(n, i); - ++n; - } -} - -void test_tss() -{ - const int NUMTHREADS=5; - boost::thread_group threads; - for (int i=0; iadd(BOOST_TEST_CASE(&test_mutex)); - test->add(BOOST_TEST_CASE(&test_try_mutex)); - test->add(BOOST_TEST_CASE(&test_timed_mutex)); - test->add(BOOST_TEST_CASE(&test_recursive_mutex)); - test->add(BOOST_TEST_CASE(&test_recursive_try_mutex)); - test->add(BOOST_TEST_CASE(&test_recursive_timed_mutex)); - test->add(BOOST_TEST_CASE(&test_condition)); - test->add(BOOST_TEST_CASE(&test_tss)); - test->add(BOOST_TEST_CASE(&test_once)); + test->add(BOOST_TEST_CASE(&test_sleep)); + test->add(BOOST_TEST_CASE(&test_creation)); + test->add(BOOST_TEST_CASE(&test_comparison)); return test; } diff --git a/test/test_tss.cpp b/test/test_tss.cpp new file mode 100644 index 00000000..88a0eb21 --- /dev/null +++ b/test/test_tss.cpp @@ -0,0 +1,59 @@ +#include +#include +#include + +#include + +namespace +{ + boost::mutex tss_mutex; + int tss_instances = 0; + + struct tss_value_t + { + tss_value_t() + { + boost::mutex::scoped_lock lock(tss_mutex); + ++tss_instances; + value = 0; + } + ~tss_value_t() + { + boost::mutex::scoped_lock lock(tss_mutex); + --tss_instances; + } + int value; + }; + + boost::thread_specific_ptr tss_value; + + void test_tss_thread() + { + tss_value.reset(new tss_value_t()); + for (int i=0; i<1000; ++i) + { + int& n = tss_value->value; + BOOST_CHECK_EQUAL(n, i); + ++n; + } + } +} + +void test_tss() +{ + const int NUMTHREADS=5; + boost::thread_group threads; + for (int i=0; iadd(BOOST_TEST_CASE(&test_tss)); + + return test; +} \ No newline at end of file