[Issue #68] Merge branch 'features/new-reporting' into bleeding
Changelog: ~ Overhauls the output reporting system + Adds registration of user defined output reporters + Adds --output CLI switch + Adds --quiet CLI switch - Removes CRITERION_ENABLE_{TAP,XML} environment variables
This commit is contained in:
commit
8624880183
19 changed files with 323 additions and 86 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -7,3 +7,6 @@
|
|||
[submodule "dependencies/wingetopt"]
|
||||
path = dependencies/wingetopt
|
||||
url = https://github.com/alex85k/wingetopt.git
|
||||
[submodule "dependencies/klib"]
|
||||
path = dependencies/klib
|
||||
url = https://github.com/attractivechaos/klib.git
|
||||
|
|
|
@ -23,6 +23,7 @@ include_directories(
|
|||
dependencies/libcsptr/include/
|
||||
dependencies/dyncall/dyncall/
|
||||
dependencies/valgrind/include/
|
||||
dependencies/klib/
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
|
@ -130,10 +131,12 @@ set(SOURCE_FILES
|
|||
src/io/event.h
|
||||
src/io/asprintf.c
|
||||
src/io/file.c
|
||||
src/io/output.c
|
||||
src/io/output.h
|
||||
src/io/tap.c
|
||||
src/io/xml.c
|
||||
src/log/logging.c
|
||||
src/log/tap.c
|
||||
src/log/normal.c
|
||||
src/log/xml.c
|
||||
src/string/i18n.c
|
||||
src/string/i18n.h
|
||||
src/entry/options.c
|
||||
|
@ -170,6 +173,7 @@ set(INTERFACE_FILES
|
|||
include/criterion/alloc.h
|
||||
include/criterion/parameterized.h
|
||||
include/criterion/redirect.h
|
||||
include/criterion/output.h
|
||||
)
|
||||
|
||||
# Generate the configure file
|
||||
|
|
1
dependencies/klib
vendored
Submodule
1
dependencies/klib
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit cdb7e9236dc47abf8da7ebd702cc6f7f21f0c502
|
14
doc/env.rst
14
doc/env.rst
|
@ -8,6 +8,7 @@ Command line arguments
|
|||
----------------------
|
||||
|
||||
* ``-h or --help``: Show a help message with the available switches.
|
||||
* ``-q or --quiet``: Disables all logging.
|
||||
* ``-v or --version``: Prints the version of criterion that has been
|
||||
linked against.
|
||||
* ``-l or --list``: Print all the tests in a list.
|
||||
|
@ -22,10 +23,17 @@ Command line arguments
|
|||
This is useful when tracking memory leaks with ``valgrind --tool=memcheck``.
|
||||
* ``-S or --short-filename``: The filenames are displayed in their short form.
|
||||
* ``--always-succeed``: The process shall exit with a status of ``0``.
|
||||
* ``--tap``: Enables the TAP (Test Anything Protocol) output format.
|
||||
* ``--xml``: Enables the JUnit4 XML output format.
|
||||
* ``--tap[=FILE]``: Writes a TAP (Test Anything Protocol) report to FILE.
|
||||
No file or ``"-"`` means ``stderr``. This option is equivalent to
|
||||
``--output=tap:FILE``.
|
||||
* ``--xml[=FILE]``: Writes JUnit4 XML report to FILE.
|
||||
No file or ``"-"`` means ``stderr``. This option is equivalent to
|
||||
``--output=xml:FILE``.
|
||||
* ``--verbose[=level]``: Makes the output verbose. When provided with an integer,
|
||||
sets the verbosity level to that integer.
|
||||
* ``-OPROVIDER:FILE or --output=PROVIDER:FILE``: Write a test report to FILE
|
||||
using the output provider named by PROVIDER. FILE may be a relative path, or
|
||||
``"-"`` to write to ``stderr``.
|
||||
|
||||
Shell Wildcard Pattern
|
||||
----------------------
|
||||
|
@ -71,8 +79,6 @@ Environment variables are alternatives to command line switches when set to 1.
|
|||
|
||||
* ``CRITERION_ALWAYS_SUCCEED``: Same as ``--always-succeed``.
|
||||
* ``CRITERION_NO_EARLY_EXIT``: Same as ``--no-early-exit``.
|
||||
* ``CRITERION_ENABLE_TAP``: Same as ``--tap``.
|
||||
* ``CRITERION_ENABLE_XML``: Same as ``--xml``.
|
||||
* ``CRITERION_FAIL_FAST``: Same as ``--fail-fast``.
|
||||
* ``CRITERION_USE_ASCII``: Same as ``--ascii``.
|
||||
* ``CRITERION_JOBS``: Same as ``--jobs``. Sets the number of jobs to
|
||||
|
|
|
@ -10,6 +10,7 @@ Criterion
|
|||
assert
|
||||
hooks
|
||||
env
|
||||
output
|
||||
parameterized
|
||||
theories
|
||||
internal
|
||||
|
|
|
@ -28,7 +28,7 @@ Field Type Description
|
|||
=================== ================================== ==============================================================
|
||||
logging_threshold enum criterion_logging_level The logging level
|
||||
------------------- ---------------------------------- --------------------------------------------------------------
|
||||
output_provider struct criterion_output_provider * The output provider (see below)
|
||||
logger struct criterion_logger * The logger (see below)
|
||||
------------------- ---------------------------------- --------------------------------------------------------------
|
||||
no_early_exit bool True iff the test worker should exit early
|
||||
------------------- ---------------------------------- --------------------------------------------------------------
|
||||
|
@ -75,15 +75,15 @@ Example main
|
|||
return result;
|
||||
}
|
||||
|
||||
Implementing your own output provider
|
||||
-------------------------------------
|
||||
Implementing your own logger
|
||||
----------------------------
|
||||
|
||||
In case you are not satisfied by the default output provider, you can implement
|
||||
yours. To do so, simply set the ``output_provider`` option to your custom
|
||||
output provider.
|
||||
In case you are not satisfied by the default logger, you can implement
|
||||
yours. To do so, simply set the ``logger`` option to your custom
|
||||
logger.
|
||||
|
||||
Each function contained in the structure is called during one of the standard
|
||||
phase of the criterion runner.
|
||||
|
||||
For more insight on how to implement this, see other existing output providers
|
||||
For more insight on how to implement this, see other existing loggers
|
||||
in ``src/log/``.
|
||||
|
|
44
doc/output.rst
Normal file
44
doc/output.rst
Normal file
|
@ -0,0 +1,44 @@
|
|||
Writing tests reports in a custom format
|
||||
========================================
|
||||
|
||||
Outputs providers are used to write tests reports in the format of your choice:
|
||||
for instance, TAP and XML reporting are implemented with output providers.
|
||||
|
||||
Adding a custom output provider
|
||||
-------------------------------
|
||||
|
||||
An output provider is a function with the following signature:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void func(FILE *out, struct criterion_global_stats *stats);
|
||||
|
||||
Once implemented, you then need to register it as an output provider:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
criterion_register_output_provider("provider name", func);
|
||||
|
||||
This needs to be done before the test runner stops, so you may want to register
|
||||
it either in a self-provided main, or in a PRE_ALL or POST_ALL report hook.
|
||||
|
||||
Writing to a file with an output provider
|
||||
-----------------------------------------
|
||||
|
||||
To tell criterion to write a report to a specific file using the output provider
|
||||
of your choice, you can either pass ``--output`` as a command-line
|
||||
parameter:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./my_tests --output="provider name":/path/to/file
|
||||
|
||||
Or, you can do so directly by calling ``criterion_add_output`` before the
|
||||
runner stops:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
criterion_add_output("provider name", "/path/to/file");
|
||||
|
||||
The path may be relative. If ``"-"`` is passed as a filename, the report will
|
||||
be written to ``stderr``.
|
|
@ -38,6 +38,8 @@ using std::va_list;
|
|||
enum criterion_logging_level {
|
||||
CRITERION_INFO = 1,
|
||||
CRITERION_IMPORTANT,
|
||||
|
||||
CRITERION_LOG_LEVEL_QUIET = 1 << 30,
|
||||
};
|
||||
|
||||
enum criterion_logging_prefix {
|
||||
|
@ -101,7 +103,7 @@ CR_API void criterion_log(enum criterion_logging_level level, const char *msg, .
|
|||
|
||||
# define criterion_perror(...) criterion_plog(CRITERION_IMPORTANT, CRITERION_PREFIX_ERR, __VA_ARGS__)
|
||||
|
||||
struct criterion_output_provider {
|
||||
struct criterion_logger {
|
||||
void (*log_pre_all )(struct criterion_test_set *set);
|
||||
void (*log_pre_suite )(struct criterion_suite_set *set);
|
||||
void (*log_pre_init )(struct criterion_test *test);
|
||||
|
@ -119,14 +121,10 @@ struct criterion_output_provider {
|
|||
void (*log_post_all )(struct criterion_global_stats *stats);
|
||||
};
|
||||
|
||||
extern struct criterion_output_provider normal_logging;
|
||||
extern struct criterion_output_provider tap_logging;
|
||||
extern struct criterion_output_provider xml_logging;
|
||||
extern struct criterion_logger normal_logging;
|
||||
|
||||
CR_END_C_API
|
||||
|
||||
#define CR_NORMAL_LOGGING (&normal_logging)
|
||||
#define CR_TAP_LOGGING (&tap_logging)
|
||||
#define CR_XML_LOGGING (&xml_logging)
|
||||
|
||||
#endif /* !CRITERION_LOGGING_H_ */
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
struct criterion_options {
|
||||
enum criterion_logging_level logging_threshold;
|
||||
struct criterion_output_provider *output_provider;
|
||||
struct criterion_logger *logger;
|
||||
bool no_early_exit;
|
||||
bool always_succeed;
|
||||
bool use_ascii;
|
||||
|
|
34
include/criterion/output.h
Normal file
34
include/criterion/output.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 CRITERION_OUTPUT_H_
|
||||
# define CRITERION_OUTPUT_H_
|
||||
|
||||
# include "stats.h"
|
||||
|
||||
typedef void criterion_reporter(FILE *stream, struct criterion_global_stats *);
|
||||
|
||||
int criterion_register_output_provider(const char *name, criterion_reporter *reporter);
|
||||
int criterion_add_output(const char *provider, const char *path);
|
||||
|
||||
#endif /* !CRITERION_OUTPUT_H_ */
|
|
@ -46,7 +46,7 @@ DECL_CALL_REPORT_HOOKS(POST_SUITE);
|
|||
DECL_CALL_REPORT_HOOKS(POST_ALL);
|
||||
|
||||
#define log(Type, ...) \
|
||||
log_(criterion_options.output_provider->log_ ## Type, __VA_ARGS__);
|
||||
log_(criterion_options.logger->log_ ## Type, __VA_ARGS__);
|
||||
#define log_(Log, ...) \
|
||||
(Log ? Log(__VA_ARGS__) : nothing());
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "wrappers/wrap.h"
|
||||
#include "string/i18n.h"
|
||||
#include "io/event.h"
|
||||
#include "io/output.h"
|
||||
#include "runner_coroutine.h"
|
||||
#include "stats.h"
|
||||
#include "runner.h"
|
||||
|
@ -347,6 +348,9 @@ struct criterion_test_set *criterion_initialize(void) {
|
|||
if (resume_child()) // (windows only) resume from the fork
|
||||
exit(0);
|
||||
|
||||
criterion_register_output_provider("tap", tap_report);
|
||||
criterion_register_output_provider("xml", xml_report);
|
||||
|
||||
return criterion_init();
|
||||
}
|
||||
|
||||
|
@ -356,6 +360,8 @@ void criterion_finalize(struct criterion_test_set *set) {
|
|||
#ifndef ENABLE_VALGRIND_ERRORS
|
||||
VALGRIND_ENABLE_ERROR_REPORTING;
|
||||
#endif
|
||||
|
||||
criterion_free_output();
|
||||
}
|
||||
|
||||
static void run_tests_async(struct criterion_test_set *set,
|
||||
|
@ -451,6 +457,8 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) {
|
|||
report(POST_ALL, stats);
|
||||
log(post_all, stats);
|
||||
|
||||
process_all_output(stats);
|
||||
|
||||
cleanup:
|
||||
sfree(g_worker_pipe);
|
||||
sfree(stats);
|
||||
|
|
|
@ -29,7 +29,10 @@
|
|||
#include "criterion/criterion.h"
|
||||
#include "criterion/options.h"
|
||||
#include "criterion/ordered-set.h"
|
||||
#include "compat/posix.h"
|
||||
#include "compat/strtok.h"
|
||||
#include "core/runner.h"
|
||||
#include "io/output.h"
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
|
||||
|
@ -52,6 +55,7 @@
|
|||
"usage: %s OPTIONS\n" \
|
||||
"options: \n" \
|
||||
" -h or --help: prints this message\n" \
|
||||
" -q or --quiet: disables all logging\n" \
|
||||
" -v or --version: prints the version of criterion " \
|
||||
"these tests have been linked against\n" \
|
||||
" -l or --list: prints all the tests in a list\n" \
|
||||
|
@ -62,13 +66,17 @@
|
|||
" -S or --short-filename: only display the base " \
|
||||
"name of the source file on a failure\n" \
|
||||
PATTERN_USAGE \
|
||||
" --tap: enables TAP formatting\n" \
|
||||
" --xml: enables XML formatting\n" \
|
||||
" --tap[=FILE]: writes TAP report in FILE " \
|
||||
"(no file or \"-\" means stderr)\n" \
|
||||
" --xml[=FILE]: writes XML report in FILE " \
|
||||
"(no file or \"-\" means stderr)\n" \
|
||||
" --always-succeed: always exit with 0\n" \
|
||||
" --no-early-exit: do not exit the test worker " \
|
||||
"prematurely after the test\n" \
|
||||
" --verbose[=level]: sets verbosity to level " \
|
||||
"(1 by default)\n"
|
||||
"(1 by default)\n" \
|
||||
" -OP:F or --output=PROVIDER=FILE: write test " \
|
||||
"report to FILE using the specified provider\n"
|
||||
|
||||
int print_usage(char *progname) {
|
||||
fprintf(stderr, USAGE, progname);
|
||||
|
@ -130,9 +138,10 @@ int atou(const char *str) {
|
|||
int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) {
|
||||
static struct option opts[] = {
|
||||
{"verbose", optional_argument, 0, 'b'},
|
||||
{"quiet", no_argument, 0, 'q'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"tap", no_argument, 0, 't'},
|
||||
{"xml", no_argument, 0, 'x'},
|
||||
{"tap", optional_argument, 0, 't'},
|
||||
{"xml", optional_argument, 0, 'x'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"list", no_argument, 0, 'l'},
|
||||
{"ascii", no_argument, 0, 'k'},
|
||||
|
@ -144,6 +153,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) {
|
|||
#endif
|
||||
{"always-succeed", no_argument, 0, 'y'},
|
||||
{"no-early-exit", no_argument, 0, 'z'},
|
||||
{"output", required_argument, 0, 'O'},
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -187,15 +197,13 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) {
|
|||
opt->pattern = env_pattern;
|
||||
#endif
|
||||
|
||||
bool use_tap = !strcmp("1", DEF(getenv("CRITERION_ENABLE_TAP"), "0"));
|
||||
bool use_xml = !strcmp("1", DEF(getenv("CRITERION_ENABLE_XML"), "0"));
|
||||
|
||||
opt->measure_time = !!strcmp("1", DEF(getenv("CRITERION_DISABLE_TIME_MEASUREMENTS"), "0"));
|
||||
|
||||
bool do_list_tests = false;
|
||||
bool do_print_version = false;
|
||||
bool do_print_usage = false;
|
||||
for (int c; (c = getopt_long(argc, argv, "hvlfj:S", opts, NULL)) != -1;) {
|
||||
bool quiet = false;
|
||||
for (int c; (c = getopt_long(argc, argv, "hvlfj:SqO:", opts, NULL)) != -1;) {
|
||||
switch (c) {
|
||||
case 'b': criterion_options.logging_threshold = atou(DEF(optarg, "1")); break;
|
||||
case 'y': criterion_options.always_succeed = true; break;
|
||||
|
@ -207,19 +215,33 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) {
|
|||
#ifdef HAVE_PCRE
|
||||
case 'p': criterion_options.pattern = optarg; break;
|
||||
#endif
|
||||
case 't': use_tap = true; break;
|
||||
case 'x': use_xml = true; break;
|
||||
case 'q': quiet = true; break;
|
||||
case 't': quiet = true; criterion_add_output("tap", DEF(optarg, "-")); break;
|
||||
case 'x': quiet = true; criterion_add_output("xml", DEF(optarg, "-")); break;
|
||||
case 'l': do_list_tests = true; break;
|
||||
case 'v': do_print_version = true; break;
|
||||
case 'h': do_print_usage = true; break;
|
||||
case 'O': {
|
||||
char *arg = strdup(optarg);
|
||||
char *buf = NULL;
|
||||
strtok_r(arg, ":", &buf);
|
||||
|
||||
char *path = strtok_r(NULL, ":", &buf);
|
||||
if (arg == NULL || path == NULL) {
|
||||
do_print_usage = true;
|
||||
break;
|
||||
}
|
||||
|
||||
quiet = true;
|
||||
criterion_add_output(arg, path);
|
||||
} break;
|
||||
case '?':
|
||||
default : do_print_usage = handle_unknown_arg; break;
|
||||
}
|
||||
}
|
||||
if (use_tap)
|
||||
criterion_options.output_provider = CR_TAP_LOGGING;
|
||||
else if (use_xml)
|
||||
criterion_options.output_provider = CR_XML_LOGGING;
|
||||
if (quiet)
|
||||
criterion_options.logging_threshold = CRITERION_LOG_LEVEL_QUIET;
|
||||
|
||||
if (do_print_usage)
|
||||
return print_usage(argv[0]);
|
||||
if (do_print_version)
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
|
||||
struct criterion_options criterion_options = {
|
||||
.logging_threshold = CRITERION_IMPORTANT,
|
||||
.output_provider = &normal_logging,
|
||||
.logger = &normal_logging,
|
||||
.measure_time = true,
|
||||
};
|
||||
|
|
89
src/io/output.c
Normal file
89
src/io/output.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <khash.h>
|
||||
#include <kvec.h>
|
||||
#include "criterion/output.h"
|
||||
|
||||
typedef kvec_t(const char *) str_vec;
|
||||
|
||||
KHASH_MAP_INIT_STR(ht_str, criterion_reporter*)
|
||||
KHASH_MAP_INIT_STR(ht_path, str_vec*)
|
||||
|
||||
static khash_t(ht_str) *reporters;
|
||||
static khash_t(ht_path) *outputs;
|
||||
|
||||
int criterion_register_output_provider(const char *name, criterion_reporter *reporter) {
|
||||
if (!reporters)
|
||||
reporters = kh_init(ht_str);
|
||||
|
||||
int absent;
|
||||
khint_t k = kh_put(ht_str, reporters, name, &absent);
|
||||
kh_value(reporters, k) = reporter;
|
||||
return absent;
|
||||
}
|
||||
|
||||
int criterion_add_output(const char *provider, const char *path) {
|
||||
if (!outputs)
|
||||
outputs = kh_init(ht_path);
|
||||
|
||||
khint_t k = kh_get(ht_path, outputs, provider);
|
||||
|
||||
if (k == kh_end(outputs)) {
|
||||
int absent;
|
||||
k = kh_put(ht_path, outputs, provider, &absent);
|
||||
if (absent == -1)
|
||||
return -1;
|
||||
|
||||
str_vec *vec = malloc(sizeof (str_vec));
|
||||
kv_init(*vec);
|
||||
kh_value(outputs, k) = vec;
|
||||
}
|
||||
str_vec *vec = kh_value(outputs, k);
|
||||
|
||||
kv_push(const char *, *vec, path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void criterion_free_output(void) {
|
||||
if (reporters)
|
||||
kh_destroy(ht_str, reporters);
|
||||
|
||||
if (outputs) {
|
||||
for (khint_t k = kh_begin(outputs); k != kh_end(outputs); ++k) {
|
||||
if (!kh_exist(outputs, k))
|
||||
continue;
|
||||
str_vec *vec = kh_value(outputs, k);
|
||||
kv_destroy(*vec);
|
||||
free(vec);
|
||||
}
|
||||
kh_destroy(ht_path, outputs);
|
||||
}
|
||||
}
|
||||
|
||||
void process_all_output(struct criterion_global_stats *stats) {
|
||||
if (!outputs || !reporters)
|
||||
return;
|
||||
|
||||
for (khint_t k = kh_begin(reporters); k != kh_end(reporters); ++k) {
|
||||
if (!kh_exist(reporters, k))
|
||||
continue;
|
||||
|
||||
criterion_reporter *report = kh_value(reporters, k);
|
||||
khint_t ko = kh_get(ht_path, outputs, kh_key(reporters, k));
|
||||
if (ko == kh_end(outputs))
|
||||
continue;
|
||||
|
||||
str_vec *vec = kh_value(outputs, ko);
|
||||
for (size_t i = 0; i < kv_size(*vec); ++i) {
|
||||
const char *path = kv_A(*vec, i);
|
||||
|
||||
FILE *f;
|
||||
if (path[0] == '-' && !path[1])
|
||||
f = stderr;
|
||||
else
|
||||
f = fopen(path, "w");
|
||||
|
||||
report(f, stats);
|
||||
}
|
||||
}
|
||||
}
|
35
src/io/output.h
Normal file
35
src/io/output.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 OUTPUT_H_
|
||||
# define OUTPUT_H_
|
||||
|
||||
# include "criterion/output.h"
|
||||
|
||||
void process_all_output(struct criterion_global_stats *stats);
|
||||
void criterion_free_output(void);
|
||||
|
||||
void tap_report(FILE *f, struct criterion_global_stats *stats);
|
||||
void xml_report(FILE *f, struct criterion_global_stats *stats);
|
||||
|
||||
#endif /* !OUTPUT_H_ */
|
|
@ -26,24 +26,22 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "criterion/stats.h"
|
||||
#include "criterion/logging.h"
|
||||
#include "criterion/options.h"
|
||||
#include "criterion/ordered-set.h"
|
||||
#include "compat/posix.h"
|
||||
#include "compat/strtok.h"
|
||||
#include "compat/time.h"
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
|
||||
static void print_prelude(struct criterion_global_stats *stats) {
|
||||
criterion_important("TAP version 13\n1.."
|
||||
static void print_prelude(FILE *f, struct criterion_global_stats *stats) {
|
||||
fprintf(f, "TAP version 13\n1.."
|
||||
CR_SIZE_T_FORMAT
|
||||
"\n", stats->nb_tests);
|
||||
criterion_important("# Criterion v%s\n", VERSION);
|
||||
fprintf(f, "# Criterion v%s\n", VERSION);
|
||||
}
|
||||
|
||||
static void print_pre_suite(struct criterion_suite_stats *stats) {
|
||||
criterion_important("\n# Running "
|
||||
static void print_pre_suite(FILE *f, struct criterion_suite_stats *stats) {
|
||||
fprintf(f, "\n# Running "
|
||||
CR_SIZE_T_FORMAT
|
||||
" tests from %s\n",
|
||||
stats->nb_tests,
|
||||
|
@ -54,10 +52,10 @@ static INLINE bool is_disabled(struct criterion_test *t, struct criterion_suite
|
|||
return t->data->disabled || (s->data && s->data->disabled);
|
||||
}
|
||||
|
||||
static void print_test_normal(struct criterion_test_stats *stats) {
|
||||
static void print_test_normal(FILE *f, struct criterion_test_stats *stats) {
|
||||
const char *format = can_measure_time() ? "%s - %s::%s %s (%3.2fs)\n"
|
||||
: "%s - %s::%s %s\n";
|
||||
criterion_important(format,
|
||||
fprintf(f, format,
|
||||
stats->failed ? "not ok" : "ok",
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
|
@ -69,64 +67,61 @@ static void print_test_normal(struct criterion_test_stats *stats) {
|
|||
char *saveptr = NULL;
|
||||
char *line = strtok_r(dup, "\n", &saveptr);
|
||||
bool sf = criterion_options.short_filename;
|
||||
criterion_important(" %s:%u: Assertion failed: %s\n",
|
||||
fprintf(f, " %s:%u: Assertion failed: %s\n",
|
||||
sf ? basename_compat(asrt->file) : asrt->file,
|
||||
asrt->line,
|
||||
line);
|
||||
|
||||
while ((line = strtok_r(NULL, "\n", &saveptr)))
|
||||
criterion_important(" %s\n", line);
|
||||
fprintf(f, " %s\n", line);
|
||||
free(dup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void print_test_crashed(struct criterion_test_stats *stats) {
|
||||
static void print_test_crashed(FILE *f, struct criterion_test_stats *stats) {
|
||||
bool sf = criterion_options.short_filename;
|
||||
criterion_important("not ok - %s::%s unexpected signal after %s:%u\n",
|
||||
fprintf(f, "not ok - %s::%s unexpected signal after %s:%u\n",
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
sf ? basename_compat(stats->file) : stats->file,
|
||||
stats->progress);
|
||||
}
|
||||
|
||||
static void print_test_timeout(struct criterion_test_stats *stats) {
|
||||
criterion_important("not ok - %s::%s timed out (%3.2fs)\n",
|
||||
static void print_test_timeout(FILE *f, struct criterion_test_stats *stats) {
|
||||
fprintf(f, "not ok - %s::%s timed out (%3.2fs)\n",
|
||||
stats->test->category,
|
||||
stats->test->name,
|
||||
stats->elapsed_time);
|
||||
}
|
||||
|
||||
static void print_test(struct criterion_test_stats *ts,
|
||||
static void print_test(FILE *f,
|
||||
struct criterion_test_stats *ts,
|
||||
struct criterion_suite_stats *ss) {
|
||||
|
||||
if (is_disabled(ts->test, ss->suite)) {
|
||||
criterion_important("ok - %s::%s %s # SKIP %s is disabled\n",
|
||||
fprintf(f, "ok - %s::%s %s # SKIP %s is disabled\n",
|
||||
ts->test->category,
|
||||
ts->test->name,
|
||||
DEF(ts->test->data->description, ""),
|
||||
ts->test->data->disabled ? "test" : "suite");
|
||||
} else if (ts->crashed) {
|
||||
print_test_crashed(ts);
|
||||
print_test_crashed(f, ts);
|
||||
} else if (ts->timed_out) {
|
||||
print_test_timeout(ts);
|
||||
print_test_timeout(f, ts);
|
||||
} else {
|
||||
print_test_normal(ts);
|
||||
print_test_normal(f, ts);
|
||||
}
|
||||
}
|
||||
|
||||
void tap_log_post_all(struct criterion_global_stats *stats) {
|
||||
print_prelude(stats);
|
||||
void tap_report(FILE *f, struct criterion_global_stats *stats) {
|
||||
print_prelude(f, stats);
|
||||
|
||||
for (struct criterion_suite_stats *ss = stats->suites; ss; ss = ss->next) {
|
||||
print_pre_suite(ss);
|
||||
print_pre_suite(f, ss);
|
||||
|
||||
for (struct criterion_test_stats *ts = ss->tests; ts; ts = ts->next) {
|
||||
print_test(ts, ss);
|
||||
print_test(f, ts, ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct criterion_output_provider tap_logging = {
|
||||
.log_post_all = tap_log_post_all,
|
||||
};
|
|
@ -112,24 +112,25 @@ const char *get_status_string(struct criterion_test_stats *ts,
|
|||
return status;
|
||||
}
|
||||
|
||||
static void print_test(struct criterion_test_stats *ts,
|
||||
static void print_test(FILE *f,
|
||||
struct criterion_test_stats *ts,
|
||||
struct criterion_suite_stats *ss) {
|
||||
|
||||
criterion_important(XML_TEST_TEMPLATE_BEGIN,
|
||||
fprintf(f, XML_TEST_TEMPLATE_BEGIN,
|
||||
ts->test->name,
|
||||
(size_t) (ts->passed_asserts + ts->failed_asserts),
|
||||
get_status_string(ts, ss)
|
||||
);
|
||||
|
||||
if (is_disabled(ts->test, ss->suite)) {
|
||||
criterion_important(XML_TEST_SKIPPED);
|
||||
fprintf(f, XML_TEST_SKIPPED);
|
||||
} else if (ts->crashed) {
|
||||
criterion_important(XML_CRASH_MSG_ENTRY);
|
||||
fprintf(f, XML_CRASH_MSG_ENTRY);
|
||||
} else if (ts->timed_out) {
|
||||
criterion_important(XML_TIMEOUT_MSG_ENTRY);
|
||||
fprintf(f, XML_TIMEOUT_MSG_ENTRY);
|
||||
} else {
|
||||
if (ts->failed) {
|
||||
criterion_important(XML_TEST_FAILED_TEMPLATE_BEGIN, ts->failed_asserts);
|
||||
fprintf(f, XML_TEST_FAILED_TEMPLATE_BEGIN, ts->failed_asserts);
|
||||
for (struct criterion_assert_stats *asrt = ts->asserts; asrt; asrt = asrt->next) {
|
||||
if (!asrt->passed) {
|
||||
bool sf = criterion_options.short_filename;
|
||||
|
@ -137,26 +138,26 @@ static void print_test(struct criterion_test_stats *ts,
|
|||
char *saveptr = NULL;
|
||||
char *line = strtok_r(dup, "\n", &saveptr);
|
||||
|
||||
criterion_important(XML_FAILURE_MSG_ENTRY,
|
||||
fprintf(f, XML_FAILURE_MSG_ENTRY,
|
||||
sf ? basename_compat(asrt->file) : asrt->file,
|
||||
asrt->line,
|
||||
line
|
||||
);
|
||||
|
||||
while ((line = strtok_r(NULL, "\n", &saveptr)))
|
||||
criterion_important(" %s" LF, line);
|
||||
fprintf(f, " %s" LF, line);
|
||||
free(dup);
|
||||
}
|
||||
}
|
||||
criterion_important(XML_TEST_FAILED_TEMPLATE_END);
|
||||
fprintf(f, XML_TEST_FAILED_TEMPLATE_END);
|
||||
}
|
||||
}
|
||||
|
||||
criterion_important(XML_TEST_TEMPLATE_END);
|
||||
fprintf(f, XML_TEST_TEMPLATE_END);
|
||||
}
|
||||
|
||||
void xml_log_post_all(struct criterion_global_stats *stats) {
|
||||
criterion_important(XML_BASE_TEMPLATE_BEGIN,
|
||||
void xml_report(FILE *f, struct criterion_global_stats *stats) {
|
||||
fprintf(f, XML_BASE_TEMPLATE_BEGIN,
|
||||
stats->nb_tests,
|
||||
stats->tests_failed,
|
||||
stats->tests_crashed,
|
||||
|
@ -165,7 +166,7 @@ void xml_log_post_all(struct criterion_global_stats *stats) {
|
|||
|
||||
for (struct criterion_suite_stats *ss = stats->suites; ss; ss = ss->next) {
|
||||
|
||||
criterion_important(XML_TESTSUITE_TEMPLATE_BEGIN,
|
||||
fprintf(f, XML_TESTSUITE_TEMPLATE_BEGIN,
|
||||
ss->suite->name,
|
||||
ss->nb_tests,
|
||||
ss->tests_failed,
|
||||
|
@ -175,15 +176,11 @@ void xml_log_post_all(struct criterion_global_stats *stats) {
|
|||
);
|
||||
|
||||
for (struct criterion_test_stats *ts = ss->tests; ts; ts = ts->next) {
|
||||
print_test(ts, ss);
|
||||
print_test(f, ts, ss);
|
||||
}
|
||||
|
||||
criterion_important(XML_TESTSUITE_TEMPLATE_END);
|
||||
fprintf(f, XML_TESTSUITE_TEMPLATE_END);
|
||||
}
|
||||
|
||||
criterion_important(XML_BASE_TEMPLATE_END);
|
||||
fprintf(f, XML_BASE_TEMPLATE_END);
|
||||
}
|
||||
|
||||
struct criterion_output_provider xml_logging = {
|
||||
.log_post_all = xml_log_post_all,
|
||||
};
|
|
@ -233,7 +233,7 @@ void normal_log_test_abort(CR_UNUSED struct criterion_test_stats *stats, const c
|
|||
free(dup);
|
||||
}
|
||||
|
||||
struct criterion_output_provider normal_logging = {
|
||||
struct criterion_logger normal_logging = {
|
||||
.log_pre_all = normal_log_pre_all,
|
||||
.log_pre_init = normal_log_pre_init,
|
||||
.log_pre_suite = normal_log_pre_suite,
|
||||
|
|
Loading…
Add table
Reference in a new issue