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