1 #include <windows.h> 2 #include <stdio.h> 3 #include <tchar.h> 4 5 #define N_TIMEOUT 3 6 7 /*******************************************************************************/ 8 9 typedef struct _TEST *PTEST; 10 11 typedef VOID (*PFNTEST)(PTEST Test, HANDLE hEvent); 12 13 typedef struct _TEST 14 { 15 TCHAR *description; 16 BOOL Result; 17 PFNTEST Routine; 18 int id; 19 } TEST; 20 21 static TEST Tests[3]; 22 23 VOID RunTests(VOID) 24 { 25 int i, nTests; 26 static HANDLE hEvent; 27 28 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 29 if(hEvent == NULL) 30 { 31 _tprintf(_T("Unable to create event!")); 32 return; 33 } 34 35 nTests = sizeof(Tests) / sizeof(TEST); 36 37 for(i = 0; i < nTests; i++) 38 { 39 Tests[i].id = i + 1; 40 41 if(Tests[i].Routine == NULL) 42 { 43 continue; 44 } 45 46 _tprintf(_T("+++ TEST %d: %s\n"), Tests[i].id, Tests[i].description); 47 48 Tests[i].Routine(&Tests[i], hEvent); 49 50 WaitForSingleObject(hEvent, INFINITE); 51 52 _tprintf(_T("\n\n")); 53 } 54 55 CloseHandle(hEvent); 56 } 57 58 VOID PrintTestResults(VOID) 59 { 60 int i, nTests, nsuccess = 0, nfailed = 0; 61 TCHAR *status; 62 63 nTests = sizeof(Tests) / sizeof(TEST); 64 65 for(i = 0; i < nTests; i++) 66 { 67 if(Tests[i].Routine == NULL) 68 { 69 status = _T("SKIPPED"); 70 } 71 else if(Tests[i].Result == TRUE) 72 { 73 status = _T("SUCCESS"); 74 nsuccess++; 75 } 76 else 77 { 78 status = _T("FAILED "); 79 nfailed++; 80 } 81 82 _tprintf(_T("Test %d: %s %s\n"), i, status, Tests[i].description); 83 } 84 85 _tprintf(_T("\nTests succeeded: %d, failed: %d\n"), nsuccess, nfailed); 86 if(nfailed == 0) 87 { 88 _tprintf(_T(" ALL TESTS SUCCESSFUL!\n")); 89 } 90 } 91 92 /*******************************************************************************/ 93 94 typedef struct _TESTINFO 95 { 96 PTEST Test; 97 int secsleft; 98 HANDLE hTimer; 99 HANDLE hEvent; 100 /* additional stuff */ 101 union 102 { 103 struct 104 { 105 HANDLE Dummy; 106 } Test1; 107 struct 108 { 109 HANDLE hWaitEvent; 110 } Test2; 111 struct 112 { 113 HANDLE hWaitEvent; 114 HANDLE hNotification; 115 } Test3; 116 }; 117 } TESTINFO, *PTESTINFO; 118 119 VOID CALLBACK TimerCallback1(PVOID Param, BOOLEAN Fired) 120 { 121 PTESTINFO Info = (PTESTINFO)Param; 122 123 _tprintf(_T("[%d]TimerCallback(0x%x, %d) called (%d)\n"), (int)Info->Test->id, (int)Info->hTimer, (int)Fired, --Info->secsleft); 124 125 if(Info->secsleft == 0) 126 { 127 BOOL stat; 128 129 _tprintf(_T("[%d]Timout finished, delete timer queue..."), (int)Info->Test->id); 130 stat = DeleteTimerQueueTimer(NULL, Info->hTimer, NULL); 131 if(stat) 132 _tprintf(_T("returned OK -> test FAILED!\n")); 133 else 134 { 135 int error = GetLastError(); 136 137 switch(error) 138 { 139 case ERROR_IO_PENDING: 140 _tprintf(_T("OK, Overlapped I/O operation in progress\n")); 141 /* this test is only successful in this case */ 142 Info->Test->Result = TRUE; 143 break; 144 default: 145 _tprintf(_T("Failed, LastError: %d\n"), (int)GetLastError()); 146 break; 147 } 148 } 149 150 /* set the event to continue tests */ 151 SetEvent(Info->hEvent); 152 } 153 } 154 155 VOID Test1(PTEST Test, HANDLE hEvent) 156 { 157 static TESTINFO Info; 158 159 Info.Test = Test; 160 Info.hEvent = hEvent; 161 Info.secsleft = N_TIMEOUT; 162 163 if(!CreateTimerQueueTimer(&Info.hTimer, NULL, TimerCallback1, &Info, 1000, 1000, 0)) 164 { 165 _tprintf(_T("[%d]CreateTimerQueueTimer() failed, LastError: %d!"), (int)Info.Test->id, (int)GetLastError()); 166 /* we failed, set the event to continue tests */ 167 SetEvent(hEvent); 168 return; 169 } 170 171 _tprintf(_T("[%d]CreateTimerQueueTimer() created timer 0x%x, countdown (%d sec)...\n"), (int)Info.Test->id, (int)Info.hTimer, (int)Info.secsleft); 172 } 173 174 /*******************************************************************************/ 175 176 VOID CALLBACK TimerCallback2(PVOID Param, BOOLEAN Fired) 177 { 178 PTESTINFO Info = (PTESTINFO)Param; 179 180 _tprintf(_T("[%d]TimerCallback(0x%x, %d) called (%d)\n"), (int)Info->Test->id, (int)Info->hTimer, (int)Fired, --Info->secsleft); 181 182 if(Info->secsleft == 0) 183 { 184 /* set the event to continue tests */ 185 SetEvent(Info->Test2.hWaitEvent); 186 187 /* sleep a bit */ 188 Sleep(1500); 189 } 190 } 191 192 VOID Test2(PTEST Test, HANDLE hEvent) 193 { 194 static TESTINFO Info; 195 BOOL stat; 196 197 Info.Test = Test; 198 Info.hEvent = hEvent; 199 Info.secsleft = N_TIMEOUT; 200 201 Info.Test2.hWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 202 if(Info.Test2.hWaitEvent == NULL) 203 { 204 _tprintf(_T("[%d]Unable to create event!\n"), (int)Info.Test->id); 205 return; 206 } 207 208 if(!CreateTimerQueueTimer(&Info.hTimer, NULL, TimerCallback2, &Info, 1000, 1000, 0)) 209 { 210 _tprintf(_T("[%d]CreateTimerQueueTimer() failed, LastError: %d!"), (int)Info.Test->id, (int)GetLastError()); 211 212 CloseHandle(Info.Test2.hWaitEvent); 213 /* we failed, set the event to continue tests */ 214 SetEvent(hEvent); 215 return; 216 } 217 218 _tprintf(_T("[%d]CreateTimerQueueTimer() created timer 0x%x, countdown (%d sec)...\n"), (int)Test->id, (int)Info.hTimer, (int)Info.secsleft); 219 220 WaitForSingleObject(Info.Test2.hWaitEvent, INFINITE); 221 222 _tprintf(_T("[%d]Timout finished, delete timer queue..."), (int)Test->id); 223 stat = DeleteTimerQueueTimer(NULL, Info.hTimer, INVALID_HANDLE_VALUE); 224 if(stat) 225 { 226 _tprintf(_T("OK\n")); 227 /* this test is only successful in this case */ 228 Test->Result = TRUE; 229 } 230 else 231 { 232 int error = GetLastError(); 233 234 switch(error) 235 { 236 case ERROR_IO_PENDING: 237 _tprintf(_T("FAILED, Overlapped I/O operation in progress\n")); 238 break; 239 default: 240 _tprintf(_T("Failed, LastError: %d\n"), (int)GetLastError()); 241 break; 242 } 243 } 244 245 SetEvent(Info.hEvent); 246 } 247 248 /*******************************************************************************/ 249 250 VOID CALLBACK TimerCallback3(PVOID Param, BOOLEAN Fired) 251 { 252 PTESTINFO Info = (PTESTINFO)Param; 253 254 _tprintf(_T("[%d]TimerCallback(0x%x, %d) called (%d)\n"), (int)Info->Test->id, (int)Info->hTimer, (int)Fired, --Info->secsleft); 255 256 if(Info->secsleft == 0) 257 { 258 /* set the event to continue tests */ 259 SetEvent(Info->Test3.hWaitEvent); 260 261 /* sleep a bit */ 262 Sleep(1500); 263 } 264 } 265 266 VOID Test3(PTEST Test, HANDLE hEvent) 267 { 268 static TESTINFO Info; 269 BOOL stat; 270 271 Info.Test = Test; 272 Info.hEvent = hEvent; 273 Info.secsleft = N_TIMEOUT; 274 275 Info.Test3.hWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 276 if(Info.Test3.hWaitEvent == NULL) 277 { 278 _tprintf(_T("[%d]Unable to create event!\n"), (int)Info.Test->id); 279 return; 280 } 281 282 Info.Test3.hNotification = CreateEvent(NULL, FALSE, FALSE, NULL); 283 if(Info.Test3.hNotification == NULL) 284 { 285 _tprintf(_T("[%d]Unable to create notification event!\n"), (int)Info.Test->id); 286 return; 287 } 288 289 if(!CreateTimerQueueTimer(&Info.hTimer, NULL, TimerCallback3, &Info, 1000, 1000, 0)) 290 { 291 _tprintf(_T("[%d]CreateTimerQueueTimer() failed, LastError: %d!"), (int)Info.Test->id, (int)GetLastError()); 292 293 CloseHandle(Info.Test3.hWaitEvent); 294 CloseHandle(Info.Test3.hNotification); 295 /* we failed, set the event to continue tests */ 296 SetEvent(hEvent); 297 return; 298 } 299 300 _tprintf(_T("[%d]CreateTimerQueueTimer() created timer 0x%x, countdown (%d sec)...\n"), (int)Test->id, (int)Info.hTimer, (int)Info.secsleft); 301 302 WaitForSingleObject(Info.Test3.hWaitEvent, INFINITE); 303 304 _tprintf(_T("[%d]Timout finished, delete timer queue..."), (int)Test->id); 305 stat = DeleteTimerQueueTimer(NULL, Info.hTimer, Info.Test3.hNotification); 306 if(stat) 307 { 308 _tprintf(_T("returned OK -> test FAILED!\n")); 309 } 310 else 311 { 312 int error = GetLastError(); 313 314 switch(error) 315 { 316 case ERROR_IO_PENDING: 317 _tprintf(_T("OK, Overlapped I/O operation in progress\n")); 318 /* this test is only successful in this case */ 319 Test->Result = TRUE; 320 break; 321 default: 322 _tprintf(_T("Failed, LastError: %d\n"), (int)GetLastError()); 323 break; 324 } 325 } 326 327 WaitForSingleObject(Info.Test3.hNotification, INFINITE); 328 329 CloseHandle(Info.Test3.hWaitEvent); 330 CloseHandle(Info.Test3.hNotification); 331 332 SetEvent(Info.hEvent); 333 } 334 335 /*******************************************************************************/ 336 337 VOID 338 InitTests(VOID) 339 { 340 ZeroMemory(Tests, sizeof(Tests)); 341 342 Tests[0].description = _T("non-blocking DeleteTimerQueueTimer() call from callback"); 343 Tests[0].Routine = Test1; 344 345 Tests[1].description = _T("blocking DeleteTimerQueueTimer() call"); 346 Tests[1].Routine = Test2; 347 348 Tests[2].description = _T("blocking DeleteTimerQueueTimer() call with specified event"); 349 Tests[2].Routine = Test3; 350 } 351 352 int main(int argc, char* argv[]) 353 { 354 _tprintf(_T("+++ TimerQueue test running +++\n\n")); 355 356 InitTests(); 357 358 RunTests(); 359 360 _tprintf(_T("\n+++ RESULTS +++\n")); 361 362 PrintTestResults(); 363 364 return 0; 365 } 366