2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite test framework declarations
5 * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
8 /* Inspired by Wine C unit tests, Copyright (C) 2002 Alexandre Julliard
9 * Inspired by ReactOS kernel-mode regression tests,
10 * Copyright (C) Aleksey Bragin, Filip Navara
13 #ifndef _KMTEST_TEST_H_
14 #define _KMTEST_TEST_H_
18 typedef VOID
KMT_TESTFUNC(VOID
);
19 typedef KMT_TESTFUNC
*PKMT_TESTFUNC
;
24 KMT_TESTFUNC
*TestFunction
;
25 } KMT_TEST
, *PKMT_TEST
;
27 typedef const KMT_TEST CKMT_TEST
, *PCKMT_TEST
;
29 extern const KMT_TEST TestList
[];
33 volatile LONG Successes
;
34 volatile LONG Failures
;
35 volatile LONG Skipped
;
36 volatile LONG LogBufferLength
;
37 LONG LogBufferMaxLength
;
38 CHAR LogBuffer
[ANYSIZE_ARRAY
];
39 } KMT_RESULTBUFFER
, *PKMT_RESULTBUFFER
;
41 #ifdef KMT_KERNEL_MODE
42 /* Device Extension layout */
45 PKMT_RESULTBUFFER ResultBuffer
;
47 } KMT_DEVICE_EXTENSION
, *PKMT_DEVICE_EXTENSION
;
48 #elif defined KMT_USER_MODE
49 VOID
KmtLoadDriver(IN PCWSTR ServiceName
, IN BOOLEAN RestartIfRunning
);
50 VOID
KmtUnloadDriver(VOID
);
51 VOID
KmtOpenDriver(VOID
);
52 VOID
KmtCloseDriver(VOID
);
54 DWORD
KmtSendToDriver(IN DWORD ControlCode
);
55 DWORD
KmtSendStringToDriver(IN DWORD ControlCode
, IN PCSTR String
);
56 DWORD
KmtSendBufferToDriver(IN DWORD ControlCode
, IN OUT PVOID Buffer
, IN OUT PDWORD Length
);
57 #endif /* defined KMT_USER_MODE */
59 extern PKMT_RESULTBUFFER ResultBuffer
;
62 #define KMT_FORMAT(type, fmt, first) __attribute__((__format__(type, fmt, first)))
63 #elif !defined __GNUC__
64 #define KMT_FORMAT(type, fmt, first)
65 #endif /* !defined __GNUC__ */
67 #define START_TEST(name) VOID Test_##name(VOID)
70 #define KMT_STRINGIZE(x) #x
71 #endif /* !defined KMT_STRINGIZE */
72 #define ok(test, ...) ok_(test, __FILE__, __LINE__, __VA_ARGS__)
73 #define trace(...) trace_( __FILE__, __LINE__, __VA_ARGS__)
74 #define skip(test, ...) skip_(test, __FILE__, __LINE__, __VA_ARGS__)
76 #define ok_(test, file, line, ...) KmtOk(test, file ":" KMT_STRINGIZE(line), __VA_ARGS__)
77 #define trace_(file, line, ...) KmtTrace( file ":" KMT_STRINGIZE(line), __VA_ARGS__)
78 #define skip_(test, file, line, ...) KmtSkip(test, file ":" KMT_STRINGIZE(line), __VA_ARGS__)
80 VOID
KmtVOk(INT Condition
, PCSTR FileAndLine
, PCSTR Format
, va_list Arguments
) KMT_FORMAT(ms_printf
, 3, 0);
81 VOID
KmtOk(INT Condition
, PCSTR FileAndLine
, PCSTR Format
, ...) KMT_FORMAT(ms_printf
, 3, 4);
82 VOID
KmtVTrace(PCSTR FileAndLine
, PCSTR Format
, va_list Arguments
) KMT_FORMAT(ms_printf
, 2, 0);
83 VOID
KmtTrace(PCSTR FileAndLine
, PCSTR Format
, ...) KMT_FORMAT(ms_printf
, 2, 3);
84 BOOLEAN
KmtVSkip(INT Condition
, PCSTR FileAndLine
, PCSTR Format
, va_list Arguments
) KMT_FORMAT(ms_printf
, 3, 0);
85 BOOLEAN
KmtSkip(INT Condition
, PCSTR FileAndLine
, PCSTR Format
, ...) KMT_FORMAT(ms_printf
, 3, 4);
87 #ifdef KMT_KERNEL_MODE
88 #define ok_irql(irql) ok(KeGetCurrentIrql() == irql, "IRQL is %d, expected %d\n", KeGetCurrentIrql(), irql)
89 #endif /* defined KMT_KERNEL_MODE */
90 #define ok_eq_print(value, expected, spec) ok((value) == (expected), #value " = " spec ", expected " spec "\n", value, expected)
91 #define ok_eq_pointer(value, expected) ok_eq_print(value, expected, "%p")
92 #define ok_eq_int(value, expected) ok_eq_print(value, expected, "%d")
93 #define ok_eq_uint(value, expected) ok_eq_print(value, expected, "%u")
94 #define ok_eq_long(value, expected) ok_eq_print(value, expected, "%ld")
95 #define ok_eq_ulong(value, expected) ok_eq_print(value, expected, "%lu")
96 #define ok_eq_hex(value, expected) ok_eq_print(value, expected, "0x%08lx")
97 #define ok_bool_true(value, desc) ok((value) == TRUE, desc " FALSE, expected TRUE\n")
98 #define ok_bool_false(value, desc) ok((value) == FALSE, desc " TRUE, expected FALSE\n")
99 #define ok_eq_bool(value, expected) ok((value) == (expected), #value " = %s, expected %s\n", \
100 (value) ? "TRUE" : "FALSE", \
101 (expected) ? "TRUE" : "FALSE")
102 #define ok_eq_str(value, expected) ok(!strcmp(value, expected), #value " = \"%s\", expected \"%s\"\n", value, expected)
103 #define ok_eq_wstr(value, expected) ok(!wcscmp(value, expected), #value " = \"%ls\", expected \"%ls\"\n", value, expected)
105 #define KMT_MAKE_CODE(ControlCode) CTL_CODE(FILE_DEVICE_UNKNOWN, \
106 0xA00 + (ControlCode), \
110 #if defined KMT_DEFINE_TEST_FUNCTIONS
111 PKMT_RESULTBUFFER ResultBuffer
= NULL
;
113 #if defined KMT_USER_MODE
114 static PKMT_RESULTBUFFER
KmtAllocateResultBuffer(SIZE_T LogBufferMaxLength
)
116 PKMT_RESULTBUFFER Buffer
= HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(KMT_RESULTBUFFER
, LogBuffer
[LogBufferMaxLength
]));
118 Buffer
->Successes
= 0;
119 Buffer
->Failures
= 0;
121 Buffer
->LogBufferLength
= 0;
122 Buffer
->LogBufferMaxLength
= LogBufferMaxLength
;
127 static VOID
KmtFreeResultBuffer(PKMT_RESULTBUFFER Buffer
)
129 HeapFree(GetProcessHeap(), 0, Buffer
);
131 #endif /* defined KMT_USER_MODE */
133 static VOID
KmtAddToLogBuffer(PKMT_RESULTBUFFER Buffer
, PCSTR String
, SIZE_T Length
)
143 OldLength
= Buffer
->LogBufferLength
;
144 NewLength
= OldLength
+ Length
;
145 if (NewLength
> Buffer
->LogBufferMaxLength
)
147 /* TODO: indicate failure somehow */
151 } while (InterlockedCompareExchange(&Buffer
->LogBufferLength
, NewLength
, OldLength
) != OldLength
);
153 memcpy(&Buffer
->LogBuffer
[OldLength
], String
, Length
);
156 #ifdef KMT_KERNEL_MODE
157 INT __cdecl
KmtVSNPrintF(PSTR Buffer
, SIZE_T BufferMaxLength
, PCSTR Format
, va_list Arguments
) KMT_FORMAT(ms_printf
, 3, 0);
158 #elif defined KMT_USER_MODE
159 #define KmtVSNPrintF vsnprintf
160 #endif /* defined KMT_USER_MODE */
162 KMT_FORMAT(ms_printf
, 5, 0)
163 static SIZE_T
KmtXVSNPrintF(PSTR Buffer
, SIZE_T BufferMaxLength
, PCSTR FileAndLine
, PCSTR Prepend
, PCSTR Format
, va_list Arguments
)
165 SIZE_T BufferLength
= 0;
171 Slash
= strrchr(FileAndLine
, '\\');
173 FileAndLine
= Slash
+ 1;
174 Slash
= strrchr(FileAndLine
, '/');
176 FileAndLine
= Slash
+ 1;
178 Length
= min(BufferMaxLength
, strlen(FileAndLine
));
179 memcpy(Buffer
, FileAndLine
, Length
);
181 BufferLength
+= Length
;
182 BufferMaxLength
-= Length
;
186 Length
= min(BufferMaxLength
, strlen(Prepend
));
187 memcpy(Buffer
, Prepend
, Length
);
189 BufferLength
+= Length
;
190 BufferMaxLength
-= Length
;
194 Length
= KmtVSNPrintF(Buffer
, BufferMaxLength
, Format
, Arguments
);
195 /* vsnprintf can return more than maxLength, we don't want to do that */
196 BufferLength
+= min(Length
, BufferMaxLength
);
201 KMT_FORMAT(ms_printf
, 5, 6)
202 static SIZE_T
KmtXSNPrintF(PSTR Buffer
, SIZE_T BufferMaxLength
, PCSTR FileAndLine
, PCSTR Prepend
, PCSTR Format
, ...)
206 va_start(Arguments
, Format
);
207 BufferLength
= KmtXVSNPrintF(Buffer
, BufferMaxLength
, FileAndLine
, Prepend
, Format
, Arguments
);
212 VOID
KmtFinishTest(PCSTR TestName
)
214 CHAR MessageBuffer
[512];
215 SIZE_T MessageLength
;
220 MessageLength
= KmtXSNPrintF(MessageBuffer
, sizeof MessageBuffer
, NULL
, NULL
,
221 "%s: %ld tests executed (0 marked as todo, %ld failures), %ld skipped.\n",
223 ResultBuffer
->Successes
+ ResultBuffer
->Failures
,
224 ResultBuffer
->Failures
,
225 ResultBuffer
->Skipped
);
226 KmtAddToLogBuffer(ResultBuffer
, MessageBuffer
, MessageLength
);
229 VOID
KmtVOk(INT Condition
, PCSTR FileAndLine
, PCSTR Format
, va_list Arguments
)
231 CHAR MessageBuffer
[512];
232 SIZE_T MessageLength
;
239 InterlockedIncrement(&ResultBuffer
->Successes
);
241 if (0/*KmtReportSuccess*/)
243 MessageLength
= KmtXSNPrintF(MessageBuffer
, sizeof MessageBuffer
, FileAndLine
, ": Test succeeded\n", NULL
);
244 KmtAddToLogBuffer(ResultBuffer
, MessageBuffer
, MessageLength
);
249 InterlockedIncrement(&ResultBuffer
->Failures
);
250 MessageLength
= KmtXVSNPrintF(MessageBuffer
, sizeof MessageBuffer
, FileAndLine
, ": Test failed: ", Format
, Arguments
);
251 KmtAddToLogBuffer(ResultBuffer
, MessageBuffer
, MessageLength
);
255 VOID
KmtOk(INT Condition
, PCSTR FileAndLine
, PCSTR Format
, ...)
258 va_start(Arguments
, Format
);
259 KmtVOk(Condition
, FileAndLine
, Format
, Arguments
);
263 VOID
KmtVTrace(PCSTR FileAndLine
, PCSTR Format
, va_list Arguments
)
265 CHAR MessageBuffer
[512];
266 SIZE_T MessageLength
;
268 MessageLength
= KmtXVSNPrintF(MessageBuffer
, sizeof MessageBuffer
, FileAndLine
, ": ", Format
, Arguments
);
269 KmtAddToLogBuffer(ResultBuffer
, MessageBuffer
, MessageLength
);
272 VOID
KmtTrace(PCSTR FileAndLine
, PCSTR Format
, ...)
275 va_start(Arguments
, Format
);
276 KmtVTrace(FileAndLine
, Format
, Arguments
);
280 BOOLEAN
KmtVSkip(INT Condition
, PCSTR FileAndLine
, PCSTR Format
, va_list Arguments
)
282 CHAR MessageBuffer
[512];
283 SIZE_T MessageLength
;
290 InterlockedIncrement(&ResultBuffer
->Skipped
);
291 MessageLength
= KmtXVSNPrintF(MessageBuffer
, sizeof MessageBuffer
, FileAndLine
, ": Tests skipped: ", Format
, Arguments
);
292 KmtAddToLogBuffer(ResultBuffer
, MessageBuffer
, MessageLength
);
298 BOOLEAN
KmtSkip(INT Condition
, PCSTR FileAndLine
, PCSTR Format
, ...)
302 va_start(Arguments
, Format
);
303 Ret
= KmtVSkip(Condition
, FileAndLine
, Format
, Arguments
);
308 #endif /* defined KMT_DEFINE_TEST_FUNCTIONS */
310 #endif /* !defined _KMTEST_TEST_H_ */