Show execution time of tests
[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 VOID InitializeTests();
151 extern VOID RegisterTests();
152 extern VOID PerformTests(TestOutputRoutine OutputRoutine, LPSTR TestName);
153
154
155 typedef struct _API_DESCRIPTION
156 {
157 PCHAR FileName;
158 PCHAR FunctionName;
159 PCHAR ForwardedFunctionName;
160 PVOID FunctionAddress;
161 PVOID MockFunctionAddress;
162 } API_DESCRIPTION, *PAPI_DESCRIPTION;
163
164 extern API_DESCRIPTION ExternalDependencies[];
165 extern ULONG MaxExternalDependency;
166
167 HANDLE STDCALL
168 _GetModuleHandleA(LPCSTR lpModuleName);
169
170 PVOID STDCALL
171 _GetProcAddress(HANDLE hModule,
172 LPCSTR lpProcName);
173
174 HANDLE STDCALL
175 _LoadLibraryA(LPCSTR lpLibFileName);
176
177 VOID STDCALL
178 _ExitProcess(UINT uExitCode);
179
180 HANDLE STDCALL
181 _CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize,
182 LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter,
183 DWORD dwCreationFlags, LPDWORD lpThreadId);
184
185 WINBOOL STDCALL
186 _TerminateThread(HANDLE hThread, DWORD dwExitCode);
187
188 DWORD STDCALL
189 _WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
190
191 DWORD STDCALL
192 _GetLastError();
193
194 VOID STDCALL
195 _CloseHandle(HANDLE handle);
196
197 BOOL STDCALL
198 _GetThreadTimes(HANDLE hThread, LPFILETIME lpCreationTime,
199 LPFILETIME lpExitTime, LPFILETIME lpKernelTime,
200 LPFILETIME lpUserTime);
201
202 BOOL STDCALL
203 _SetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass);
204
205 BOOL STDCALL
206 _SetThreadPriority(HANDLE hThread, int nPriority);
207
208
209 static inline PCHAR
210 FrameworkGetExportedFunctionNameInternal(PAPI_DESCRIPTION ApiDescription)
211 {
212 if (ApiDescription->ForwardedFunctionName != NULL)
213 {
214 return ApiDescription->ForwardedFunctionName;
215 }
216 else
217 {
218 return ApiDescription->FunctionName;
219 }
220 }
221
222 static inline PVOID
223 FrameworkGetFunction(PAPI_DESCRIPTION ApiDescription)
224 {
225 HANDLE hModule;
226 PVOID function = NULL;
227 PCHAR exportedFunctionName;
228
229 exportedFunctionName = FrameworkGetExportedFunctionNameInternal(ApiDescription);
230
231 hModule = _GetModuleHandleA(ApiDescription->FileName);
232 if (hModule != NULL)
233 {
234 function = _GetProcAddress(hModule, exportedFunctionName);
235 }
236 else
237 {
238 hModule = _LoadLibraryA(ApiDescription->FileName);
239 if (hModule != NULL)
240 {
241 function = _GetProcAddress(hModule, exportedFunctionName);
242 //FreeLibrary(hModule);
243 }
244 }
245 return function;
246 }
247
248 static inline PVOID
249 FrameworkGetHookInternal(ULONG index)
250 {
251 PVOID address;
252 PCHAR exportedFunctionName;
253
254 if (index > MaxExternalDependency)
255 return NULL;
256
257 if (ExternalDependencies[index].MockFunctionAddress != NULL)
258 return ExternalDependencies[index].MockFunctionAddress;
259
260 if (ExternalDependencies[index].FunctionAddress != NULL)
261 return ExternalDependencies[index].FunctionAddress;
262
263 exportedFunctionName = FrameworkGetExportedFunctionNameInternal(&ExternalDependencies[index]);
264
265 printf("Calling function '%s' in DLL '%s'.\n",
266 exportedFunctionName,
267 ExternalDependencies[index].FileName);
268
269 address = FrameworkGetFunction(&ExternalDependencies[index]);
270
271 if (address == NULL)
272 {
273 printf("Function '%s' not found in DLL '%s'.\n",
274 exportedFunctionName,
275 ExternalDependencies[index].FileName);
276 }
277 ExternalDependencies[index].FunctionAddress = address;
278
279 return address;
280 }
281
282
283 static inline VOID
284 _SetHook(PCHAR name,
285 PVOID address)
286 {
287 PAPI_DESCRIPTION api;
288 ULONG index;
289
290 for (index = 0; index <= MaxExternalDependency; index++)
291 {
292 api = &ExternalDependencies[index];
293 if (strcmp(api->FunctionName, name) == 0)
294 {
295 api->MockFunctionAddress = address;
296 return;
297 }
298 }
299 }
300
301 typedef struct _HOOK
302 {
303 PCHAR FunctionName;
304 PVOID FunctionAddress;
305 } HOOK, *PHOOK;
306
307 static inline VOID
308 _SetHooks(PHOOK hookTable)
309 {
310 PHOOK hook;
311
312 hook = &hookTable[0];
313 while (hook->FunctionName != NULL)
314 {
315 _SetHook(hook->FunctionName,
316 hook->FunctionAddress);
317 hook++;
318 }
319 }
320
321 static inline VOID
322 _UnsetHooks(PHOOK hookTable)
323 {
324 PHOOK hook;
325
326 hook = &hookTable[0];
327 while (hook->FunctionName != NULL)
328 {
329 _SetHook(hook->FunctionName,
330 NULL);
331 hook++;
332 }
333 }
334
335 static inline VOID
336 _UnsetAllHooks()
337 {
338 PAPI_DESCRIPTION api;
339 ULONG index;
340
341 for (index = 0; index <= MaxExternalDependency; index++)
342 {
343 api = &ExternalDependencies[index];
344 api->MockFunctionAddress = NULL;
345 }
346 }