diff options
| author | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2023-04-14 15:25:50 +0000 |
|---|---|---|
| committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2023-04-14 15:47:55 +0000 |
| commit | 3e5d0784b9b5296bda801add034b057ad68237f7 (patch) | |
| tree | 09c1ac8db59cbdf84d2b457c45ffdca09b1d3bdf /sys/tests | |
| parent | 2f53b5991ce05b7e6f2b1eb826cd902fb255a9eb (diff) | |
Diffstat (limited to 'sys/tests')
| -rw-r--r-- | sys/tests/ktest.c | 414 | ||||
| -rw-r--r-- | sys/tests/ktest.h | 141 | ||||
| -rw-r--r-- | sys/tests/ktest_example.c | 134 |
3 files changed, 689 insertions, 0 deletions
diff --git a/sys/tests/ktest.c b/sys/tests/ktest.c new file mode 100644 index 000000000000..fcb40130bcef --- /dev/null +++ b/sys/tests/ktest.c @@ -0,0 +1,414 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Alexander V. Chernikov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_netlink.h" + +#include <sys/param.h> +#include <sys/refcount.h> +#include <sys/types.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/socket.h> +#include <sys/priv.h> + +#include <netlink/netlink.h> +#include <netlink/netlink_ctl.h> +#include <netlink/netlink_generic.h> +#include <netlink/netlink_message_parser.h> + +#include <machine/stdarg.h> +#include <tests/ktest.h> + +struct mtx ktest_mtx; +#define KTEST_LOCK() mtx_lock(&ktest_mtx) +#define KTEST_UNLOCK() mtx_unlock(&ktest_mtx) +#define KTEST_LOCK_ASSERT() mtx_assert(&ktest_mtx, MA_OWNED) + +MTX_SYSINIT(ktest_mtx, &ktest_mtx, "ktest mutex", MTX_DEF); + +struct ktest_module { + struct ktest_module_info *info; + volatile u_int refcount; + TAILQ_ENTRY(ktest_module) entries; +}; +static TAILQ_HEAD(, ktest_module) module_list = TAILQ_HEAD_INITIALIZER(module_list); + +struct nl_ktest_parsed { + char *mod_name; + char *test_name; + struct nlattr *test_meta; +}; + +#define _IN(_field) offsetof(struct genlmsghdr, _field) +#define _OUT(_field) offsetof(struct nl_ktest_parsed, _field) + +static const struct nlattr_parser nla_p_get[] = { + { .type = KTEST_ATTR_MOD_NAME, .off = _OUT(mod_name), .cb = nlattr_get_string }, + { .type = KTEST_ATTR_TEST_NAME, .off = _OUT(test_name), .cb = nlattr_get_string }, + { .type = KTEST_ATTR_TEST_META, .off = _OUT(test_meta), .cb = nlattr_get_nla }, +}; +static const struct nlfield_parser nlf_p_get[] = { +}; +NL_DECLARE_PARSER(ktest_parser, struct genlmsghdr, nlf_p_get, nla_p_get); +#undef _IN +#undef _OUT + +static bool +create_reply(struct nl_writer *nw, struct nlmsghdr *hdr, int cmd) +{ + if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) + return (false); + + struct genlmsghdr *ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr); + ghdr_new->cmd = cmd; + ghdr_new->version = 0; + ghdr_new->reserved = 0; + + return (true); +} + +static int +dump_mod_test(struct nlmsghdr *hdr, struct nl_pstate *npt, + struct ktest_module *mod, const struct ktest_test_info *test_info) +{ + struct nl_writer *nw = npt->nw; + + if (!create_reply(nw, hdr, KTEST_CMD_NEWTEST)) + goto enomem; + + nlattr_add_string(nw, KTEST_ATTR_MOD_NAME, mod->info->name); + nlattr_add_string(nw, KTEST_ATTR_TEST_NAME, test_info->name); + nlattr_add_string(nw, KTEST_ATTR_TEST_DESCR, test_info->desc); + + if (nlmsg_end(nw)) + return (0); +enomem: + nlmsg_abort(nw); + return (ENOMEM); +} + +static int +dump_mod_tests(struct nlmsghdr *hdr, struct nl_pstate *npt, + struct ktest_module *mod, struct nl_ktest_parsed *attrs) +{ + for (int i = 0; i < mod->info->num_tests; i++) { + const struct ktest_test_info *test_info = &mod->info->tests[i]; + if (attrs->test_name != NULL && strcmp(attrs->test_name, test_info->name)) + continue; + int error = dump_mod_test(hdr, npt, mod, test_info); + if (error != 0) + return (error); + } + + return (0); +} + +static int +dump_tests(struct nlmsghdr *hdr, struct nl_pstate *npt) +{ + struct nl_ktest_parsed attrs = { }; + struct ktest_module *mod; + int error; + + error = nl_parse_nlmsg(hdr, &ktest_parser, npt, &attrs); + if (error != 0) + return (error); + + hdr->nlmsg_flags |= NLM_F_MULTI; + + KTEST_LOCK(); + TAILQ_FOREACH(mod, &module_list, entries) { + if (attrs.mod_name && strcmp(attrs.mod_name, mod->info->name)) + continue; + error = dump_mod_tests(hdr, npt, mod, &attrs); + if (error != 0) + break; + } + KTEST_UNLOCK(); + + if (!nlmsg_end_dump(npt->nw, error, hdr)) { + //NL_LOG(LOG_DEBUG, "Unable to finalize the dump"); + return (ENOMEM); + } + + return (error); +} + +static int +run_test(struct nlmsghdr *hdr, struct nl_pstate *npt) +{ + struct nl_ktest_parsed attrs = { }; + struct ktest_module *mod; + int error; + + error = nl_parse_nlmsg(hdr, &ktest_parser, npt, &attrs); + if (error != 0) + return (error); + + if (attrs.mod_name == NULL) { + nlmsg_report_err_msg(npt, "KTEST_ATTR_MOD_NAME not set"); + return (EINVAL); + } + + if (attrs.test_name == NULL) { + nlmsg_report_err_msg(npt, "KTEST_ATTR_TEST_NAME not set"); + return (EINVAL); + } + + const struct ktest_test_info *test = NULL; + + KTEST_LOCK(); + TAILQ_FOREACH(mod, &module_list, entries) { + if (strcmp(attrs.mod_name, mod->info->name)) + continue; + + const struct ktest_module_info *info = mod->info; + + for (int i = 0; i < info->num_tests; i++) { + const struct ktest_test_info *test_info = &info->tests[i]; + + if (!strcmp(attrs.test_name, test_info->name)) { + test = test_info; + break; + } + } + break; + } + if (test != NULL) + refcount_acquire(&mod->refcount); + KTEST_UNLOCK(); + + if (test == NULL) + return (ESRCH); + + /* Run the test */ + struct ktest_test_context ctx = { + .npt = npt, + .hdr = hdr, + .buf = npt_alloc(npt, KTEST_MAX_BUF), + .bufsize = KTEST_MAX_BUF, + }; + + if (ctx.buf == NULL) { + //NL_LOG(LOG_DEBUG, "unable to allocate temporary buffer"); + return (ENOMEM); + } + + if (test->parse != NULL && attrs.test_meta != NULL) { + error = test->parse(&ctx, attrs.test_meta); + if (error != 0) + return (error); + } + + hdr->nlmsg_flags |= NLM_F_MULTI; + + KTEST_LOG_LEVEL(&ctx, LOG_INFO, "start running %s", test->name); + error = test->func(&ctx); + KTEST_LOG_LEVEL(&ctx, LOG_INFO, "end running %s", test->name); + + refcount_release(&mod->refcount); + + if (!nlmsg_end_dump(npt->nw, error, hdr)) { + //NL_LOG(LOG_DEBUG, "Unable to finalize the dump"); + return (ENOMEM); + } + + return (error); +} + + +/* USER API */ +static void +register_test_module(struct ktest_module_info *info) +{ + struct ktest_module *mod = malloc(sizeof(*mod), M_TEMP, M_WAITOK | M_ZERO); + + mod->info = info; + info->module_ptr = mod; + KTEST_LOCK(); + TAILQ_INSERT_TAIL(&module_list, mod, entries); + KTEST_UNLOCK(); +} + +static void +unregister_test_module(struct ktest_module_info *info) +{ + struct ktest_module *mod = info->module_ptr; + + info->module_ptr = NULL; + + KTEST_LOCK(); + TAILQ_REMOVE(&module_list, mod, entries); + KTEST_UNLOCK(); + + free(mod, M_TEMP); +} + +static bool +can_unregister(struct ktest_module_info *info) +{ + struct ktest_module *mod = info->module_ptr; + + return (refcount_load(&mod->refcount) == 0); +} + +int +ktest_default_modevent(module_t mod, int type, void *arg) +{ + struct ktest_module_info *info = (struct ktest_module_info *)arg; + int error = 0; + + switch (type) { + case MOD_LOAD: + register_test_module(info); + break; + case MOD_UNLOAD: + if (!can_unregister(info)) + return (EBUSY); + unregister_test_module(info); + break; + default: + error = EOPNOTSUPP; + break; + } + return (error); +} + +bool +ktest_start_msg(struct ktest_test_context *ctx) +{ + return (create_reply(ctx->npt->nw, ctx->hdr, KTEST_CMD_NEWMESSAGE)); +} + +void +ktest_add_msg_meta(struct ktest_test_context *ctx, const char *func, + const char *fname, int line) +{ + struct nl_writer *nw = ctx->npt->nw; + struct timespec ts; + + nanouptime(&ts); + nlattr_add(nw, KTEST_MSG_ATTR_TS, sizeof(ts), &ts); + + nlattr_add_string(nw, KTEST_MSG_ATTR_FUNC, func); + nlattr_add_string(nw, KTEST_MSG_ATTR_FILE, fname); + nlattr_add_u32(nw, KTEST_MSG_ATTR_LINE, line); +} + +void +ktest_add_msg_text(struct ktest_test_context *ctx, int msg_level, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsnprintf(ctx->buf, ctx->bufsize, fmt, ap); + va_end(ap); + + nlattr_add_u8(ctx->npt->nw, KTEST_MSG_ATTR_LEVEL, msg_level); + nlattr_add_string(ctx->npt->nw, KTEST_MSG_ATTR_TEXT, ctx->buf); +} + +void +ktest_end_msg(struct ktest_test_context *ctx) +{ + nlmsg_end(ctx->npt->nw); +} + +/* Module glue */ + +static const struct nlhdr_parser *all_parsers[] = { &ktest_parser }; + +static const struct genl_cmd ktest_cmds[] = { + { + .cmd_num = KTEST_CMD_LIST, + .cmd_name = "KTEST_CMD_LIST", + .cmd_cb = dump_tests, + .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, + }, + { + .cmd_num = KTEST_CMD_RUN, + .cmd_name = "KTEST_CMD_RUN", + .cmd_cb = run_test, + .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, + .cmd_priv = PRIV_KLD_LOAD, + }, +}; + +static void +ktest_nl_register(void) +{ + bool ret __diagused; + int family_id __diagused; + + NL_VERIFY_PARSERS(all_parsers); + family_id = genl_register_family(KTEST_FAMILY_NAME, 0, 1, KTEST_CMD_MAX); + MPASS(family_id != 0); + + ret = genl_register_cmds(KTEST_FAMILY_NAME, ktest_cmds, NL_ARRAY_LEN(ktest_cmds)); + MPASS(ret); +} + +static void +ktest_nl_unregister(void) +{ + MPASS(TAILQ_EMPTY(&module_list)); + + genl_unregister_family(KTEST_FAMILY_NAME); +} + +static int +ktest_modevent(module_t mod, int type, void *unused) +{ + int error = 0; + + switch (type) { + case MOD_LOAD: + ktest_nl_register(); + break; + case MOD_UNLOAD: + ktest_nl_unregister(); + break; + default: + error = EOPNOTSUPP; + break; + } + return (error); +} + +static moduledata_t ktestmod = { + "ktest", + ktest_modevent, + 0 +}; + +DECLARE_MODULE(ktestmod, ktestmod, SI_SUB_PSEUDO, SI_ORDER_ANY); +MODULE_VERSION(ktestmod, 1); +MODULE_DEPEND(ktestmod, netlink, 1, 1, 1); + diff --git a/sys/tests/ktest.h b/sys/tests/ktest.h new file mode 100644 index 000000000000..feadb800551b --- /dev/null +++ b/sys/tests/ktest.h @@ -0,0 +1,141 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Alexander V. Chernikov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef SYS_TESTS_KTEST_H_ +#define SYS_TESTS_KTEST_H_ + +#ifdef _KERNEL + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/syslog.h> + +struct nlattr; +struct nl_pstate; +struct nlmsghdr; + +struct ktest_test_context { + void *arg; + struct nl_pstate *npt; + struct nlmsghdr *hdr; + char *buf; + size_t bufsize; +}; + +typedef int (*ktest_run_t)(struct ktest_test_context *ctx); +typedef int (*ktest_parse_t)(struct ktest_test_context *ctx, struct nlattr *container); + +struct ktest_test_info { + const char *name; + const char *desc; + ktest_run_t func; + ktest_parse_t parse; +}; + +struct ktest_module_info { + const char *name; + const struct ktest_test_info *tests; + int num_tests; + void *module_ptr; +}; + +int ktest_default_modevent(module_t mod, int type, void *arg); + +bool ktest_start_msg(struct ktest_test_context *ctx); +void ktest_add_msg_meta(struct ktest_test_context *ctx, const char *func, + const char *fname, int line); +void ktest_add_msg_text(struct ktest_test_context *ctx, int msg_level, + const char *fmt, ...); +void ktest_end_msg(struct ktest_test_context *ctx); + +#define KTEST_LOG_LEVEL(_ctx, _l, _fmt, ...) { \ + if (ktest_start_msg(_ctx)) { \ + ktest_add_msg_meta(_ctx, __func__, __FILE__, __LINE__); \ + ktest_add_msg_text(_ctx, _l, _fmt, ## __VA_ARGS__); \ + ktest_end_msg(_ctx); \ + } \ +} + +#define KTEST_LOG(_ctx, _fmt, ...) \ + KTEST_LOG_LEVEL(_ctx, LOG_DEBUG, _fmt, ## __VA_ARGS__) + +#define KTEST_MAX_BUF 512 + +#define KTEST_MODULE_DECLARE(_n, _t) \ +static struct ktest_module_info _module_info = { \ + .name = #_n, \ + .tests = _t, \ + .num_tests = nitems(_t), \ +}; \ + \ +static moduledata_t _module_data = { \ + "__" #_n "_module", \ + ktest_default_modevent, \ + &_module_info, \ +}; \ + \ +DECLARE_MODULE(ktest_##_n, _module_data, SI_SUB_PSEUDO, SI_ORDER_ANY); \ +MODULE_VERSION(ktest_##_n, 1); \ +MODULE_DEPEND(ktest_##_n, ktestmod, 1, 1, 1); \ + +#endif /* _KERNEL */ + +/* genetlink definitions */ +#define KTEST_FAMILY_NAME "ktest" + +/* commands */ +enum { + KTEST_CMD_UNSPEC = 0, + KTEST_CMD_LIST = 1, + KTEST_CMD_RUN = 2, + KTEST_CMD_NEWTEST = 3, + KTEST_CMD_NEWMESSAGE = 4, + __KTEST_CMD_MAX, +}; +#define KTEST_CMD_MAX (__KTEST_CMD_MAX - 1) + +enum ktest_attr_type_t { + KTEST_ATTR_UNSPEC, + KTEST_ATTR_MOD_NAME = 1, /* string: test module name */ + KTEST_ATTR_TEST_NAME = 2, /* string: test name */ + KTEST_ATTR_TEST_DESCR = 3, /* string: test description */ + KTEST_ATTR_TEST_META = 4, /* nested: container with test-specific metadata */ +}; + +enum ktest_msg_attr_type_t { + KTEST_MSG_ATTR_UNSPEC, + KTEST_MSG_ATTR_TS = 1, /* struct timespec */ + KTEST_MSG_ATTR_FUNC = 2, /* string: function name */ + KTEST_MSG_ATTR_FILE = 3, /* string: file name */ + KTEST_MSG_ATTR_LINE = 4, /* u32: line in the file */ + KTEST_MSG_ATTR_TEXT = 5, /* string: actual message data */ + KTEST_MSG_ATTR_LEVEL = 6, /* u8: syslog loglevel */ + KTEST_MSG_ATTR_META = 7, /* nested: message metadata */ +}; + +#endif diff --git a/sys/tests/ktest_example.c b/sys/tests/ktest_example.c new file mode 100644 index 000000000000..7cccaad7a855 --- /dev/null +++ b/sys/tests/ktest_example.c @@ -0,0 +1,134 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Alexander V. Chernikov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <tests/ktest.h> +#include <sys/cdefs.h> +#include <sys/systm.h> + + +static int +test_something(struct ktest_test_context *ctx) +{ + KTEST_LOG(ctx, "I'm here, [%s]", __func__); + + pause("sleeping...", hz / 10); + + KTEST_LOG(ctx, "done"); + + return (0); +} + +static int +test_something_else(struct ktest_test_context *ctx) +{ + return (0); +} + +static int +test_failed(struct ktest_test_context *ctx) +{ + return (EBUSY); +} + +static int +test_failed2(struct ktest_test_context *ctx) +{ + KTEST_LOG(ctx, "failed because it always fails"); + return (EBUSY); +} + +#include <sys/malloc.h> +#include <netlink/netlink.h> +#include <netlink/netlink_ctl.h> + +struct test1_attrs { + uint32_t arg1; + uint32_t arg2; + char *text; +}; + +#define _OUT(_field) offsetof(struct test1_attrs, _field) +static const struct nlattr_parser nla_p_test1[] = { + { .type = 1, .off = _OUT(arg1), .cb = nlattr_get_uint32 }, + { .type = 2, .off = _OUT(arg2), .cb = nlattr_get_uint32 }, + { .type = 3, .off = _OUT(text), .cb = nlattr_get_string }, +}; +#undef _OUT +NL_DECLARE_ATTR_PARSER(test1_parser, nla_p_test1); + +static int +test_with_params_parser(struct ktest_test_context *ctx, struct nlattr *nla) +{ + struct test1_attrs *attrs = npt_alloc(ctx->npt, sizeof(*attrs)); + + ctx->arg = attrs; + if (attrs != NULL) + return (nl_parse_nested(nla, &test1_parser, ctx->npt, attrs)); + return (ENOMEM); +} + +static int +test_with_params(struct ktest_test_context *ctx) +{ + struct test1_attrs *attrs = ctx->arg; + + if (attrs->text != NULL) + KTEST_LOG(ctx, "Get '%s'", attrs->text); + KTEST_LOG(ctx, "%u + %u = %u", attrs->arg1, attrs->arg2, + attrs->arg1 + attrs->arg2); + return (0); +} + +static const struct ktest_test_info tests[] = { + { + .name = "test_something", + .desc = "example description", + .func = &test_something, + }, + { + .name = "test_something_else", + .desc = "example description 2", + .func = &test_something_else, + }, + { + .name = "test_failed", + .desc = "always failing test", + .func = &test_failed, + }, + { + .name = "test_failed2", + .desc = "always failing test", + .func = &test_failed2, + }, + { + .name = "test_with_params", + .desc = "test summing integers", + .func = &test_with_params, + .parse = &test_with_params_parser, + }, +}; +KTEST_MODULE_DECLARE(ktest_example, tests); |
