diff --git a/src/util-munit.c b/src/util-munit.c index 696ee1d..cf8535e 100644 --- a/src/util-munit.c +++ b/src/util-munit.c @@ -35,6 +35,14 @@ * __attribute__(section) documentation. */ DECLARE_TEST_SECTION(); +DECLARE_GLOBAL_SETUP_SECTION(); + +/* If the tests don't use MUNIT_GLOBAL_SETUP the the above has no linkage, so + * let's always define a noop internal one. + */ +MUNIT_GLOBAL_SETUP(__internal) +{ +} int munit_tests_run(int argc, char **argv) @@ -55,6 +63,20 @@ munit_tests_run(int argc, char **argv) tests[idx++] = test; } + struct munit_setup setup = { + .argc = argc, + .argv = argv, + .userdata = NULL, + }; + size_t setup_count = 0; + foreach_setup(s) { + if (!streq(s->name, "__internal")) { + assert(setup_count == 0); /* Only one setup func per suite */ + s->func(&setup); + ++setup_count; + } + } + MunitSuite suite = { "", tests, @@ -67,7 +89,7 @@ munit_tests_run(int argc, char **argv) const struct rlimit corelimit = { 0, 0 }; setrlimit(RLIMIT_CORE, &corelimit); - int rc = munit_suite_main(&suite, NULL, argc, argv); + int rc = munit_suite_main(&suite, setup.userdata, setup.argc, setup.argv); for (idx = 0; idx < count; idx++) free(tests[idx].name); diff --git a/src/util-munit.h b/src/util-munit.h index 3d5de85..26b111b 100644 --- a/src/util-munit.h +++ b/src/util-munit.h @@ -63,6 +63,34 @@ struct test_function { munit_test_func_t func; /* test function */ } __attribute__((aligned(16))); +/** + * Put at the top of the file somewhere, declares the start/stop for the setup section we need. + */ +#define DECLARE_GLOBAL_SETUP_SECTION() \ + extern const struct global_setup_function __start_setup_functions_section, __stop_setup_functions_section + +/** + * Helper to loop through each setup function. + */ +#define foreach_setup(s_) \ + for (const struct global_setup_function *s_ = &__start_setup_functions_section; \ + s_ < &__stop_setup_functions_section; \ + s_++) + +struct munit_setup { + int argc; + char **argv; + void *userdata; +}; + +typedef void (*munit_setup_func_t)(struct munit_setup *setup); + +struct global_setup_function { + const char *name; /* function name */ + munit_setup_func_t func; /* setup function */ +} __attribute__((aligned(16))); + + /** * Defines a struct test_function in a custom ELF section that we can then * loop over in munit_tests_run() to extract the tests. This removes the @@ -79,5 +107,25 @@ __attribute__((section("test_functions_section"))) = { \ }; \ static MunitResult _func(const MunitParameter params[], void *user_data) +/** + * Defines a struct global_setup_function in a custom ELF section that we can + * then find in munit_tests_run() to do setup based on argv and/or pass userdata + * to the tests. + * + * Note that there can only be one of those per process. + * + * The argument to this function is a pointer to a struct munit_setup that has + * argc/argv and a (initially NULL) userdata pointer. + */ +#define MUNIT_GLOBAL_SETUP(_func) \ +static void _func(struct munit_setup *setup); \ +static const struct global_setup_function _setup_##_func \ +__attribute__((used)) \ +__attribute__((section("setup_functions_section"))) = { \ + .name = #_func, \ + .func = _func, \ +}; \ +static void _func(struct munit_setup *setup) \ + int munit_tests_run(int argc, char **argv);