Refactored outputting logic out of the report hook code
This commit is contained in:
parent
6a7161598c
commit
6b5d4f95d6
7 changed files with 201 additions and 80 deletions
|
@ -45,6 +45,8 @@ libcriterion_la_SOURCES = \
|
|||
src/stats.c \
|
||||
src/stats.h \
|
||||
src/logging.c \
|
||||
src/log/tap.c \
|
||||
src/log/normal.c \
|
||||
src/options.c \
|
||||
src/timer.c \
|
||||
src/timer.h \
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
# include <stdbool.h>
|
||||
# include "common.h"
|
||||
# include "ordered-set.h"
|
||||
|
||||
enum criterion_logging_level {
|
||||
CRITERION_INFO = 1,
|
||||
|
@ -38,4 +39,21 @@ void criterion_log(enum criterion_logging_level level, const char *msg, ...);
|
|||
# define criterion_info(...) criterion_log(CRITERION_INFO, __VA_ARGS__)
|
||||
# define criterion_important(...) criterion_log(CRITERION_IMPORTANT, __VA_ARGS__)
|
||||
|
||||
struct criterion_output_provider {
|
||||
void (*log_pre_all )(struct criterion_test_set *set);
|
||||
void (*log_pre_init )(struct criterion_test *test);
|
||||
void (*log_pre_test )(struct criterion_test *test);
|
||||
void (*log_assert )(struct criterion_assert_stats *stats);
|
||||
void (*log_test_crash)(struct criterion_test_stats *stats);
|
||||
void (*log_post_test )(struct criterion_test_stats *stats);
|
||||
void (*log_post_fini )(struct criterion_test_stats *stats);
|
||||
void (*log_post_all )(struct criterion_global_stats *stats);
|
||||
};
|
||||
|
||||
extern struct criterion_output_provider normal_logging;
|
||||
extern struct criterion_output_provider tap_logging;
|
||||
|
||||
#define NORMAL_LOGGING (&normal_logging)
|
||||
#define TAP_LOGGING (&tap_logging)
|
||||
|
||||
#endif /* !CRITERION_LOGGING_H_ */
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
struct criterion_options {
|
||||
enum criterion_logging_level logging_threshold;
|
||||
bool enable_tap_format;
|
||||
struct criterion_output_provider *output_provider;
|
||||
bool no_early_exit;
|
||||
bool always_succeed;
|
||||
bool use_ascii;
|
||||
|
|
77
src/log/normal.c
Normal file
77
src/log/normal.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include "criterion/stats.h"
|
||||
#include "criterion/logging.h"
|
||||
#include "criterion/options.h"
|
||||
#include "criterion/ordered-set.h"
|
||||
#include "timer.h"
|
||||
|
||||
void normal_log_pre_init(struct criterion_test *test) {
|
||||
criterion_info("%s::%s: RUNNING\n", test->category, test->name);
|
||||
}
|
||||
|
||||
void normal_log_post_test(struct criterion_test_stats *stats) {
|
||||
const char *format = can_measure_time() ? "%s::%s: %s (%3.2fs)\n" : "%s::%s: %s\n";
|
||||
criterion_log(stats->failed ? CRITERION_IMPORTANT : CRITERION_INFO,
|
||||
format,
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
stats->failed ? "FAILURE" : "SUCCESS",
|
||||
stats->elapsed_time);
|
||||
}
|
||||
|
||||
void normal_log_post_all(struct criterion_global_stats *stats) {
|
||||
criterion_important("Synthesis: " SIZE_T_FORMAT " tests were run. " SIZE_T_FORMAT " passed, " SIZE_T_FORMAT " failed (with " SIZE_T_FORMAT " crashes)\n",
|
||||
stats->nb_tests,
|
||||
stats->tests_passed,
|
||||
stats->tests_failed,
|
||||
stats->tests_crashed);
|
||||
}
|
||||
|
||||
void normal_log_assert(struct criterion_assert_stats *stats) {
|
||||
if (!stats->passed) {
|
||||
criterion_important("%s:%d: Assertion failed: %s\n",
|
||||
stats->file,
|
||||
stats->line,
|
||||
*stats->message ? stats->message : stats->condition);
|
||||
}
|
||||
}
|
||||
|
||||
void normal_log_test_crash(struct criterion_test_stats *stats) {
|
||||
criterion_important("Unexpected signal after %s:%u!\n%s::%s: FAILURE (CRASH!)\n",
|
||||
stats->file,
|
||||
stats->progress,
|
||||
stats->test->category,
|
||||
stats->test->name);
|
||||
}
|
||||
|
||||
struct criterion_output_provider normal_logging = {
|
||||
.log_pre_init = normal_log_pre_init,
|
||||
.log_post_test = normal_log_post_test,
|
||||
.log_assert = normal_log_assert,
|
||||
.log_post_all = normal_log_post_all,
|
||||
.log_test_crash = normal_log_test_crash,
|
||||
};
|
85
src/log/tap.c
Normal file
85
src/log/tap.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include "criterion/stats.h"
|
||||
#include "criterion/logging.h"
|
||||
#include "criterion/options.h"
|
||||
#include "criterion/ordered-set.h"
|
||||
#include "timer.h"
|
||||
|
||||
static size_t tap_test_index = 1;
|
||||
|
||||
void tap_log_pre_all(struct criterion_test_set *set) {
|
||||
size_t enabled_count = 0;
|
||||
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 (!test->data->disabled)
|
||||
++enabled_count;
|
||||
}
|
||||
}
|
||||
criterion_important("1.." SIZE_T_FORMAT "\n", enabled_count);
|
||||
}
|
||||
|
||||
void tap_log_post_test(struct criterion_test_stats *stats) {
|
||||
const char *format = can_measure_time() ? "%s " SIZE_T_FORMAT " - %s::%s (%3.2fs)\n"
|
||||
: "%s " SIZE_T_FORMAT " - %s::%s\n";
|
||||
criterion_important(format,
|
||||
stats->failed ? "not ok" : "ok",
|
||||
tap_test_index++,
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
stats->elapsed_time);
|
||||
for (struct criterion_assert_stats *asrt = stats->asserts; asrt; asrt = asrt->next) {
|
||||
if (!asrt->passed) {
|
||||
char *dup = strdup(*asrt->message ? asrt->message : asrt->condition), *saveptr = NULL;
|
||||
char *line = strtok_r(dup, "\n", &saveptr);
|
||||
criterion_important("\t%s:%u: Assertion failed: %s\n",
|
||||
asrt->file,
|
||||
asrt->line,
|
||||
line);
|
||||
while ((line = strtok_r(NULL, "\n", &saveptr)))
|
||||
criterion_important("\t%s\n", line);
|
||||
free(dup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tap_log_test_crash(struct criterion_test_stats *stats) {
|
||||
criterion_important("not ok " SIZE_T_FORMAT " - %s::%s unexpected signal after %s:%u\n",
|
||||
tap_test_index++,
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
stats->file,
|
||||
stats->progress);
|
||||
}
|
||||
|
||||
struct criterion_output_provider tap_logging = {
|
||||
.log_pre_all = tap_log_pre_all,
|
||||
.log_test_crash = tap_log_test_crash,
|
||||
.log_post_test = tap_log_post_test,
|
||||
};
|
|
@ -121,28 +121,32 @@ int main(int argc, char *argv[]) {
|
|||
criterion_options = (struct criterion_options) {
|
||||
.always_succeed = !strcmp("1", getenv("CRITERION_ALWAYS_SUCCEED") ?: "0"),
|
||||
.no_early_exit = !strcmp("1", getenv("CRITERION_NO_EARLY_EXIT") ?: "0"),
|
||||
.enable_tap_format = !strcmp("1", getenv("CRITERION_ENABLE_TAP") ?: "0"),
|
||||
.logging_threshold = atoi(getenv("CRITERION_VERBOSITY_LEVEL") ?: "2"),
|
||||
.output_provider = NORMAL_LOGGING,
|
||||
};
|
||||
|
||||
bool use_tap = !strcmp("1", getenv("CRITERION_ENABLE_TAP") ?: "0");
|
||||
|
||||
bool do_list_tests = false;
|
||||
bool do_print_version = false;
|
||||
bool do_print_usage = false;
|
||||
for (int c; (c = getopt_long(argc, argv, "hvlf", opts, NULL)) != -1;) {
|
||||
switch (c) {
|
||||
case 'b': criterion_options.logging_threshold = atoi(optarg ?: "1"); break;
|
||||
case 't': criterion_options.enable_tap_format = true; break;
|
||||
case 'y': criterion_options.always_succeed = true; break;
|
||||
case 'z': criterion_options.no_early_exit = true; break;
|
||||
case 'k': criterion_options.use_ascii = true; break;
|
||||
case 'f': criterion_options.fail_fast = true; break;
|
||||
case 'p': criterion_options.pattern = optarg; break;
|
||||
case 't': use_tap = true; break;
|
||||
case 'l': do_list_tests = true; break;
|
||||
case 'v': do_print_version = true; break;
|
||||
case 'h':
|
||||
default : do_print_usage = true; break;
|
||||
}
|
||||
}
|
||||
if (use_tap)
|
||||
criterion_options.output_provider = TAP_LOGGING;
|
||||
if (do_print_usage)
|
||||
return print_usage(argv[0]);
|
||||
if (do_print_version)
|
||||
|
|
89
src/report.c
89
src/report.c
|
@ -42,7 +42,8 @@
|
|||
} \
|
||||
}
|
||||
|
||||
static size_t tap_test_index = 1;
|
||||
#define log(Type, Arg) \
|
||||
(criterion_options.output_provider->log_ ## Type ?: nothing)(Arg);
|
||||
|
||||
IMPL_CALL_REPORT_HOOKS(PRE_ALL);
|
||||
IMPL_CALL_REPORT_HOOKS(PRE_INIT);
|
||||
|
@ -53,44 +54,15 @@ IMPL_CALL_REPORT_HOOKS(POST_TEST);
|
|||
IMPL_CALL_REPORT_HOOKS(POST_FINI);
|
||||
IMPL_CALL_REPORT_HOOKS(POST_ALL);
|
||||
|
||||
ReportHook(PRE_INIT)(struct criterion_test *test) {
|
||||
if (criterion_options.enable_tap_format) return;
|
||||
__attribute__((always_inline))
|
||||
static inline void nothing() {}
|
||||
|
||||
criterion_info("%s::%s: RUNNING\n", test->category, test->name);
|
||||
ReportHook(PRE_INIT)(struct criterion_test *test) {
|
||||
log(pre_init, test);
|
||||
}
|
||||
|
||||
ReportHook(POST_TEST)(struct criterion_test_stats *stats) {
|
||||
if (criterion_options.enable_tap_format) {
|
||||
const char *format = can_measure_time() ? "%s " SIZE_T_FORMAT " - %s::%s (%3.2fs)\n"
|
||||
: "%s " SIZE_T_FORMAT " - %s::%s\n";
|
||||
criterion_important(format,
|
||||
stats->failed ? "not ok" : "ok",
|
||||
tap_test_index++,
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
stats->elapsed_time);
|
||||
for (struct criterion_assert_stats *asrt = stats->asserts; asrt; asrt = asrt->next) {
|
||||
if (!asrt->passed) {
|
||||
char *dup = strdup(*asrt->message ? asrt->message : asrt->condition), *saveptr = NULL;
|
||||
char *line = strtok_r(dup, "\n", &saveptr);
|
||||
criterion_important("\t%s:%u: Assertion failed: %s\n",
|
||||
asrt->file,
|
||||
asrt->line,
|
||||
line);
|
||||
while ((line = strtok_r(NULL, "\n", &saveptr)))
|
||||
criterion_important("\t%s\n", line);
|
||||
free(dup);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const char *format = can_measure_time() ? "%s::%s: %s (%3.2fs)\n" : "%s::%s: %s\n";
|
||||
criterion_log(stats->failed ? CRITERION_IMPORTANT : CRITERION_INFO,
|
||||
format,
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
stats->failed ? "FAILURE" : "SUCCESS",
|
||||
stats->elapsed_time);
|
||||
}
|
||||
log(post_test, stats);
|
||||
}
|
||||
|
||||
ReportHook(PRE_TEST)() {}
|
||||
|
@ -112,54 +84,17 @@ ReportHook(PRE_ALL)(struct criterion_test_set *set) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (criterion_options.enable_tap_format) {
|
||||
size_t enabled_count = 0;
|
||||
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 (!test->data->disabled)
|
||||
++enabled_count;
|
||||
}
|
||||
}
|
||||
criterion_important("1.." SIZE_T_FORMAT "\n", enabled_count);
|
||||
}
|
||||
log(pre_all, set);
|
||||
}
|
||||
ReportHook(POST_ALL)(struct criterion_global_stats *stats) {
|
||||
if (criterion_options.enable_tap_format) return;
|
||||
|
||||
criterion_important("Synthesis: " SIZE_T_FORMAT " tests were run. " SIZE_T_FORMAT " passed, " SIZE_T_FORMAT " failed (with " SIZE_T_FORMAT " crashes)\n",
|
||||
stats->nb_tests,
|
||||
stats->tests_passed,
|
||||
stats->tests_failed,
|
||||
stats->tests_crashed);
|
||||
ReportHook(POST_ALL)(struct criterion_global_stats *stats) {
|
||||
log(post_all, stats);
|
||||
}
|
||||
|
||||
ReportHook(ASSERT)(struct criterion_assert_stats *stats) {
|
||||
if (criterion_options.enable_tap_format) return;
|
||||
|
||||
if (!stats->passed) {
|
||||
criterion_important("%s:%d: Assertion failed: %s\n",
|
||||
stats->file,
|
||||
stats->line,
|
||||
*stats->message ? stats->message : stats->condition);
|
||||
}
|
||||
log(assert, stats);
|
||||
}
|
||||
|
||||
ReportHook(TEST_CRASH)(struct criterion_test_stats *stats) {
|
||||
if (criterion_options.enable_tap_format) {
|
||||
criterion_important("not ok " SIZE_T_FORMAT " - %s::%s unexpected signal after %s:%u\n",
|
||||
tap_test_index++,
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
stats->file,
|
||||
stats->progress);
|
||||
} else {
|
||||
criterion_important("Unexpected signal after %s:%u!\n%s::%s: FAILURE (CRASH!)\n",
|
||||
stats->file,
|
||||
stats->progress,
|
||||
stats->test->category,
|
||||
stats->test->name);
|
||||
}
|
||||
log(test_crash, stats);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue