xref: /illumos-gate/usr/src/uts/common/sys/ktest.h (revision 08855964b9970604433f7b19dcd71cf5af5e5f14)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2023 Oxide Computer Company
14  * Copyright 2024 Ryan Zezeski
15  */
16 
17 /*
18  * This file defines both the userspace ioctl API/ABI as well as the
19  * ktest module API/ABI. The latter is everything hidden behind the
20  * _KERNEL guard.
21  */
22 #ifndef	_SYS_KTEST_H
23 #define	_SYS_KTEST_H
24 
25 #include <sys/ddi.h>
26 #include <sys/sunddi.h>
27 #include <sys/modctl.h>
28 #include <sys/param.h>
29 #include <sys/types.h>
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #define	KTEST_SEPARATOR		":"
36 #define	KTEST_DEF_TRIPLE	"*:*:*"
37 #define	KTEST_DEF_TRIPLE_SZ	6
38 #define	KTEST_MAX_NAME_LEN	64
39 #define	KTEST_MAX_TRIPLE_LEN	((KTEST_MAX_NAME_LEN * 3) + 3)
40 #define	KTEST_MAX_LOG_LEN	4096
41 #define	KTEST_NAME_KEY		"name"
42 #define	KTEST_MODULE_KEY	"module"
43 #define	KTEST_MODULE_SUITES_KEY	"suites"
44 #define	KTEST_SUITE_KEY		"suite"
45 #define	KTEST_SUITE_TESTS_KEY	"tests"
46 #define	KTEST_TEST_KEY		"test"
47 #define	KTEST_TEST_INPUT_KEY	"input_required"
48 #define	KTEST_GMATCH_CHARS	"*?[]"
49 
50 #define	KTEST_SER_FMT_KEY	"ser_fmt_version"
51 #define	KTEST_SER_FMT_VSN	1ULL
52 
53 /*
54  * The maximum amount of memory a user ioctl could require ktest to
55  * allocate in order to respond to the request. This doesn't include
56  * the actions of the test themselves. It's more to prevent a
57  * negligent ioctl directly causing ktest to kmem_alloc(9F) an
58  * arbitrarily large buffer.
59  *
60  * This also currently includes any input streams for a test, thus the
61  * cap is larger than you might expect it would be. In the future we
62  * should have the ktest driver directly read the file from kernel
63  * space, but for now we pass them as part of the packed nvlist via
64  * the ioctl interface.
65  */
66 #define	KTEST_IOCTL_MAX_LEN	(64 * 1024 * 1024)
67 
68 #define	KTEST_IOCTL	(('k' << 16) | ('t' << 8))
69 
70 typedef enum ktest_ioctl {
71 	KTEST_IOCTL_RUN_TEST	= (KTEST_IOCTL | 1),
72 	KTEST_IOCTL_LIST_TESTS	= (KTEST_IOCTL | 2),
73 } ktest_ioctl_t;
74 
75 /*
76  * Flags used to alter the behavior of ktest or convey additional
77  * information about the test. Passed as the final argument to
78  * ktest_add_test(9F).
79  *
80  * KTEST_FLAG_INPUT
81  *
82  *    This test requires an input stream.
83  *
84  */
85 typedef enum ktest_test_flags {
86 	KTEST_FLAG_NONE	= 0,
87 	KTEST_FLAG_INPUT	= (1 << 0),
88 } ktest_test_flags_t;
89 
90 /*
91  * See the ktest architecture comment in ktest.c for the semantics of
92  * these values. The KTEST_RESULT_NONE value indicates that the test
93  * failed to set a result and should be considered a bug in the test.
94  */
95 typedef enum ktest_result_type {
96 	KTEST_RESULT_NONE,
97 	KTEST_RESULT_PASS,
98 	KTEST_RESULT_FAIL,
99 	KTEST_RESULT_SKIP,
100 	KTEST_RESULT_ERROR
101 } ktest_result_type_t;
102 
103 /* The result of a single test. */
104 typedef struct ktest_result {
105 	char			kr_msg_prepend[KTEST_MAX_LOG_LEN];
106 	char			kr_msg[KTEST_MAX_LOG_LEN];
107 	ktest_result_type_t	kr_type;
108 	int			kr_line;
109 } ktest_result_t;
110 
111 typedef struct ktest_run_op {
112 	char		kro_module[KTEST_MAX_NAME_LEN];
113 	char		kro_suite[KTEST_MAX_NAME_LEN];
114 	char		kro_test[KTEST_MAX_NAME_LEN];
115 	char		kro_input_path[MAXPATHLEN];
116 	uchar_t		*kro_input_bytes;
117 	uint64_t	kro_input_len;
118 	ktest_result_t	kro_result;
119 } ktest_run_op_t;
120 
121 typedef struct ktest_list_op {
122 	char		*klo_resp;
123 	size_t		klo_resp_len;
124 } ktest_list_op_t;
125 
126 /*
127  * The following API/ABI is for the ktest modules.
128  */
129 #ifdef _KERNEL
130 
131 typedef struct __ktest_module_hdl ktest_module_hdl_t;
132 typedef struct __ktest_suite_hdl ktest_suite_hdl_t;
133 typedef struct __ktest_test_hdl ktest_test_hdl_t;
134 typedef struct __ktest_ctx_hdl ktest_ctx_hdl_t;
135 
136 typedef void (*ktest_fn_t)(ktest_ctx_hdl_t *);
137 
138 /*
139  * Module, suite, and test creation/registration.
140  */
141 int ktest_create_module(const char *, ktest_module_hdl_t **);
142 int ktest_add_suite(ktest_module_hdl_t *, const char *, ktest_suite_hdl_t **);
143 int ktest_add_test(ktest_suite_hdl_t *, const char *, ktest_fn_t,
144     ktest_test_flags_t);
145 int ktest_register_module(ktest_module_hdl_t *);
146 void ktest_unregister_module(const char *);
147 void ktest_free_module(ktest_module_hdl_t *);
148 
149 /*
150  * Utility for getting a handle to static functions.
151  */
152 int ktest_hold_mod(const char *, ddi_modhandle_t *);
153 void ktest_release_mod(ddi_modhandle_t);
154 int ktest_get_fn(ddi_modhandle_t, const char *, void **);
155 
156 /*
157  * Retrieve the input stream for a test.
158  */
159 void ktest_get_input(const ktest_ctx_hdl_t *, uchar_t **, size_t *);
160 
161 /*
162  * Set the test result.
163  */
164 void ktest_result_skip(ktest_ctx_hdl_t *, int, const char *, ...);
165 void ktest_result_fail(ktest_ctx_hdl_t *, int, const char *, ...);
166 void ktest_result_error(ktest_ctx_hdl_t *, int, const char *, ...);
167 void ktest_result_pass(ktest_ctx_hdl_t *, int);
168 void ktest_msg_clear(ktest_ctx_hdl_t *);
169 void ktest_msg_prepend(ktest_ctx_hdl_t *, const char *fmt, ...);
170 
171 /*
172  * Note: All the macros wrap the stringizing parameters in parentheses,
173  * otherwise make check complains "preprocessor statement not in column 1".
174  */
175 
176 #define	KT_PASS(ctx)	ktest_result_pass((ctx), __LINE__)
177 
178 #define	KT_FAIL(ctx, msg, ...)						\
179 	ktest_result_fail((ctx), __LINE__, (msg), ##__VA_ARGS__)
180 
181 #define	KT_ERROR(ctx, msg, ...)						\
182 	ktest_result_error((ctx), __LINE__, (msg), ##__VA_ARGS__)
183 
184 #define	KT_SKIP(ctx, msg, ...)						\
185 	ktest_result_skip((ctx), __LINE__, (msg), ##__VA_ARGS__)
186 
187 /*
188  * KTest ASSERT
189  *
190  * If the expression fails, then stash the failure message in ctx and
191  * return from the calling function.
192  */
193 #define	KT_ASSERT_IMPL(LEFT, OP, RIGHT, TYPE, ctx) do {			\
194 	const TYPE __left = (TYPE)(LEFT);				\
195 	const TYPE __right = (TYPE)(RIGHT);				\
196 	const boolean_t __res = __left OP __right;			\
197 	if (!__res) {							\
198 		ktest_result_fail((ctx), __LINE__,			\
199 		    "%s %s %s"						\
200 		    " (0x%" PRIxMAX " %s 0x%" PRIxMAX ")",		\
201 		    (#LEFT), (#OP), (#RIGHT),				\
202 		    (uintmax_t)__left, (#OP), (uintmax_t)__right);	\
203 		return;							\
204 	}								\
205 	_NOTE(CONSTCOND)  } while (0)
206 
207 #define	KT_ASSERT3S(l, op, r, ctx)			\
208 	KT_ASSERT_IMPL(l, op, r, int64_t, ctx)
209 
210 #define	KT_ASSERT3U(l, op, r, ctx)			\
211 	KT_ASSERT_IMPL(l, op, r, uint64_t, ctx)
212 
213 #define	KT_ASSERT3P(l, op, r, ctx)			\
214 	KT_ASSERT_IMPL(l, op, r, uintptr_t, ctx)
215 
216 #define	KT_ASSERT(exp, ctx)				\
217 	KT_ASSERT_IMPL(exp, ==, B_TRUE, boolean_t, ctx)
218 
219 #define	KT_ASSERT0(exp, ctx)				\
220 	KT_ASSERT_IMPL(exp, ==, 0, uintmax_t, ctx)
221 
222 /*
223  * KTest ASSERT Goto
224  *
225  * If the expression fails, then stash the failure message in ctx and
226  * goto label.
227  */
228 #define	KT_ASSERTG_IMPL(LEFT, OP, RIGHT, TYPE, ctx, label) do {		\
229 	const TYPE __left = (TYPE)(LEFT);				\
230 	const TYPE __right = (TYPE)(RIGHT);				\
231 	const boolean_t __res = __left OP __right;			\
232 	if (!__res) {							\
233 		ktest_result_fail((ctx), __LINE__,			\
234 		    "%s %s %s"						\
235 		    " (0x%" PRIxMAX " %s 0x%" PRIxMAX ")",		\
236 		    (#LEFT), (#OP), (#RIGHT),				\
237 		    (uintmax_t)__left, (#OP), (uintmax_t)__right);	\
238 		goto label;						\
239 	}								\
240 	_NOTE(CONSTCOND)  } while (0)
241 
242 #define	KT_ASSERT3SG(l, op, r, ctx, label)			\
243 	KT_ASSERTG_IMPL(l, op, r, int64_t, ctx, label)
244 
245 #define	KT_ASSERT3UG(l, op, r, ctx, label)			\
246 	KT_ASSERTG_IMPL(l, op, r, uint64_t, ctx, label)
247 
248 #define	KT_ASSERT3PG(l, op, r, ctx, label)			\
249 	KT_ASSERTG_IMPL(l, op, r, uintptr_t, ctx, label)
250 
251 #define	KT_ASSERTG(exp, ctx, label)				\
252 	KT_ASSERTG_IMPL(exp, ==, B_TRUE, boolean_t, ctx, label)
253 
254 #define	KT_ASSERT0G(x, ctx, label)				\
255 	KT_ASSERTG_IMPL(x, ==, 0, uintmax_t, ctx, label)
256 
257 /*
258  * KTest ERROR Macros
259  *
260  * These are modeled after the KTest ASSERT macros, but are instead
261  * used to check for error conditions.
262  */
263 #define	KT_EASSERT_IMPL(LEFT, OP, RIGHT, TYPE, ctx) do {		\
264 	const TYPE __left = (TYPE)(LEFT);				\
265 	const TYPE __right = (TYPE)(RIGHT);				\
266 	const boolean_t __res = __left OP __right;			\
267 	if (!__res) {							\
268 		ktest_result_error((ctx), __LINE__,			\
269 		    "%s %s %s"						\
270 		    " (0x%" PRIxMAX " %s 0x%" PRIxMAX ")",		\
271 		    (#LEFT), (#OP), (#RIGHT),				\
272 		    (uintmax_t)__left, #OP, (uintmax_t)__right);	\
273 		return;							\
274 	}								\
275 	_NOTE(CONSTCOND)  } while (0)
276 
277 #define	KT_EASSERT3S(l, op, r, ctx)			\
278 	KT_EASSERT_IMPL(l, op, r, int64_t, ctx)
279 
280 #define	KT_EASSERT3U(l, op, r, ctx)			\
281 	KT_EASSERT_IMPL(l, op, r, uint64_t, ctx)
282 
283 #define	KT_EASSERT3P(l, op, r, ctx)			\
284 	KT_EASSERT_IMPL(l, op, r, uintptr_t, ctx)
285 
286 #define	KT_EASSERT(exp, ctx)				\
287 	KT_EASSERT_IMPL(exp, ==, B_TRUE, boolean_t, ctx)
288 
289 #define	KT_EASSERT0(exp, ctx)				\
290 	KT_EASSERT_IMPL(exp, ==, 0, uintmax_t, ctx)
291 
292 /*
293  * KTest ERROR Goto
294  *
295  * These are modeled after the KTest ASSERT Goto macros, but are
296  * instead used to check for error conditions.
297  */
298 #define	KT_EASSERTG_IMPL(LEFT, OP, RIGHT, TYPE, ctx, label) do {	\
299 	const TYPE __left = (TYPE)(LEFT);				\
300 	const TYPE __right = (TYPE)(RIGHT);				\
301 	const boolean_t __res = __left OP __right;			\
302 	if (!__res) {							\
303 		ktest_result_error((ctx), __LINE__,			\
304 		    "%s %s %s"						\
305 		    " (0x%" PRIxMAX " %s 0x%" PRIxMAX ")",		\
306 		    (#LEFT), (#OP), (#RIGHT),				\
307 		    (uintmax_t)__left, #OP, (uintmax_t)__right);	\
308 		goto label;						\
309 	}								\
310 	_NOTE(CONSTCOND)  } while (0)
311 
312 #define	KT_EASSERT3SG(l, op, r, ctx, label)			\
313 	KT_EASSERTG_IMPL(l, op, r, int64_t, ctx, label)
314 
315 #define	KT_EASSERT3UG(l, op, r, ctx, label)			\
316 	KT_EASSERTG_IMPL(l, op, r, uint64_t, ctx, label)
317 
318 #define	KT_EASSERT3PG(l, op, r, ctx, label)			\
319 	KT_EASSERTG_IMPL(l, op, r, uintptr_t, ctx, label)
320 
321 #define	KT_EASSERTG(exp, ctx, label)				\
322 	KT_EASSERTG_IMPL(exp, ==, B_TRUE, boolean_t, ctx, label)
323 
324 #define	KT_EASSERT0G(x, ctx, label)				\
325 	KT_EASSERTG_IMPL(x, ==, 0, uintmax_t, ctx, label)
326 
327 #endif	/* _KERNEL */
328 
329 #ifdef __cplusplus
330 }
331 #endif
332 
333 #endif /* _SYS_KTEST_H */
334