// -*- c++ -*- // Generated by assa-genesis //------------------------------------------------------------------------------ // $Id: rt_test.cpp,v 1.8 2006/07/20 02:30:56 vlg Exp $ //------------------------------------------------------------------------------ // RTTest.cpp //------------------------------------------------------------------------------ // Copyright (c) 2002,2005 by Vladislav Grinchenko // // Permission to use, copy, modify, and distribute this software // and its documentation for any purpose and without fee is hereby // granted, provided that the above copyright notice appear in all // copies. The author makes no representations about the suitability // of this software for any purpose. It is provided "as is" without // express or implied warranty. //------------------------------------------------------------------------------ // // Date : Wed Oct 16 18:00:40 2002 // //------------------------------------------------------------------------------ static const char help_msg[]= " \n" " NAME: \n" " \n" " rt_test \n" " \n" " DESCRIPTION: \n" " \n" " rt_test is a simple test program to validate scheduling/termination \n" " of the Timers with the Reactor. We test installation, expiration, \n" " cancellation and rescheduling of a set of Timers. \n" " \n" " USAGE: \n" " \n" " shell> rt_test [OPTIONS] \n" " \n" " OPTIONS: \n" " \n" " -t, --max-timers NUM - Number of timers to run. (default: 5) \n" " \n" " -D, --log-file NAME - Write debug to NAME file \n" " -d, --log-stdout - Write debug to standard output \n" " -z, --log-size NUM - Maximum size debug file can reach (dfl: is 10Mb) \n" " -m, --mask MASK - Mask (default: ALL = 0x7fffffff) \n" " -h, --help - Print this messag \n" " -v, --version - Print version number \n"; //------------------------------------------------------------------------------ #include #include using namespace std; #include "assa/EventHandler.h" #include "assa/GenServer.h" #include "assa/Singleton.h" #include "assa/Reactor.h" #include "assa/Assure.h" using namespace ASSA; static int done; static const size_t MAXTIMERS = 20; TimeVal zt (TimeVal::zeroTime ()); // Non-blocking wait (spin) inline bool isEven (const int n_) { return (n_ & 1) == 0; } static void log_header (const string& msg_) { cout << msg_; DL((APP,"%s\n", msg_.c_str ())); } /****************************************************************************** Class Timer_Handler_1 ******************************************************************************/ class Timer_Handler_1 : public EventHandler { public: Timer_Handler_1 (); int handle_timeout (TimerId); void set_id (TimerId tid_) { m_tid = tid_; } private: TimerId m_tid; public: static void count_plus () { m_count++; } static void count_minus () { m_count--; } static u_int count () { return m_count; } private: static int m_count; }; int Timer_Handler_1::m_count = 0; /******************************************************************************* Timer_Handler_1 member function ******************************************************************************/ Timer_Handler_1:: Timer_Handler_1 () : m_tid (0) { trace("Timer_Handler_1::Timer_Handler_1"); } int Timer_Handler_1:: handle_timeout (TimerId tid_) { trace("Timer_Handler_1::handle_timeout"); std::ostringstream msg; DL((APP,"tid_ = %d, m_tid = %d\n", tid_, m_tid)); Assure_exit (tid_ == m_tid); msg << "Timer # " << m_tid << " timed out on " << TimeVal::gettimeofday().fmt_hh_mm_ss () << std::ends; DL((APP,"%s\n", msg.str().c_str ())); Timer_Handler_1::count_minus (); if (Timer_Handler_1::count () == 0) { // Done? DL((APP,"All timers done!\n")); done = 1; } return 0; } /****************************************************************************** Class Timer_Handler_2 ******************************************************************************/ class Timer_Handler_2 : public EventHandler { public: Timer_Handler_2 (); ~Timer_Handler_2 (); Timer_Handler_2 operator++(); Timer_Handler_2 operator++(int); Timer_Handler_2 operator--(); Timer_Handler_2 operator--(int); void resetCount (void); int getCount (void) const; virtual int handle_timeout (TimerId); private: int m_count; }; /******************************************************************************* Timer_Handler_2 member function *******************************************************************************/ Timer_Handler_2:: Timer_Handler_2 () : m_count (0) { trace("Timer_Handler_2::Timer_Handler_2"); } Timer_Handler_2:: ~Timer_Handler_2 () { trace("Timer_Handler_2::~Timer_Handler_2"); DL((APP,"m_count - %d\n",m_count)); } Timer_Handler_2 Timer_Handler_2:: operator++() // prefix { m_count++; return *this; } Timer_Handler_2 Timer_Handler_2:: operator++(int) // postfix { Timer_Handler_2 th = *this; ++*this; return th; } Timer_Handler_2 Timer_Handler_2:: operator--() // prefix { m_count--; return *this; } Timer_Handler_2 Timer_Handler_2:: operator--(int) // postfix { Timer_Handler_2 th = *this; --*this; return th; } void Timer_Handler_2:: resetCount (void) { trace("Timer_Handler_2::incrementCount"); m_count=0; DL((APP,"m_count reset to 0\n")); } int Timer_Handler_2:: getCount (void) const { return m_count; } int Timer_Handler_2:: handle_timeout (TimerId /* tid */) { trace("Timer_Handler_2::handle_timeout"); std::ostringstream msg; msg << "Count # " << m_count << " timed out on " << TimeVal::gettimeofday().fmt_hh_mm_ss (); DL((APP,"%s\n", msg.str().c_str ())); DL((APP,"m_count: %d before test\n",m_count)); if (--m_count == 0) { DL((APP,"All timers done!\n")); done = 1; } DL((APP,"m_count: %d after test\n", m_count)); return 0; } /****************************************************************************** Class Timer_Handler_3 Timer_Handler_3 will reschedule itself count_ times with the Reactor. ******************************************************************************/ class Timer_Handler_3 : public EventHandler { public: Timer_Handler_3 (int count_); ~Timer_Handler_3 (); virtual int handle_timeout (TimerId); Timer_Handler_3 operator++(); Timer_Handler_3 operator++(int); Timer_Handler_3 operator--(); Timer_Handler_3 operator--(int); int getCount (void) const; private: int m_count; // how many times to reschedule }; /******************************************************************************* Timer_Handler_3 member function *******************************************************************************/ Timer_Handler_3:: Timer_Handler_3 (int count_) : m_count (count_) { trace("Timer_Handler_3::Timer_Handler_3"); } Timer_Handler_3:: ~Timer_Handler_3 () { trace("Timer_Handler_3::~Timer_Handler_3"); DL((APP,"m_count - %d\n",m_count)); } Timer_Handler_3 Timer_Handler_3:: operator++() // prefix { m_count++; return *this; } Timer_Handler_3 Timer_Handler_3:: operator++(int) // postfix { Timer_Handler_3 th = *this; ++*this; return th; } Timer_Handler_3 Timer_Handler_3:: operator--() // prefix { m_count--; return *this; } Timer_Handler_3 Timer_Handler_3:: operator--(int) // postfix { Timer_Handler_3 th = *this; --*this; return th; } int Timer_Handler_3:: getCount (void) const { return m_count; } int Timer_Handler_3:: handle_timeout (TimerId /* tid */) { trace("Timer_Handler_3::handle_timeout"); std::ostringstream msg; msg << "Count # " << m_count << " timed out on " << TimeVal::gettimeofday().fmt_hh_mm_ss (); DL((APP,"%s\n", msg.str().c_str ())); DL((APP,"m_count: %d before test\n",m_count)); if (--m_count == 0) { DL((APP,"All timers done!\n")); done = 1; return 0; } DL((APP,"m_count: %d after test - rescheduling ...\n", m_count)); return 1; } /****************************************************************************** Class RTTest ******************************************************************************/ class RTTest : public GenServer, public Singleton { public: RTTest (); virtual void init_service (); virtual void process_events (); private: TimeVal m_tv; int m_max_timers; // Number of timers to run }; /* Useful definitions */ #define RTTEST RTTest::get_instance() #define REACTOR RTTEST->get_reactor() // Static declarations mandated by Singleton class ASSA_DECL_SINGLETON(RTTest); /****************************************************************************** Class RTTest member functions ******************************************************************************/ RTTest::RTTest () : m_max_timers (5) { add_opt ('t', "max-timers", &m_max_timers); // ---Configuration--- rm_opt ('f', "config-file" ); rm_opt ('n', "instance" ); rm_opt ('p', "port" ); // ---Process bookkeeping--- rm_opt ('b', "daemon" ); rm_opt ('l', "pidfile" ); rm_opt ('L', "ommit-pidfile"); m_mask = ASSA::APP | ASSA::ASSAERR; m_log_file = "rt_test.log"; } void RTTest:: init_service () { trace("RTTest::init_service"); Log::disable_timestamp (); DL((APP,"Service has been initialized\n")); } void RTTest:: process_events () { trace("RTTest::process_events"); string msg; size_t i; //---------------------------------------------------------------------- log_header ("TEST 1: Testing registration of different Timers.\n"); Timer_Handler_1 thI [m_max_timers]; for (i=0; i < m_max_timers; i++) { m_tv = 2*i+1; thI [i].set_id (REACTOR->registerTimerHandler (&thI [i], m_tv)); Timer_Handler_1::count_plus (); } done = 0; while (!done && service_is_active ()) { REACTOR->waitForEvents (&zt); } if (!service_is_active ()) { std::cout << "Test failed\n"; set_exit_value (1); return; } //---------------------------------------------------------------------- log_header ("TEST 2: Testing multiple registration the same Timer.\n"); Timer_Handler_2 th2; for (i=0; i < m_max_timers; i++) { m_tv = 2*i+1; th2++; REACTOR->registerTimerHandler (&th2, m_tv); } done = 0; DL((APP,"Timer_Handler_2::m_count - %d\n",th2.getCount ())); while (!done && service_is_active ()) { DL((APP,"Timer_Handler_2::m_count - %d\n", th2.getCount ())); REACTOR->waitForEvents (&zt); } if (!service_is_active ()) { std::cout << "Test failed\n"; set_exit_value (1); return; } //---------------------------------------------------------------------- log_header ("TEST 3: Testing Timer rescheduling.\n"); Timer_Handler_3 th3 (5); REACTOR->registerTimerHandler (&th3, m_tv, "multi-timer"); DL((APP,"Timer_Handler_3::m_count - %d\n", th3.getCount ())); done = 0; while (!done && service_is_active ()) { DL((APP,"Timer_Handler_3::m_count - %d\n", th3.getCount ())); REACTOR->waitForEvents (&zt); } if (!service_is_active ()) { std::cout << "Test failed\n"; set_exit_value (1); return; } //---------------------------------------------------------------------- log_header ("TEST 4: Testing Timer cancellation by TimerId.\n"); Timer_Handler_2 th4; int tid; for (i=0; i < m_max_timers; i++) { m_tv = 2*i+1; th4++; tid = REACTOR->registerTimerHandler (&th4, m_tv); if (isEven (i)) { assert (REACTOR->removeTimerHandler (tid)); th4--; } } done = 0; while (!done && service_is_active ()) { REACTOR->waitForEvents (&zt); } if (!service_is_active ()) { std::cout << "Test failed\n"; set_exit_value (1); return; } //---------------------------------------------------------------------- msg = "Test passed\n"; std::cout << msg << std::flush; DL((APP,"%s\n", msg.c_str())); m_reactor.stopReactor (); DL((APP,"Service stopped!\n")); } /******************************************************************************/ #ifdef HAVE_CONFIG_H # include "config.h" #endif int main (int argc, char* argv[]) { static const char release[] = "VERSION"; int patch_level = 0; std::cout << "= Running rt_test Test =\n"; RTTEST->set_version (release, patch_level); RTTEST->set_author ("Vladislav Grinchenko"); RTTEST->set_flags (GenServer::RMLOG); RTTEST->init (&argc, argv, help_msg); RTTEST->init_service (); RTTEST->process_events (); return RTTEST->get_exit_value (); }