00001 //////////////////////////////////////////////////////////////////////////////// 00002 /// 00003 /// \file 00004 /// \author Gerald Fahrnholz 00005 /// 00006 /// \defgroup GrpPollingCheck Using PollingCheck 00007 /// @{ 00008 /// \ingroup GrpTestUtils 00009 /// \brief 00010 /// Class PollingCheck allows to repeatedly execute a funtional check 00011 /// for some condition until it becomes true or a timeout has elapsed. 00012 /// 00013 /// In the context of testing this function should only be used when the 00014 /// following conditions apply: 00015 /// - the condition represents the reaction of an test object 00016 /// - the reaction occures asynchronously after some trigger action 00017 /// - there is no other way to detect the moment of reaction (e.g. 00018 /// by receiving a notification about some state change) 00019 /// 00020 /// The check of the condition is implemented within a boolean user function. 00021 /// The user function can optionally make use of any other test features 00022 /// (e.g. writing/ checking TestEvents). 00023 /// 00024 /// <b>\n Concept for PollingCheck::Run</b>\n 00025 /// A user definable function/functor is repeatedly called until 00026 /// the return value is true. If the user function returns false 00027 /// the next call is executed after a definable sleep time. 00028 /// The polling stops as soon as the user function returns true or a definable 00029 /// timeout value has been reached. 00030 /// The return value of Run() indicates whether the condition was fulfilled. 00031 /// The return value can be checked with one of the following methods: 00032 /// - if 00033 /// - assert 00034 /// - BOOST_CHECK 00035 /// - convenience macro POLL_VERIFY (requires usage of some EventReceiver class 00036 /// e.g. TTB::EventReceiverStdOut) 00037 /// 00038 /// <b>\n Elementar usage with if, assert, bind, BOOST_CHECK</b>\n 00039 /// \code 00040 /// 00041 /// bool VerifyCounterIsZero () 00042 /// {return s_pSomeTestObject->GetCounter() == 0;} 00043 /// 00044 /// bool VerifyCounterHasValue ( 00045 /// int in_value) 00046 /// {return s_pSomeTestObject->GetCounter() == in_value;} 00047 /// 00048 /// ... 00049 /// 00050 /// // Configure timeouts used for polling 00051 /// TTB::ThePollingCheck()->SetSleepTimeMs(100); 00052 /// TTB::ThePollingCheck()->SetTimeoutMs(500); 00053 /// 00054 /// // check with if 00055 /// if (!TTB::ThePollingCheck()->Run(&VerifyCounterIsZero)) 00056 /// { 00057 /// cout << "VerifyCounterIsZero failed!" << endl; 00058 /// } 00059 /// 00060 /// // check with assert 00061 /// assert(TTB::ThePollingCheck()->Run(&VerifyCounterIsZero)); 00062 /// 00063 /// // Check with Boost verification macro 00064 /// BOOST_CHECK(TTB::ThePollingCheck()->Run(&VerifyCounterIsZero)); 00065 /// 00066 /// // using bind to make use of any number of function arguments 00067 /// assert(TTB::ThePollingCheck()->Run(boost::bind(&VerifyCounterHasValue,98))); 00068 /// 00069 /// // directly using the member function to check 00070 /// assert(TTB::ThePollingCheck()->Run(boost::bind( 00071 /// &SomeTestObject::GetCounter, 00072 /// s_pSomeTestObject)==94)); 00073 /// \endcode 00074 /// 00075 /// <b>\n Convenience macro POLL_VERIFY</b>\n 00076 /// \code 00077 /// // define an EventReceiver to process events detected from the execution and 00078 /// // compare mechanism (e.g. use TTB::EventReceiverStdOut) 00079 /// TTB::EventReceiverStdOut eventReceiver; 00080 /// TTB::ThePollingCheck()->SetEventReceiver(&eventReceiver); 00081 /// // optional: configure amount of infos written to stdout 00082 /// // eventReceiver.SetOutputFilter(TTB::CTX_ONLY_ERROR); 00083 /// 00084 /// // Macro for use with free functions (other variants support also member functions) 00085 /// POLL_VERIFY_F1(VerifyCounterHasValue, 96); 00086 /// \endcode 00087 /// In case of error the following output is produced: 00088 /// \code 00089 /// <VerifyCounterHasValue 96 [polling] 00090 /// INFO: Poll-Timeout after 515 ms 00091 /// c:\userdata\gerald\sw\c\testtoolbox\test\testpollingcheck\testpollingcheck.cpp (184): POLL-ERROR: verification failed 00092 /// \endcode 00093 /// 00094 /// \sa PollingCheck.h (File documentation) 00095 /// \sa TestToolBox::PollingCheck (class documentation) 00096 /// \sa GrpTestPollingCheck (unit test for class Environment) 00097 /// 00098 //////////////////////////////////////////////////////////////////////////////// 00099 00100 #pragma once 00101 00102 #include <boost/function.hpp> 00103 00104 struct IEventReceiver; 00105 00106 //************************************************************************ 00107 00108 namespace TestToolBox 00109 { 00110 00111 //! \brief Defines a boolean functor without arguments 00112 typedef boost::function<bool()> BoolFunctor; 00113 00114 00115 //************************************************************************ 00116 //************************************************************************ 00117 00118 00119 /// Convenience macros (output of called function and possible error results via EventReceiver) 00120 00121 /// Using memberfunction 00122 #define POLL_VERIFY(Func) \ 00123 {TTB::ThePollingCheck()->Run(boost::bind(&Func,this),#Func,"", __FILE__, __LINE__);} 00124 00125 /// Using member function with single argument 00126 #define POLL_VERIFY1(Func,arg) \ 00127 {TTB::ThePollingCheck()->Run(boost::bind(&Func,this,arg),#Func,#arg, __FILE__, __LINE__);} 00128 00129 /// Using free function 00130 #define POLL_VERIFY_F(Func) \ 00131 {TTB::ThePollingCheck()->Run(boost::bind(&Func),#Func,"", __FILE__, __LINE__);} 00132 00133 /// Using free function with single argument 00134 #define POLL_VERIFY_F1(Func,arg) \ 00135 {TTB::ThePollingCheck()->Run(boost::bind(&Func,arg),#Func,#arg, __FILE__, __LINE__);} 00136 00137 00138 00139 //************************************************************************ 00140 //************************************************************************ 00141 00142 00143 /// \brief Repeated polling until some condition comes true. 00144 /// For more info about usage see \ref GrpPollingCheck. 00145 /// 00146 /// \nosubgrouping 00147 /// \sa PollingCheck.h (File documentation) 00148 /// \sa GrpTestPollingCheck (unit test for class Environment) 00149 /// \sa GrpPollingCheck (Usage documentation) 00150 class PollingCheck 00151 { 00152 public: 00153 00154 ///\cond do not document 00155 00156 // Constructor 00157 PollingCheck(); 00158 00159 // Destructor 00160 virtual ~PollingCheck(); 00161 00162 // Get the pointer to the only instance of this class 00163 static PollingCheck* Get (void) 00164 {if (!s_pPollingCheck) s_pPollingCheck = new PollingCheck; 00165 return s_pPollingCheck;} 00166 static PollingCheck* s_pPollingCheck; 00167 ///\endcond 00168 00169 //--------------------------------------------------------------- 00170 //! \name Configuration 00171 //! \{ 00172 00173 /// Set initial sleep time before making the first call 00174 void SetInitialSleepTimeMs (long in_timeMs) 00175 {m_initialSleepTimeMs = in_timeMs;} 00176 00177 /// Set delay time between the repeated polling calls 00178 void SetSleepTimeMs (long in_timeMs) 00179 {m_sleepTimeMs = in_timeMs;} 00180 00181 /// When this amount of time has elapsed the polling will be stopped with failure 00182 void SetTimeoutMs (long in_timeMs) 00183 {m_timeoutMs = in_timeMs;} 00184 00185 /// Define to which destination test events (e.g. failures) are reported 00186 void SetEventReceiver (IEventReceiver* in_pEventReceiver) 00187 {m_pEventReceiver = in_pEventReceiver;} 00188 00189 /// \} 00190 00191 //--------------------------------------------------------------- 00192 /// \name Execute polling 00193 /// \{ 00194 00195 00196 /// \brief Execute the check for some condition by calling repeatedly the 00197 /// functor until true is returned or the configured timeout has elapsed. 00198 /// 00199 /// \return false if condition was not fulfilled and timeout has elapsed 00200 bool Run( 00201 BoolFunctor in_functor, ///< function checking condition 00202 char const * in_functionName = 0, ///< optional function name for protocol 00203 char const * in_argValue = 0, ///< optional argument value for protocol 00204 char const * in_file = 0, ///< optional file name used in case of error 00205 long in_lineNum = 0 ///< optional line number used in case of error 00206 ); 00207 00208 /// \} 00209 00210 00211 protected: 00212 00213 /// Initial sleep time before making the first call 00214 long m_initialSleepTimeMs; 00215 00216 /// Delay time between the repeated calls 00217 long m_sleepTimeMs; 00218 00219 /// \brief When this amount of time has elapsed the polling will 00220 /// be stopped with failure 00221 long m_timeoutMs; 00222 00223 /// Interface for receiving all kind of test events 00224 IEventReceiver* m_pEventReceiver; 00225 00226 00227 }; // class PollingCheck 00228 00229 ///\cond do not document 00230 __declspec(selectany) PollingCheck* PollingCheck::s_pPollingCheck = 0; 00231 ///\endcond 00232 00233 /// Access/create the singleton instance of PollingCheck 00234 PollingCheck* ThePollingCheck (void) 00235 {return PollingCheck::Get();} 00236 00237 00238 //************************************************************************ 00239 //************************************************************************ 00240 00241 } // namespace TestToolBox 00242 00243 ///@} // end group GrpPollingCheck 00244