3513911b60064cf88852bc3e378a4d0e7163375e
[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 #define WIN32_NO_STATUS
10 #include <windows.h>
11 #define NTOS_MODE_USER
12 #include <ndk/ntndk.h>
13 #include <pseh/pseh.h>
14 #include "regtests.h"
15
16 #define NDEBUG
17 #include <debug.h>
18
19 typedef struct _PERFORM_TEST_ARGS
20 {
21 TestOutputRoutine OutputRoutine;
22 _PTEST Test;
23 LPSTR TestName;
24 DWORD Result;
25 char Buffer[5000];
26 DWORD Time;
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, ULONG milliseconds)
42 {
43 sprintf(buffer,
44 "%ldms",
45 milliseconds);
46 return buffer;
47 }
48
49 DWORD WINAPI
50 PerformTest(PVOID _arg)
51 {
52 PERFORM_TEST_ARGS *Args = (PERFORM_TEST_ARGS *)_arg;
53 _PTEST Test = Args->Test;
54
55 _SetThreadPriority(_GetCurrentThread(), THREAD_PRIORITY_IDLE);
56
57 memset(Args->Buffer, 0, sizeof(Args->Buffer));
58
59 _SEH_TRY {
60 _Result = TS_OK;
61 _Buffer = Args->Buffer;
62 (Test->Routine)(TESTCMD_RUN);
63 Args->Result = _Result;
64 } _SEH_HANDLE {
65 Args->Result = TS_FAILED;
66 sprintf(Args->Buffer, "due to exception 0x%lx", _SEH_GetExceptionCode());
67 } _SEH_END;
68 return 1;
69 }
70
71 VOID
72 ControlNormalTest(HANDLE hThread,
73 PERFORM_TEST_ARGS *Args,
74 DWORD TimeOut)
75 {
76 _FILETIME time;
77 _FILETIME executionTime;
78 DWORD status;
79
80 status = _WaitForSingleObject(hThread, TimeOut);
81 if (status == WAIT_TIMEOUT)
82 {
83 _TerminateThread(hThread, 0);
84 Args->Result = TS_TIMEDOUT;
85 }
86 status = _GetThreadTimes(hThread,
87 &time,
88 &time,
89 &time,
90 &executionTime);
91 Args->Time = executionTime.dwLowDateTime / 10000;
92 }
93
94 VOID
95 DisplayResult(PERFORM_TEST_ARGS* Args,
96 LPSTR OutputBuffer)
97 {
98 char Format[100];
99
100 if (Args->Result == TS_OK)
101 {
102 sprintf(OutputBuffer,
103 "[%s] Success [%s]\n",
104 Args->TestName,
105 FormatExecutionTime(Format,
106 Args->Time));
107 }
108 else if (Args->Result == TS_TIMEDOUT)
109 {
110 sprintf(OutputBuffer,
111 "[%s] Timed out [%s]\n",
112 Args->TestName,
113 FormatExecutionTime(Format,
114 Args->Time));
115 }
116 else
117 sprintf(OutputBuffer, "[%s] Failed (%s)\n", Args->TestName, Args->Buffer);
118
119 if (Args->OutputRoutine != NULL)
120 (*Args->OutputRoutine)(OutputBuffer);
121 else
122 DbgPrint(OutputBuffer);
123 }
124
125 VOID
126 ControlTest(HANDLE hThread,
127 PERFORM_TEST_ARGS *Args,
128 DWORD TestType,
129 DWORD TimeOut)
130 {
131 switch (TestType)
132 {
133 case TT_NORMAL:
134 ControlNormalTest(hThread, Args, TimeOut);
135 break;
136 default:
137 printf("Unknown test type %ld\n", TestType);
138 break;
139 }
140 }
141
142 VOID
143 PerformTests(TestOutputRoutine OutputRoutine, LPSTR TestName)
144 {
145 PLIST_ENTRY CurrentEntry;
146 PLIST_ENTRY NextEntry;
147 _PTEST Current;
148 PERFORM_TEST_ARGS Args;
149 HANDLE hThread;
150 char OutputBuffer[1024];
151 char Name[200];
152 DWORD TestType;
153 DWORD TimeOut;
154
155 Args.OutputRoutine = OutputRoutine;
156 Args.TestName = Name;
157 Args.Time = 0;
158
159 CurrentEntry = AllTests.Flink;
160 for (; CurrentEntry != &AllTests; CurrentEntry = NextEntry)
161 {
162 NextEntry = CurrentEntry->Flink;
163 Current = CONTAINING_RECORD(CurrentEntry, _TEST, ListEntry);
164 Args.Test = Current;
165
166 /* Get name of test */
167 memset(Name, 0, sizeof(Name));
168
169 _Result = TS_OK;
170 _Buffer = Name;
171 (Current->Routine)(TESTCMD_TESTNAME);
172 if (_Result != TS_OK)
173 {
174 if (TestName != NULL)
175 continue;
176 strcpy(Name, "Unnamed");
177 }
178
179 if ((TestName != NULL) && (_stricmp(Name, TestName) != 0))
180 continue;
181
182 TestType = TT_NORMAL;
183 _Result = TS_OK;
184 _Buffer = (char *)&TestType;
185 (Current->Routine)(TESTCMD_TESTTYPE);
186 if (_Result != TS_OK)
187 TestType = TT_NORMAL;
188
189 /* Get timeout for test */
190 TimeOut = 0;
191 _Result = TS_OK;
192 _Buffer = (char *)&TimeOut;
193 (Current->Routine)(TESTCMD_TIMEOUT);
194 if (_Result != TS_OK || TimeOut == INFINITE)
195 TimeOut = 5000;
196
197 /* Run test in a separate thread */
198 hThread = _CreateThread(NULL, 0, PerformTest, (PVOID)&Args, 0, NULL);
199 if (hThread == NULL)
200 {
201 printf("[%s] Failed (CreateThread() failed: %ld)\n",
202 Name,
203 _GetLastError());
204 Args.Result = TS_FAILED;
205 }
206 else
207 ControlTest(hThread, &Args, TestType, TimeOut);
208
209 DisplayResult(&Args, OutputBuffer);
210 }
211 }
212
213 VOID
214 AddTest(TestRoutine Routine)
215 {
216 _PTEST Test;
217
218 Test = (_PTEST) malloc(sizeof(_TEST));
219 if (Test == NULL)
220 {
221 DbgPrint("Out of memory");
222 return;
223 }
224
225 Test->Routine = Routine;
226
227 InsertTailList(&AllTests, &Test->ListEntry);
228 }
229
230 PVOID STDCALL
231 FrameworkGetHook(ULONG index)
232 {
233 return FrameworkGetHookInternal(index);
234 }