Boyscouting
This commit is contained in:
parent
fe65034ecd
commit
260b88c5d7
11 changed files with 112 additions and 48 deletions
|
@ -26,10 +26,12 @@
|
|||
|
||||
# include "types.h"
|
||||
|
||||
typedef int (*f_criterion_cmp)(void *, void *);
|
||||
|
||||
struct criterion_ordered_set {
|
||||
struct criterion_ordered_set_node *first;
|
||||
size_t size;
|
||||
int (*const cmp)(void *, void *);
|
||||
f_criterion_cmp cmp;
|
||||
void (*const dtor)(void *, void *);
|
||||
};
|
||||
|
||||
|
@ -48,12 +50,16 @@ struct criterion_test_set {
|
|||
size_t tests;
|
||||
};
|
||||
|
||||
struct criterion_ordered_set *new_ordered_set(int (*cmp)(void *, void *), void (*dtor)(void *, void *));
|
||||
void *insert_ordered_set(struct criterion_ordered_set *l, void *ptr, size_t size);
|
||||
struct criterion_ordered_set *new_ordered_set(f_criterion_cmp cmp,
|
||||
void (*dtor)(void *, void *));
|
||||
|
||||
# define FOREACH_SET(Elt, Set) \
|
||||
for (struct criterion_ordered_set_node *n = Set->first; n; n = n->next) \
|
||||
for (int cond = 1; cond;) \
|
||||
void *insert_ordered_set(struct criterion_ordered_set *l,
|
||||
void *ptr,
|
||||
size_t size);
|
||||
|
||||
# define FOREACH_SET(Elt, Set) \
|
||||
for (struct criterion_ordered_set_node *n = Set->first; n; n = n->next) \
|
||||
for (int cond = 1; cond;) \
|
||||
for (Elt = (void*) n->data; cond && (cond = 0, 1);)
|
||||
|
||||
#endif /* !CRITERION_ORDERED_SET_H_ */
|
||||
|
|
|
@ -48,14 +48,18 @@ struct event *read_event(FILE *f) {
|
|||
if (fread(buf, assert_size, 1, f) == 0)
|
||||
return NULL;
|
||||
|
||||
return unique_ptr(struct event, { .kind = kind, .data = buf }, destroy_event);
|
||||
return unique_ptr(struct event,
|
||||
.value = { .kind = kind, .data = buf },
|
||||
.dtor = destroy_event);
|
||||
}
|
||||
case POST_TEST: {
|
||||
double *elapsed_time = malloc(sizeof (double));
|
||||
if (fread(elapsed_time, sizeof (double), 1, f) == 0)
|
||||
return NULL;
|
||||
|
||||
return unique_ptr(struct event, { .kind = kind, .data = elapsed_time }, destroy_event);
|
||||
return unique_ptr(struct event,
|
||||
.value = { .kind = kind, .data = elapsed_time },
|
||||
.dtor = destroy_event);
|
||||
}
|
||||
default:
|
||||
return unique_ptr(struct event, { .kind = kind, .data = NULL });
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
# else
|
||||
# include <libintl.h>
|
||||
# define _(String) dgettext(PACKAGE, String)
|
||||
# define _s(String, Plural, Quantity) dngettext(PACKAGE, String, Plural, (Quantity))
|
||||
# define _s(String, Plural, Quantity) \
|
||||
dngettext(PACKAGE, String, Plural, (Quantity))
|
||||
# endif
|
||||
|
||||
#endif /* !I18N_H_ */
|
||||
|
|
|
@ -39,13 +39,18 @@ void normal_log_pre_all(UNUSED struct criterion_test_set *set) {
|
|||
}
|
||||
|
||||
void normal_log_pre_init(struct criterion_test *test) {
|
||||
criterion_pinfo(CRITERION_PREFIX_RUN, _("%1$s::%2$s\n"), test->category, test->name);
|
||||
criterion_pinfo(CRITERION_PREFIX_RUN, _("%1$s::%2$s\n"),
|
||||
test->category,
|
||||
test->name);
|
||||
|
||||
if (test->data->description)
|
||||
criterion_pinfo(CRITERION_PREFIX_RUN, _(" %s\n"), test->data->description);
|
||||
criterion_pinfo(CRITERION_PREFIX_RUN, _(" %s\n"),
|
||||
test->data->description);
|
||||
}
|
||||
|
||||
void normal_log_post_test(struct criterion_test_stats *stats) {
|
||||
const char *format = can_measure_time() ? "%1$s::%2$s: (%3$3.2fs)\n" : "%1$s::%2$s\n";
|
||||
const char *format = can_measure_time() ? "%1$s::%2$s: (%3$3.2fs)\n"
|
||||
: "%1$s::%2$s\n";
|
||||
|
||||
const enum criterion_logging_level level
|
||||
= stats->failed ? CRITERION_IMPORTANT : CRITERION_INFO;
|
||||
|
@ -59,7 +64,8 @@ void normal_log_post_test(struct criterion_test_stats *stats) {
|
|||
}
|
||||
|
||||
__attribute__((always_inline))
|
||||
static inline bool is_disabled(struct criterion_test *t, struct criterion_suite *s) {
|
||||
static inline bool is_disabled(struct criterion_test *t,
|
||||
struct criterion_suite *s) {
|
||||
return t->data->disabled || (s->data && s->data->disabled);
|
||||
}
|
||||
|
||||
|
@ -75,7 +81,8 @@ void normal_log_post_suite(struct criterion_suite_stats *stats) {
|
|||
ts->test->name);
|
||||
|
||||
if (ts->test->data->description)
|
||||
criterion_pinfo(CRITERION_PREFIX_DASHES, " %s\n", ts->test->data->description);
|
||||
criterion_pinfo(CRITERION_PREFIX_DASHES, " %s\n",
|
||||
ts->test->data->description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,8 +104,10 @@ void normal_log_post_all(struct criterion_global_stats *stats) {
|
|||
|
||||
void normal_log_assert(struct criterion_assert_stats *stats) {
|
||||
if (!stats->passed) {
|
||||
char *dup = strdup(*stats->message ? stats->message : stats->condition), *saveptr = NULL;
|
||||
char *line = strtok_r(dup, "\n", &saveptr);
|
||||
char *dup = strdup(*stats->message ? stats->message
|
||||
: stats->condition);
|
||||
char *saveptr = NULL;
|
||||
char *line = strtok_r(dup, "\n", &saveptr);
|
||||
|
||||
criterion_pimportant(CRITERION_PREFIX_DASHES,
|
||||
_("%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n"),
|
||||
|
|
|
@ -23,4 +23,6 @@
|
|||
*/
|
||||
# include "criterion/options.h"
|
||||
|
||||
struct criterion_options criterion_options = { .logging_threshold = CRITERION_IMPORTANT };
|
||||
struct criterion_options criterion_options = {
|
||||
.logging_threshold = CRITERION_IMPORTANT,
|
||||
};
|
||||
|
|
|
@ -39,12 +39,17 @@ static void destroy_ordered_set_node(void *ptr, void *meta) {
|
|||
sfree(((struct criterion_ordered_set_node *) ptr)->next);
|
||||
}
|
||||
|
||||
struct criterion_ordered_set *new_ordered_set(int (*cmp)(void *, void *), f_destructor dtor) {
|
||||
struct criterion_ordered_set *new_ordered_set(f_criterion_cmp cmp,
|
||||
f_destructor dtor) {
|
||||
|
||||
return unique_ptr(struct criterion_ordered_set,
|
||||
{ .cmp = cmp, .dtor = dtor }, destroy_ordered_set);
|
||||
.value = { .cmp = cmp, .dtor = dtor },
|
||||
.dtor = destroy_ordered_set);
|
||||
}
|
||||
|
||||
void *insert_ordered_set(struct criterion_ordered_set *l, void *ptr, size_t size) {
|
||||
void *insert_ordered_set(struct criterion_ordered_set *l,
|
||||
void *ptr,
|
||||
size_t size) {
|
||||
int cmp;
|
||||
struct criterion_ordered_set_node *n, *prev = NULL;
|
||||
for (n = l->first; n && (cmp = l->cmp(ptr, n->data)) > 0; n = n->next)
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
&(StartupInfo), \
|
||||
&(Info))
|
||||
|
||||
# define WRITE_PROCESS_(Proc, What, Size) \
|
||||
WriteProcessMemory(Proc, &What, &What, Size, NULL);
|
||||
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <sys/wait.h>
|
||||
|
@ -87,20 +90,26 @@ s_proc_handle *fork_process() {
|
|||
child_suite = *g_worker_context.suite;
|
||||
child_pipe = *g_worker_context.pipe;
|
||||
|
||||
g_worker_context = (struct worker_context) { &child_test, &child_suite, child_func, &child_pipe };
|
||||
g_worker_context = (struct worker_context) {
|
||||
&child_test,
|
||||
&child_suite,
|
||||
child_func,
|
||||
&child_pipe
|
||||
};
|
||||
|
||||
child_test.data = &child_test_data;
|
||||
|
||||
if (g_worker_context.suite->data) {
|
||||
child_suite_data = *g_worker_context.suite->data;
|
||||
child_suite.data = &child_suite_data;
|
||||
WriteProcessMemory(info.hProcess, &child_suite_data, &child_suite_data, sizeof (child_suite_data), NULL);
|
||||
WRITE_PROCESS_(info.hProcess, child_suite_data, sizeof (child_suite_data));
|
||||
}
|
||||
|
||||
WriteProcessMemory(info.hProcess, &child_test, &child_test, sizeof (child_test), NULL);
|
||||
WriteProcessMemory(info.hProcess, &child_test_data, &child_test_data, sizeof (child_test_data), NULL);
|
||||
WriteProcessMemory(info.hProcess, &child_suite, &child_suite, sizeof (child_suite), NULL);
|
||||
WriteProcessMemory(info.hProcess, &child_pipe, &child_pipe, sizeof (child_pipe), NULL);
|
||||
WriteProcessMemory(info.hProcess, &g_worker_context, &g_worker_context, sizeof (struct worker_context), NULL);
|
||||
WRITE_PROCESS_(info.hProcess, child_test, sizeof (child_test));
|
||||
WRITE_PROCESS_(info.hProcess, child_test_data, sizeof (child_test_data));
|
||||
WRITE_PROCESS_(info.hProcess, child_suite, sizeof (child_suite));
|
||||
WRITE_PROCESS_(info.hProcess, child_pipe, sizeof (child_pipe));
|
||||
WRITE_PROCESS_(info.hProcess, g_worker_context, sizeof (struct worker_context));
|
||||
|
||||
ResumeThread(info.hThread);
|
||||
CloseHandle(info.hThread);
|
||||
|
@ -167,7 +176,10 @@ FILE *pipe_out(s_pipe_handle *p) {
|
|||
s_pipe_handle *stdpipe() {
|
||||
#ifdef VANILLA_WIN32
|
||||
HANDLE fhs[2];
|
||||
SECURITY_ATTRIBUTES attr = { .nLength = sizeof (SECURITY_ATTRIBUTES), .bInheritHandle = TRUE };
|
||||
SECURITY_ATTRIBUTES attr = {
|
||||
.nLength = sizeof (SECURITY_ATTRIBUTES),
|
||||
.bInheritHandle = TRUE
|
||||
};
|
||||
if (!CreatePipe(fhs, fhs + 1, &attr, 0))
|
||||
return NULL;
|
||||
return unique_ptr(s_pipe_handle, {{ fhs[0], fhs[1] }});
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
# endif
|
||||
|
||||
# ifdef VANILLA_WIN32
|
||||
# define WEXITSTATUS(Status) (((Status) & 0xFF00) >> 8)
|
||||
# define WTERMSIG(Status) ((Status) & 0x7F)
|
||||
# define WIFEXITED(Status) (WTERMSIG(Status) == 0)
|
||||
# define WIFSIGNALED(Status) (((signed char) (WTERMSIG(Status) + 1) >> 1) > 0)
|
||||
# define WEXITSTATUS(Status) (((Status) & 0xFF00) >> 8)
|
||||
# define WTERMSIG(Status) ((Status) & 0x7F)
|
||||
# define WIFEXITED(Status) (WTERMSIG(Status) == 0)
|
||||
# define WIFSIGNALED(Status) (((signed char) (WTERMSIG(Status) + 1) >> 1) > 0)
|
||||
# else
|
||||
# include <sys/wait.h>
|
||||
# endif
|
||||
|
|
|
@ -94,7 +94,9 @@ struct process *spawn_test_worker(struct criterion_test *test,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return unique_ptr(struct process, { .proc = proc, .in = pipe_in(pipe) }, close_process);
|
||||
return unique_ptr(struct process,
|
||||
.value = { .proc = proc, .in = pipe_in(pipe) },
|
||||
.dtor = close_process);
|
||||
}
|
||||
|
||||
struct process_status wait_proc(struct process *proc) {
|
||||
|
@ -102,10 +104,16 @@ struct process_status wait_proc(struct process *proc) {
|
|||
wait_process(proc->proc, &status);
|
||||
|
||||
if (WIFEXITED(status))
|
||||
return (struct process_status) { .kind = EXIT_STATUS, .status = WEXITSTATUS(status) };
|
||||
return (struct process_status) {
|
||||
.kind = EXIT_STATUS,
|
||||
.status = WEXITSTATUS(status)
|
||||
};
|
||||
|
||||
if (WIFSIGNALED(status))
|
||||
return (struct process_status) { .kind = SIGNAL, .status = WTERMSIG(status) };
|
||||
return (struct process_status) {
|
||||
.kind = SIGNAL,
|
||||
.status = WTERMSIG(status)
|
||||
};
|
||||
|
||||
return (struct process_status) { .kind = STOPPED };
|
||||
}
|
||||
|
|
24
src/report.c
24
src/report.c
|
@ -56,18 +56,24 @@
|
|||
__attribute__((always_inline))
|
||||
static inline void nothing() {}
|
||||
|
||||
#ifdef HAVE_FNMATCH
|
||||
void disable_unmatching(struct criterion_test_set *set) {
|
||||
FOREACH_SET(struct criterion_suite_set *s, set->suites) {
|
||||
if ((s->suite.data && s->suite.data->disabled) || !s->tests)
|
||||
continue;
|
||||
|
||||
FOREACH_SET(struct criterion_test *test, s->tests) {
|
||||
if (fnmatch(criterion_options.pattern, test->data->identifier_, 0))
|
||||
test->data->disabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
IMPL_REPORT_HOOK(PRE_ALL)(struct criterion_test_set *set) {
|
||||
#ifdef HAVE_FNMATCH
|
||||
if (criterion_options.pattern) {
|
||||
FOREACH_SET(struct criterion_suite_set *s, set->suites) {
|
||||
if ((s->suite.data && s->suite.data->disabled) || !s->tests)
|
||||
continue;
|
||||
|
||||
FOREACH_SET(struct criterion_test *test, s->tests) {
|
||||
if (fnmatch(criterion_options.pattern, test->data->identifier_, 0))
|
||||
test->data->disabled = true;
|
||||
}
|
||||
}
|
||||
disable_unmatching(set);
|
||||
}
|
||||
#endif
|
||||
log(pre_all, set);
|
||||
|
|
19
src/runner.c
19
src/runner.c
|
@ -38,6 +38,7 @@
|
|||
IMPL_SECTION_LIMITS(struct criterion_test, criterion_tests);
|
||||
IMPL_SECTION_LIMITS(struct criterion_suite, crit_suites);
|
||||
|
||||
// This is here to make the test suite section non-empty
|
||||
TestSuite(default);
|
||||
|
||||
int cmp_suite(void *a, void *b) {
|
||||
|
@ -95,7 +96,10 @@ typedef void (*f_test_run)(struct criterion_global_stats *,
|
|||
struct criterion_test *,
|
||||
struct criterion_suite *);
|
||||
|
||||
static void map_tests(struct criterion_test_set *set, struct criterion_global_stats *stats, f_test_run fun) {
|
||||
static void map_tests(struct criterion_test_set *set,
|
||||
struct criterion_global_stats *stats,
|
||||
f_test_run fun) {
|
||||
|
||||
FOREACH_SET(struct criterion_suite_set *s, set->suites) {
|
||||
if (!s->tests)
|
||||
continue;
|
||||
|
@ -122,7 +126,9 @@ static void map_tests(struct criterion_test_set *set, struct criterion_global_st
|
|||
__attribute__ ((always_inline))
|
||||
static inline void nothing() {}
|
||||
|
||||
static void run_test_child(struct criterion_test *test, struct criterion_suite *suite) {
|
||||
static void run_test_child(struct criterion_test *test,
|
||||
struct criterion_suite *suite) {
|
||||
|
||||
send_event(PRE_INIT, NULL, 0);
|
||||
if (suite->data)
|
||||
(suite->data->init ?: nothing)();
|
||||
|
@ -144,7 +150,9 @@ static void run_test_child(struct criterion_test *test, struct criterion_suite *
|
|||
}
|
||||
|
||||
__attribute__((always_inline))
|
||||
static inline bool is_disabled(struct criterion_test *t, struct criterion_suite *s) {
|
||||
static inline bool is_disabled(struct criterion_test *t,
|
||||
struct criterion_suite *s) {
|
||||
|
||||
return t->data->disabled || (s->data && s->data->disabled);
|
||||
}
|
||||
|
||||
|
@ -165,7 +173,10 @@ static void run_test(struct criterion_global_stats *stats,
|
|||
smart struct criterion_test_stats *test_stats = test_stats_init(test);
|
||||
|
||||
if (is_disabled(test, suite)) {
|
||||
stat_push_event(stats, suite_stats, test_stats, &(struct event) { .kind = PRE_TEST });
|
||||
stat_push_event(stats,
|
||||
suite_stats,
|
||||
test_stats,
|
||||
&(struct event) { .kind = PRE_TEST });
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue