Show execution time of tests
[reactos.git] / reactos / regtests / shared / regtests.c
index 952c45a..553c523 100755 (executable)
@@ -6,32 +6,30 @@
  * UPDATE HISTORY:
  *      06-07-2003  CSH  Created
  */
-#include <roscfg.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
 #define NTOS_MODE_USER
 #include <ntos.h>
+#include <pseh.h>
 #include "regtests.h"
-#include <string.h>
 
 #define NDEBUG
 #include <debug.h>
 
-LIST_ENTRY AllTests;
-
-int
-DriverTest()
+typedef struct _PERFORM_TEST_ARGS
 {
-  /* Dummy */
-  return 0;
-}
+  TestOutputRoutine OutputRoutine;
+  PROS_TEST Test;
+  LPSTR TestName;
+} PERFORM_TEST_ARGS;
 
+int _Result;
+char *_Buffer;
 
-int
-_regtestsTest()
-{
-  /* Dummy */
-  return 0;
-}
-
+static LIST_ENTRY AllTests;
 
 VOID
 InitializeTests()
@@ -39,56 +37,144 @@ InitializeTests()
   InitializeListHead(&AllTests);
 }
 
-VOID
-PerformTest(PROS_TEST Test)
+char*
+FormatExecutionTime(char *buffer, LPFILETIME time)
 {
-  char TestName[200];
-  char Buffer[200];
-  int Result;
+  ULONG milliseconds = time->dwLowDateTime / 10000;
+  
+  sprintf(buffer,
+             "%ldms",
+             milliseconds);
+  return buffer;
+}
 
-  memset(TestName, 0, sizeof(TestName));
-  memset(Buffer, 0, sizeof(Buffer));
+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;
+  HANDLE hThread;
+  FILETIME time;
+  FILETIME ExecutionTime;
+  char OutputBuffer[5000];
+  char Buffer[5000];
+  char Format[100];
+
+  hThread = GetCurrentThread();
+  _SetThreadPriority(hThread, THREAD_PRIORITY_IDLE);
 
-  if (!((Test->Routine)(TESTCMD_TESTNAME, TestName) == 0))
+  memset(Buffer, 0, sizeof(Buffer));
+  
+  _SEH_TRY {
+    _Result = TS_OK;
+    _Buffer = Buffer;
+    (Test->Routine)(TESTCMD_RUN);
+  } _SEH_HANDLE {
+    _Result = TS_FAILED;
+    sprintf(Buffer, "due to exception 0x%lx", _SEH_GetExceptionCode());
+  } _SEH_END;
+
+  if (_Result == TS_OK)
     {
-      strcpy(TestName, "Unnamed");
+      if (!_GetThreadTimes(hThread,
+                              &time,
+                              &time,
+                              &time,
+                              &ExecutionTime))
+      {
+        ExecutionTime.dwLowDateTime = 10;
+        ExecutionTime.dwHighDateTime = 10;
+      }
+      sprintf(OutputBuffer,
+              "[%s] Success [%s]\n",
+              TestName,
+              FormatExecutionTime(Format,
+                                  &ExecutionTime));
     }
+  else
+      sprintf(OutputBuffer, "[%s] Failed (%s)\n", TestName, Buffer);
 
-#ifdef SEH
-  __try {
-#endif
-    Result = (Test->Routine)(TESTCMD_RUN, Buffer);
-#ifdef SEH
-  } __except(EXCEPTION_EXECUTE_HANDLER) {
-    Result = TS_FAILED;
-    strcpy(Buffer, "Failed due to exception");
-  }
-#endif
-
-  if (Result != TS_OK)
-    {
-      DbgPrint("ROSREGTEST: (%s) Status: Failed (%s)\n", TestName, Buffer);
-    }
+  if (OutputRoutine != NULL)
+      (*OutputRoutine)(OutputBuffer);
   else
-    {
-      DbgPrint("ROSREGTEST: (%s) Status: Success\n", TestName);
-    }
+      DbgPrint(OutputBuffer);
+  return 1;
 }
 
 VOID
-PerformTests()
+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(Current);
-      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) && (_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,
+                  "[%s] Failed (CreateThread() failed: %d)\n",
+                  Name, (unsigned int)_GetLastError());
+      else if (_WaitForSingleObject(hThread, TimeOut) == WAIT_TIMEOUT)
+        {
+          if (!_TerminateThread(hThread, 0))
+              sprintf(OutputBuffer,
+                      "[%s] Failed (timed out after %dms; TerminateThread() failed: %d)\n",
+                      Name, (int)TimeOut, (unsigned int)_GetLastError());
+          else
+              sprintf(OutputBuffer, "[%s] Failed (timed out after %dms)\n", Name, (int)TimeOut);          
+         _CloseHandle(hThread);
+        }
+      else
+        {
+         _CloseHandle(hThread);
+          continue;
+        }
+
+      if (OutputRoutine != NULL)
+          (*OutputRoutine)(OutputBuffer);
+      else
+          DbgPrint(OutputBuffer);
     }
 }
 
@@ -97,7 +183,7 @@ AddTest(TestRoutine Routine)
 {
   PROS_TEST Test;
 
-  Test = (PROS_TEST) AllocateMemory(sizeof(ROS_TEST));
+  Test = (PROS_TEST) malloc(sizeof(ROS_TEST));
   if (Test == NULL)
     {
       DbgPrint("Out of memory");
@@ -108,3 +194,9 @@ AddTest(TestRoutine Routine)
 
   InsertTailList(&AllTests, &Test->ListEntry);
 }
+
+PVOID STDCALL
+FrameworkGetHook(ULONG index)
+{
+  return FrameworkGetHookInternal(index);
+}