diff options
Diffstat (limited to 'libs/pbd/test/timer_test.cc')
-rw-r--r-- | libs/pbd/test/timer_test.cc | 550 |
1 files changed, 550 insertions, 0 deletions
diff --git a/libs/pbd/test/timer_test.cc b/libs/pbd/test/timer_test.cc new file mode 100644 index 0000000000..7c78b9c3c0 --- /dev/null +++ b/libs/pbd/test/timer_test.cc @@ -0,0 +1,550 @@ +#include "timer_test.h" + +#include <iostream> +#include <sstream> +#include <algorithm> + +#include "pbd/timer.h" + +#ifdef PLATFORM_WINDOWS +#include <windows.h> +#endif + +CPPUNIT_TEST_SUITE_REGISTRATION (TimerTest); + +using namespace std; + +#ifdef PLATFORM_WINDOWS +UINT& +min_timer_resolution () +{ + static UINT min_res_ms = 0; + return min_res_ms; +} + +bool +set_min_timer_resolution () +{ + TIMECAPS caps; + + if (timeGetDevCaps(&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) { + cerr << "Could not get timer device capabilities..." << endl; + } else { + if (timeBeginPeriod(caps.wPeriodMin) != TIMERR_NOERROR) { + cerr << "Could not set minimum timer resolution to: " << caps.wPeriodMin << "ms" << endl; + return false; + } + else { + cerr << "Multimedia timer resolution set to: " << caps.wPeriodMin << "ms" << endl; + min_timer_resolution() = caps.wPeriodMin; + return true; + } + } + return false; +} + +bool +reset_timer_resolution () +{ + if (min_timer_resolution()) { + if (timeEndPeriod(min_timer_resolution()) != TIMERR_NOERROR) { + cerr << "Could not reset timer resolution" << endl; + return false; + } else { + cerr << "Multimedia timer resolution reset" << endl; + return true; + } + } + return true; +} + +#endif + +void +TimerTest::simulate_load (const string& name, guint64 load_usecs) +{ + PBD::Timing timing; + std::ostringstream oss; + oss << name << " Load."; + + guint64 i = 0; + do { + timing.update (); + + // totally arbitrary + if (i % 10000 == 0) { + oss << "."; + } + + ++i; + } while (timing.elapsed () < load_usecs); + + oss << "Expected = " << load_usecs; + oss << ", Elapsed = " << timing.elapsed (); + oss << endl; + //cerr << oss.str(); +} + +void +TimerTest::on_second_timeout () +{ + cerr << endl; + cerr << "Timing Summary: " << m_current_test_name << endl; + + if (m_idle_timing_data.size()) { + cerr << "Idle Timing: " << m_idle_timing_data.summary(); + } + if (m_fast_timing_data.size()) { + cerr << "Fast Timing: " << m_fast_timing_data.summary(); + } + if (m_rapid1_timing_data.size()) { + cerr << "Rapid1 Timing: " << m_rapid1_timing_data.summary(); + } + if (m_rapid2_timing_data.size()) { + cerr << "Rapid2 Timing: " << m_rapid2_timing_data.summary(); + } + reset_timing (); +} + +bool +TimerTest::on_second_timeout_glibmm () +{ + TimerTest::on_second_timeout (); + return true; +} + +void +TimerTest::on_fast_timeout () +{ + m_fast_timing_data.add_interval (); + if (m_block_idle) { + // do nothing, handled in rapid timers + } else { + simulate_load ("Rapid1", 4000); + } +} + +bool +TimerTest::on_fast_timeout_glibmm () +{ + on_fast_timeout (); + return true; +} + +void +TimerTest::on_rapid1_timeout () +{ + m_rapid1_timing_data.add_interval (); + if (m_block_idle) { + simulate_load ("Rapid1", rapid1_timer_usecs () * 0.5); + } else { + simulate_load ("Rapid1", 2000); + } +} + +bool +TimerTest::on_rapid1_timeout_glibmm () +{ + on_rapid1_timeout (); + return true; +} + +void +TimerTest::on_rapid2_timeout () +{ + m_rapid2_timing_data.add_interval (); + if (m_block_idle) { + simulate_load ("Rapid2", rapid2_timer_usecs () * 0.5); + } else { + simulate_load ("Rapid2", 2000); + } +} + +bool +TimerTest::on_rapid2_timeout_glibmm () +{ + on_rapid2_timeout (); + return true; +} + +bool +TimerTest::on_idle_handler () +{ + m_idle_timing_data.add_interval (); + if (m_block_idle) { + simulate_load ("Idle", rapid2_timer_usecs ()); + } + return true; +} + +bool +TimerTest::on_quit_handler () +{ + cerr << "Quit Handler" << endl; + m_main->quit (); + return false; +} + +void +TimerTest::reset_timing () +{ + m_idle_timing_data.reset (); + m_fast_timing_data.reset (); + m_rapid1_timing_data.reset (); + m_rapid2_timing_data.reset (); +} + +void +TimerTest::start_timing () +{ + m_idle_timing_data.start_timing (); + m_fast_timing_data.start_timing (); + m_rapid1_timing_data.start_timing (); + m_rapid2_timing_data.start_timing (); +} + +gboolean +TimerTest::_second_timeout_handler (void *data) +{ + TimerTest *const tt = static_cast<TimerTest*>(data); + tt->on_second_timeout (); + return TRUE; +} + +gboolean +TimerTest::_fast_timeout_handler (void *data) +{ + TimerTest *const tt = static_cast<TimerTest*>(data); + tt->on_fast_timeout (); + return TRUE; +} + +gboolean +TimerTest::_rapid1_timeout_handler (void *data) +{ + TimerTest *const tt = static_cast<TimerTest*>(data); + tt->on_rapid1_timeout (); + return TRUE; +} + +gboolean +TimerTest::_rapid2_timeout_handler (void *data) +{ + TimerTest *const tt = static_cast<TimerTest*>(data); + tt->on_rapid2_timeout (); + return TRUE; +} + +void +TimerTest::reset_timing_run_main () +{ + reset_timing (); + start_timing (); + + connect_quit_timeout (); + + m_main = Glib::MainLoop::create (m_context); + m_main->run (); +} + +void +TimerTest::testGlibTimeoutSources () +{ + m_current_test_name = "testGlibTimeoutSources"; + _testGlibTimeoutSources (); +} + +void +TimerTest::_testGlibTimeoutSources () +{ + m_context = Glib::MainContext::create (); + + GSource * second_timeout_source = g_timeout_source_new (second_timer_ms ()); + + g_source_set_callback (second_timeout_source , &TimerTest::_second_timeout_handler, this, NULL); + + g_source_attach (second_timeout_source, m_context->gobj()); + + if (m_connect_idle) { + connect_idle_handler (); + reset_timing_run_main (); + } + + GSource * fast_timeout_source = g_timeout_source_new (fast_timer_ms ()); + + g_source_set_callback (fast_timeout_source , &TimerTest::_fast_timeout_handler, this, NULL); + + g_source_attach (fast_timeout_source, m_context->gobj()); + + // now run with fast timeout + reset_timing_run_main (); + + GSource * rapid1_timeout_source = g_timeout_source_new (rapid1_timer_ms ()); + + g_source_set_callback (rapid1_timeout_source , &TimerTest::_rapid1_timeout_handler, this, NULL); + + g_source_attach (rapid1_timeout_source, m_context->gobj()); + + // now run with fast and rapid1 timeouts + reset_timing_run_main (); + + GSource * rapid2_timeout_source = g_timeout_source_new (rapid2_timer_ms ()); + + g_source_set_callback (rapid2_timeout_source , &TimerTest::_rapid2_timeout_handler, this, NULL); + + g_source_attach (rapid2_timeout_source, m_context->gobj()); + + // now run with fast, rapid1 and rapid2 timeouts + reset_timing_run_main (); + + // cleanup + g_source_destroy (second_timeout_source); + g_source_unref (second_timeout_source); + + g_source_destroy (fast_timeout_source); + g_source_unref (fast_timeout_source); + + g_source_destroy (rapid1_timeout_source); + g_source_unref (rapid1_timeout_source); + + g_source_destroy (rapid2_timeout_source); + g_source_unref (rapid2_timeout_source); +} + +void +TimerTest::testGlibmmSignalTimeouts () +{ + m_current_test_name = "testGlibmmSignalTimeouts"; + _testGlibmmSignalTimeouts (); +} + +void +TimerTest::_testGlibmmSignalTimeouts () +{ + m_context = Glib::MainContext::get_default (); + + Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_second_timeout_glibmm), second_timer_ms()); + + if (m_connect_idle) { + connect_idle_handler (); + reset_timing_run_main (); + } + + Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_fast_timeout_glibmm), fast_timer_ms()); + + reset_timing_run_main (); + + Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_rapid1_timeout_glibmm), rapid1_timer_ms()); + + reset_timing_run_main (); + + Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_rapid2_timeout_glibmm), rapid2_timer_ms()); + + reset_timing_run_main (); +} + +void +TimerTest::testGlibmmTimeoutSources () +{ + m_current_test_name = "testGlibmmTimeoutSources"; + _testGlibmmTimeoutSources (); +} + +void +TimerTest::_testGlibmmTimeoutSources () +{ + m_context = Glib::MainContext::create (); + + const Glib::RefPtr<Glib::TimeoutSource> second_source = Glib::TimeoutSource::create(second_timer_ms()); + second_source->connect(sigc::mem_fun(*this, &TimerTest::on_second_timeout_glibmm)); + + second_source->attach(m_context); + + if (m_connect_idle) { + connect_idle_handler (); + reset_timing_run_main (); + } + + const Glib::RefPtr<Glib::TimeoutSource> fast_source = Glib::TimeoutSource::create(fast_timer_ms()); + fast_source->connect(sigc::mem_fun(*this, &TimerTest::on_fast_timeout_glibmm)); + + fast_source->attach(m_context); + + reset_timing_run_main (); + + const Glib::RefPtr<Glib::TimeoutSource> rapid1_source = Glib::TimeoutSource::create(rapid1_timer_ms()); + sigc::connection rapid1_connection = rapid1_source->connect(sigc::mem_fun(*this, &TimerTest::on_rapid1_timeout_glibmm)); + + rapid1_source->attach(m_context); + + reset_timing_run_main (); + + const Glib::RefPtr<Glib::TimeoutSource> rapid2_source = Glib::TimeoutSource::create(rapid2_timer_ms()); + sigc::connection rapid2_connection = rapid2_source->connect(sigc::mem_fun(*this, &TimerTest::on_rapid2_timeout_glibmm)); + + rapid2_source->attach(m_context); + + reset_timing_run_main (); +} + +void +TimerTest::connect_idle_handler () +{ + const Glib::RefPtr<Glib::IdleSource> idle_source = Glib::IdleSource::create(); + idle_source->connect(sigc::mem_fun(*this, &TimerTest::on_idle_handler)); + + idle_source->attach(m_context); +} + +void +TimerTest::connect_quit_timeout () +{ + const Glib::RefPtr<Glib::TimeoutSource> quit_source = Glib::TimeoutSource::create(test_length_ms()); + quit_source->connect(sigc::mem_fun(*this, &TimerTest::on_quit_handler)); + + quit_source->attach(m_context); +} + +void +TimerTest::testTimers () +{ + m_current_test_name = "testTimers"; + _testTimers (); +} + +void +TimerTest::_testTimers () +{ + m_context = Glib::MainContext::create (); + + PBD::StandardTimer second_timer (second_timer_ms (), m_context); + sigc::connection second_connection = second_timer.connect (sigc::mem_fun (this, &TimerTest::on_second_timeout)); + + if (m_connect_idle) { + connect_idle_handler (); + // let the idle handler run as fast as it can + reset_timing_run_main(); + } + + PBD::StandardTimer fast_timer (fast_timer_ms (), m_context); + sigc::connection fast_connection = fast_timer.connect (sigc::mem_fun (this, &TimerTest::on_fast_timeout)); + + reset_timing_run_main(); + + PBD::StandardTimer rapid1_timer (rapid1_timer_ms (), m_context); + sigc::connection rapid1_connection = rapid1_timer.connect (sigc::mem_fun (this, &TimerTest::on_rapid1_timeout)); + + reset_timing_run_main(); + + PBD::StandardTimer rapid2_timer (rapid2_timer_ms (), m_context); + sigc::connection rapid2_connection = rapid2_timer.connect (sigc::mem_fun (this, &TimerTest::on_rapid2_timeout)); + + reset_timing_run_main(); +} + +void +TimerTest::testTimersIdleFrequency () +{ + m_current_test_name = "testTimersIdleFrequency"; + _testTimersIdleFrequency (); +} + +void +TimerTest::_testTimersIdleFrequency () +{ + m_block_idle = false; + m_connect_idle = true; + + _testTimers (); + + m_block_idle = false; + m_connect_idle = false; +} + +void +TimerTest::testTimersBlockIdle () +{ + m_current_test_name = "testTimersBlockIdle"; + _testTimersBlockIdle (); +} + +void +TimerTest::_testTimersBlockIdle () +{ + m_block_idle = true; + m_connect_idle = true; + + _testTimers (); + + m_block_idle = false; + m_connect_idle = false; +} + +#ifdef PLATFORM_WINDOWS +void +TimerTest::testGlibTimeoutSourcesHR () +{ + CPPUNIT_ASSERT(set_min_timer_resolution()); + + m_current_test_name = "testGlibTimeoutSourcesHR"; + _testGlibTimeoutSources (); + + CPPUNIT_ASSERT(reset_timer_resolution()); +} + +void +TimerTest::testGlibmmSignalTimeoutsHR () +{ + CPPUNIT_ASSERT(set_min_timer_resolution()); + + m_current_test_name = "testGlibmmSignalTimeoutsHR"; + _testGlibmmSignalTimeouts (); + + CPPUNIT_ASSERT(reset_timer_resolution()); +} + +void +TimerTest::testGlibmmTimeoutSourcesHR () +{ + CPPUNIT_ASSERT(set_min_timer_resolution()); + + m_current_test_name = "testGlibmmTimeoutSourcesHR"; + _testGlibmmTimeoutSources (); + + CPPUNIT_ASSERT(reset_timer_resolution()); +} + +void +TimerTest::testTimersHR () +{ + CPPUNIT_ASSERT(set_min_timer_resolution()); + + m_current_test_name = "testTimersHR"; + _testTimers (); + + CPPUNIT_ASSERT(reset_timer_resolution()); +} + +void +TimerTest::testTimersIdleFrequencyHR () +{ + CPPUNIT_ASSERT(set_min_timer_resolution()); + + m_current_test_name = "testTimersIdleFrequencyHR"; + _testTimersIdleFrequency (); + + CPPUNIT_ASSERT(reset_timer_resolution()); +} + +void +TimerTest::testTimersBlockIdleHR () +{ + CPPUNIT_ASSERT(set_min_timer_resolution()); + + m_current_test_name = "testTimersIdleFrequencyHR"; + _testTimersBlockIdle (); + + CPPUNIT_ASSERT(reset_timer_resolution()); +} + +#endif |