Catch hang-up regtests, added _DispatcherTimeout macros for tests to specify timeout...
authorGregor Anich <blight@blight.eu.org>
Wed, 1 Dec 2004 23:23:47 +0000 (23:23 +0000)
committerGregor Anich <blight@blight.eu.org>
Wed, 1 Dec 2004 23:23:47 +0000 (23:23 +0000)
svn path=/trunk/; revision=11896

reactos/regtests/regtests/regtests.c
reactos/regtests/regtests/regtests.def
reactos/regtests/shared/regtests.c
reactos/regtests/shared/regtests.h

index db0170b..b59807a 100755 (executable)
@@ -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);
+}
+
index a6f552a..652c3d3 100644 (file)
@@ -4,3 +4,7 @@ _ExitProcess@4
 _GetModuleHandleA@4
 _GetProcAddress@8
 _LoadLibraryA@4
+_CreateThread@24
+_TerminateThread@8
+_WaitForSingleObject@8
+
index 7c41412..2452857 100755 (executable)
 #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);
+        }
     }
 }
 
index eea2aa8..f5dfc32 100755 (executable)
@@ -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)
 {