thread/test/test_time_jumps.cpp

2399 lines
95 KiB
C++

#ifdef _WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
#include "boost/bind.hpp"
#include "boost/chrono.hpp"
#include "boost/chrono/ceil.hpp"
#include "boost/date_time.hpp"
#include "boost/thread/concurrent_queues/sync_priority_queue.hpp"
#include "boost/thread/concurrent_queues/sync_timed_queue.hpp"
#include "boost/thread/future.hpp"
#include "boost/thread/mutex.hpp"
#include "boost/thread/recursive_mutex.hpp"
#include "boost/thread/shared_lock_guard.hpp"
#include "boost/thread/shared_mutex.hpp"
#include "boost/thread/thread.hpp"
#include <iomanip>
#ifdef TEST_CPP14_FEATURES
#include <future>
#include <mutex>
#include <shared_mutex>
#include <thread>
#endif
/******************************************************************************/
/*
* Summary:
*
* This code tests the behavior of time-related functions in the presence of
* system clock changes (jumps). It requires root/Administrator privileges in
* order to run because it changes the system clock. NTP should also be disabled
* while running this code so that NTP can't change the system clock.
*
* Each function to be tested is executed five times. The amount of time the
* function waits before returning is measured against the amount of time the
* function was expected to wait. If the difference exceeds a threshold value
* (defined below) then the test fails.
*
* The following values are intentially:
* - more than 200 milliseconds
* - more than 200 milliseconds apart
* - not a multiple of 100 milliseconds
* - not a multiple of each other
* - don't sum or diff to a multiple of 100 milliseconds
*/
const long long s_waitMs = 580;
const long long s_shortJumpMs = 230;
const long long s_longJumpMs = 870; // Causes additional, unavoidable failures when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC is disabled
const long long s_sleepBeforeJumpMs = 110;
#ifdef _WIN32
const long long s_maxEarlyErrorMs = 10
+ 100; // Windows is unpredictable, especially in a VM, so allow extra time if the function returns early
const long long s_maxLateErrorMs = 110 // due to polling, functions may not return for up to 100 milliseconds after they are supposed to
+ 100; // Windows is slow, especially in a VM, so allow extra time for the functions to return
#else
const long long s_maxEarlyErrorMs = 10;
const long long s_maxLateErrorMs = 110; // Due to polling, functions may not return for up to 100 milliseconds after they are supposed to
#endif
int g_numTestsRun = 0;
int g_numTestsPassed = 0;
int g_numTestsFailed = 0;
/******************************************************************************/
// A custom clock based off the system clock but with a different epoch.
namespace custom
{
class custom_boost_clock
{
public:
typedef boost::chrono::microseconds duration; // intentionally not nanoseconds
typedef duration::rep rep;
typedef duration::period period;
typedef boost::chrono::time_point<custom_boost_clock> time_point;
static bool is_steady;
static time_point now();
};
bool custom_boost_clock::is_steady = false;
custom_boost_clock::time_point custom_boost_clock::now()
{
return time_point(boost::chrono::ceil<duration>(boost::chrono::system_clock::now().time_since_epoch()) - boost::chrono::hours(10 * 365 * 24));
}
#ifdef TEST_CPP14_FEATURES
class custom_std_clock
{
public:
typedef std::chrono::microseconds duration; // intentionally not nanoseconds
typedef duration::rep rep;
typedef duration::period period;
typedef std::chrono::time_point<custom_std_clock> time_point;
static bool is_steady;
static time_point now();
};
bool custom_std_clock::is_steady = false;
custom_std_clock::time_point custom_std_clock::now()
{
return time_point(std::chrono::duration_cast<duration>(std::chrono::system_clock::now().time_since_epoch()) - std::chrono::hours(10 * 365 * 24));
}
#endif
}
/******************************************************************************/
template <typename MutexType = boost::mutex, typename CondType = boost::condition_variable>
struct BoostHelper
{
typedef MutexType mutex;
typedef CondType cond;
typedef boost::lock_guard<MutexType> lock_guard;
typedef boost::unique_lock<MutexType> unique_lock;
typedef boost::chrono::milliseconds milliseconds;
typedef boost::chrono::nanoseconds nanoseconds;
typedef boost::chrono::system_clock system_clock;
typedef boost::chrono::steady_clock steady_clock;
typedef custom::custom_boost_clock custom_clock;
typedef system_clock::time_point system_time_point;
typedef steady_clock::time_point steady_time_point;
typedef custom_clock::time_point custom_time_point;
typedef boost::cv_status cv_status;
typedef boost::future_status future_status;
typedef boost::packaged_task<bool> packaged_task;
typedef boost::future<bool> future;
typedef boost::shared_future<bool> shared_future;
typedef boost::thread thread;
static const milliseconds waitDur;
template <typename T>
static void sleep_for(T d)
{
boost::this_thread::sleep_for(d);
}
template <typename T>
static void sleep_for_no_int(T d)
{
boost::this_thread::no_interruption_point::sleep_for(d);
}
template <typename T>
static void sleep_until(T t)
{
boost::this_thread::sleep_until(t);
}
template <typename T>
static void sleep_until_no_int(T t)
{
boost::this_thread::no_interruption_point::sleep_until(t);
}
static system_time_point systemNow()
{
return system_clock::now();
}
static steady_time_point steadyNow()
{
return steady_clock::now();
}
static custom_time_point customNow()
{
return custom_clock::now();
}
template <class ToDuration, class Rep, class Period>
static ToDuration duration_cast(const boost::chrono::duration<Rep, Period>& d)
{
return boost::chrono::duration_cast<ToDuration>(d);
}
static milliseconds zero()
{
return milliseconds(0);
}
};
template <typename MutexType, typename CondType>
const typename BoostHelper<MutexType, CondType>::milliseconds
BoostHelper<MutexType, CondType>::waitDur = typename BoostHelper<MutexType, CondType>::milliseconds(s_waitMs);
#ifdef TEST_CPP14_FEATURES
template <typename MutexType = std::mutex, typename CondType = std::condition_variable>
struct StdHelper
{
typedef MutexType mutex;
typedef CondType cond;
typedef std::lock_guard<MutexType> lock_guard;
typedef std::unique_lock<MutexType> unique_lock;
typedef std::chrono::milliseconds milliseconds;
typedef std::chrono::nanoseconds nanoseconds;
typedef std::chrono::system_clock system_clock;
typedef std::chrono::steady_clock steady_clock;
typedef custom::custom_std_clock custom_clock;
typedef system_clock::time_point system_time_point;
typedef steady_clock::time_point steady_time_point;
typedef custom_clock::time_point custom_time_point;
typedef std::cv_status cv_status;
typedef std::future_status future_status;
typedef std::packaged_task<bool()> packaged_task;
typedef std::future<bool> future;
typedef std::shared_future<bool> shared_future;
typedef std::thread thread;
static const milliseconds waitDur;
template <typename T>
static void sleep_for(T d)
{
std::this_thread::sleep_for(d);
}
template <typename T>
static void sleep_until(T t)
{
std::this_thread::sleep_until(t);
}
static system_time_point systemNow()
{
return system_clock::now();
}
static steady_time_point steadyNow()
{
return steady_clock::now();
}
static custom_time_point customNow()
{
return custom_clock::now();
}
template <class ToDuration, class Rep, class Period>
static ToDuration duration_cast(const std::chrono::duration<Rep, Period>& d)
{
return std::chrono::duration_cast<ToDuration>(d);
}
static milliseconds zero()
{
return milliseconds(0);
}
};
template <typename MutexType, typename CondType>
const typename StdHelper<MutexType, CondType>::milliseconds
StdHelper<MutexType, CondType>::waitDur = typename StdHelper<MutexType, CondType>::milliseconds(s_waitMs);
#endif
/******************************************************************************/
#ifdef _WIN32
void changeSystemTime(long long changeMs)
{
Sleep(s_sleepBeforeJumpMs);
SYSTEMTIME systemTime;
GetSystemTime(&systemTime);
FILETIME fileTime;
if (!SystemTimeToFileTime(&systemTime, &fileTime))
{
std::cout << "ERROR: Couldn't convert system time to file time" << std::endl;
}
ULARGE_INTEGER largeInt;
largeInt.LowPart = fileTime.dwLowDateTime;
largeInt.HighPart = fileTime.dwHighDateTime;
largeInt.QuadPart += changeMs * 10000;
fileTime.dwLowDateTime = largeInt.LowPart;
fileTime.dwHighDateTime = largeInt.HighPart;
if (!FileTimeToSystemTime(&fileTime, &systemTime))
{
std::cout << "ERROR: Couldn't convert file time to system time" << std::endl;
}
if (!SetSystemTime(&systemTime))
{
std::cout << "ERROR: Couldn't set system time" << std::endl;
}
}
#else
void changeSystemTime(long long changeMs)
{
struct timespec sleepTs;
sleepTs.tv_sec = (s_sleepBeforeJumpMs / 1000);
sleepTs.tv_nsec = (s_sleepBeforeJumpMs % 1000) * 1000000;
nanosleep(&sleepTs, NULL);
struct timeval tv;
if (gettimeofday(&tv, NULL) != 0)
{
std::cout << "ERROR: Couldn't get system time" << std::endl;
}
changeMs += tv.tv_sec * 1000;
changeMs += tv.tv_usec / 1000;
tv.tv_sec = (changeMs / 1000);
tv.tv_usec = (changeMs % 1000) * 1000;
if (settimeofday(&tv, NULL) != 0)
{
std::cout << "ERROR: Couldn't set system time" << std::endl;
}
}
#endif
enum RcEnum
{
e_no_timeout,
e_timeout,
e_failed_bad,
e_failed_good,
e_succeeded_bad,
e_succeeded_good,
e_ready_bad,
e_not_ready_good,
e_na
};
template <typename Helper>
void checkWaitTime(typename Helper::nanoseconds expected, typename Helper::nanoseconds actual, RcEnum rc)
{
if (expected != Helper::zero() && expected < typename Helper::milliseconds(s_sleepBeforeJumpMs))
{
expected = typename Helper::milliseconds(s_sleepBeforeJumpMs);
}
typename Helper::milliseconds expectedMs = Helper::template duration_cast<typename Helper::milliseconds>(expected);
typename Helper::milliseconds actualMs = Helper::template duration_cast<typename Helper::milliseconds>(actual);
std::cout << "Expected: " << std::setw(4) << expectedMs.count() << " ms"
<< ", Actual: " << std::setw(4) << actualMs.count() << " ms"
<< ", Returned: ";
switch (rc)
{
case e_no_timeout : std::cout << "no_timeout, "; break;
case e_timeout : std::cout << "timeout, "; break;
case e_failed_bad : std::cout << "failed, "; break;
case e_failed_good : std::cout << "failed, "; break;
case e_succeeded_bad : std::cout << "succeeded, "; break;
case e_succeeded_good : std::cout << "succeeded, "; break;
case e_ready_bad : std::cout << "ready, "; break;
case e_not_ready_good : std::cout << "not_ready, "; break;
default : std::cout << "N/A, "; break;
}
if (expectedMs == Helper::zero())
{
std::cout << "FAILED: SKIPPED (test would lock up if run)";
g_numTestsFailed++;
}
else if (actual < expected - typename Helper::milliseconds(s_maxEarlyErrorMs))
{
std::cout << "FAILED: TOO SHORT";
if (rc == e_timeout) // bad
{
std::cout << ", RETURNED TIMEOUT";
}
else if (rc == e_failed_bad)
{
std::cout << ", RETURNED FAILED";
}
else if (rc == e_succeeded_bad)
{
std::cout << ", RETURNED SUCCEEDED";
}
else if (rc == e_ready_bad)
{
std::cout << ", RETURNED READY";
}
g_numTestsFailed++;
}
else if (actual > expected + typename Helper::milliseconds(s_maxLateErrorMs))
{
std::cout << "FAILED: TOO LONG";
if (rc == e_no_timeout) // bad
{
std::cout << ", RETURNED NO_TIMEOUT";
}
else if (rc == e_failed_bad)
{
std::cout << ", RETURNED FAILED";
}
else if (rc == e_succeeded_bad)
{
std::cout << ", RETURNED SUCCEEDED";
}
else if (rc == e_ready_bad)
{
std::cout << ", RETURNED READY";
}
g_numTestsFailed++;
}
else if (rc == e_no_timeout) // bad
{
std::cout << "FAILED: RETURNED NO_TIMEOUT";
g_numTestsFailed++;
}
else if (rc == e_failed_bad)
{
std::cout << "FAILED: RETURNED FAILED";
g_numTestsFailed++;
}
else if (rc == e_succeeded_bad)
{
std::cout << "FAILED: RETURNED SUCCEEDED";
g_numTestsFailed++;
}
else if (rc == e_ready_bad)
{
std::cout << "FAILED: RETURNED READY";
g_numTestsFailed++;
}
else
{
std::cout << "Passed";
g_numTestsPassed++;
}
std::cout << std::endl;
g_numTestsRun++;
}
void sleepForLongTime()
{
#ifdef _WIN32
Sleep(10000);
#else
struct timespec ts = {5, 0};
nanosleep(&ts, NULL);
#endif
}
bool returnFalse()
{
return false;
}
/******************************************************************************/
// Run the test in the context provided, which may be the current thread or a separate thread.
template <typename Helper, typename Context, typename Function>
void runTestInContext(Context context, Function func, const std::string name)
{
std::cout << name << ":" << std::endl;
{
std::cout << " While system clock remains stable: ";
context(func, 0);
}
{
std::cout << " While system clock jumps back (short): ";
typename Helper::thread t(boost::bind(changeSystemTime, -s_shortJumpMs));
context(func, -s_shortJumpMs);
t.join();
}
{
std::cout << " While system clock jumps back (long): ";
typename Helper::thread t(boost::bind(changeSystemTime, -s_longJumpMs));
context(func, -s_longJumpMs);
t.join();
}
{
std::cout << " While system clock jumps forward (short): ";
typename Helper::thread t(boost::bind(changeSystemTime, s_shortJumpMs));
context(func, s_shortJumpMs);
t.join();
}
{
std::cout << " While system clock jumps forward (long): ";
typename Helper::thread t(boost::bind(changeSystemTime, s_longJumpMs));
context(func, s_longJumpMs);
t.join();
}
}
//--------------------------------------
template <typename Helper, typename Function>
void noThreadContext(Function func, const long long jumpMs)
{
func(jumpMs);
}
template <typename Helper, typename Function>
void threadContextWithNone(Function func, const long long jumpMs)
{
typename Helper::thread t(boost::bind(func, jumpMs));
t.join();
}
template <typename Helper, typename Function>
void threadContextWithUnique(Function func, const long long jumpMs)
{
typename Helper::mutex m;
typename Helper::lock_guard g(m);
typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs));
t.join();
}
template <typename Helper, typename Function>
void threadContextWithShared(Function func, const long long jumpMs)
{
typename Helper::mutex m;
boost::shared_lock_guard<typename Helper::mutex> g(m);
typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs));
t.join();
}
template <typename Helper, typename Function>
void threadContextWithUpgrade(Function func, const long long jumpMs)
{
typename Helper::mutex m;
boost::upgrade_lock<typename Helper::mutex> g(m);
typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs));
t.join();
}
//--------------------------------------
// Run the test in the current thread.
template <typename Helper, typename Function>
void runTest(Function func, const std::string name)
{
runTestInContext<Helper>(noThreadContext<Helper, Function>, func, name);
}
// Run the test in a separate thread.
template <typename Helper, typename Function>
void runTestWithNone(Function func, const std::string name)
{
runTestInContext<Helper>(threadContextWithNone<Helper, Function>, func, name);
}
// Run the test in a separate thread. Pass a locked mutex to the function under test.
template <typename Helper, typename Function>
void runTestWithUnique(Function func, const std::string name)
{
runTestInContext<Helper>(threadContextWithUnique<Helper, Function>, func, name);
}
// Run the test in a separate thread. Pass a shared-locked mutex to the function under test.
template <typename Helper, typename Function>
void runTestWithShared(Function func, const std::string name)
{
runTestInContext<Helper>(threadContextWithShared<Helper, Function>, func, name);
}
// Run the test in a separate thread. Pass an upgrade-locked mutex to the function under test.
template <typename Helper, typename Function>
void runTestWithUpgrade(Function func, const std::string name)
{
runTestInContext<Helper>(threadContextWithUpgrade<Helper, Function>, func, name);
}
/******************************************************************************/
// Test Sleep
template <typename Helper>
void testSleepFor(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
Helper::sleep_for(Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
}
template <typename Helper>
void testSleepUntilSteady(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
Helper::sleep_until(Helper::steadyNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
}
template <typename Helper>
void testSleepUntilSystem(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
Helper::sleep_until(Helper::systemNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
}
template <typename Helper>
void testSleepUntilCustom(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
Helper::sleep_until(Helper::customNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
}
//--------------------------------------
template <typename Helper>
void testSleepRelative(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
boost::this_thread::sleep(ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
template <typename Helper>
void testSleepAbsolute(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
boost::this_thread::sleep(ptNow + ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
//--------------------------------------
template <typename Helper>
void testSleepStd(const std::string& name)
{
std::cout << std::endl;
runTestWithNone<Helper>(testSleepFor <Helper>, name + "::this_thread::sleep_for()");
runTestWithNone<Helper>(testSleepUntilSteady<Helper>, name + "::this_thread::sleep_until(), steady time");
runTestWithNone<Helper>(testSleepUntilSystem<Helper>, name + "::this_thread::sleep_until(), system time");
runTestWithNone<Helper>(testSleepUntilCustom<Helper>, name + "::this_thread::sleep_until(), custom time");
}
template <typename Helper>
void testSleepBoost(const std::string& name)
{
testSleepStd<Helper>(name);
// Boost-only functions
runTestWithNone<Helper>(testSleepRelative<Helper>, name + "::this_thread::sleep(), relative time");
runTestWithNone<Helper>(testSleepAbsolute<Helper>, name + "::this_thread::sleep(), absolute time");
}
template <typename Helper>
void testSleepNoThreadStd(const std::string& name)
{
std::cout << std::endl;
runTest<Helper>(testSleepFor <Helper>, name + "::this_thread::sleep_for(), no thread");
runTest<Helper>(testSleepUntilSteady<Helper>, name + "::this_thread::sleep_until(), no thread, steady time");
runTest<Helper>(testSleepUntilSystem<Helper>, name + "::this_thread::sleep_until(), no thread, system time");
runTest<Helper>(testSleepUntilCustom<Helper>, name + "::this_thread::sleep_until(), no thread, custom time");
}
template <typename Helper>
void testSleepNoThreadBoost(const std::string& name)
{
testSleepNoThreadStd<Helper>(name);
// Boost-only functions
runTest<Helper>(testSleepRelative<Helper>, name + "::this_thread::sleep(), no thread, relative time");
runTest<Helper>(testSleepAbsolute<Helper>, name + "::this_thread::sleep(), no thread, absolute time");
}
/******************************************************************************/
// Test Sleep, No Interruption Point
template <typename Helper>
void testSleepForNoInt(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
Helper::sleep_for_no_int(Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
}
template <typename Helper>
void testSleepUntilNoIntSteady(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
Helper::sleep_until_no_int(Helper::steadyNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
}
template <typename Helper>
void testSleepUntilNoIntSystem(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
Helper::sleep_until_no_int(Helper::systemNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
}
template <typename Helper>
void testSleepUntilNoIntCustom(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
Helper::sleep_until_no_int(Helper::customNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
}
//--------------------------------------
#ifndef SKIP_NO_INT_SLEEP
template <typename Helper>
void testSleepNoIntRelative(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
boost::this_thread::no_interruption_point::sleep(ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
template <typename Helper>
void testSleepNoIntAbsolute(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
boost::this_thread::no_interruption_point::sleep(ptNow + ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
#endif
//--------------------------------------
// Only Boost supports no_interruption_point
template <typename Helper>
void testSleepNoIntBoost(const std::string& name)
{
std::cout << std::endl;
runTestWithNone<Helper>(testSleepForNoInt <Helper>, name + "::this_thread::no_interruption_point::sleep_for()");
runTestWithNone<Helper>(testSleepUntilNoIntSteady<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), steady time");
runTestWithNone<Helper>(testSleepUntilNoIntSystem<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), system time");
runTestWithNone<Helper>(testSleepUntilNoIntCustom<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), custom time");
#ifndef SKIP_NO_INT_SLEEP
runTestWithNone<Helper>(testSleepNoIntRelative<Helper>, name + "::this_thread::no_interruption_point::sleep(), relative time");
runTestWithNone<Helper>(testSleepNoIntAbsolute<Helper>, name + "::this_thread::no_interruption_point::sleep(), absolute time");
#endif
}
template <typename Helper>
void testSleepNoThreadNoIntBoost(const std::string& name)
{
std::cout << std::endl;
runTest<Helper>(testSleepForNoInt <Helper>, name + "::this_thread::no_interruption_point::sleep_for(), no thread");
runTest<Helper>(testSleepUntilNoIntSteady<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, steady time");
runTest<Helper>(testSleepUntilNoIntSystem<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, system time");
runTest<Helper>(testSleepUntilNoIntCustom<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, custom time");
#ifndef SKIP_NO_INT_SLEEP
runTest<Helper>(testSleepNoIntRelative<Helper>, name + "::this_thread::no_interruption_point::sleep(), no thread, relative time");
runTest<Helper>(testSleepNoIntAbsolute<Helper>, name + "::this_thread::no_interruption_point::sleep(), no thread, absolute time");
#endif
}
/******************************************************************************/
// Test Try Join
template <typename Helper>
void testTryJoinFor(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
typename Helper::thread t3(sleepForLongTime);
bool succeeded = t3.try_join_for(Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryJoinUntilSteady(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
typename Helper::thread t3(sleepForLongTime);
bool succeeded = t3.try_join_until(Helper::steadyNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryJoinUntilSystem(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
typename Helper::thread t3(sleepForLongTime);
bool succeeded = t3.try_join_until(Helper::systemNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryJoinUntilCustom(const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
typename Helper::thread t3(sleepForLongTime);
bool succeeded = t3.try_join_until(Helper::customNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
//--------------------------------------
template <typename Helper>
void testTimedJoinRelative(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
typename Helper::thread t3(sleepForLongTime);
bool succeeded = t3.timed_join(ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
template <typename Helper>
void testTimedJoinAbsolute(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
typename Helper::thread t3(sleepForLongTime);
bool succeeded = t3.timed_join(ptNow + ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
//--------------------------------------
// Only Boost supports timed try_join functions
template <typename Helper>
void testJoinBoost(const std::string& name)
{
std::cout << std::endl;
runTestWithNone<Helper>(testTryJoinFor <Helper>, name + "::thread::try_join_for()");
runTestWithNone<Helper>(testTryJoinUntilSteady<Helper>, name + "::thread::try_join_until(), steady time");
runTestWithNone<Helper>(testTryJoinUntilSystem<Helper>, name + "::thread::try_join_until(), system time");
runTestWithNone<Helper>(testTryJoinUntilCustom<Helper>, name + "::thread::try_join_until(), custom time");
runTestWithNone<Helper>(testTimedJoinRelative <Helper>, name + "::thread::timed_join(), relative time");
runTestWithNone<Helper>(testTimedJoinAbsolute <Helper>, name + "::thread::timed_join(), absolute time");
}
/******************************************************************************/
// Test Condition Variable Wait
template <typename Helper>
void testCondVarWaitFor(const long long jumpMs)
{
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool noTimeout = (cv.wait_for(g, Helper::waitDur) == Helper::cv_status::no_timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
}
template <typename Helper>
void testCondVarWaitUntilSteady(const long long jumpMs)
{
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool noTimeout = (cv.wait_until(g, Helper::steadyNow() + Helper::waitDur) == Helper::cv_status::no_timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
}
template <typename Helper>
void testCondVarWaitUntilSystem(const long long jumpMs)
{
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool noTimeout = (cv.wait_until(g, Helper::systemNow() + Helper::waitDur) == Helper::cv_status::no_timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
}
template <typename Helper>
void testCondVarWaitUntilCustom(const long long jumpMs)
{
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool noTimeout = (cv.wait_until(g, Helper::customNow() + Helper::waitDur) == Helper::cv_status::no_timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
}
//--------------------------------------
template <typename Helper>
void testCondVarTimedWaitRelative(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool noTimeout = cv.timed_wait(g, ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
template <typename Helper>
void testCondVarTimedWaitAbsolute(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool noTimeout = cv.timed_wait(g, ptNow + ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
//--------------------------------------
template <typename Helper>
void testCondVarStd(const std::string& name)
{
std::cout << std::endl;
runTestWithNone<Helper>(testCondVarWaitFor <Helper>, name + "::wait_for()");
runTestWithNone<Helper>(testCondVarWaitUntilSteady<Helper>, name + "::wait_until(), steady time");
runTestWithNone<Helper>(testCondVarWaitUntilSystem<Helper>, name + "::wait_until(), system time");
runTestWithNone<Helper>(testCondVarWaitUntilCustom<Helper>, name + "::wait_until(), custom time");
}
template <typename Helper>
void testCondVarBoost(const std::string& name)
{
testCondVarStd<Helper>(name);
// Boost-only functions
runTestWithNone<Helper>(testCondVarTimedWaitRelative<Helper>, name + "::timed_wait(), relative time");
runTestWithNone<Helper>(testCondVarTimedWaitAbsolute<Helper>, name + "::timed_wait(), absolute time");
}
/******************************************************************************/
// Test Condition Variable Wait with Predicate
template <typename Helper>
void testCondVarWaitForPred(const long long jumpMs)
{
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool noTimeout = cv.wait_for(g, Helper::waitDur, returnFalse);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
}
template <typename Helper>
void testCondVarWaitUntilPredSteady(const long long jumpMs)
{
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool noTimeout = cv.wait_until(g, Helper::steadyNow() + Helper::waitDur, returnFalse);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
}
template <typename Helper>
void testCondVarWaitUntilPredSystem(const long long jumpMs)
{
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool noTimeout = cv.wait_until(g, Helper::systemNow() + Helper::waitDur, returnFalse);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
}
template <typename Helper>
void testCondVarWaitUntilPredCustom(const long long jumpMs)
{
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool noTimeout = cv.wait_until(g, Helper::customNow() + Helper::waitDur, returnFalse);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
}
//--------------------------------------
template <typename Helper>
void testCondVarTimedWaitPredRelative(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool noTimeout = cv.timed_wait(g, ptDur, returnFalse);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
template <typename Helper>
void testCondVarTimedWaitPredAbsolute(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::cond cv;
typename Helper::mutex m;
typename Helper::unique_lock g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool noTimeout = cv.timed_wait(g, ptNow + ptDur, returnFalse);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
//--------------------------------------
template <typename Helper>
void testCondVarPredStd(const std::string& name)
{
std::cout << std::endl;
runTestWithNone<Helper>(testCondVarWaitForPred <Helper>, name + "::wait_for(), with predicate");
runTestWithNone<Helper>(testCondVarWaitUntilPredSteady<Helper>, name + "::wait_until(), with predicate, steady time");
runTestWithNone<Helper>(testCondVarWaitUntilPredSystem<Helper>, name + "::wait_until(), with predicate, system time");
runTestWithNone<Helper>(testCondVarWaitUntilPredCustom<Helper>, name + "::wait_until(), with predicate, custom time");
}
template <typename Helper>
void testCondVarPredBoost(const std::string& name)
{
testCondVarPredStd<Helper>(name);
// Boost-only functions
runTestWithNone<Helper>(testCondVarTimedWaitPredRelative<Helper>, name + "::timed_wait(), with predicate, relative time");
runTestWithNone<Helper>(testCondVarTimedWaitPredAbsolute<Helper>, name + "::timed_wait(), with predicate, absolute time");
}
/******************************************************************************/
// Test Try Lock
template <typename Helper>
void testTryLockFor(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_for(Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryLockUntilSteady(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_until(Helper::steadyNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryLockUntilSystem(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_until(Helper::systemNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryLockUntilCustom(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_until(Helper::customNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
//--------------------------------------
template <typename Helper>
void testTimedLockRelative(typename Helper::mutex& m, const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool succeeded = m.timed_lock(ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
template <typename Helper>
void testTimedLockAbsolute(typename Helper::mutex& m, const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool succeeded = m.timed_lock(ptNow + ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
//--------------------------------------
template <typename Helper>
void testMutexStd(const std::string& name)
{
std::cout << std::endl;
runTestWithUnique<Helper>(testTryLockFor <Helper>, name + "::try_lock_for()");
runTestWithUnique<Helper>(testTryLockUntilSteady<Helper>, name + "::try_lock_until(), steady time");
runTestWithUnique<Helper>(testTryLockUntilSystem<Helper>, name + "::try_lock_until(), system time");
runTestWithUnique<Helper>(testTryLockUntilCustom<Helper>, name + "::try_lock_until(), custom time");
}
template <typename Helper>
void testMutexBoost(const std::string& name)
{
testMutexStd<Helper>(name);
// Boost-only functions
runTestWithUnique<Helper>(testTimedLockRelative<Helper>, name + "::timed_lock(), relative time");
runTestWithUnique<Helper>(testTimedLockAbsolute<Helper>, name + "::timed_lock(), absolute time");
}
/******************************************************************************/
// Test Try Lock Shared
template <typename Helper>
void testTryLockSharedFor(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_shared_for(Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryLockSharedUntilSteady(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_shared_until(Helper::steadyNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryLockSharedUntilSystem(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_shared_until(Helper::systemNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryLockSharedUntilCustom(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_shared_until(Helper::customNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
//--------------------------------------
template <typename Helper>
void testTimedLockSharedRelative(typename Helper::mutex& m, const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool succeeded = m.timed_lock_shared(ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
template <typename Helper>
void testTimedLockSharedAbsolute(typename Helper::mutex& m, const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool succeeded = m.timed_lock_shared(ptNow + ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
//--------------------------------------
template <typename Helper>
void testMutexSharedStd(const std::string& name)
{
std::cout << std::endl;
runTestWithUnique<Helper>(testTryLockSharedFor <Helper>, name + "::try_lock_shared_for()");
runTestWithUnique<Helper>(testTryLockSharedUntilSteady<Helper>, name + "::try_lock_shared_until(), steady time");
runTestWithUnique<Helper>(testTryLockSharedUntilSystem<Helper>, name + "::try_lock_shared_until(), system time");
runTestWithUnique<Helper>(testTryLockSharedUntilCustom<Helper>, name + "::try_lock_shared_until(), custom time");
}
template <typename Helper>
void testMutexSharedBoost(const std::string& name)
{
testMutexSharedStd<Helper>(name);
// Boost-only functions
runTestWithUnique<Helper>(testTimedLockSharedRelative<Helper>, name + "::timed_lock_shared(), relative time");
runTestWithUnique<Helper>(testTimedLockSharedAbsolute<Helper>, name + "::timed_lock_shared(), absolute time");
}
/******************************************************************************/
// Test Try Lock Upgrade
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
template <typename Helper>
void testTryLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_upgrade_for(Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_upgrade_until(Helper::steadyNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_upgrade_until(Helper::systemNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs)
{
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_lock_upgrade_until(Helper::customNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
//--------------------------------------
template <typename Helper>
void testTimedLockUpgradeRelative(typename Helper::mutex& m, const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool succeeded = m.timed_lock_upgrade(ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
template <typename Helper>
void testTimedLockUpgradeAbsolute(typename Helper::mutex& m, const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool succeeded = m.timed_lock_upgrade(ptNow + ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
//--------------------------------------
template <typename Helper>
void testTryUnlockSharedAndLockFor(typename Helper::mutex& m, const long long jumpMs)
{
boost::shared_lock_guard<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_shared_and_lock_for(Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryUnlockSharedAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs)
{
boost::shared_lock_guard<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_shared_and_lock_until(Helper::steadyNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryUnlockSharedAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs)
{
boost::shared_lock_guard<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_shared_and_lock_until(Helper::systemNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryUnlockSharedAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs)
{
boost::shared_lock_guard<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_shared_and_lock_until(Helper::customNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
//--------------------------------------
template <typename Helper>
void testTryUnlockUpgradeAndLockFor(typename Helper::mutex& m, const long long jumpMs)
{
boost::upgrade_lock<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_upgrade_and_lock_for(Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryUnlockUpgradeAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs)
{
boost::upgrade_lock<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::steadyNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryUnlockUpgradeAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs)
{
boost::upgrade_lock<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::systemNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryUnlockUpgradeAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs)
{
boost::upgrade_lock<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::customNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
//--------------------------------------
template <typename Helper>
void testTryUnlockSharedAndLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs)
{
boost::shared_lock_guard<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_shared_and_lock_upgrade_for(Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryUnlockSharedAndLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs)
{
boost::shared_lock_guard<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::steadyNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryUnlockSharedAndLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs)
{
boost::shared_lock_guard<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::systemNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
template <typename Helper>
void testTryUnlockSharedAndLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs)
{
boost::shared_lock_guard<typename Helper::mutex> g(m);
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::customNow() + Helper::waitDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
}
#endif
//--------------------------------------
// Only Boost supports upgrade mutexes
template <typename Helper>
void testMutexUpgradeBoost(const std::string& name)
{
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
std::cout << std::endl;
runTestWithUnique<Helper>(testTryLockUpgradeFor <Helper>, name + "::try_lock_upgrade_for()");
runTestWithUnique<Helper>(testTryLockUpgradeUntilSteady<Helper>, name + "::try_lock_upgrade_until(), steady time");
runTestWithUnique<Helper>(testTryLockUpgradeUntilSystem<Helper>, name + "::try_lock_upgrade_until(), system time");
runTestWithUnique<Helper>(testTryLockUpgradeUntilCustom<Helper>, name + "::try_lock_upgrade_until(), custom time");
runTestWithUnique<Helper>(testTimedLockUpgradeRelative <Helper>, name + "::timed_lock_upgrade(), relative time");
runTestWithUnique<Helper>(testTimedLockUpgradeAbsolute <Helper>, name + "::timed_lock_upgrade(), absolute time");
std::cout << std::endl;
runTestWithShared<Helper>(testTryUnlockSharedAndLockFor <Helper>, name + "::try_unlock_shared_and_lock_for()");
runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilSteady<Helper>, name + "::try_unlock_shared_and_lock_until(), steady time");
runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilSystem<Helper>, name + "::try_unlock_shared_and_lock_until(), system time");
runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilCustom<Helper>, name + "::try_unlock_shared_and_lock_until(), custom time");
std::cout << std::endl;
runTestWithShared<Helper>(testTryUnlockUpgradeAndLockFor <Helper>, name + "::try_unlock_upgrade_and_lock_for()");
runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilSteady<Helper>, name + "::try_unlock_upgrade_and_lock_until(), steady time");
runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilSystem<Helper>, name + "::try_unlock_upgrade_and_lock_until(), system time");
runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilCustom<Helper>, name + "::try_unlock_upgrade_and_lock_until(), custom time");
std::cout << std::endl;
runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockFor <Helper>, name + "::try_unlock_shared_and_lock_upgrade_for()");
runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilSteady<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), steady time");
runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilSystem<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), system time");
runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilCustom<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), custom time");
#endif
}
/******************************************************************************/
// Test Future Wait
template <typename Helper>
void testFutureWaitFor(const long long jumpMs)
{
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (f.wait_for(Helper::waitDur) == Helper::future_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testFutureWaitUntilSteady(const long long jumpMs)
{
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (f.wait_until(Helper::steadyNow() + Helper::waitDur) == Helper::future_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testFutureWaitUntilSystem(const long long jumpMs)
{
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (f.wait_until(Helper::systemNow() + Helper::waitDur) == Helper::future_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testFutureWaitUntilCustom(const long long jumpMs)
{
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (f.wait_until(Helper::customNow() + Helper::waitDur) == Helper::future_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
}
//--------------------------------------
template <typename Helper>
void testFutureTimedWaitRelative(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool noTimeout = f.timed_wait(ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
template <typename Helper>
void testFutureTimedWaitAbsolute(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool noTimeout = f.timed_wait_until(ptNow + ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
//--------------------------------------
template <typename Helper>
void testFutureStd(const std::string& name)
{
std::cout << std::endl;
runTestWithNone<Helper>(testFutureWaitFor <Helper>, name + "::wait_for()");
runTestWithNone<Helper>(testFutureWaitUntilSteady<Helper>, name + "::wait_until(), steady time");
runTestWithNone<Helper>(testFutureWaitUntilSystem<Helper>, name + "::wait_until(), system time");
runTestWithNone<Helper>(testFutureWaitUntilCustom<Helper>, name + "::wait_until(), custom time");
}
template <typename Helper>
void testFutureBoost(const std::string& name)
{
testFutureStd<Helper>(name);
// Boost-only functions
runTestWithNone<Helper>(testFutureTimedWaitRelative<Helper>, name + "::timed_wait(), relative time");
runTestWithNone<Helper>(testFutureTimedWaitAbsolute<Helper>, name + "::timed_wait_until(), absolute time");
}
/******************************************************************************/
// Test Shared Future Wait
template <typename Helper>
void testSharedFutureWaitFor(const long long jumpMs)
{
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::shared_future sf = boost::move(f);
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (sf.wait_for(Helper::waitDur) == Helper::future_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSharedFutureWaitUntilSteady(const long long jumpMs)
{
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::shared_future sf = boost::move(f);
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (sf.wait_until(Helper::steadyNow() + Helper::waitDur) == Helper::future_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSharedFutureWaitUntilSystem(const long long jumpMs)
{
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::shared_future sf = boost::move(f);
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (sf.wait_until(Helper::systemNow() + Helper::waitDur) == Helper::future_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSharedFutureWaitUntilCustom(const long long jumpMs)
{
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::shared_future sf = boost::move(f);
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (sf.wait_until(Helper::customNow() + Helper::waitDur) == Helper::future_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
}
//--------------------------------------
template <typename Helper>
void testSharedFutureTimedWaitRelative(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::shared_future sf = boost::move(f);
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool noTimeout = sf.timed_wait(ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
template <typename Helper>
void testSharedFutureTimedWaitAbsolute(const long long jumpMs)
{
#ifndef SKIP_DATETIME_FUNCTIONS
typename Helper::packaged_task pt(returnFalse);
typename Helper::future f = pt.get_future();
typename Helper::shared_future sf = boost::move(f);
typename Helper::steady_time_point before(Helper::steadyNow());
boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
bool noTimeout = sf.timed_wait_until(ptNow + ptDur);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
#else
checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
#endif
}
//--------------------------------------
template <typename Helper>
void testSharedFutureStd(const std::string& name)
{
std::cout << std::endl;
runTestWithNone<Helper>(testSharedFutureWaitFor <Helper>, name + "::wait_for()");
runTestWithNone<Helper>(testSharedFutureWaitUntilSteady<Helper>, name + "::wait_until(), steady time");
runTestWithNone<Helper>(testSharedFutureWaitUntilSystem<Helper>, name + "::wait_until(), system time");
runTestWithNone<Helper>(testSharedFutureWaitUntilCustom<Helper>, name + "::wait_until(), custom time");
}
template <typename Helper>
void testSharedFutureBoost(const std::string& name)
{
testSharedFutureStd<Helper>(name);
// Boost-only functions
runTestWithNone<Helper>(testSharedFutureTimedWaitRelative<Helper>, name + "::timed_wait(), relative time");
runTestWithNone<Helper>(testSharedFutureTimedWaitAbsolute<Helper>, name + "::timed_wait_until(), absolute time");
}
/******************************************************************************/
// Test Sync Priority Queue
template <typename Helper>
void testSyncPriorityQueuePullFor(const long long jumpMs)
{
boost::sync_priority_queue<int> q;
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSyncPriorityQueuePullUntilSteady(const long long jumpMs)
{
boost::sync_priority_queue<int> q;
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSyncPriorityQueuePullUntilSystem(const long long jumpMs)
{
boost::sync_priority_queue<int> q;
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSyncPriorityQueuePullUntilCustom(const long long jumpMs)
{
boost::sync_priority_queue<int> q;
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
}
//--------------------------------------
// Only Boost supports sync_priority_queue
template <typename Helper>
void testSyncPriorityQueueBoost(const std::string& name)
{
std::cout << std::endl;
runTestWithNone<Helper>(testSyncPriorityQueuePullFor <Helper>, name + "::pull_for()");
runTestWithNone<Helper>(testSyncPriorityQueuePullUntilSteady<Helper>, name + "::pull_until(), steady time");
runTestWithNone<Helper>(testSyncPriorityQueuePullUntilSystem<Helper>, name + "::pull_until(), system time");
runTestWithNone<Helper>(testSyncPriorityQueuePullUntilCustom<Helper>, name + "::pull_until(), custom time");
}
/******************************************************************************/
// Test Sync Timed Queue
template <typename Helper>
void testSyncTimedQueuePullForEmptySteady(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::steady_clock> q;
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSyncTimedQueuePullForEmptySystem(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::system_clock> q;
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSyncTimedQueuePullForEmptyCustom(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::custom_clock> q;
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSyncTimedQueuePullUntilEmptySteady(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::steady_clock> q;
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSyncTimedQueuePullUntilEmptySystem(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::system_clock> q;
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
}
template <typename Helper>
void testSyncTimedQueuePullUntilEmptyCustom(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::custom_clock> q;
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool timeout = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
}
//--------------------------------------
template <typename Helper>
void testSyncTimedQueuePullForNotReadySteady(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::steady_clock> q;
q.push(0, typename Helper::milliseconds(10000)); // a long time
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad);
}
template <typename Helper>
void testSyncTimedQueuePullForNotReadySystem(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::system_clock> q;
q.push(0, typename Helper::milliseconds(10000)); // a long time
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad);
}
template <typename Helper>
void testSyncTimedQueuePullForNotReadyCustom(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::custom_clock> q;
q.push(0, typename Helper::milliseconds(10000)); // a long time
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad);
}
template <typename Helper>
void testSyncTimedQueuePullUntilNotReadySteady(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::steady_clock> q;
q.push(0, typename Helper::milliseconds(10000)); // a long time
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool notReady = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad);
}
template <typename Helper>
void testSyncTimedQueuePullUntilNotReadySystem(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::system_clock> q;
q.push(0, typename Helper::milliseconds(10000)); // a long time
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool notReady = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad);
}
template <typename Helper>
void testSyncTimedQueuePullUntilNotReadyCustom(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::custom_clock> q;
q.push(0, typename Helper::milliseconds(10000)); // a long time
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool notReady = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad);
}
//--------------------------------------
template <typename Helper>
void testSyncTimedQueuePullForSucceedsSteady(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::steady_clock> q;
q.push(0, Helper::waitDur);
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad);
}
template <typename Helper>
void testSyncTimedQueuePullForSucceedsSystem(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::system_clock> q;
q.push(0, Helper::waitDur);
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
}
template <typename Helper>
void testSyncTimedQueuePullForSucceedsCustom(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::custom_clock> q;
q.push(0, Helper::waitDur);
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
}
template <typename Helper>
void testSyncTimedQueuePullUntilSucceedsSteady(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::steady_clock> q;
q.push(0, Helper::steadyNow() + Helper::waitDur);
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = (q.pull_until(Helper::steadyNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad);
}
template <typename Helper>
void testSyncTimedQueuePullUntilSucceedsSystem(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::system_clock> q;
q.push(0, Helper::systemNow() + Helper::waitDur);
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = (q.pull_until(Helper::systemNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
}
template <typename Helper>
void testSyncTimedQueuePullUntilSucceedsCustom(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::custom_clock> q;
q.push(0, Helper::customNow() + Helper::waitDur);
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = (q.pull_until(Helper::customNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
}
//--------------------------------------
template <typename Helper>
void testSyncTimedQueueWaitPullSucceedsSteady(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::steady_clock> q;
q.push(0, Helper::steadyNow() + Helper::waitDur);
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad);
}
template <typename Helper>
void testSyncTimedQueueWaitPullSucceedsSystem(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::system_clock> q;
q.push(0, Helper::systemNow() + Helper::waitDur);
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
}
template <typename Helper>
void testSyncTimedQueueWaitPullSucceedsCustom(const long long jumpMs)
{
boost::sync_timed_queue<int, typename Helper::custom_clock> q;
q.push(0, Helper::customNow() + Helper::waitDur);
int i;
typename Helper::steady_time_point before(Helper::steadyNow());
bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success);
typename Helper::steady_time_point after(Helper::steadyNow());
checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
}
//--------------------------------------
// Only Boost supports sync_timed_queue
template <typename Helper>
void testSyncTimedQueueBoost(const std::string& name)
{
std::cout << std::endl;
runTestWithNone<Helper>(testSyncTimedQueuePullForEmptySteady <Helper>, name + "::pull_for(), empty, steady time");
runTestWithNone<Helper>(testSyncTimedQueuePullForEmptySystem <Helper>, name + "::pull_for(), empty, system time");
runTestWithNone<Helper>(testSyncTimedQueuePullForEmptyCustom <Helper>, name + "::pull_for(), empty, custom time");
runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptySteady<Helper>, name + "::pull_until(), empty, steady time");
runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptySystem<Helper>, name + "::pull_until(), empty, system time");
runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptyCustom<Helper>, name + "::pull_until(), empty, custom time");
std::cout << std::endl;
runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadySteady <Helper>, name + "::pull_for(), not ready, steady time");
runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadySystem <Helper>, name + "::pull_for(), not ready, system time");
runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadyCustom <Helper>, name + "::pull_for(), not ready, custom time");
runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadySteady<Helper>, name + "::pull_until(), not ready, steady time");
runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadySystem<Helper>, name + "::pull_until(), not ready, system time");
runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadyCustom<Helper>, name + "::pull_until(), not ready, custom time");
std::cout << std::endl;
runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsSteady <Helper>, name + "::pull_for(), succeeds, steady time");
runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsSystem <Helper>, name + "::pull_for(), succeeds, system time");
runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsCustom <Helper>, name + "::pull_for(), succeeds, custom time");
runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsSteady<Helper>, name + "::pull_until(), succeeds, steady time");
runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsSystem<Helper>, name + "::pull_until(), succeeds, system time");
runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsCustom<Helper>, name + "::pull_until(), succeeds, custom time");
std::cout << std::endl;
runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsSteady<Helper>, name + "::wait_pull(), succeeds, steady time");
runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsSystem<Helper>, name + "::wait_pull(), succeeds, system time");
runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsCustom<Helper>, name + "::wait_pull(), succeeds, custom time");
}
/******************************************************************************/
int main()
{
std::cout << std::endl;
std::cout << "INFO: This test requires root/Administrator privileges in order to change the system clock." << std::endl;
std::cout << "INFO: Disable NTP while running this test to prevent NTP from changing the system clock." << std::endl;
std::cout << std::endl;
std::cout << "BOOST_HAS_PTHREAD_DELAY_NP: ";
#ifdef BOOST_HAS_PTHREAD_DELAY_NP
std::cout << "YES" << std::endl;
#else
std::cout << "NO" << std::endl;
#endif
std::cout << "BOOST_HAS_NANOSLEEP: ";
#ifdef BOOST_HAS_NANOSLEEP
std::cout << "YES" << std::endl;
#else
std::cout << "NO" << std::endl;
#endif
std::cout << "BOOST_THREAD_SLEEP_FOR_IS_STEADY: ";
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
std::cout << "YES" << std::endl;
#else
std::cout << "NO" << std::endl;
#endif
std::cout << "CLOCK_MONOTONIC: ";
#ifdef CLOCK_MONOTONIC
std::cout << "YES" << std::endl;
#else
std::cout << "NO" << std::endl;
#endif
std::cout << "BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN: ";
#ifdef BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
std::cout << "YES" << std::endl;
#else
std::cout << "NO" << std::endl;
#endif
std::cout << "BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS: ";
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
std::cout << "YES" << std::endl;
#else
std::cout << "NO" << std::endl;
#endif
std::cout << "BOOST_THREAD_V2_SHARED_MUTEX: ";
#ifdef BOOST_THREAD_V2_SHARED_MUTEX
std::cout << "YES" << std::endl;
#else
std::cout << "NO" << std::endl;
#endif
std::cout << "BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC: ";
#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
std::cout << "YES" << std::endl;
#else
std::cout << "NO" << std::endl;
#endif
std::cout << std::endl;
std::cout << "Wait Time: " << s_waitMs << " ms" << std::endl;
std::cout << "Short Jump Time: " << s_shortJumpMs << " ms" << std::endl;
std::cout << "Long Jump Time: " << s_longJumpMs << " ms" << std::endl;
std::cout << "Sleep Before Jump Time: " << s_sleepBeforeJumpMs << " ms" << std::endl;
std::cout << "Max Early Error: " << s_maxEarlyErrorMs << " ms" << std::endl;
std::cout << "Max Late Error: " << s_maxLateErrorMs << " ms" << std::endl;
testSleepBoost <BoostHelper< > >("boost");
testSleepNoIntBoost <BoostHelper< > >("boost");
testSleepNoThreadBoost <BoostHelper< > >("boost");
testSleepNoThreadNoIntBoost<BoostHelper< > >("boost");
testJoinBoost <BoostHelper< > >("boost");
testCondVarBoost <BoostHelper<boost::mutex, boost::condition_variable > >("boost::condition_variable");
testCondVarPredBoost <BoostHelper<boost::mutex, boost::condition_variable > >("boost::condition_variable");
testCondVarBoost <BoostHelper<boost::mutex, boost::condition_variable_any> >("boost::condition_variable_any");
testCondVarPredBoost <BoostHelper<boost::mutex, boost::condition_variable_any> >("boost::condition_variable_any");
testMutexBoost <BoostHelper<boost::timed_mutex > >("boost::timed_mutex");
testMutexBoost <BoostHelper<boost::recursive_timed_mutex > >("boost::recursive_timed_mutex");
testMutexBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex
testMutexSharedBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex
testMutexUpgradeBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex
testFutureBoost <BoostHelper< > >("boost::future");
testSharedFutureBoost <BoostHelper< > >("boost::shared_future");
testSyncPriorityQueueBoost <BoostHelper< > >("boost::sync_priority_queue");
testSyncTimedQueueBoost <BoostHelper< > >("boost::sync_timed_queue");
#ifdef TEST_CPP14_FEATURES
testSleepStd <StdHelper< > >("std");
testSleepNoThreadStd<StdHelper< > >("std");
testCondVarStd <StdHelper<std::mutex, std::condition_variable > >("std::condition_variable");
testCondVarPredStd <StdHelper<std::mutex, std::condition_variable > >("std::condition_variable");
testCondVarStd <StdHelper<std::mutex, std::condition_variable_any> >("std::condition_variable_any");
testCondVarPredStd <StdHelper<std::mutex, std::condition_variable_any> >("std::condition_variable_any");
testMutexStd <StdHelper<std::timed_mutex > >("std::timed_mutex");
testMutexStd <StdHelper<std::recursive_timed_mutex > >("std::recursive_timed_mutex");
testMutexStd <StdHelper<std::shared_timed_mutex > >("std::shared_timed_mutex");
testMutexSharedStd <StdHelper<std::shared_timed_mutex > >("std::shared_timed_mutex");
testFutureStd <StdHelper< > >("std::future");
testSharedFutureStd <StdHelper< > >("std::shared_future");
#endif
std::cout << std::endl;
std::cout << "Number of Tests Run: " << g_numTestsRun << std::endl;
std::cout << "Number of Tests Passed: " << g_numTestsPassed << std::endl;
std::cout << "Number of Tests Failed: " << g_numTestsFailed << std::endl;
return 0;
}