(file) Return to test_timer.cpp CVS log (file) (dir) Up to [OMI] / omi / tests / base

  1 krisbash 1.1 #include <ut/ut.h>
  2              #include <base/Strand.h>
  3              #include <pal/sleep.h>
  4              
  5              #if defined(CONFIG_OS_WINDOWS)
  6              #include <windows.h>
  7              #endif
  8              
  9              using namespace std;
 10              
 11              struct TimerFakeStrand
 12              {
 13                  Strand strand;
 14              
 15                  MI_Uint32 callbackCounter;
 16                  PAL_Uint64 timeoutTime;
 17                  TimerReason reason;
 18              };
 19              
 20              NITS_EXTERN_C void TimerTest_Post_NO_OP( _In_ Strand* self_, _In_ Message* msg)
 21              {
 22 krisbash 1.1     MI_UNUSED( msg );
 23                  MI_UNUSED(self_);
 24              }
 25              
 26              NITS_EXTERN_C void TimerTest_PostControl_NO_OP( _In_ Strand* self, _In_ Message* msg)
 27              {
 28                  MI_UNUSED( self );
 29                  MI_UNUSED( msg );
 30              }
 31              
 32              NITS_EXTERN_C void TimerTest_Ack_NO_OP( _In_ Strand* self )
 33              {
 34                  MI_UNUSED( self );
 35              }
 36              
 37              NITS_EXTERN_C void TimerTest_Close_NO_OP( _In_ Strand* self_ )
 38              {
 39                  MI_UNUSED( self_ );
 40              }
 41              
 42              NITS_EXTERN_C void TimerTest_Finish_NO_OP( _In_ Strand* self_ )
 43 krisbash 1.1 {
 44                  MI_UNUSED( self_ );
 45              }
 46              
 47              NITS_EXTERN_C void TimerTest_UserCallback(
 48                  _In_ Strand* self,
 49                  TimerReason reason)
 50              {
 51                  TimerFakeStrand* fakeStrand = (TimerFakeStrand*)self;
 52              
 53                  fakeStrand->callbackCounter++;
 54                  fakeStrand->reason = reason;
 55              
 56                  NitsAssert( MI_TRUE == PAL_Time(&fakeStrand->timeoutTime), PAL_T("Unable to get end time") );    
 57              }
 58              
 59              /*
 60               * StrandFT functions and table for a faked "Left" side of an interaction.
 61               */
 62              static StrandFT TimerTest_Left_InteractionFT =
 63              {
 64 krisbash 1.1     TimerTest_Post_NO_OP, 
 65                  TimerTest_PostControl_NO_OP, 
 66                  TimerTest_Ack_NO_OP,
 67                  NULL, 
 68                  TimerTest_Close_NO_OP,
 69                  TimerTest_Finish_NO_OP,
 70                  TimerTest_UserCallback,
 71                  NULL,
 72                  NULL,
 73                  NULL,
 74                  NULL,
 75                  NULL 
 76              };
 77              
 78              Selector testSelector;  // For POSIX implementations
 79              TimerFakeStrand timerTestStrand; // Implemented as a "left" strand
 80              
 81              static const MI_Uint64 FIFTY_MILLISECONDS_AS_USEC = 50 * 1000;
 82              static const MI_Uint64 SIXTY_SECONDS_AS_USEC = 60 * 1000 * 1000;
 83              
 84              
 85 krisbash 1.1 //
 86              // Basic checks on uninitialized structures.
 87              //
 88              NitsTest0(TimerTest_CloseOrFire_on_Uninitialized_Does_Nothing)
 89              {
 90                  Timer timer;
 91              
 92                  memset( &timer, 0, sizeof(Timer) );
 93              
 94                  Timer_Close( &timer );
 95                  NitsAssert( TimerReason_Expired == timer.reason, PAL_T("Value should not be changed") );
 96              
 97                  Timer_Fire( &timer, &timerTestStrand.strand, TimerReason_ManuallyFired );
 98                  NitsAssert( TimerReason_Expired == timer.reason, PAL_T("Value should not be changed") );
 99              }
