From cd05d46c007583a27be23e2ae8cedc5ea9746373 Mon Sep 17 00:00:00 2001 From: Tim Mayberry Date: Mon, 14 Sep 2015 10:33:48 +1000 Subject: [PATCH] Add windows specific test for pbd/windows_timer_utils.h API --- libs/pbd/test/windows_timer_utils_test.cc | 163 ++++++++++++++++++++++ libs/pbd/test/windows_timer_utils_test.h | 15 ++ libs/pbd/wscript | 2 + 3 files changed, 180 insertions(+) create mode 100644 libs/pbd/test/windows_timer_utils_test.cc create mode 100644 libs/pbd/test/windows_timer_utils_test.h diff --git a/libs/pbd/test/windows_timer_utils_test.cc b/libs/pbd/test/windows_timer_utils_test.cc new file mode 100644 index 0000000000..fe5e1a24df --- /dev/null +++ b/libs/pbd/test/windows_timer_utils_test.cc @@ -0,0 +1,163 @@ +#include "windows_timer_utils_test.h" + +#include "pbd/windows_timer_utils.h" + +#include + +#include + +using namespace std; + +CPPUNIT_TEST_SUITE_REGISTRATION (WindowsTimerUtilsTest); + +void +WindowsTimerUtilsTest::testQPC () +{ + CPPUNIT_ASSERT (PBD::QPC::get_timer_valid()); + + int64_t last_timer_val = PBD::QPC::get_microseconds (); + CPPUNIT_ASSERT (last_timer_val >= 0); + + int64_t min_interval = 1000000; + int64_t max_interval = 0; + + for (int i = 0; i < 10000; ++i) { + int64_t timer_val = PBD::QPC::get_microseconds (); + CPPUNIT_ASSERT (timer_val >= 0); + // try and test for non-syncronized TSC(AMD K8/etc) + CPPUNIT_ASSERT (timer_val >= last_timer_val); + min_interval = std::min (min_interval, timer_val - last_timer_val); + // We may get swapped out so a max interval is not so informative + max_interval = std::max (max_interval, timer_val - last_timer_val); + last_timer_val = timer_val; + } + + cout << endl; + cout << "Min QPC interval = " << min_interval << endl; + cout << "Max QPC interval = " << max_interval << endl; +} + +namespace { + +void get_tgt_granularity(uint32_t& min_elapsed, + uint32_t& max_elapsed, + uint32_t& avg_elapsed) +{ + min_elapsed = 1000; + max_elapsed = 0; + uint32_t count = 64; + uint32_t total_elapsed = 0; + + uint32_t last_time_ms = timeGetTime(); + for (uint32_t i = 0; i < count;) { + uint32_t current_time_ms = timeGetTime(); + if (current_time_ms == last_time_ms) continue; + uint32_t elapsed = current_time_ms - last_time_ms; + cout << "TGT elapsed = " << elapsed << endl; + min_elapsed = std::min (min_elapsed, elapsed); + max_elapsed = std::max (max_elapsed, elapsed); + total_elapsed += elapsed; + last_time_ms = current_time_ms; + ++i; + } + avg_elapsed = total_elapsed / count; +} + +void get_sleep_granularity(uint32_t& min_elapsed, + uint32_t& max_elapsed, + uint32_t& avg_elapsed) +{ + min_elapsed = 1000; + max_elapsed = 0; + uint32_t count = 64; + uint32_t total_elapsed = 0; + + uint32_t last_time_ms = timeGetTime(); + for (uint32_t i = 0; i < count; ++i) { + Sleep(1); + uint32_t current_time_ms = timeGetTime(); + uint32_t elapsed = current_time_ms - last_time_ms; + cout << "Sleep elapsed = " << elapsed << endl; + min_elapsed = std::min (min_elapsed, current_time_ms - last_time_ms); + max_elapsed = std::max (max_elapsed, current_time_ms - last_time_ms); + total_elapsed += elapsed; + last_time_ms = current_time_ms; + } + avg_elapsed = total_elapsed / count; +} + +void +test_tgt_granularity (const std::string& test_name, uint32_t& tgt_avg_elapsed) +{ + uint32_t tgt_min_elapsed = 0; + uint32_t tgt_max_elapsed = 0; + + get_tgt_granularity( + tgt_min_elapsed, tgt_max_elapsed, tgt_avg_elapsed); + + cout << endl; + cout << "TGT " << test_name << " min elapsed = " << tgt_min_elapsed << endl; + cout << "TGT " << test_name << " max elapsed = " << tgt_max_elapsed << endl; + cout << "TGT " << test_name << " avg elapsed = " << tgt_avg_elapsed << endl; +} + +void +test_sleep_granularity (const std::string& test_name, uint32_t& sleep_avg_elapsed) +{ + uint32_t sleep_min_elapsed = 0; + uint32_t sleep_max_elapsed = 0; + + get_sleep_granularity( + sleep_min_elapsed, sleep_max_elapsed, sleep_avg_elapsed); + + cout << endl; + cout << "Sleep " << test_name << " min elapsed = " << sleep_min_elapsed << endl; + cout << "Sleep " << test_name << " max elapsed = " << sleep_max_elapsed << endl; + cout << "Sleep " << test_name << " avg elapsed = " << sleep_avg_elapsed << endl; +} + +} // namespace + +/** + * This test will not succeed if the current system wide timer resolution is + * already at the minimum but in most cases it won't be and it will test + * whether setting the minimum timer resolution is successful. + */ +void +WindowsTimerUtilsTest::testMMTimers () +{ + uint32_t min_timer_res = 0; + CPPUNIT_ASSERT (PBD::MMTIMERS::get_min_resolution (min_timer_res)); + CPPUNIT_ASSERT (min_timer_res == 1); + + uint32_t avg_orig_res_tgt_elapsed = 0; + + test_tgt_granularity ("Original Timer Resolution", avg_orig_res_tgt_elapsed); + + uint32_t avg_orig_res_sleep_elapsed = 0; + + test_sleep_granularity ("Original Timer Resolution", avg_orig_res_sleep_elapsed); + + // set the min timer resolution + CPPUNIT_ASSERT (PBD::MMTIMERS::set_min_resolution ()); + + uint32_t avg_min_res_tgt_elapsed = 0; + + test_tgt_granularity ("Minimum Timer Resolution", avg_min_res_tgt_elapsed); + + // test that it is less than original granularity + CPPUNIT_ASSERT (avg_min_res_tgt_elapsed < avg_orig_res_tgt_elapsed); + + uint32_t avg_min_res_sleep_elapsed = 0; + + test_sleep_granularity ("Minimum Timer Resolution", avg_min_res_sleep_elapsed); + + // test that it is less than original granularity + CPPUNIT_ASSERT (avg_min_res_sleep_elapsed < avg_orig_res_sleep_elapsed); + + CPPUNIT_ASSERT (PBD::MMTIMERS::reset_resolution()); + + // You can't test setting the max timer resolution because AFAIR Windows + // will use the minimum requested resolution of all the applications on the + // system. +} diff --git a/libs/pbd/test/windows_timer_utils_test.h b/libs/pbd/test/windows_timer_utils_test.h new file mode 100644 index 0000000000..11ab4a45b4 --- /dev/null +++ b/libs/pbd/test/windows_timer_utils_test.h @@ -0,0 +1,15 @@ +#include +#include + +class WindowsTimerUtilsTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE (WindowsTimerUtilsTest); + CPPUNIT_TEST (testQPC); + CPPUNIT_TEST (testMMTimers); + CPPUNIT_TEST_SUITE_END (); + +public: + void testQPC (); + void testMMTimers (); + +}; diff --git a/libs/pbd/wscript b/libs/pbd/wscript index ed79593dd0..2d832669d1 100644 --- a/libs/pbd/wscript +++ b/libs/pbd/wscript @@ -165,6 +165,8 @@ def build(bld): test/xml_test.cc test/test_common.cc '''.split() + if bld.env['build_target'] == 'mingw': + testobj.source += [ 'test/windows_timer_utils_test.cc' ] testobj.target = 'run-tests' testobj.includes = obj.includes + ['test', '../pbd'] testobj.uselib = 'CPPUNIT XML SNDFILE'