// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #include <sstream> #include <string> #include <cstdlib> #include <ctime> #include <dlib/timer.h> #include <dlib/timeout.h> #include "tester.h" namespace { using namespace test; using namespace std; using namespace dlib; logger dlog("test.timer"); class timer_test_helper { public: dlib::mutex m; int count; dlib::uint64 timestamp; dlib::timestamper ts; timer_test_helper():count(0), timestamp(0){} void add() { m.lock(); ++count; m.unlock(); } void delayed_add() { dlib::sleep(1000); print_spinner(); add(); } void set_timestamp() { m.lock(); timestamp = ts.get_timestamp(); dlog << LTRACE << "in set_timestamp(), time is " << timestamp; dlib::sleep(1); print_spinner(); m.unlock(); } }; template < typename timer_t > void timer_test2 ( ) /*! requires - timer_t is an implementation of dlib/timer/timer_abstract.h is instantiated timer_test_helper ensures - runs tests on timer_t for compliance with the specs !*/ { for (int j = 0; j < 4; ++j) { print_spinner(); timer_test_helper h; timer_t t1(h,&timer_test_helper::set_timestamp); t1.set_delay_time(0); dlog << LTRACE << "t1.start()"; t1.start(); dlib::sleep(60); print_spinner(); t1.stop_and_wait(); dlib::uint64 cur_time = h.ts.get_timestamp(); dlog << LTRACE << "get current time: " << cur_time; // make sure the action function has been called recently DLIB_TEST_MSG((cur_time-h.timestamp)/1000 < 30, (cur_time-h.timestamp)/1000); } } template < typename timer_t > void timer_test ( ) /*! requires - timer_t is an implementation of dlib/timer/timer_abstract.h is instantiated timer_test_helper ensures - runs tests on timer_t for compliance with the specs !*/ { print_spinner(); for (int j = 0; j < 3; ++j) { timer_test_helper h; timer_t t1(h,&timer_test_helper::add); timer_t t2(h,&timer_test_helper::add); timer_t t3(h,&timer_test_helper::add); DLIB_TEST(t1.delay_time() == 1000); DLIB_TEST(t2.delay_time() == 1000); DLIB_TEST(t3.delay_time() == 1000); DLIB_TEST(t1.is_running() == false); DLIB_TEST(t2.is_running() == false); DLIB_TEST(t3.is_running() == false); DLIB_TEST(t1.action_function() == &timer_test_helper::add); DLIB_TEST(t2.action_function() == &timer_test_helper::add); DLIB_TEST(t3.action_function() == &timer_test_helper::add); DLIB_TEST(&t1.action_object() == &h); DLIB_TEST(&t2.action_object() == &h); DLIB_TEST(&t3.action_object() == &h); t1.set_delay_time(1000); t2.set_delay_time(500); t3.set_delay_time(200); DLIB_TEST(t1.delay_time() == 1000); DLIB_TEST(t2.delay_time() == 500); DLIB_TEST(t3.delay_time() == 200); DLIB_TEST(t1.is_running() == false); DLIB_TEST(t2.is_running() == false); DLIB_TEST(t3.is_running() == false); DLIB_TEST(t1.action_function() == &timer_test_helper::add); DLIB_TEST(t2.action_function() == &timer_test_helper::add); DLIB_TEST(t3.action_function() == &timer_test_helper::add); DLIB_TEST(&t1.action_object() == &h); DLIB_TEST(&t2.action_object() == &h); DLIB_TEST(&t3.action_object() == &h); dlib::sleep(1100); print_spinner(); DLIB_TEST(h.count == 0); t1.stop_and_wait(); t2.stop_and_wait(); t3.stop_and_wait(); dlib::sleep(1100); print_spinner(); DLIB_TEST(h.count == 0); DLIB_TEST(t1.delay_time() == 1000); DLIB_TEST(t2.delay_time() == 500); DLIB_TEST(t3.delay_time() == 200); DLIB_TEST(t1.is_running() == false); DLIB_TEST(t2.is_running() == false); DLIB_TEST(t3.is_running() == false); DLIB_TEST(t1.action_function() == &timer_test_helper::add); DLIB_TEST(t2.action_function() == &timer_test_helper::add); DLIB_TEST(t3.action_function() == &timer_test_helper::add); DLIB_TEST(&t1.action_object() == &h); DLIB_TEST(&t2.action_object() == &h); DLIB_TEST(&t3.action_object() == &h); t1.start(); t2.start(); t3.start(); DLIB_TEST(t1.delay_time() == 1000); DLIB_TEST(t2.delay_time() == 500); DLIB_TEST(t3.delay_time() == 200); DLIB_TEST(t1.is_running() == true); DLIB_TEST(t2.is_running() == true); DLIB_TEST(t3.is_running() == true); DLIB_TEST(t1.action_function() == &timer_test_helper::add); DLIB_TEST(t2.action_function() == &timer_test_helper::add); DLIB_TEST(t3.action_function() == &timer_test_helper::add); DLIB_TEST(&t1.action_object() == &h); DLIB_TEST(&t2.action_object() == &h); DLIB_TEST(&t3.action_object() == &h); t1.stop(); t2.stop(); t3.stop(); DLIB_TEST(t1.delay_time() == 1000); DLIB_TEST(t2.delay_time() == 500); DLIB_TEST(t3.delay_time() == 200); DLIB_TEST(t1.is_running() == false); DLIB_TEST(t2.is_running() == false); DLIB_TEST(t3.is_running() == false); DLIB_TEST(t1.action_function() == &timer_test_helper::add); DLIB_TEST(t2.action_function() == &timer_test_helper::add); DLIB_TEST(t3.action_function() == &timer_test_helper::add); DLIB_TEST(&t1.action_object() == &h); DLIB_TEST(&t2.action_object() == &h); DLIB_TEST(&t3.action_object() == &h); DLIB_TEST(h.count == 0); dlib::sleep(1100); print_spinner(); DLIB_TEST(h.count == 0); for (int i = 1; i <= 3; ++i) { t1.start(); t2.start(); t3.start(); DLIB_TEST(t1.is_running() == true); DLIB_TEST(t2.is_running() == true); DLIB_TEST(t3.is_running() == true); dlib::sleep(1100); print_spinner(); // this should allow the timers to trigger 8 times t1.stop(); t2.stop(); t3.stop(); DLIB_TEST_MSG(h.count == 8*i,"h.count: " << h.count << " i: " << i); dlib::sleep(1100); DLIB_TEST_MSG(h.count == 8*i,"h.count: " << h.count << " i: " << i); } t1.stop_and_wait(); h.count = 0; t1.start(); dlib::sleep(300); print_spinner(); DLIB_TEST_MSG(h.count == 0,h.count); t1.set_delay_time(400); dlib::sleep(200); print_spinner(); DLIB_TEST_MSG(h.count == 1,h.count); dlib::sleep(250); print_spinner(); DLIB_TEST_MSG(h.count == 1,h.count); dlib::sleep(100); print_spinner(); DLIB_TEST_MSG(h.count == 2,h.count); t1.set_delay_time(2000); DLIB_TEST_MSG(h.count == 2,h.count); dlib::sleep(1000); print_spinner(); DLIB_TEST_MSG(h.count == 2,h.count); t1.clear(); h.count = 0; t3.start(); DLIB_TEST(t3.is_running() == true); DLIB_TEST(t3.delay_time() == 200); DLIB_TEST_MSG(h.count == 0,h.count); t3.clear(); DLIB_TEST(t3.is_running() == false); DLIB_TEST(t3.delay_time() == 1000); DLIB_TEST_MSG(h.count == 0,h.count); dlib::sleep(200); print_spinner(); DLIB_TEST(t3.is_running() == false); DLIB_TEST(t3.delay_time() == 1000); DLIB_TEST_MSG(h.count == 0,h.count); { h.count = 0; timer_t t4(h,&timer_test_helper::delayed_add); t4.set_delay_time(100); t4.start(); DLIB_TEST_MSG(h.count == 0,h.count); dlib::sleep(400); print_spinner(); DLIB_TEST_MSG(h.count == 0,h.count); t4.stop_and_wait(); DLIB_TEST_MSG(h.count == 1,h.count); DLIB_TEST(t4.is_running() == false); } { h.count = 0; timer_t t4(h,&timer_test_helper::delayed_add); t4.set_delay_time(100); t4.start(); DLIB_TEST_MSG(h.count == 0,h.count); dlib::sleep(400); print_spinner(); DLIB_TEST_MSG(h.count == 0,h.count); t4.clear(); DLIB_TEST(t4.is_running() == false); DLIB_TEST_MSG(h.count == 0,h.count); t4.stop_and_wait(); DLIB_TEST_MSG(h.count == 1,h.count); DLIB_TEST(t4.is_running() == false); } { h.count = 0; timer_t t5(h,&timer_test_helper::delayed_add); t5.set_delay_time(100); t5.start(); DLIB_TEST_MSG(h.count == 0,h.count); dlib::sleep(400); print_spinner(); DLIB_TEST_MSG(h.count == 0,h.count); } DLIB_TEST_MSG(h.count == 1,h.count); } } class timer_tester : public tester { public: timer_tester ( ) : tester ("test_timer", "Runs tests on the timer component.") {} void perform_test ( ) { dlog << LINFO << "testing timer_heavy with test_timer"; timer_test<timer_heavy<timer_test_helper> > (); dlog << LINFO << "testing timer_heavy with test_timer2"; timer_test2<timer_heavy<timer_test_helper> > (); dlog << LINFO << "testing timer with test_timer"; timer_test<timer<timer_test_helper> > (); dlog << LINFO << "testing timer with test_timer2"; timer_test2<timer<timer_test_helper> > (); } } a; }