#ifndef _SYS_KTEST_H
#define _SYS_KTEST_H
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/modctl.h>
#include <sys/param.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define KTEST_SEPARATOR ":"
#define KTEST_DEF_TRIPLE "*:*:*"
#define KTEST_DEF_TRIPLE_SZ 6
#define KTEST_MAX_NAME_LEN 64
#define KTEST_MAX_TRIPLE_LEN ((KTEST_MAX_NAME_LEN * 3) + 3)
#define KTEST_MAX_LOG_LEN 4096
#define KTEST_NAME_KEY "name"
#define KTEST_MODULE_KEY "module"
#define KTEST_MODULE_SUITES_KEY "suites"
#define KTEST_SUITE_KEY "suite"
#define KTEST_SUITE_TESTS_KEY "tests"
#define KTEST_TEST_KEY "test"
#define KTEST_TEST_INPUT_KEY "input_required"
#define KTEST_GMATCH_CHARS "*?[]"
#define KTEST_SER_FMT_KEY "ser_fmt_version"
#define KTEST_SER_FMT_VSN 1ULL
#define KTEST_IOCTL_MAX_LEN (64 * 1024 * 1024)
#define KTEST_IOCTL (('k' << 16) | ('t' << 8))
typedef enum ktest_ioctl {
KTEST_IOCTL_RUN_TEST = (KTEST_IOCTL | 1),
KTEST_IOCTL_LIST_TESTS = (KTEST_IOCTL | 2),
} ktest_ioctl_t;
typedef enum ktest_test_flags {
KTEST_FLAG_NONE = 0,
KTEST_FLAG_INPUT = (1 << 0),
} ktest_test_flags_t;
typedef enum ktest_result_type {
KTEST_RESULT_NONE,
KTEST_RESULT_PASS,
KTEST_RESULT_FAIL,
KTEST_RESULT_SKIP,
KTEST_RESULT_ERROR
} ktest_result_type_t;
typedef struct ktest_result {
char kr_msg_prepend[KTEST_MAX_LOG_LEN];
char kr_msg[KTEST_MAX_LOG_LEN];
ktest_result_type_t kr_type;
int kr_line;
} ktest_result_t;
typedef struct ktest_run_op {
char kro_module[KTEST_MAX_NAME_LEN];
char kro_suite[KTEST_MAX_NAME_LEN];
char kro_test[KTEST_MAX_NAME_LEN];
char kro_input_path[MAXPATHLEN];
uchar_t *kro_input_bytes;
uint64_t kro_input_len;
ktest_result_t kro_result;
} ktest_run_op_t;
typedef struct ktest_list_op {
char *klo_resp;
size_t klo_resp_len;
} ktest_list_op_t;
#ifdef _KERNEL
typedef struct __ktest_module_hdl ktest_module_hdl_t;
typedef struct __ktest_suite_hdl ktest_suite_hdl_t;
typedef struct __ktest_test_hdl ktest_test_hdl_t;
typedef struct __ktest_ctx_hdl ktest_ctx_hdl_t;
typedef void (*ktest_fn_t)(ktest_ctx_hdl_t *);
int ktest_create_module(const char *, ktest_module_hdl_t **);
int ktest_add_suite(ktest_module_hdl_t *, const char *, ktest_suite_hdl_t **);
int ktest_add_test(ktest_suite_hdl_t *, const char *, ktest_fn_t,
ktest_test_flags_t);
int ktest_register_module(ktest_module_hdl_t *);
void ktest_unregister_module(const char *);
void ktest_free_module(ktest_module_hdl_t *);
int ktest_hold_mod(const char *, ddi_modhandle_t *);
void ktest_release_mod(ddi_modhandle_t);
int ktest_get_fn(ddi_modhandle_t, const char *, void **);
void ktest_get_input(const ktest_ctx_hdl_t *, uchar_t **, size_t *);
void ktest_result_skip(ktest_ctx_hdl_t *, int, const char *, ...);
void ktest_result_fail(ktest_ctx_hdl_t *, int, const char *, ...);
void ktest_result_error(ktest_ctx_hdl_t *, int, const char *, ...);
void ktest_result_pass(ktest_ctx_hdl_t *, int);
void ktest_msg_clear(ktest_ctx_hdl_t *);
void ktest_msg_prepend(ktest_ctx_hdl_t *, const char *fmt, ...);
#define KT_PASS(ctx) ktest_result_pass((ctx), __LINE__)
#define KT_FAIL(ctx, msg, ...) \
ktest_result_fail((ctx), __LINE__, (msg), ##__VA_ARGS__)
#define KT_ERROR(ctx, msg, ...) \
ktest_result_error((ctx), __LINE__, (msg), ##__VA_ARGS__)
#define KT_SKIP(ctx, msg, ...) \
ktest_result_skip((ctx), __LINE__, (msg), ##__VA_ARGS__)
#define KT_ASSERT_IMPL(LEFT, OP, RIGHT, TYPE, ctx) do { \
const TYPE __left = (TYPE)(LEFT); \
const TYPE __right = (TYPE)(RIGHT); \
const boolean_t __res = __left OP __right; \
if (!__res) { \
ktest_result_fail((ctx), __LINE__, \
"%s %s %s" \
" (0x%" PRIxMAX " %s 0x%" PRIxMAX ")", \
(#LEFT), (#OP), (#RIGHT), \
(uintmax_t)__left, (#OP), (uintmax_t)__right); \
return; \
} \
_NOTE(CONSTCOND) } while (0)
#define KT_ASSERT3S(l, op, r, ctx) \
KT_ASSERT_IMPL(l, op, r, int64_t, ctx)
#define KT_ASSERT3U(l, op, r, ctx) \
KT_ASSERT_IMPL(l, op, r, uint64_t, ctx)
#define KT_ASSERT3P(l, op, r, ctx) \
KT_ASSERT_IMPL(l, op, r, uintptr_t, ctx)
#define KT_ASSERT(exp, ctx) \
KT_ASSERT_IMPL(exp, ==, B_TRUE, boolean_t, ctx)
#define KT_ASSERT0(exp, ctx) \
KT_ASSERT_IMPL(exp, ==, 0, uintmax_t, ctx)
#define KT_ASSERTG_IMPL(LEFT, OP, RIGHT, TYPE, ctx, label) do { \
const TYPE __left = (TYPE)(LEFT); \
const TYPE __right = (TYPE)(RIGHT); \
const boolean_t __res = __left OP __right; \
if (!__res) { \
ktest_result_fail((ctx), __LINE__, \
"%s %s %s" \
" (0x%" PRIxMAX " %s 0x%" PRIxMAX ")", \
(#LEFT), (#OP), (#RIGHT), \
(uintmax_t)__left, (#OP), (uintmax_t)__right); \
goto label; \
} \
_NOTE(CONSTCOND) } while (0)
#define KT_ASSERT3SG(l, op, r, ctx, label) \
KT_ASSERTG_IMPL(l, op, r, int64_t, ctx, label)
#define KT_ASSERT3UG(l, op, r, ctx, label) \
KT_ASSERTG_IMPL(l, op, r, uint64_t, ctx, label)
#define KT_ASSERT3PG(l, op, r, ctx, label) \
KT_ASSERTG_IMPL(l, op, r, uintptr_t, ctx, label)
#define KT_ASSERTG(exp, ctx, label) \
KT_ASSERTG_IMPL(exp, ==, B_TRUE, boolean_t, ctx, label)
#define KT_ASSERT0G(x, ctx, label) \
KT_ASSERTG_IMPL(x, ==, 0, uintmax_t, ctx, label)
#define KT_EASSERT_IMPL(LEFT, OP, RIGHT, TYPE, ctx) do { \
const TYPE __left = (TYPE)(LEFT); \
const TYPE __right = (TYPE)(RIGHT); \
const boolean_t __res = __left OP __right; \
if (!__res) { \
ktest_result_error((ctx), __LINE__, \
"%s %s %s" \
" (0x%" PRIxMAX " %s 0x%" PRIxMAX ")", \
(#LEFT), (#OP), (#RIGHT), \
(uintmax_t)__left, #OP, (uintmax_t)__right); \
return; \
} \
_NOTE(CONSTCOND) } while (0)
#define KT_EASSERT3S(l, op, r, ctx) \
KT_EASSERT_IMPL(l, op, r, int64_t, ctx)
#define KT_EASSERT3U(l, op, r, ctx) \
KT_EASSERT_IMPL(l, op, r, uint64_t, ctx)
#define KT_EASSERT3P(l, op, r, ctx) \
KT_EASSERT_IMPL(l, op, r, uintptr_t, ctx)
#define KT_EASSERT(exp, ctx) \
KT_EASSERT_IMPL(exp, ==, B_TRUE, boolean_t, ctx)
#define KT_EASSERT0(exp, ctx) \
KT_EASSERT_IMPL(exp, ==, 0, uintmax_t, ctx)
#define KT_EASSERTG_IMPL(LEFT, OP, RIGHT, TYPE, ctx, label) do { \
const TYPE __left = (TYPE)(LEFT); \
const TYPE __right = (TYPE)(RIGHT); \
const boolean_t __res = __left OP __right; \
if (!__res) { \
ktest_result_error((ctx), __LINE__, \
"%s %s %s" \
" (0x%" PRIxMAX " %s 0x%" PRIxMAX ")", \
(#LEFT), (#OP), (#RIGHT), \
(uintmax_t)__left, #OP, (uintmax_t)__right); \
goto label; \
} \
_NOTE(CONSTCOND) } while (0)
#define KT_EASSERT3SG(l, op, r, ctx, label) \
KT_EASSERTG_IMPL(l, op, r, int64_t, ctx, label)
#define KT_EASSERT3UG(l, op, r, ctx, label) \
KT_EASSERTG_IMPL(l, op, r, uint64_t, ctx, label)
#define KT_EASSERT3PG(l, op, r, ctx, label) \
KT_EASSERTG_IMPL(l, op, r, uintptr_t, ctx, label)
#define KT_EASSERTG(exp, ctx, label) \
KT_EASSERTG_IMPL(exp, ==, B_TRUE, boolean_t, ctx, label)
#define KT_EASSERT0G(x, ctx, label) \
KT_EASSERTG_IMPL(x, ==, 0, uintmax_t, ctx, label)
#endif
#ifdef __cplusplus
}
#endif
#endif