diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a51244..063037c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,8 @@ set(SOURCE_FILES src/core/report.h src/core/runner.c src/core/runner.h + src/core/runner_coroutine.c + src/core/runner_coroutine.h src/core/worker.c src/core/worker.h src/core/stats.c diff --git a/src/core/coroutine.h b/src/core/coroutine.h index a8fad9b..badea85 100644 --- a/src/core/coroutine.h +++ b/src/core/coroutine.h @@ -153,8 +153,15 @@ #define ccrContParam void **ccrParam -#define ccrBeginContext struct ccrContextTag { int ccrLine -#define ccrEndContext(x) } *x = (struct ccrContextTag *)*ccrParam +#define ccrBeginContext typedef struct { int ccrLine +#define ccrEndContext(x) } ccrContextTag; ccrContextTag *x = (ccrContextTag *)*ccrParam + +#define ccrUseNamedContext(Name, x) \ + typedef struct Name ccrContextTag; \ + ccrContextTag *x = (ccrContextTag *)*ccrParam + +#define ccrBeginDefineContextType(Name) struct Name { int ccrLine +#define ccrEndDefineContextType } #define ccrBegin(x) if(!x) {x= *ccrParam=malloc(sizeof(*x)); x->ccrLine=0;}\ if (x) switch(x->ccrLine) { case 0:; @@ -163,12 +170,12 @@ #define ccrReturn(z) \ do {\ - ((struct ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ + ((ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ return (z); case __LINE__:;\ } while (0) #define ccrReturnV \ do {\ - ((struct ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ + ((ccrContextTag *)*ccrParam)->ccrLine=__LINE__;\ return; case __LINE__:;\ } while (0) diff --git a/src/core/report.h b/src/core/report.h index bc2d166..bdcffac 100644 --- a/src/core/report.h +++ b/src/core/report.h @@ -25,6 +25,7 @@ # define REPORT_H_ # include "criterion/hooks.h" +# include "criterion/options.h" # define report(Kind, Data) call_report_hooks_##Kind(Data) diff --git a/src/core/runner.c b/src/core/runner.c index 6ac3711..ea1a7fe 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -33,6 +33,7 @@ #include "compat/processor.h" #include "string/i18n.h" #include "io/event.h" +#include "runner_coroutine.h" #include "stats.h" #include "runner.h" #include "report.h" @@ -40,7 +41,6 @@ #include "abort.h" #include "config.h" #include "common.h" -#include "coroutine.h" #ifdef HAVE_PCRE #include "string/extmatch.h" @@ -132,8 +132,8 @@ struct criterion_test_set *criterion_init(void) { return set; } -static void run_test_child(struct criterion_test *test, - struct criterion_suite *suite) { +void run_test_child(struct criterion_test *test, + struct criterion_suite *suite) { if (suite->data && suite->data->timeout != 0 && test->data->timeout == 0) setup_timeout((uint64_t) (suite->data->timeout * 1e9)); @@ -170,12 +170,6 @@ static void run_test_child(struct criterion_test *test, send_event(POST_FINI, NULL, 0); } -static INLINE bool is_disabled(struct criterion_test *t, - struct criterion_suite *s) { - - return t->data->disabled || (s->data && s->data->disabled); -} - #define push_event(Kind, ...) \ do { \ stat_push_event(ctx->stats, \ @@ -295,23 +289,6 @@ static void handle_event(struct event *ev) { } } -static struct worker *run_test(struct criterion_global_stats *stats, - struct criterion_suite_stats *suite_stats, - struct criterion_test_stats *test_stats, - struct test_single_param *param) { - - struct execution_context ctx = { - .stats = sref(stats), - .test = test_stats->test, - .test_stats = sref(test_stats), - .suite = suite_stats->suite, - .suite_stats = sref(suite_stats), - .param = param, - }; - return spawn_test_worker(&ctx, run_test_child, g_worker_pipe); - -} - #ifdef HAVE_PCRE void disable_unmatching(struct criterion_test_set *set) { FOREACH_SET(struct criterion_suite_set *s, set->suites) { @@ -345,125 +322,6 @@ void criterion_finalize(struct criterion_test_set *set) { sfree(set); } -static struct worker *run_next_test(struct criterion_test_set *p_set, - struct criterion_global_stats *p_stats, - ccrContParam) { - ccrBeginContext; - struct criterion_suite_set *suite_set; - struct criterion_test *test; - struct criterion_suite_stats *suite_stats; - struct criterion_test_stats *test_stats; - struct criterion_test_set *set; - struct criterion_global_stats *stats; - struct criterion_test_params params; - - struct criterion_ordered_set_node *ns; - struct criterion_ordered_set_node *nt; - size_t i; - ccrEndContext(ctx); - - ccrBegin(ctx); - - ctx->set = p_set; - ctx->stats = p_stats; - ccrReturn(NULL); - - for (ctx->ns = ctx->set->suites->first; ctx->ns; ctx->ns = ctx->ns->next) { - ctx->suite_set = (void*) ctx->ns->data; - - if (!ctx->suite_set->tests) - continue; - - report(PRE_SUITE, ctx->suite_set); - log(pre_suite, ctx->suite_set); - - ctx->suite_stats = suite_stats_init(&ctx->suite_set->suite); - - struct event ev = { .kind = PRE_SUITE }; - stat_push_event(ctx->stats, ctx->suite_stats, NULL, &ev); - - for (ctx->nt = ctx->suite_set->tests->first; ctx->nt; ctx->nt = ctx->nt->next) { - ctx->test = (void*) ctx->nt->data; - - if (ctx->test->data->kind_ == CR_TEST_PARAMETERIZED - && ctx->test->data->param_) { - - if (is_disabled(ctx->test, ctx->suite_stats->suite)) { - ctx->test_stats = test_stats_init(ctx->test); - stat_push_event(ctx->stats, - ctx->suite_stats, - ctx->test_stats, - &(struct event) { .kind = PRE_INIT }); - sfree(ctx->test_stats); - continue; - } - - ctx->params = ctx->test->data->param_(); - for (ctx->i = 0; ctx->i < ctx->params.length; ++ctx->i) { - ctx->test_stats = test_stats_init(ctx->test); - - struct test_single_param param = { - ctx->params.size, - (char *) ctx->params.params + ctx->i * ctx->params.size - }; - - struct worker *worker = run_test(ctx->stats, - ctx->suite_stats, - ctx->test_stats, - ¶m); - - sfree(ctx->test_stats); - - if (!is_runner()) { - sfree(ctx->suite_stats); - if (ctx->params.cleanup) - ctx->params.cleanup(&ctx->params); - - ccrReturn(NULL); - } else { - ccrReturn(worker); - } - } - - if (ctx->params.cleanup) - ctx->params.cleanup(&ctx->params); - } else { - ctx->test_stats = test_stats_init(ctx->test); - - if (is_disabled(ctx->test, ctx->suite_stats->suite)) { - stat_push_event(ctx->stats, - ctx->suite_stats, - ctx->test_stats, - &(struct event) { .kind = PRE_INIT }); - sfree(ctx->test_stats); - continue; - } - - struct worker *worker = run_test(ctx->stats, - ctx->suite_stats, - ctx->test_stats, - NULL); - - sfree(ctx->test_stats); - - if (!is_runner()) { - sfree(ctx->suite_stats); - ccrReturn(NULL); - } else { - ccrReturn(worker); - } - } - } - - report(POST_SUITE, ctx->suite_stats); - log(post_suite, ctx->suite_stats); - - sfree(ctx->suite_stats); - } - - ccrFinish(NULL); -} - static void run_tests_async(struct criterion_test_set *set, struct criterion_global_stats *stats) { diff --git a/src/core/runner.h b/src/core/runner.h index 9ddb57f..9b49839 100644 --- a/src/core/runner.h +++ b/src/core/runner.h @@ -31,6 +31,7 @@ DECL_SECTION_LIMITS(struct criterion_test*, cr_tst); DECL_SECTION_LIMITS(struct criterion_suite*, cr_sts); struct criterion_test_set *criterion_init(void); +void run_test_child(struct criterion_test *test, struct criterion_suite *suite); # define FOREACH_TEST_SEC(Test) \ for (struct criterion_test **Test = GET_SECTION_START(cr_tst); \ diff --git a/src/core/runner_coroutine.c b/src/core/runner_coroutine.c new file mode 100644 index 0000000..31a271c --- /dev/null +++ b/src/core/runner_coroutine.c @@ -0,0 +1,178 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include "criterion/logging.h" +#include "runner_coroutine.h" +#include "worker.h" +#include "stats.h" +#include "runner.h" +#include "report.h" + +static INLINE void nothing(void) {} + +ccrBeginDefineContextType(run_next_context); + + struct criterion_suite_set *suite_set; + struct criterion_test *test; + struct criterion_suite_stats *suite_stats; + struct criterion_test_stats *test_stats; + struct criterion_test_set *set; + struct criterion_global_stats *stats; + struct criterion_test_params params; + + struct criterion_ordered_set_node *ns; + struct criterion_ordered_set_node *nt; + size_t i; + +ccrEndDefineContextType; + +static struct worker *run_test(struct criterion_global_stats *stats, + struct criterion_suite_stats *suite_stats, + struct criterion_test_stats *test_stats, + struct test_single_param *param) { + + struct execution_context ctx = { + .stats = sref(stats), + .test = test_stats->test, + .test_stats = sref(test_stats), + .suite = suite_stats->suite, + .suite_stats = sref(suite_stats), + .param = param, + }; + return spawn_test_worker(&ctx, run_test_child, g_worker_pipe); +} + +static INLINE bool is_disabled(struct criterion_test *t, + struct criterion_suite *s) { + + return t->data->disabled || (s->data && s->data->disabled); +} + + +static struct worker *cleanup_and_return_worker(struct run_next_context *ctx, + struct worker *worker) { + + sfree(ctx->test_stats); + if (!is_runner()) { + worker = NULL; + sfree(ctx->suite_stats); + if (ctx->test->data->kind_ == CR_TEST_PARAMETERIZED + && ctx->params.cleanup) + ctx->params.cleanup(&ctx->params); + } + return worker; +} + +static int skip_disabled(struct run_next_context *ctx) { + if (is_disabled(ctx->test, ctx->suite_stats->suite)) { + ctx->test_stats = test_stats_init(ctx->test); + stat_push_event(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + &(struct event) { .kind = PRE_INIT }); + sfree(ctx->test_stats); + return 1; + } + return 0; +} + +struct worker *run_next_test(struct criterion_test_set *p_set, + struct criterion_global_stats *p_stats, + ccrContParam) { + + ccrUseNamedContext(run_next_context, ctx); + + ccrBegin(ctx); + + ctx->set = p_set; + ctx->stats = p_stats; + ccrReturn(NULL); + + for (ctx->ns = ctx->set->suites->first; ctx->ns; ctx->ns = ctx->ns->next) { + ctx->suite_set = (void*) ctx->ns->data; + + if (!ctx->suite_set->tests) + continue; + + report(PRE_SUITE, ctx->suite_set); + log(pre_suite, ctx->suite_set); + + ctx->suite_stats = suite_stats_init(&ctx->suite_set->suite); + + struct event ev = { .kind = PRE_SUITE }; + stat_push_event(ctx->stats, ctx->suite_stats, NULL, &ev); + + for (ctx->nt = ctx->suite_set->tests->first; ctx->nt; ctx->nt = ctx->nt->next) { + ctx->test = (void*) ctx->nt->data; + + if (ctx->test->data->kind_ == CR_TEST_PARAMETERIZED + && ctx->test->data->param_) { + + if (skip_disabled(ctx)) + continue; + + ctx->params = ctx->test->data->param_(); + for (ctx->i = 0; ctx->i < ctx->params.length; ++ctx->i) { + ctx->test_stats = test_stats_init(ctx->test); + + struct test_single_param param = { + ctx->params.size, + (char *) ctx->params.params + ctx->i * ctx->params.size + }; + + struct worker *worker = run_test(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + ¶m); + + ccrReturn(cleanup_and_return_worker(ctx, worker)); + } + + if (ctx->params.cleanup) + ctx->params.cleanup(&ctx->params); + } else { + ctx->test_stats = test_stats_init(ctx->test); + + if (skip_disabled(ctx)) + continue; + + struct worker *worker = run_test(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + NULL); + + ccrReturn(cleanup_and_return_worker(ctx, worker)); + } + } + + report(POST_SUITE, ctx->suite_stats); + log(post_suite, ctx->suite_stats); + + sfree(ctx->suite_stats); + } + + ccrFinish(NULL); +} diff --git a/src/core/runner_coroutine.h b/src/core/runner_coroutine.h new file mode 100644 index 0000000..0b8773a --- /dev/null +++ b/src/core/runner_coroutine.h @@ -0,0 +1,33 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef RUNNER_COROUTINE_H_ +# define RUNNER_COROUTINE_H_ + +# include "coroutine.h" + +struct worker *run_next_test(struct criterion_test_set *p_set, + struct criterion_global_stats *p_stats, + ccrContParam); + +#endif /* !RUNNER_COROUTINE_H_ */