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