100              NitsEndTest
101              
102              STRAND_DEBUGNAME(TestTimer);
103              
104              //
105              // Initializes a Selector and Strand for timer tests.
106 krisbash 1.1 //
107              NitsSetup0(TimerTest_SetupSelectorAndStrand, NitsEmptyStruct)
108              {        
109                  // Note: This is not required for Windows, but it is included for test uniformity
110                  memset( &testSelector, 0, sizeof(Selector) );
111              
112                  NitsAssert( MI_RESULT_OK == Selector_Init( &testSelector ), PAL_T("Unable to initialize Selector") );
113              
114                  Timer_SetSelector(&testSelector);
115              
116                  // Strand initialization is needed for all test flavors
117                  memset( &timerTestStrand, 0, sizeof(TimerFakeStrand) );
118                  Strand_Init( STRAND_DEBUG(TestTimer) &timerTestStrand.strand, &TimerTest_Left_InteractionFT, STRAND_FLAG_ENTERSTRAND, NULL );
119              }
120              NitsEndSetup
121              
122              NitsCleanup(TimerTest_SetupSelectorAndStrand)
123              {
124                  // Posix-specific test cleanup
125                  Selector_Destroy( &testSelector );
126                  Timer_SetSelector( NULL );
127 krisbash 1.1 }
128              NitsEndCleanup
129              
130              //
131              // Verifies that a timeout occurs within a reasonable amount of time after the
132              // specified time.
133              //
134              NitsTest1(TimerTest_BasicTimeout_Success, TimerTest_SetupSelectorAndStrand, NitsEmptyValue)
135              {
136                  NitsFaultSimMarkForRerun;
137                  Timer timer;
138                  PAL_Uint64 startTimeUsec = 0;
139              
140                  memset( &timer, 0, sizeof(Timer) );
141              
142                  timerTestStrand.callbackCounter = 0;
143                  NitsAssert( MI_TRUE == PAL_Time(&startTimeUsec), PAL_T("Unable to get start time") );    
144              
145                  Strand_StartTimer( &timerTestStrand.strand, &timer, FIFTY_MILLISECONDS_AS_USEC );
146                  Strand_Leave( &timerTestStrand.strand );
147              
148 krisbash 1.1     while (0 == timerTestStrand.callbackCounter)
149                  {
150                      // This is specific to non-Windows, but it acts as a wait loop for Windows
151                      // as well depending on the length of the timeout value.
152                      Selector_Run( &testSelector, SELECT_BASE_TIMEOUT_MSEC * 1000, MI_FALSE );
153                  }
154              
155                  // "Natural" because it was not manually triggered
156                  NitsAssert( TimerReason_Expired == timerTestStrand.reason, PAL_T("Triggered flag not set correctly") );
157                  NitsAssert( 1 == timerTestStrand.callbackCounter, PAL_T("Only one callback call expected") );
158              
159                  /* Verify that the timeout occurred after waiting at least 50 milliseconds */
160                  NitsAssert( timerTestStrand.timeoutTime-startTimeUsec >= FIFTY_MILLISECONDS_AS_USEC, PAL_T("Timeout took shorter than expected") );
161              }
162              NitsEndTest
163              
164              //
165              // Verifies that Strand_FireTimer works in a normal scenario.
166              //
167              NitsTest1(TimerTest_BasicFireTimer, TimerTest_SetupSelectorAndStrand, NitsEmptyValue)
168              {
169 krisbash 1.1     NitsFaultSimMarkForRerun;
170                  Timer timer;
171                  PAL_Uint64 startTimeUsec = 0;
172              
173                  memset( &timer, 0, sizeof(Timer) );
174              
175                  timerTestStrand.callbackCounter = 0;
176                  NitsAssert( MI_TRUE == PAL_Time(&startTimeUsec), PAL_T("Unable to get start time") );    
177              
178                  Strand_StartTimer( &timerTestStrand.strand, &timer, SIXTY_SECONDS_AS_USEC ); // Large value to ensure that the timer gets manually triggered.  The system will not actually wait this long unless the test case fails.
179                  Strand_Leave( &timerTestStrand.strand );
180              
181                  // Manually trigger the timer early
182                  Timer_Fire( &timer, &timerTestStrand.strand, TimerReason_ManuallyFired );
183              
184                  while (0 == timerTestStrand.callbackCounter)
185                  {
186                      // This is specific to non-Windows, but it acts as a wait loop for Windows
187                      // as well depending on the length of the timeout value.
188                      Selector_Run( &testSelector, SELECT_BASE_TIMEOUT_MSEC * 1000, MI_FALSE );
189                  }
190 krisbash 1.1 
191                  // Manually triggered, so it is not "natural."
192                  NitsAssert( TimerReason_ManuallyFired == timerTestStrand.reason, PAL_T("Triggered flag not set correctly") );
193                  NitsAssert( 1 == timerTestStrand.callbackCounter, PAL_T("Only one callback call expected") );
194              }
195              NitsEndTest
196              
197              //
198              // Verifies that the timer is fired/closed uppon strand finish.
199              //
200              NitsTest1(TimerTest_StrandFinish, TimerTest_SetupSelectorAndStrand, NitsEmptyValue)
201              {
202                  NitsFaultSimMarkForRerun;
203                  Timer timer;
204                  PAL_Uint64 startTimeUsec = 0;
205              
206                  memset( &timer, 0, sizeof(Timer) );
207              
208                  timerTestStrand.callbackCounter = 0;
209                  NitsAssert( MI_TRUE == PAL_Time(&startTimeUsec), PAL_T("Unable to get start time") );    
210              
211 krisbash 1.1     Strand_StartTimer( &timerTestStrand.strand, &timer, SIXTY_SECONDS_AS_USEC ); // Large value to ensure that the timer gets canceled.  The system will not actually wait this long unless the test case fails.
212              
213                  // Simutlate closed interaction
214                  timerTestStrand.strand.info.thisAckPending = timerTestStrand.strand.info.otherAckPending = MI_FALSE;
215                  timerTestStrand.strand.info.thisClosedOther = timerTestStrand.strand.info.otherClosedThis = MI_TRUE;
216                  
217                  Strand_Leave( &timerTestStrand.strand );
218              
219                  while (0 == timerTestStrand.callbackCounter)
220                  {
221                      // This is specific to non-Windows, but it acts as a wait loop for Windows
222                      // as well depending on the length of the timeout value.
223                      Selector_Run( &testSelector, SELECT_BASE_TIMEOUT_MSEC * 1000, MI_FALSE );
224                  }
225                  
226                  // It should be Canceled
227                  NitsAssert( TimerReason_Canceled == timerTestStrand.reason, PAL_T("Triggered flag not set correctly") );
228                  NitsAssert( 1 == timerTestStrand.callbackCounter, PAL_T("Only one callback call expected") );
229              }
230              NitsEndTest
231              
232 krisbash 1.1 
233              //
234              // Verifies that it is OK to have Strand_FireTimer called twice prior to the 
235              // Strand's timer method getting called.  This simulates a race between two
236              // threads to trigger a timer.
237              //
238              NitsTest1(TimerTest_DoubleFireTimer, TimerTest_SetupSelectorAndStrand, NitsEmptyValue)
239              {
240                  NitsFaultSimMarkForRerun;
241                  Timer timer;
242                  PAL_Uint64 startTimeUsec = 0;
243              
244                  memset( &timer, 0, sizeof(Timer) );
245              
246                  timerTestStrand.callbackCounter = 0;
247                  NitsAssert( MI_TRUE == PAL_Time(&startTimeUsec), PAL_T("Unable to get start time") );    
248              
249                  Strand_StartTimer( &timerTestStrand.strand, &timer, SIXTY_SECONDS_AS_USEC ); // Large value to ensure that the timer gets manually triggered.  The system will not actually wait this long unless the test case fails.
250                  Strand_Leave( &timerTestStrand.strand );
251              
252                  // Manually trigger the timer early twice
253 krisbash 1.1     Timer_Fire( &timer, &timerTestStrand.strand, TimerReason_ManuallyFired );
254                  Timer_Fire( &timer, &timerTestStrand.strand, TimerReason_ManuallyFired );
255              
256                  while (0 == timerTestStrand.callbackCounter)
257                  {
258                      // This is specific to non-Windows, but it acts as a wait loop for Windows
259                      // as well depending on the length of the timeout value.
260                      Selector_Run( &testSelector, SELECT_BASE_TIMEOUT_MSEC * 1000, MI_FALSE );
261                  }
262              
263                  // Manually triggered, so it is not a "natural" timeout
264                  NitsAssert( TimerReason_ManuallyFired == timerTestStrand.reason, PAL_T("Triggered flag not set correctly") );
265                  NitsAssert( 1 == timerTestStrand.callbackCounter, PAL_T("Only one callback call expected") );
266              }
267              NitsEndTest
268              
269              //
270              // Verifies that calling Timer_Start twice has no effect on the timer's timeout.
271              //
272              NitsTest1(TimerTest_DoubleStart, TimerTest_SetupSelectorAndStrand, NitsEmptyValue)
273              {
274 krisbash 1.1     NitsFaultSimMarkForRerun;
275                  Timer timer;
276                  PAL_Uint64 startTimeUsec = 0;
277              
278                  memset( &timer, 0, sizeof(Timer) );
279              
280                  timerTestStrand.callbackCounter = 0;
281                  NitsAssert( MI_TRUE == PAL_Time(&startTimeUsec), PAL_T("Unable to get start time") );
282              
283                  Strand_StartTimer( &timerTestStrand.strand, &timer, FIFTY_MILLISECONDS_AS_USEC );
284                  Strand_Leave( &timerTestStrand.strand );
285              
286                  // Manually call Timer_Start a second time.  It should fail and not interfere
287                  // with the timer already started.
288                  NitsAssert( TimerResult_InvalidArgument == Timer_Start( &timer, &timerTestStrand.strand ), PAL_T("Start while already running not supported") );
289              
290                  while (0 == timerTestStrand.callbackCounter)
291                  {
292                      // This is specific to non-Windows, but it acts as a wait loop for Windows
293                      // as well depending on the length of the timeout value.
294                      Selector_Run( &testSelector, SELECT_BASE_TIMEOUT_MSEC * 1000, MI_FALSE );
295 krisbash 1.1     }
296              
297                  // "Natural" because it was not manually triggered
298                  NitsAssert( TimerReason_Expired == timerTestStrand.reason, PAL_T("Triggered flag not set correctly") );
299                  NitsAssert( 1 == timerTestStrand.callbackCounter, PAL_T("Only one callback call expected") );
300              
301                  /* Verify that the timeout occurred after waiting at least 50 milliseconds */
302                  NitsAssert( timerTestStrand.timeoutTime-startTimeUsec >= FIFTY_MILLISECONDS_AS_USEC, PAL_T("Timeout took shorter than expected") );
303              }
304              NitsEndTest
305              
306              
307              #if defined(CONFIG_POSIX)
308              
309              NitsTest0(TimerTest_Start_Without_Selector_Fails_Posix)
310              {
311                  Timer timer;
312              
313                  memset( &timer, 0, sizeof(Timer) );
314              
315                  TimerResult result = Timer_Start( &timer, &timerTestStrand.strand );
316 krisbash 1.1 
317                  NitsAssert( TimerResult_InvalidArgument == result, PAL_T("Selector required for operation") );
318              }
319              NitsEndTest
320              
321              #endif // #if defined(CONFIG_POSIX)

ViewCVS 0.9.2