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_ */