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