Catch hang-up regtests, added _DispatcherTimeout macros for tests to specify timeout...
[reactos.git] / reactos / regtests / shared / regtests.h
1 /*
2 * PROJECT: ReactOS kernel
3 * FILE: regtests/shared/regtests.h
4 * PURPOSE: Regression testing
5 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
6 * UPDATE HISTORY:
7 * 06-07-2003 CSH Created
8 */
9 #include <stdio.h>
10 #include <string.h>
11
12 extern void SetupOnce();
13
14 #define _SetupOnce() \
15 void SetupOnce()
16
17 /* Valid values for Command parameter of TestRoutine */
18 #define TESTCMD_RUN 0 /* Buffer contains information about what failed */
19 #define TESTCMD_TESTNAME 1 /* Buffer contains description of test */
20 #define TESTCMD_TIMEOUT 2 /* Buffer contains timeout for test (DWORD, default is 5000 ms) */
21
22 /* Valid values for return values of TestRoutine */
23 #define TS_EXCEPTION -1
24 #define TS_OK 0
25 #define TS_FAILED 1
26
27 extern int _Result;
28 extern char *_Buffer;
29
30 /* Macros to simplify tests */
31 #define _DispatcherTimeout(FunctionName, TestName, TimeOut) \
32 void \
33 FunctionName(int Command) \
34 { \
35 switch (Command) \
36 { \
37 case TESTCMD_RUN: \
38 RunTest(); \
39 break; \
40 case TESTCMD_TESTNAME: \
41 strcpy(_Buffer, TestName); \
42 break; \
43 case TESTCMD_TIMEOUT: \
44 *(PDWORD)_Buffer = (DWORD)TimeOut; \
45 break; \
46 default: \
47 _Result = TS_FAILED; \
48 break; \
49 } \
50 }
51
52 #define _Dispatcher(FunctionName, TestName) _DispatcherTimeout(FunctionName, TestName, 5000)
53
54 static inline void
55 AppendAssertion(char *message)
56 {
57 if (strlen(_Buffer) != 0)
58 strcat(_Buffer, "\n");
59 strcat(_Buffer, message);
60 _Result = TS_FAILED;
61 }
62
63 #define _AssertTrue(_Condition) \
64 { \
65 if (!(_Condition)) \
66 { \
67 char _message[100]; \
68 sprintf(_message, "Condition was not true at %s:%d", \
69 __FILE__, __LINE__); \
70 AppendAssertion(_message); \
71 } \
72 }
73
74 #define _AssertFalse(_Condition) \
75 { \
76 if (_Condition) \
77 { \
78 char _message[100]; \
79 sprintf(_message, "Condition was not false at %s:%d", \
80 __FILE__, __LINE__); \
81 AppendAssertion(_message); \
82 } \
83 }
84
85 #define _AssertEqualValue(_Expected, _Actual) \
86 { \
87 ULONG __Expected = (ULONG) (_Expected); \
88 ULONG __Actual = (ULONG) (_Actual); \
89 if ((__Expected) != (__Actual)) \
90 { \
91 char _message[100]; \
92 sprintf(_message, "Expected %ld/0x%.08lx was %ld/0x%.08lx at %s:%d", \
93 (__Expected), (__Expected), (__Actual), (__Actual), __FILE__, __LINE__); \
94 AppendAssertion(_message); \
95 } \
96 }
97
98 #define _AssertEqualWideString(_Expected, _Actual) \
99 { \
100 LPWSTR __Expected = (LPWSTR) (_Expected); \
101 LPWSTR __Actual = (LPWSTR) (_Actual); \
102 if (wcscmp((__Expected), (__Actual)) != 0) \
103 { \
104 char _message[100]; \
105 sprintf(_message, "Expected %S was %S at %s:%d", \
106 (__Expected), (__Actual), __FILE__, __LINE__); \
107 AppendAssertion(_message); \
108 } \
109 }
110
111 #define _AssertNotEqualValue(_Expected, _Actual) \
112 { \
113 ULONG __Expected = (ULONG) (_Expected); \
114 ULONG __Actual = (ULONG) (_Actual); \
115 if ((__Expected) == (__Actual)) \
116 { \
117 char _message[100]; \
118 sprintf(_message, "Actual value expected to be different from %ld/0x%.08lx at %s:%d", \
119 (__Expected), (__Expected), __FILE__, __LINE__); \
120 AppendAssertion(_message); \
121 } \
122 }
123
124
125 /*
126 * Test routine prototype
127 * Command - The command to process
128 */
129 typedef void (*TestRoutine)(int Command);
130
131 /*
132 * Test output routine prototype
133 * Buffer - Address of buffer with text to output
134 */
135 typedef void (*TestOutputRoutine)(char *Buffer);
136
137 /*
138 * Test driver entry routine.
139 * OutputRoutine - Output routine.
140 * TestName - If NULL all tests are run. If non-NULL specifies the test to be run
141 */
142 typedef void STDCALL (*TestDriverMain)(TestOutputRoutine OutputRoutine, char *TestName);
143
144 typedef struct _ROS_TEST
145 {
146 LIST_ENTRY ListEntry;
147 TestRoutine Routine;
148 } ROS_TEST, *PROS_TEST;
149
150 extern LIST_ENTRY AllTests;
151
152 extern VOID InitializeTests();
153 extern VOID RegisterTests();
154 extern VOID PerformTests(TestOutputRoutine OutputRoutine, LPSTR TestName);
155
156
157 typedef struct _API_DESCRIPTION
158 {
159 PCHAR FileName;
160 PCHAR FunctionName;
161 PCHAR ForwardedFunctionName;
162 PVOID FunctionAddress;
163 PVOID MockFunctionAddress;
164 } API_DESCRIPTION, *PAPI_DESCRIPTION;
165
166 extern API_DESCRIPTION ExternalDependencies[];
167 extern ULONG MaxExternalDependency;
168
169 HANDLE STDCALL
170 _GetModuleHandleA(LPCSTR lpModuleName);
171
172 PVOID STDCALL
173 _GetProcAddress(HANDLE hModule,
174 LPCSTR lpProcName);
175
176 HANDLE STDCALL
177 _LoadLibraryA(LPCSTR lpLibFileName);
178
179 VOID STDCALL
180 _ExitProcess(UINT uExitCode);
181
182 HANDLE STDCALL
183 _CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize,
184 LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter,
185 DWORD dwCreationFlags, LPDWORD lpThreadId);
186
187 WINBOOL STDCALL
188 _TerminateThread(HANDLE hThread, DWORD dwExitCode);
189
190 DWORD STDCALL
191 _WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
192
193
194 static inline PCHAR
195 FrameworkGetExportedFunctionNameInternal(PAPI_DESCRIPTION ApiDescription)
196 {
197 if (ApiDescription->ForwardedFunctionName != NULL)
198 {
199 return ApiDescription->ForwardedFunctionName;
200 }
201 else
202 {
203 return ApiDescription->FunctionName;
204 }
205 }
206
207 static inline PVOID
208 FrameworkGetFunction(PAPI_DESCRIPTION ApiDescription)
209 {
210 HANDLE hModule;
211 PVOID function;
212 PCHAR exportedFunctionName;
213
214 exportedFunctionName = FrameworkGetExportedFunctionNameInternal(ApiDescription);
215
216 hModule = _GetModuleHandleA(ApiDescription->FileName);
217 if (hModule != NULL)
218 {
219 function = _GetProcAddress(hModule, exportedFunctionName);
220 }
221 else
222 {
223 hModule = _LoadLibraryA(ApiDescription->FileName);
224 if (hModule != NULL)
225 {
226 function = _GetProcAddress(hModule, exportedFunctionName);
227 //FreeLibrary(hModule);
228 }
229 }
230 return function;
231 }
232
233 static inline PVOID
234 FrameworkGetHookInternal(ULONG index)
235 {
236 PVOID address;
237 PCHAR exportedFunctionName;
238
239 if (index > MaxExternalDependency)
240 return NULL;
241
242 if (ExternalDependencies[index].MockFunctionAddress != NULL)
243 return ExternalDependencies[index].MockFunctionAddress;
244
245 if (ExternalDependencies[index].FunctionAddress != NULL)
246 return ExternalDependencies[index].FunctionAddress;
247
248 exportedFunctionName = FrameworkGetExportedFunctionNameInternal(&ExternalDependencies[index]);
249
250 printf("Calling function '%s' in DLL '%s'.\n",
251 exportedFunctionName,
252 ExternalDependencies[index].FileName);
253
254 address = FrameworkGetFunction(&ExternalDependencies[index]);
255
256 if (address == NULL)
257 {
258 printf("Function '%s' not found in DLL '%s'.\n",
259 exportedFunctionName,
260 ExternalDependencies[index].FileName);
261 }
262 ExternalDependencies[index].FunctionAddress = address;
263
264 return address;
265 }
266
267
268 static inline VOID
269 _SetHook(PCHAR name,
270 PVOID address)
271 {
272 PAPI_DESCRIPTION api;
273 ULONG index;
274
275 for (index = 0; index <= MaxExternalDependency; index++)
276 {
277 api = &ExternalDependencies[index];
278 if (strcmp(api->FunctionName, name) == 0)
279 {
280 api->MockFunctionAddress = address;
281 return;
282 }
283 }
284 }
285
286 typedef struct _HOOK
287 {
288 PCHAR FunctionName;
289 PVOID FunctionAddress;
290 } HOOK, *PHOOK;
291
292 static inline VOID
293 _SetHooks(PHOOK hookTable)
294 {
295 PHOOK hook;
296
297 hook = &hookTable[0];
298 while (hook->FunctionName != NULL)
299 {
300 _SetHook(hook->FunctionName,
301 hook->FunctionAddress);
302 hook++;
303 }
304 }
305
306 static inline VOID
307 _UnsetHooks(PHOOK hookTable)
308 {
309 PHOOK hook;
310
311 hook = &hookTable[0];
312 while (hook->FunctionName != NULL)
313 {
314 _SetHook(hook->FunctionName,
315 NULL);
316 hook++;
317 }
318 }
319
320 static inline VOID
321 _UnsetAllHooks()
322 {
323 PAPI_DESCRIPTION api;
324 ULONG index;
325
326 for (index = 0; index <= MaxExternalDependency; index++)
327 {
328 api = &ExternalDependencies[index];
329 api->MockFunctionAddress = NULL;
330 }
331 }