mirror of
https://github.com/reactos/reactos.git
synced 2024-08-27 21:58:49 +00:00
![Stefan Ginsberg](/assets/img/avatar_default.png)
- tmrqueue: Don't use empty structures, MSVC doe - w32knapi: Implement IntSyscall in MSVC assembly, be compatible with C89 variable initialization and use '%' instead of '\%' to avoid a msvc warning. svn path=/trunk/; revision=42845
366 lines
8.4 KiB
C
366 lines
8.4 KiB
C
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <tchar.h>
|
|
|
|
#define N_TIMEOUT 3
|
|
|
|
/*******************************************************************************/
|
|
|
|
typedef struct _TEST *PTEST;
|
|
|
|
typedef VOID (*PFNTEST)(PTEST Test, HANDLE hEvent);
|
|
|
|
typedef struct _TEST
|
|
{
|
|
TCHAR *description;
|
|
BOOL Result;
|
|
PFNTEST Routine;
|
|
int id;
|
|
} TEST;
|
|
|
|
static TEST Tests[3];
|
|
|
|
VOID RunTests(VOID)
|
|
{
|
|
int i, nTests;
|
|
static HANDLE hEvent;
|
|
|
|
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if(hEvent == NULL)
|
|
{
|
|
_tprintf(_T("Unable to create event!"));
|
|
return;
|
|
}
|
|
|
|
nTests = sizeof(Tests) / sizeof(TEST);
|
|
|
|
for(i = 0; i < nTests; i++)
|
|
{
|
|
Tests[i].id = i + 1;
|
|
|
|
if(Tests[i].Routine == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
_tprintf(_T("+++ TEST %d: %s\n"), Tests[i].id, Tests[i].description);
|
|
|
|
Tests[i].Routine(&Tests[i], hEvent);
|
|
|
|
WaitForSingleObject(hEvent, INFINITE);
|
|
|
|
_tprintf(_T("\n\n"));
|
|
}
|
|
|
|
CloseHandle(hEvent);
|
|
}
|
|
|
|
VOID PrintTestResults(VOID)
|
|
{
|
|
int i, nTests, nsuccess = 0, nfailed = 0;
|
|
TCHAR *status;
|
|
|
|
nTests = sizeof(Tests) / sizeof(TEST);
|
|
|
|
for(i = 0; i < nTests; i++)
|
|
{
|
|
if(Tests[i].Routine == NULL)
|
|
{
|
|
status = _T("SKIPPED");
|
|
}
|
|
else if(Tests[i].Result == TRUE)
|
|
{
|
|
status = _T("SUCCESS");
|
|
nsuccess++;
|
|
}
|
|
else
|
|
{
|
|
status = _T("FAILED ");
|
|
nfailed++;
|
|
}
|
|
|
|
_tprintf(_T("Test %d: %s %s\n"), i, status, Tests[i].description);
|
|
}
|
|
|
|
_tprintf(_T("\nTests succeeded: %d, failed: %d\n"), nsuccess, nfailed);
|
|
if(nfailed == 0)
|
|
{
|
|
_tprintf(_T(" ALL TESTS SUCCESSFUL!\n"));
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
|
|
typedef struct _TESTINFO
|
|
{
|
|
PTEST Test;
|
|
int secsleft;
|
|
HANDLE hTimer;
|
|
HANDLE hEvent;
|
|
/* additional stuff */
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
HANDLE Dummy;
|
|
} Test1;
|
|
struct
|
|
{
|
|
HANDLE hWaitEvent;
|
|
} Test2;
|
|
struct
|
|
{
|
|
HANDLE hWaitEvent;
|
|
HANDLE hNotification;
|
|
} Test3;
|
|
};
|
|
} TESTINFO, *PTESTINFO;
|
|
|
|
VOID CALLBACK TimerCallback1(PVOID Param, BOOLEAN Fired)
|
|
{
|
|
PTESTINFO Info = (PTESTINFO)Param;
|
|
|
|
_tprintf(_T("[%d]TimerCallback(0x%x, %d) called (%d)\n"), (int)Info->Test->id, (int)Info->hTimer, (int)Fired, --Info->secsleft);
|
|
|
|
if(Info->secsleft == 0)
|
|
{
|
|
BOOL stat;
|
|
|
|
_tprintf(_T("[%d]Timout finished, delete timer queue..."), (int)Info->Test->id);
|
|
stat = DeleteTimerQueueTimer(NULL, Info->hTimer, NULL);
|
|
if(stat)
|
|
_tprintf(_T("returned OK -> test FAILED!\n"));
|
|
else
|
|
{
|
|
int error = GetLastError();
|
|
|
|
switch(error)
|
|
{
|
|
case ERROR_IO_PENDING:
|
|
_tprintf(_T("OK, Overlapped I/O operation in progress\n"));
|
|
/* this test is only successful in this case */
|
|
Info->Test->Result = TRUE;
|
|
break;
|
|
default:
|
|
_tprintf(_T("Failed, LastError: %d\n"), (int)GetLastError());
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* set the event to continue tests */
|
|
SetEvent(Info->hEvent);
|
|
}
|
|
}
|
|
|
|
VOID Test1(PTEST Test, HANDLE hEvent)
|
|
{
|
|
static TESTINFO Info;
|
|
|
|
Info.Test = Test;
|
|
Info.hEvent = hEvent;
|
|
Info.secsleft = N_TIMEOUT;
|
|
|
|
if(!CreateTimerQueueTimer(&Info.hTimer, NULL, TimerCallback1, &Info, 1000, 1000, 0))
|
|
{
|
|
_tprintf(_T("[%d]CreateTimerQueueTimer() failed, LastError: %d!"), (int)Info.Test->id, (int)GetLastError());
|
|
/* we failed, set the event to continue tests */
|
|
SetEvent(hEvent);
|
|
return;
|
|
}
|
|
|
|
_tprintf(_T("[%d]CreateTimerQueueTimer() created timer 0x%x, countdown (%d sec)...\n"), (int)Info.Test->id, (int)Info.hTimer, (int)Info.secsleft);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
|
|
VOID CALLBACK TimerCallback2(PVOID Param, BOOLEAN Fired)
|
|
{
|
|
PTESTINFO Info = (PTESTINFO)Param;
|
|
|
|
_tprintf(_T("[%d]TimerCallback(0x%x, %d) called (%d)\n"), (int)Info->Test->id, (int)Info->hTimer, (int)Fired, --Info->secsleft);
|
|
|
|
if(Info->secsleft == 0)
|
|
{
|
|
/* set the event to continue tests */
|
|
SetEvent(Info->Test2.hWaitEvent);
|
|
|
|
/* sleep a bit */
|
|
Sleep(1500);
|
|
}
|
|
}
|
|
|
|
VOID Test2(PTEST Test, HANDLE hEvent)
|
|
{
|
|
static TESTINFO Info;
|
|
BOOL stat;
|
|
|
|
Info.Test = Test;
|
|
Info.hEvent = hEvent;
|
|
Info.secsleft = N_TIMEOUT;
|
|
|
|
Info.Test2.hWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if(Info.Test2.hWaitEvent == NULL)
|
|
{
|
|
_tprintf(_T("[%d]Unable to create event!\n"), (int)Info.Test->id);
|
|
return;
|
|
}
|
|
|
|
if(!CreateTimerQueueTimer(&Info.hTimer, NULL, TimerCallback2, &Info, 1000, 1000, 0))
|
|
{
|
|
_tprintf(_T("[%d]CreateTimerQueueTimer() failed, LastError: %d!"), (int)Info.Test->id, (int)GetLastError());
|
|
|
|
CloseHandle(Info.Test2.hWaitEvent);
|
|
/* we failed, set the event to continue tests */
|
|
SetEvent(hEvent);
|
|
return;
|
|
}
|
|
|
|
_tprintf(_T("[%d]CreateTimerQueueTimer() created timer 0x%x, countdown (%d sec)...\n"), (int)Test->id, (int)Info.hTimer, (int)Info.secsleft);
|
|
|
|
WaitForSingleObject(Info.Test2.hWaitEvent, INFINITE);
|
|
|
|
_tprintf(_T("[%d]Timout finished, delete timer queue..."), (int)Test->id);
|
|
stat = DeleteTimerQueueTimer(NULL, Info.hTimer, INVALID_HANDLE_VALUE);
|
|
if(stat)
|
|
{
|
|
_tprintf(_T("OK\n"));
|
|
/* this test is only successful in this case */
|
|
Test->Result = TRUE;
|
|
}
|
|
else
|
|
{
|
|
int error = GetLastError();
|
|
|
|
switch(error)
|
|
{
|
|
case ERROR_IO_PENDING:
|
|
_tprintf(_T("FAILED, Overlapped I/O operation in progress\n"));
|
|
break;
|
|
default:
|
|
_tprintf(_T("Failed, LastError: %d\n"), (int)GetLastError());
|
|
break;
|
|
}
|
|
}
|
|
|
|
SetEvent(Info.hEvent);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
|
|
VOID CALLBACK TimerCallback3(PVOID Param, BOOLEAN Fired)
|
|
{
|
|
PTESTINFO Info = (PTESTINFO)Param;
|
|
|
|
_tprintf(_T("[%d]TimerCallback(0x%x, %d) called (%d)\n"), (int)Info->Test->id, (int)Info->hTimer, (int)Fired, --Info->secsleft);
|
|
|
|
if(Info->secsleft == 0)
|
|
{
|
|
/* set the event to continue tests */
|
|
SetEvent(Info->Test3.hWaitEvent);
|
|
|
|
/* sleep a bit */
|
|
Sleep(1500);
|
|
}
|
|
}
|
|
|
|
VOID Test3(PTEST Test, HANDLE hEvent)
|
|
{
|
|
static TESTINFO Info;
|
|
BOOL stat;
|
|
|
|
Info.Test = Test;
|
|
Info.hEvent = hEvent;
|
|
Info.secsleft = N_TIMEOUT;
|
|
|
|
Info.Test3.hWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if(Info.Test3.hWaitEvent == NULL)
|
|
{
|
|
_tprintf(_T("[%d]Unable to create event!\n"), (int)Info.Test->id);
|
|
return;
|
|
}
|
|
|
|
Info.Test3.hNotification = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if(Info.Test3.hNotification == NULL)
|
|
{
|
|
_tprintf(_T("[%d]Unable to create notification event!\n"), (int)Info.Test->id);
|
|
return;
|
|
}
|
|
|
|
if(!CreateTimerQueueTimer(&Info.hTimer, NULL, TimerCallback3, &Info, 1000, 1000, 0))
|
|
{
|
|
_tprintf(_T("[%d]CreateTimerQueueTimer() failed, LastError: %d!"), (int)Info.Test->id, (int)GetLastError());
|
|
|
|
CloseHandle(Info.Test3.hWaitEvent);
|
|
CloseHandle(Info.Test3.hNotification);
|
|
/* we failed, set the event to continue tests */
|
|
SetEvent(hEvent);
|
|
return;
|
|
}
|
|
|
|
_tprintf(_T("[%d]CreateTimerQueueTimer() created timer 0x%x, countdown (%d sec)...\n"), (int)Test->id, (int)Info.hTimer, (int)Info.secsleft);
|
|
|
|
WaitForSingleObject(Info.Test3.hWaitEvent, INFINITE);
|
|
|
|
_tprintf(_T("[%d]Timout finished, delete timer queue..."), (int)Test->id);
|
|
stat = DeleteTimerQueueTimer(NULL, Info.hTimer, Info.Test3.hNotification);
|
|
if(stat)
|
|
{
|
|
_tprintf(_T("returned OK -> test FAILED!\n"));
|
|
}
|
|
else
|
|
{
|
|
int error = GetLastError();
|
|
|
|
switch(error)
|
|
{
|
|
case ERROR_IO_PENDING:
|
|
_tprintf(_T("OK, Overlapped I/O operation in progress\n"));
|
|
/* this test is only successful in this case */
|
|
Test->Result = TRUE;
|
|
break;
|
|
default:
|
|
_tprintf(_T("Failed, LastError: %d\n"), (int)GetLastError());
|
|
break;
|
|
}
|
|
}
|
|
|
|
WaitForSingleObject(Info.Test3.hNotification, INFINITE);
|
|
|
|
CloseHandle(Info.Test3.hWaitEvent);
|
|
CloseHandle(Info.Test3.hNotification);
|
|
|
|
SetEvent(Info.hEvent);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
|
|
VOID
|
|
InitTests(VOID)
|
|
{
|
|
ZeroMemory(Tests, sizeof(Tests));
|
|
|
|
Tests[0].description = _T("non-blocking DeleteTimerQueueTimer() call from callback");
|
|
Tests[0].Routine = Test1;
|
|
|
|
Tests[1].description = _T("blocking DeleteTimerQueueTimer() call");
|
|
Tests[1].Routine = Test2;
|
|
|
|
Tests[2].description = _T("blocking DeleteTimerQueueTimer() call with specified event");
|
|
Tests[2].Routine = Test3;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
_tprintf(_T("+++ TimerQueue test running +++\n\n"));
|
|
|
|
InitTests();
|
|
|
|
RunTests();
|
|
|
|
_tprintf(_T("\n+++ RESULTS +++\n"));
|
|
|
|
PrintTestResults();
|
|
|
|
return 0;
|
|
}
|