20
#include <framework/test/api.h>
21
#include <framework/test/assert.h>
22
#include <framework/test/emit.h>
23
#include <kernel/panic.h>
24
#include <util/location.h>
30
struct test_run_context {
32
struct test_emit_buffer emitting;
35
static struct test_run_context *current;
37
#define EMIT_BUFFER_SZ 64
39
static char emit_buffer[EMIT_BUFFER_SZ];
41
static int test_case_run(const struct test_case *test_case,
42
const struct __test_fixture_ops *fixtures);
43
static const struct __test_assertion_point *test_run(test_case_run_t run);
45
static void handle_suite_fixture_failure(const struct test_suite *, int code,
47
static void handle_suite_result(const struct test_suite *, int failures,
50
static void handle_case_fixture_failure(const struct test_case *, int code,
52
static void handle_case_result(const struct test_case *,
53
const struct __test_assertion_point *failure);
55
int test_suite_run(const struct test_suite *test) {
56
const struct test_case *test_case;
57
const struct __test_fixture_ops *fixture_ops;
58
__test_fixture_op_t fx_op;
59
int failures = 0, total = 0;
66
fixture_ops = &test->suite_fixture_ops;
68
log_info("running %s.%s", test_package(test), test_name(test));
70
if ((fx_op = *fixture_ops->p_setup) && (ret = fx_op()) != 0) {
71
handle_suite_fixture_failure(test, ret, 1);
75
array_spread_nullterm_foreach(test_case, test->test_cases) {
76
if ((ret = test_case_run(test_case, &test->case_fixture_ops)) != 0) {
86
if ((fx_op = *fixture_ops->p_teardown) && (ret = fx_op()) != 0) {
87
handle_suite_fixture_failure(test, ret, 0);
91
handle_suite_result(test, failures, total);
96
static int test_case_run(const struct test_case *test_case,
97
const struct __test_fixture_ops *fixtures) {
98
const struct __test_assertion_point *failure;
99
__test_fixture_op_t fx_op;
102
if ((fx_op = *fixtures->p_setup) && (ret = fx_op()) != 0) {
103
handle_case_fixture_failure(test_case, ret, 1);
107
failure = test_run(test_case->run);
109
if ((fx_op = *fixtures->p_teardown) && (ret = fx_op()) != 0) {
110
handle_case_fixture_failure(test_case, ret, 0);
114
handle_case_result(test_case, failure);
119
static const struct __test_assertion_point *test_run(test_case_run_t run) {
120
struct test_run_context ctx;
124
test_emit_buffer_init(¤t->emitting, emit_buffer, EMIT_BUFFER_SZ);
125
if (!(caught = setjmp(ctx.before_run))) {
130
return (const struct __test_assertion_point *)(uintptr_t)caught;
133
struct test_emit_buffer *__test_emit_buffer_current(void) {
134
assert(current != NULL);
135
return ¤t->emitting;
138
void __test_assertion_handle(int pass,
139
const struct __test_assertion_point *point) {
147
longjmp(current->before_run, (intptr_t)point);
150
handle_case_result(NULL, point);
151
panic("\ntest_assert failed inside fixture\n");
155
static void handle_suite_fixture_failure(const struct test_suite *test_suite,
156
int code, int setup) {
157
log_error("suite fixture %s failed with code %d: %s",
158
setup ? "setup" : "tear down", code, strerror(-code));
161
static void handle_suite_result(const struct test_suite *test_suite,
162
int failures, int total) {
164
log_error("testing \"%s\": %d/%d failures", test_suite->description,
169
static void handle_case_fixture_failure(const struct test_case *test_case,
170
int code, int setup) {
171
log_error("case fixture %s failed with code %d: %s",
172
setup ? "setup" : "tear down", code, strerror(-code));
175
static void handle_case_result(const struct test_case *test_case,
176
const struct __test_assertion_point *failure) {
177
const struct location __attribute__((unused)) * test_loc;
178
const struct location_func __attribute__((unused)) * fail_loc;
184
fail_loc = &failure->location;
185
log_error("failure at %s:%d", fail_loc->at.file, fail_loc->at.line);