Refactored runner coroutine into its own file

This commit is contained in:
Snaipe 2015-09-24 16:08:58 +02:00
parent 5ec278c7d6
commit b347b70bdb
7 changed files with 229 additions and 149 deletions

View file

@ -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

View file

@ -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)

View file

@ -25,6 +25,7 @@
# define REPORT_H_
# include "criterion/hooks.h"
# include "criterion/options.h"
# define report(Kind, Data) call_report_hooks_##Kind(Data)

View file

@ -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,
&param);
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) {

View file

@ -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); \

178
src/core/runner_coroutine.c Normal file
View file

@ -0,0 +1,178 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* 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 <stdlib.h>
#include <stdio.h>
#include <csptr/smalloc.h>
#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,
&param);
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);
}

View file

@ -0,0 +1,33 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* 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_ */