Build regtess with standard windows header only, not NTOS
[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 <windows.h>
10 #include <pseh.h>
11 #include "regtests.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 typedef struct _PERFORM_TEST_ARGS
17 {
18 TestOutputRoutine OutputRoutine;
19 _PTEST Test;
20 LPSTR TestName;
21 DWORD Result;
22 char Buffer[5000];
23 DWORD Time;
24 } PERFORM_TEST_ARGS;
25
26 int _Result;
27 char *_Buffer;
28
29 static LIST_ENTRY AllTests;
30
31 VOID
32 InitializeTests()
33 {
34 InitializeListHead(&AllTests);
35 }
36
37 char*
38 FormatExecutionTime(char *buffer, ULONG milliseconds)
39 {
40 sprintf(buffer,
41 "%ldms",
42 milliseconds);
43 return buffer;
44 }
45
46 DWORD WINAPI
47 PerformTest(PVOID _arg)
48 {
49 PERFORM_TEST_ARGS *Args = (PERFORM_TEST_ARGS *)_arg;
50 _PTEST Test = Args->Test;
51
52 _SetThreadPriority(_GetCurrentThread(), THREAD_PRIORITY_IDLE);
53
54 memset(Args->Buffer, 0, sizeof(Args->Buffer));
55
56 _SEH_TRY {
57 _Result = TS_OK;
58 _Buffer = Args->Buffer;
59 (Test->Routine)(TESTCMD_RUN);
60 Args->Result = _Result;
61 } _SEH_HANDLE {
62 Args->Result = TS_FAILED;
63 sprintf(Args->Buffer, "due to exception 0x%lx", _SEH_GetExceptionCode());
64 } _SEH_END;
65 return 1;
66 }
67
68 BOOL
69 IsContextChanged(LPCONTEXT context1, LPCONTEXT context2)
70 {
71 return memcmp(context1, context2, sizeof(CONTEXT)) != 0;
72 }
73
74 VOID
75 ControlNormalTest(HANDLE hThread,
76 PERFORM_TEST_ARGS *Args,
77 DWORD TimeOut)
78 {
79 FILETIME time;
80 FILETIME executionTime;
81 DWORD status;
82
83 status = _WaitForSingleObject(hThread, TimeOut);
84 if (status == WAIT_TIMEOUT)
85 {
86 _TerminateThread(hThread, 0);
87 Args->Result = TS_TIMEDOUT;
88 }
89 status = _GetThreadTimes(hThread,
90 &time,
91 &time,
92 &time,
93 &executionTime);
94 Args->Time = executionTime.dwLowDateTime / 10000;
95 }
96
97 VOID
98 ControlPerformanceTest(HANDLE hThread,
99 PERFORM_TEST_ARGS *Args,
100 DWORD TimeOut)
101 {
102 DWORD status;
103 CONTEXT lastContext;
104 CONTEXT currentContext;
105
106 ZeroMemory(&lastContext, sizeof(CONTEXT));
107 lastContext.ContextFlags = CONTEXT_FULL;
108 ZeroMemory(&currentContext, sizeof(CONTEXT));
109 currentContext.ContextFlags = CONTEXT_FULL;
110
111 do {
112 _Sleep(1);
113
114 if (_SuspendThread(hThread) == -1)
115 break;
116
117 if (_GetThreadContext(hThread, &currentContext) == 0)
118 break;
119
120 if (IsContextChanged(&currentContext, &lastContext))
121 Args->Time++;
122
123 if (_ResumeThread(hThread) == -1)
124 break;
125
126 if (Args->Time >= TimeOut)
127 {
128 _TerminateThread(hThread, 0);
129 Args->Result = TS_TIMEDOUT;
130 break;
131 }
132
133 status = _WaitForSingleObject(hThread, 0);
134 if (status == WAIT_OBJECT_0 || status == WAIT_FAILED)
135 break;
136
137 lastContext = currentContext;
138 } while (TRUE);
139 }
140
141 VOID
142 DisplayResult(PERFORM_TEST_ARGS* Args,
143 LPSTR OutputBuffer)
144 {
145 char Buffer[5000];
146 char Format[100];
147
148 if (Args->Result == TS_OK)
149 {
150 sprintf(OutputBuffer,
151 "[%s] Success [%s]\n",
152 Args->TestName,
153 FormatExecutionTime(Format,
154 Args->Time));
155 }
156 else if (Args->Result == TS_TIMEDOUT)
157 {
158 sprintf(OutputBuffer,
159 "[%s] Timed out [%s]\n",
160 Args->TestName,
161 FormatExecutionTime(Format,
162 Args->Time));
163 }
164 else
165 sprintf(OutputBuffer, "[%s] Failed (%s)\n", Args->TestName, Buffer);
166
167 if (Args->OutputRoutine != NULL)
168 (*Args->OutputRoutine)(OutputBuffer);
169 else
170 DbgPrint(OutputBuffer);
171 }
172
173 VOID
174 ControlTest(HANDLE hThread,
175 PERFORM_TEST_ARGS *Args,
176 DWORD TestType,
177 DWORD TimeOut)
178 {
179 switch (TestType)
180 {
181 case TT_NORMAL:
182 ControlNormalTest(hThread, Args, TimeOut);
183 break;
184 case TT_PERFORMANCE:
185 ControlPerformanceTest(hThread, Args, TimeOut);
186 break;
187 default:
188 printf("Unknown test type %ld\n", TestType);
189 break;
190 }
191 }
192
193 VOID
194 PerformTests(TestOutputRoutine OutputRoutine, LPSTR TestName)
195 {
196 PLIST_ENTRY CurrentEntry;
197 PLIST_ENTRY NextEntry;
198 _PTEST Current;
199 PERFORM_TEST_ARGS Args;
200 HANDLE hThread;
201 char OutputBuffer[1024];
202 char Name[200];
203 DWORD TestType;
204 DWORD TimeOut;
205
206 Args.OutputRoutine = OutputRoutine;
207 Args.TestName = Name;
208 Args.Time = 0;
209
210 CurrentEntry = AllTests.Flink;
211 for (; CurrentEntry != &AllTests; CurrentEntry = NextEntry)
212 {
213 NextEntry = CurrentEntry->Flink;
214 Current = CONTAINING_RECORD(CurrentEntry, _TEST, ListEntry);
215 Args.Test = Current;
216
217 /* Get name of test */
218 memset(Name, 0, sizeof(Name));
219
220 _Result = TS_OK;
221 _Buffer = Name;
222 (Current->Routine)(TESTCMD_TESTNAME);
223 if (_Result != TS_OK)
224 {
225 if (TestName != NULL)
226 continue;
227 strcpy(Name, "Unnamed");
228 }
229
230 if ((TestName != NULL) && (_stricmp(Name, TestName) != 0))
231 continue;
232
233 TestType = TT_NORMAL;
234 _Result = TS_OK;
235 _Buffer = (char *)&TestType;
236 (Current->Routine)(TESTCMD_TESTTYPE);
237 if (_Result != TS_OK)
238 TestType = TT_NORMAL;
239
240 /* Get timeout for test */
241 TimeOut = 0;
242 _Result = TS_OK;
243 _Buffer = (char *)&TimeOut;
244 (Current->Routine)(TESTCMD_TIMEOUT);
245 if (_Result != TS_OK || TimeOut == INFINITE)
246 TimeOut = 5000;
247
248 /* Run test in a separate thread */
249 hThread = _CreateThread(NULL, 0, PerformTest, (PVOID)&Args, 0, NULL);
250 if (hThread == NULL)
251 {
252 printf("[%s] Failed (CreateThread() failed: %ld)\n",
253 Name,
254 _GetLastError());
255 Args.Result = TS_FAILED;
256 }
257 else
258 ControlTest(hThread, &Args, TestType, TimeOut);
259
260 DisplayResult(&Args, OutputBuffer);
261 }
262 }
263
264 VOID
265 AddTest(TestRoutine Routine)
266 {
267 _PTEST Test;
268
269 Test = (_PTEST) malloc(sizeof(_TEST));
270 if (Test == NULL)
271 {
272 DbgPrint("Out of memory");
273 return;
274 }
275
276 Test->Routine = Routine;
277
278 InsertTailList(&AllTests, &Test->ListEntry);
279 }
280
281 PVOID STDCALL
282 FrameworkGetHook(ULONG index)
283 {
284 return FrameworkGetHookInternal(index);
285 }