From d7466dc0e57126820fea202939695caa1d1c6bc9 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Mon, 7 Sep 2015 15:55:36 +0200 Subject: [PATCH] Refactored the default main to allow dynamic test registration --- doc/internal.rst | 18 +++++++-- include/criterion/criterion.h | 8 +++- src/entry.c | 10 ++++- src/main.c | 2 +- src/runner.c | 73 ++++++++++++++++++++--------------- 5 files changed, 72 insertions(+), 39 deletions(-) diff --git a/doc/internal.rst b/doc/internal.rst index 873d6be..69b5f0a 100644 --- a/doc/internal.rst +++ b/doc/internal.rst @@ -10,6 +10,13 @@ can define your own main function. Configuring the test runner ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +First and foremost, you need to generate the test set; this is done by calling +``criterion_initialize()``. The function returns a ``struct criterion_test_set *``, +that you need to pass to ``criterion_run_all_tests`` later on. + +At the very end of your main, you also need to call ``criterion_finalize`` with +the test set as parameter to free any ressources initialized by criterion earlier. + You'd usually want to configure the test runner before calling it. Configuration is done by setting fields in a global variable named ``criterion_options`` (include criterion/options.h). @@ -35,7 +42,7 @@ pattern const char * The pattern of the tests =================== ================================== ============================================================== if you want criterion to provide its own default CLI parameters and environment -variables handling, you can also call ``criterion_initialize(int argc, char *argv[], bool handle_unknown_arg)`` +variables handling, you can also call ``criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg)`` with the proper ``argc/argv``. ``handle_unknown_arg``, if set to true, is here to tell criterion to print its usage when an unknown CLI parameter is encountered. If you want to add your own parameters, you should set it to false. @@ -57,10 +64,15 @@ Example main #include int main(int argc, char *argv[]) { - if (!criterion_initialize(argc, argv, true)) + struct criterion_test_set *tests = criterion_initialize(); + + if (!criterion_handle_args(argc, argv, true)) return 0; - return !criterion_run_all_tests(); + int result = !criterion_run_all_tests(set); + + criterion_finalize(set); + return result; } Implementing your own output provider diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index ba8185a..82dab63 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -78,8 +78,12 @@ CR_BEGIN_C_API -CR_API int criterion_run_all_tests(void); -CR_API int criterion_initialize(int argc, char *argv[], bool handle_unknown_arg); +CR_API struct criterion_test_set *criterion_initialize(void); +CR_API void criterion_finalize(struct criterion_test_set *tests); +CR_API int criterion_run_all_tests(struct criterion_test_set *tests); +CR_API int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg); +CR_API void criterion_register_test(struct criterion_test_set *tests, + struct criterion_test *test); CR_END_C_API diff --git a/src/entry.c b/src/entry.c index b5700b0..71e9b9d 100644 --- a/src/entry.c +++ b/src/entry.c @@ -1,8 +1,14 @@ #include "criterion/criterion.h" CR_API int main(int argc, char *argv[]) { - if (!criterion_initialize(argc, argv, true)) + struct criterion_test_set *tests = criterion_initialize(); + + if (!criterion_handle_args(argc, argv, true)) return 0; - return !criterion_run_all_tests(); + int result = !criterion_run_all_tests(tests); + + criterion_finalize(tests); + + return result; } diff --git a/src/main.c b/src/main.c index 86d49fa..3aa9584 100644 --- a/src/main.c +++ b/src/main.c @@ -120,7 +120,7 @@ int list_tests(bool unicode) { return 0; } -CR_API int criterion_initialize(int argc, char *argv[], bool handle_unknown_arg) { +int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { static struct option opts[] = { {"verbose", optional_argument, 0, 'b'}, {"version", no_argument, 0, 'v'}, diff --git a/src/runner.c b/src/runner.c index 388d0da..ed05315 100644 --- a/src/runner.c +++ b/src/runner.c @@ -80,6 +80,20 @@ static void dtor_test_set(void *ptr, UNUSED void *meta) { sfree(t->suites); } +void criterion_register_test(struct criterion_test_set *set, + struct criterion_test *test) { + + struct criterion_suite_set css = { + .suite = { .name = test->category }, + }; + struct criterion_suite_set *s = insert_ordered_set(set->suites, &css, sizeof (css)); + if (!s->tests) + s->tests = new_ordered_set(cmp_test, NULL); + + insert_ordered_set(s->tests, test, sizeof(*test)); + ++set->tests; +} + struct criterion_test_set *criterion_init(void) { struct criterion_ordered_set *suites = new_ordered_set(cmp_suite, dtor_suite_set); @@ -93,25 +107,6 @@ struct criterion_test_set *criterion_init(void) { insert_ordered_set(suites, &css, sizeof (css)); } - size_t nb_tests = 0; - FOREACH_TEST_SEC(test) { - if (!test->category) - break; - - if (!*test->category) - continue; - - struct criterion_suite_set css = { - .suite = { .name = test->category }, - }; - struct criterion_suite_set *s = insert_ordered_set(suites, &css, sizeof (css)); - if (!s->tests) - s->tests = new_ordered_set(cmp_test, NULL); - - insert_ordered_set(s->tests, test, sizeof(*test)); - ++nb_tests; - } - struct criterion_test_set *set = smalloc( .size = sizeof (struct criterion_test_set), .dtor = dtor_test_set @@ -119,9 +114,19 @@ struct criterion_test_set *criterion_init(void) { *set = (struct criterion_test_set) { suites, - nb_tests, + 0, }; + FOREACH_TEST_SEC(test) { + if (!test->category) + break; + + if (!*test->category) + continue; + + criterion_register_test(set, test); + } + return set; } @@ -341,16 +346,27 @@ void disable_unmatching(struct criterion_test_set *set) { } #endif -static int criterion_run_all_tests_impl(void) { +struct criterion_test_set *criterion_initialize(void) { + init_i18n(); + if (resume_child()) // (windows only) resume from the fork - return -1; + exit(0); struct criterion_test_set *set = criterion_init(); -#ifdef HAVE_PCRE + + #ifdef HAVE_PCRE if (criterion_options.pattern) disable_unmatching(set); -#endif + #endif + return set; +} + +void criterion_finalize(struct criterion_test_set *set) { + sfree(set); +} + +static int criterion_run_all_tests_impl(struct criterion_test_set *set) { report(PRE_ALL, set); log(pre_all, set); @@ -368,19 +384,14 @@ static int criterion_run_all_tests_impl(void) { log(post_all, stats); cleanup: - sfree(set); sfree(stats); return result; } -int criterion_run_all_tests(void) { - init_i18n(); +int criterion_run_all_tests(struct criterion_test_set *set) { set_runner_process(); - int res = criterion_run_all_tests_impl(); + int res = criterion_run_all_tests_impl(set); unset_runner_process(); - if (res == -1) // if this is the test worker terminating - exit(0); - return criterion_options.always_succeed || res; }