mirror of
https://github.com/reactos/reactos.git
synced 2026-06-03 17:59:48 +08:00
Catch hang-up regtests, added _DispatcherTimeout macros for tests to specify timeout (default is 5000ms)
svn path=/trunk/; revision=11896
This commit is contained in:
@@ -32,3 +32,25 @@ _ExitProcess(UINT uExitCode)
|
||||
{
|
||||
ExitProcess(uExitCode);
|
||||
}
|
||||
|
||||
HANDLE STDCALL
|
||||
_CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize,
|
||||
LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter,
|
||||
DWORD dwCreationFlags, LPDWORD lpThreadId)
|
||||
{
|
||||
return CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress,
|
||||
lpParameter, dwCreationFlags, lpThreadId);
|
||||
}
|
||||
|
||||
WINBOOL STDCALL
|
||||
_TerminateThread(HANDLE hThread, DWORD dwExitCode)
|
||||
{
|
||||
return TerminateThread(hThread, dwExitCode);
|
||||
}
|
||||
|
||||
DWORD STDCALL
|
||||
_WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
||||
{
|
||||
return WaitForSingleObject(hHandle, dwMilliseconds);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,3 +4,7 @@ _ExitProcess@4
|
||||
_GetModuleHandleA@4
|
||||
_GetProcAddress@8
|
||||
_LoadLibraryA@4
|
||||
_CreateThread@24
|
||||
_TerminateThread@8
|
||||
_WaitForSingleObject@8
|
||||
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
typedef struct _PERFORM_TEST_ARGS
|
||||
{
|
||||
TestOutputRoutine OutputRoutine;
|
||||
PROS_TEST Test;
|
||||
LPSTR TestName;
|
||||
} PERFORM_TEST_ARGS;
|
||||
|
||||
int _Result;
|
||||
char *_Buffer;
|
||||
|
||||
@@ -30,35 +37,17 @@ InitializeTests()
|
||||
InitializeListHead(&AllTests);
|
||||
}
|
||||
|
||||
VOID
|
||||
PerformTest(TestOutputRoutine OutputRoutine, PROS_TEST Test, LPSTR TestName)
|
||||
DWORD WINAPI
|
||||
PerformTest(PVOID _arg)
|
||||
{
|
||||
PERFORM_TEST_ARGS *Args = (PERFORM_TEST_ARGS *)_arg;
|
||||
TestOutputRoutine OutputRoutine = Args->OutputRoutine;
|
||||
PROS_TEST Test = Args->Test;
|
||||
LPSTR TestName = Args->TestName;
|
||||
char OutputBuffer[5000];
|
||||
char Buffer[5000];
|
||||
char Name[200];
|
||||
|
||||
memset(Buffer, 0, sizeof(Buffer));
|
||||
memset(Name, 0, sizeof(Name));
|
||||
|
||||
_Result = TS_OK;
|
||||
_Buffer = Name;
|
||||
(Test->Routine)(TESTCMD_TESTNAME);
|
||||
if (_Result != TS_OK)
|
||||
{
|
||||
if (TestName != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
strcpy(Name, "Unnamed");
|
||||
}
|
||||
|
||||
if (TestName != NULL)
|
||||
{
|
||||
if (_stricmp(Name, TestName) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_SEH_TRY {
|
||||
_Result = TS_OK;
|
||||
@@ -71,11 +60,11 @@ PerformTest(TestOutputRoutine OutputRoutine, PROS_TEST Test, LPSTR TestName)
|
||||
|
||||
if (_Result != TS_OK)
|
||||
{
|
||||
sprintf(OutputBuffer, "ROSREGTEST: |%s| Status: Failed (%s)\n", Name, Buffer);
|
||||
sprintf(OutputBuffer, "ROSREGTEST: |%s| Status: Failed (%s)\n", TestName, Buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(OutputBuffer, "ROSREGTEST: |%s| Status: Success\n", Name);
|
||||
sprintf(OutputBuffer, "ROSREGTEST: |%s| Status: Success\n", TestName);
|
||||
}
|
||||
if (OutputRoutine != NULL)
|
||||
{
|
||||
@@ -85,6 +74,7 @@ PerformTest(TestOutputRoutine OutputRoutine, PROS_TEST Test, LPSTR TestName)
|
||||
{
|
||||
DbgPrint(OutputBuffer);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
VOID
|
||||
@@ -93,14 +83,89 @@ PerformTests(TestOutputRoutine OutputRoutine, LPSTR TestName)
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PROS_TEST Current;
|
||||
PERFORM_TEST_ARGS Args;
|
||||
HANDLE hThread;
|
||||
char OutputBuffer[1024];
|
||||
char Name[200];
|
||||
DWORD TimeOut;
|
||||
|
||||
Args.OutputRoutine = OutputRoutine;
|
||||
Args.TestName = Name;
|
||||
|
||||
CurrentEntry = AllTests.Flink;
|
||||
while (CurrentEntry != &AllTests)
|
||||
for (; CurrentEntry != &AllTests; CurrentEntry = NextEntry)
|
||||
{
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, ROS_TEST, ListEntry);
|
||||
PerformTest(OutputRoutine, Current, TestName);
|
||||
CurrentEntry = NextEntry;
|
||||
Args.Test = Current;
|
||||
|
||||
/* Get name of test */
|
||||
memset(Name, 0, sizeof(Name));
|
||||
|
||||
_Result = TS_OK;
|
||||
_Buffer = Name;
|
||||
(Current->Routine)(TESTCMD_TESTNAME);
|
||||
if (_Result != TS_OK)
|
||||
{
|
||||
if (TestName != NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
strcpy(Name, "Unnamed");
|
||||
}
|
||||
|
||||
if (TestName != NULL)
|
||||
{
|
||||
if (_stricmp(Name, TestName) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get timeout for test */
|
||||
TimeOut = 0;
|
||||
_Result = TS_OK;
|
||||
_Buffer = (char *)&TimeOut;
|
||||
(Current->Routine)(TESTCMD_TIMEOUT);
|
||||
if (_Result != TS_OK || TimeOut == INFINITE)
|
||||
{
|
||||
TimeOut = 5000;
|
||||
}
|
||||
|
||||
/* Run test in thread */
|
||||
hThread = _CreateThread(NULL, 0, PerformTest, (PVOID)&Args, 0, NULL);
|
||||
if (hThread == NULL)
|
||||
{
|
||||
sprintf(OutputBuffer,
|
||||
"ROSREGTEST: |%s| Status: Failed (CreateThread failed: 0x%x)\n",
|
||||
Name, (unsigned int)GetLastError());
|
||||
}
|
||||
else if (_WaitForSingleObject(hThread, TimeOut) == WAIT_TIMEOUT)
|
||||
{
|
||||
if (!_TerminateThread(hThread, 0))
|
||||
{
|
||||
sprintf(OutputBuffer,
|
||||
"ROSREGTEST: |%s| Status: Failed (Test timed out - %d ms, TerminateThread failed: 0x%x)\n",
|
||||
Name, (int)TimeOut, (unsigned int)GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(OutputBuffer, "ROSREGTEST: |%s| Status: Failed (Test timed out - %d ms)\n", Name, (int)TimeOut);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (OutputRoutine != NULL)
|
||||
{
|
||||
(*OutputRoutine)(OutputBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgPrint(OutputBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ void SetupOnce()
|
||||
/* Valid values for Command parameter of TestRoutine */
|
||||
#define TESTCMD_RUN 0 /* Buffer contains information about what failed */
|
||||
#define TESTCMD_TESTNAME 1 /* Buffer contains description of test */
|
||||
#define TESTCMD_TIMEOUT 2 /* Buffer contains timeout for test (DWORD, default is 5000 ms) */
|
||||
|
||||
/* Valid values for return values of TestRoutine */
|
||||
#define TS_EXCEPTION -1
|
||||
@@ -27,7 +28,7 @@ extern int _Result;
|
||||
extern char *_Buffer;
|
||||
|
||||
/* Macros to simplify tests */
|
||||
#define _Dispatcher(FunctionName, TestName) \
|
||||
#define _DispatcherTimeout(FunctionName, TestName, TimeOut) \
|
||||
void \
|
||||
FunctionName(int Command) \
|
||||
{ \
|
||||
@@ -39,12 +40,17 @@ FunctionName(int Command) \
|
||||
case TESTCMD_TESTNAME: \
|
||||
strcpy(_Buffer, TestName); \
|
||||
break; \
|
||||
case TESTCMD_TIMEOUT: \
|
||||
*(PDWORD)_Buffer = (DWORD)TimeOut; \
|
||||
break; \
|
||||
default: \
|
||||
_Result = TS_FAILED; \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _Dispatcher(FunctionName, TestName) _DispatcherTimeout(FunctionName, TestName, 5000)
|
||||
|
||||
static inline void
|
||||
AppendAssertion(char *message)
|
||||
{
|
||||
@@ -173,6 +179,18 @@ _LoadLibraryA(LPCSTR lpLibFileName);
|
||||
VOID STDCALL
|
||||
_ExitProcess(UINT uExitCode);
|
||||
|
||||
HANDLE STDCALL
|
||||
_CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize,
|
||||
LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter,
|
||||
DWORD dwCreationFlags, LPDWORD lpThreadId);
|
||||
|
||||
WINBOOL STDCALL
|
||||
_TerminateThread(HANDLE hThread, DWORD dwExitCode);
|
||||
|
||||
DWORD STDCALL
|
||||
_WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
|
||||
|
||||
|
||||
static inline PCHAR
|
||||
FrameworkGetExportedFunctionNameInternal(PAPI_DESCRIPTION ApiDescription)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user