Show execution time of tests
[reactos.git] / reactos / regtests / shared / regtests.c
1 /*
2 * PROJECT: ReactOS kernel
3 * FILE: regtests/shared/regtests.c
4 * PURPOSE: Regression testing framework
5 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
6 * UPDATE HISTORY:
7 * 06-07-2003 CSH Created
8 */
9 #include <ctype.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <malloc.h>
14 #define NTOS_MODE_USER
15 #include <ntos.h>
16 #include <pseh.h>
17 #include "regtests.h"
18
19 #define NDEBUG
20 #include <debug.h>
21
22 typedef struct _PERFORM_TEST_ARGS
23 {
24 TestOutputRoutine OutputRoutine;
25 PROS_TEST Test;
26 LPSTR TestName;
27 } PERFORM_TEST_ARGS;
28
29 int _Result;
30 char *_Buffer;
31
32 static LIST_ENTRY AllTests;
33
34 VOID
35 InitializeTests()
36 {
37 InitializeListHead(&AllTests);
38 }
39
40 char*
41 FormatExecutionTime(char *buffer, LPFILETIME time)
42 {
43 ULONG milliseconds = time->dwLowDateTime / 10000;
44
45 sprintf(buffer,
46 "%ldms",
47 milliseconds);
48 return buffer;
49 }
50
51 DWORD WINAPI
52 PerformTest(PVOID _arg)
53 {
54 PERFORM_TEST_ARGS *Args = (PERFORM_TEST_ARGS *)_arg;
55 TestOutputRoutine OutputRoutine = Args->OutputRoutine;
56 PROS_TEST Test = Args->Test;
57 LPSTR TestName = Args->TestName;
58 HANDLE hThread;
59 FILETIME time;
60 FILETIME ExecutionTime;
61 char OutputBuffer[5000];
62 char Buffer[5000];
63 char Format[100];
64
65 hThread = GetCurrentThread();
66 _SetThreadPriority(hThread, THREAD_PRIORITY_IDLE);
67
68 memset(Buffer, 0, sizeof(Buffer));
69
70 _SEH_TRY {
71 _Result = TS_OK;
72 _Buffer = Buffer;
73 (Test->Routine)(TESTCMD_RUN);
74 } _SEH_HANDLE {
75 _Result = TS_FAILED;
76 sprintf(Buffer, "due to exception 0x%lx", _SEH_GetExceptionCode());
77 } _SEH_END;
78
79 if (_Result == TS_OK)
80 {
81 if (!_GetThreadTimes(hThread,
82 &time,
83 &time,
84 &time,
85 &ExecutionTime))
86 {
87 ExecutionTime.dwLowDateTime = 10;
88 ExecutionTime.dwHighDateTime = 10;
89 }
90 sprintf(OutputBuffer,
91 "[%s] Success [%s]\n",
92 TestName,
93 FormatExecutionTime(Format,
94 &ExecutionTime));
95 }
96 else
97 sprintf(OutputBuffer, "[%s] Failed (%s)\n", TestName, Buffer);
98
99 if (OutputRoutine != NULL)
100 (*OutputRoutine)(OutputBuffer);
101 else
102 DbgPrint(OutputBuffer);
103 return 1;
104 }
105
106 VOID
107 PerformTests(TestOutputRoutine OutputRoutine, LPSTR TestName)
108 {
109 PLIST_ENTRY CurrentEntry;
110 PLIST_ENTRY NextEntry;
111 PROS_TEST Current;
112 PERFORM_TEST_ARGS Args;
113 HANDLE hThread;
114 char OutputBuffer[1024];
115 char Name[200];
116 DWORD TimeOut;
117
118 Args.OutputRoutine = OutputRoutine;
119 Args.TestName = Name;
120
121 CurrentEntry = AllTests.Flink;
122 for (; CurrentEntry != &AllTests; CurrentEntry = NextEntry)
123 {
124 NextEntry = CurrentEntry->Flink;
125 Current = CONTAINING_RECORD(CurrentEntry, ROS_TEST, ListEntry);
126 Args.Test = Current;
127
128 /* Get name of test */
129 memset(Name, 0, sizeof(Name));
130
131 _Result = TS_OK;
132 _Buffer = Name;
133 (Current->Routine)(TESTCMD_TESTNAME);
134 if (_Result != TS_OK)
135 {
136 if (TestName != NULL)
137 continue;
138 strcpy(Name, "Unnamed");
139 }
140
141 if ((TestName != NULL) && (_stricmp(Name, TestName) != 0))
142 continue;
143
144 /* Get timeout for test */
145 TimeOut = 0;
146 _Result = TS_OK;
147 _Buffer = (char *)&TimeOut;
148 (Current->Routine)(TESTCMD_TIMEOUT);
149 if (_Result != TS_OK || TimeOut == INFINITE)
150 TimeOut = 5000;
151
152 /* Run test in thread */
153 hThread = _CreateThread(NULL, 0, PerformTest, (PVOID)&Args, 0, NULL);
154 if (hThread == NULL)
155 sprintf(OutputBuffer,
156 "[%s] Failed (CreateThread() failed: %d)\n",
157 Name, (unsigned int)_GetLastError());
158 else if (_WaitForSingleObject(hThread, TimeOut) == WAIT_TIMEOUT)
159 {
160 if (!_TerminateThread(hThread, 0))
161 sprintf(OutputBuffer,
162 "[%s] Failed (timed out after %dms; TerminateThread() failed: %d)\n",
163 Name, (int)TimeOut, (unsigned int)_GetLastError());
164 else
165 sprintf(OutputBuffer, "[%s] Failed (timed out after %dms)\n", Name, (int)TimeOut);
166 _CloseHandle(hThread);
167 }
168 else
169 {
170 _CloseHandle(hThread);
171 continue;
172 }
173
174 if (OutputRoutine != NULL)
175 (*OutputRoutine)(OutputBuffer);
176 else
177 DbgPrint(OutputBuffer);
178 }
179 }
180
181 VOID
182 AddTest(TestRoutine Routine)
183 {
184 PROS_TEST Test;
185
186 Test = (PROS_TEST) malloc(sizeof(ROS_TEST));
187 if (Test == NULL)
188 {
189 DbgPrint("Out of memory");
190 return;
191 }
192
193 Test->Routine = Routine;
194
195 InsertTailList(&AllTests, &Test->ListEntry);
196 }
197
198 PVOID STDCALL
199 FrameworkGetHook(ULONG index)
200 {
201 return FrameworkGetHookInternal(index);
202 }