Merge branch 'features/xml-reporting' into bleeding

This commit is contained in:
Snaipe 2015-10-06 15:52:11 +02:00
commit 5fb367c338
12 changed files with 276 additions and 49 deletions

View file

@ -129,6 +129,7 @@ set(SOURCE_FILES
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

View file

@ -23,6 +23,7 @@ Command line arguments
* ``-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.
* ``--verbose[=level]``: Makes the output verbose. When provided with an integer,
sets the verbosity level to that integer.
@ -71,6 +72,7 @@ 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

View file

@ -121,10 +121,12 @@ struct criterion_output_provider {
extern struct criterion_output_provider normal_logging;
extern struct criterion_output_provider tap_logging;
extern struct criterion_output_provider xml_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_ */

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: criterion 2.0.0\n"
"Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n"
"POT-Creation-Date: 2015-10-01 23:09+0200\n"
"POT-Creation-Date: 2015-10-05 16:20+0200\n"
"PO-Revision-Date: 2015-04-03 17:58+0200\n"
"Last-Translator: <franklinmathieu@gmail.com>\n"
"Language-Team: French\n"
@ -18,70 +18,70 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: src/log/normal.c:50
#: src/log/normal.c:41
#, c-format
msgid "Criterion v%s\n"
msgstr "Criterion v%s\n"
#: src/log/normal.c:51
#: src/log/normal.c:42
#, c-format
msgid " %s\n"
msgstr " %s\n"
#: src/log/normal.c:54 src/log/normal.c:56
#: src/log/normal.c:45 src/log/normal.c:47
#, c-format
msgid "%1$s::%2$s\n"
msgstr "%1$s::%2$s\n"
#: src/log/normal.c:55
#: src/log/normal.c:46
#, fuzzy, c-format
msgid "%1$s::%2$s: (%3$3.2fs)\n"
msgstr "%1$s::%2$s: (%3$3.2fs)\n"
#: src/log/normal.c:57
#: src/log/normal.c:48
#, c-format
msgid "%1$s::%2$s: Test is disabled\n"
msgstr "%1$s::%2$s: Le test est désactivé\n"
#: src/log/normal.c:58
#: src/log/normal.c:49
#, c-format
msgid "%1$s::%2$s: Suite is disabled\n"
msgstr "%1$s::%2$s: La suite est désactivée\n"
#: src/log/normal.c:59
#: src/log/normal.c:50
#, c-format
msgid "%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n"
msgstr "%1$s%2$s%3$s:%4$s%5$d%6$s: Échec d'assertion: %7$s\n"
#: src/log/normal.c:60
#: src/log/normal.c:51
#, fuzzy, c-format
msgid " Theory %1$s::%2$s failed with the following parameters: (%3$s)\n"
msgstr ""
" La théorie %1$s::%2$s a échoué avec les paramètres suivants: (%3$s)\n"
#: src/log/normal.c:61
#: src/log/normal.c:52
#, fuzzy, c-format
msgid "%1$s::%2$s: Timed out. (%3$3.2fs)\n"
msgstr "%1$s::%2$s: Délai expiré. (%3$3.2fs)\n"
#: src/log/normal.c:62
#: src/log/normal.c:53
#, c-format
msgid "%1$s%2$s%3$s:%4$s%5$u%6$s: Unexpected signal caught below this line!\n"
msgstr ""
"%1$s%2$s%3$s:%4$s%5$u%6$s: Un signal inattendu a été reçu après cette "
"ligne!\n"
#: src/log/normal.c:63
#: src/log/normal.c:54
#, c-format
msgid "%1$s::%2$s: CRASH!\n"
msgstr "%1$s::%2$s: PLANTAGE!\n"
#: src/log/normal.c:64
#: src/log/normal.c:55
#, fuzzy, c-format
msgid "%1$s::%2$s: %3$s\n"
msgstr "%1$s::%2$s: (%3$3.2fs)\n"
#: src/log/normal.c:65
#: src/log/normal.c:56
#, fuzzy, c-format
msgid ""
"%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown."
@ -90,7 +90,7 @@ msgstr ""
"%1$sAttention! Le test `%2$s::%3$s` a planté pendant son initialisation ou "
"sa finalisation.%4$s\n"
#: src/log/normal.c:66
#: src/log/normal.c:57
#, fuzzy, c-format
msgid ""
"%1$sWarning! The test `%2$s::%3$s` exited during its setup or teardown.%4$s\n"
@ -98,14 +98,14 @@ msgstr ""
"%1$sAttention! Le test `%2$s::%3$s` a quitté pendant son initialisation ou "
"sa finalisation.%4$s\n"
#: src/log/normal.c:67
#: src/log/normal.c:58
#, c-format
msgid "Running %1$s%2$lu%3$s test from %4$s%5$s%6$s:\n"
msgid_plural "Running %1$s%2$lu%3$s tests from %4$s%5$s%6$s:\n"
msgstr[0] "Lancement de %1$s%2$lu%3$s test dans %4$s%5$s%6$s:\n"
msgstr[1] "Lancement de %1$s%2$lu%3$s tests dans %4$s%5$s%6$s:\n"
#: src/log/normal.c:69
#: src/log/normal.c:60
#, c-format
msgid ""
"%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s"
@ -114,7 +114,7 @@ msgstr ""
"%1$sSynthèse: Testés: %2$s%3$lu%4$s | Validés: %5$s%6$lu%7$s | Échoués: %8$s"
"%9$lu%10$s | Plantages: %11$s%12$lu%13$s %14$s\n"
#: src/log/normal.c:85
#: src/log/normal.c:76
#, fuzzy, c-format
msgid "%s::%s: %s\n"
msgstr "%1$s::%2$s: (%3$3.2fs)\n"

View file

@ -34,6 +34,7 @@ set(SAMPLES
set(SCRIPTS
tap_test
xml_test
early_exit
verbose
list

7
samples/tests/xml_test.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/sh
./simple.c.bin --xml --always-succeed
./signal.c.bin --xml --always-succeed
./asserts.c.bin --xml --always-succeed
./more-suites.c.bin --xml --always-succeed
./long-messages.c.bin --xml --always-succeed
./description.c.bin --xml --always-succeed

View file

@ -24,9 +24,9 @@
#ifndef POSIX_COMPAT_H_
# define POSIX_COMPAT_H_
#if defined(_WIN32) && !defined(__CYGWIN__)
# define VANILLA_WIN32
#endif
# if defined(_WIN32) && !defined(__CYGWIN__)
# define VANILLA_WIN32
# endif
# if defined(BSD) \
|| defined(__FreeBSD__) \
@ -45,6 +45,7 @@
# define off64_t _off64_t
# endif
# include <stdio.h>
# include <string.h>
# if defined(__MINGW32__) || defined(__MINGW64__)
# undef off_t
# undef off64_t
@ -62,6 +63,7 @@
# define SIGPROF 27
# define CR_EXCEPTION_TIMEOUT 0xC0001042
# else
# include <sys/wait.h>
# endif

43
src/compat/strtok.h Normal file
View file

@ -0,0 +1,43 @@
/*
* 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 COMPAT_STRTOK_H_
# define COMPAT_STRTOK_H_
# include "config.h"
# ifdef VANILLA_WIN32
# if HAVE_STRTOK_S
# define strtok_r strtok_s
# else
static CR_INLINE char *strtok_r(char *str, const char *delim, CR_UNUSED char **saveptr) {
return strtok(str, delim);
}
# endif
# ifdef _MSC_VER
# define strdup _strdup
# endif
# endif
#endif /* !COMPAT_STRTOK_H_ */

View file

@ -62,6 +62,7 @@
"name of the source file on a failure\n" \
PATTERN_USAGE \
" --tap: enables TAP formatting\n" \
" --xml: enables XML formatting\n" \
" --always-succeed: always exit with 0\n" \
" --no-early-exit: do not exit the test worker " \
"prematurely after the test\n" \
@ -130,6 +131,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) {
{"verbose", optional_argument, 0, 'b'},
{"version", no_argument, 0, 'v'},
{"tap", no_argument, 0, 't'},
{"xml", no_argument, 0, 'x'},
{"help", no_argument, 0, 'h'},
{"list", no_argument, 0, 'l'},
{"ascii", no_argument, 0, 'k'},
@ -182,6 +184,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) {
#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"));
@ -201,6 +204,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) {
case 'p': criterion_options.pattern = optarg; break;
#endif
case 't': use_tap = true; break;
case 'x': use_xml = true; break;
case 'l': do_list_tests = true; break;
case 'v': do_print_version = true; break;
case 'h': do_print_usage = true; break;
@ -209,6 +213,8 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) {
}
if (use_tap)
criterion_options.output_provider = CR_TAP_LOGGING;
else if (use_xml)
criterion_options.output_provider = CR_XML_LOGGING;
if (do_print_usage)
return print_usage(argv[0]);
if (do_print_version)

View file

@ -31,25 +31,12 @@
#include "criterion/options.h"
#include "criterion/ordered-set.h"
#include "compat/posix.h"
#include "compat/strtok.h"
#include "compat/time.h"
#include "string/i18n.h"
#include "config.h"
#include "common.h"
#ifdef VANILLA_WIN32
# if HAVE_STRTOK_S
# define strtok_r strtok_s
# else
static char *strtok_r(char *str, const char *delim, CR_UNUSED char **saveptr) {
return strtok(str, delim);
}
# endif
#endif
#ifdef _MSC_VER
# define strdup _strdup
#endif
typedef const char *const msg_t;
static msg_t msg_pre_all = N_("Criterion v%s\n");

View file

@ -30,24 +30,11 @@
#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"
#ifdef VANILLA_WIN32
# if HAVE_STRTOK_S
# define strtok_r strtok_s
# else
static char *strtok_r(char *str, const char *delim, CR_UNUSED char **saveptr) {
return strtok(str, delim);
}
# endif
#endif
#ifdef _MSC_VER
# define strdup _strdup
#endif
static void print_prelude(struct criterion_global_stats *stats) {
criterion_important("TAP version 13\n1.."
CR_SIZE_T_FORMAT

189
src/log/xml.c Normal file
View file

@ -0,0 +1,189 @@
/*
* 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 <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"
#define TESTSUITES_PROPERTIES \
"name=\"Criterion Tests\" " \
"tests=\"" CR_SIZE_T_FORMAT "\" " \
"failures=\"" CR_SIZE_T_FORMAT "\" " \
"errors=\"" CR_SIZE_T_FORMAT "\" " \
"disabled=\"" CR_SIZE_T_FORMAT "\""
#define XML_BASE_TEMPLATE_BEGIN \
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
"<!-- Tests compiled with Criterion v" VERSION " -->\n" \
"<testsuites " TESTSUITES_PROPERTIES ">\n" \
#define XML_BASE_TEMPLATE_END \
"</testsuites>\n"
#define TESTSUITE_PROPERTIES \
"name=\"%s\" " \
"tests=\"" CR_SIZE_T_FORMAT "\" " \
"failures=\"" CR_SIZE_T_FORMAT "\" " \
"errors=\"" CR_SIZE_T_FORMAT "\" " \
"disabled=\"" CR_SIZE_T_FORMAT "\" " \
"skipped=\"" CR_SIZE_T_FORMAT "\""
#define XML_TESTSUITE_TEMPLATE_BEGIN \
" <testsuite " TESTSUITE_PROPERTIES ">\n"
#define XML_TESTSUITE_TEMPLATE_END \
" </testsuite>\n"
#define TEST_PROPERTIES \
"name=\"%s\" " \
"assertions=\"" CR_SIZE_T_FORMAT "\" " \
"status=\"%s\""
#define XML_TEST_TEMPLATE_BEGIN \
" <testcase " TEST_PROPERTIES ">\n" \
#define XML_TEST_TEMPLATE_END \
" </testcase>\n"
#define XML_TEST_SKIPPED " <skipped/>\n"
#define LF "&#10;"
#define XML_FAILURE_MSG_ENTRY \
"%s:%u: %s" LF
#define XML_TEST_FAILED_TEMPLATE_BEGIN \
" <failure type=\"assert\" message=\"%d assertion(s) failed.\">"
#define XML_TEST_FAILED_TEMPLATE_END \
"</failure>\n"
#define XML_CRASH_MSG_ENTRY \
" <error type=\"crash\" message=\"The test crashed.\" />"
#define XML_TIMEOUT_MSG_ENTRY \
" <error type=\"timeout\" message=\"The test timed out.\" />"
static INLINE bool is_disabled(struct criterion_test *t, struct criterion_suite *s) {
return t->data->disabled || (s->data && s->data->disabled);
}
static CR_INLINE
const char *get_status_string(struct criterion_test_stats *ts,
struct criterion_suite_stats *ss) {
const char *status = "PASSED";
if (ts->crashed || ts->timed_out)
status = "ERRORED";
else if (ts->failed)
status = "FAILED";
else if (is_disabled(ts->test, ss->suite))
status = "SKIPPED";
return status;
}
static void print_test(struct criterion_test_stats *ts,
struct criterion_suite_stats *ss) {
criterion_important(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);
} else if (ts->crashed) {
criterion_important(XML_CRASH_MSG_ENTRY);
} else if (ts->timed_out) {
criterion_important(XML_TIMEOUT_MSG_ENTRY);
} else {
if (ts->failed) {
criterion_important(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;
char *dup = strdup(*asrt->message ? asrt->message : "");
char *saveptr = NULL;
char *line = strtok_r(dup, "\n", &saveptr);
criterion_important(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);
free(dup);
}
}
criterion_important(XML_TEST_FAILED_TEMPLATE_END);
}
}
criterion_important(XML_TEST_TEMPLATE_END);
}
void xml_log_post_all(struct criterion_global_stats *stats) {
criterion_important(XML_BASE_TEMPLATE_BEGIN,
stats->nb_tests,
stats->tests_failed,
stats->tests_crashed,
stats->tests_skipped
);
for (struct criterion_suite_stats *ss = stats->suites; ss; ss = ss->next) {
criterion_important(XML_TESTSUITE_TEMPLATE_BEGIN,
ss->suite->name,
ss->nb_tests,
ss->tests_failed,
ss->tests_crashed,
ss->tests_skipped,
ss->tests_skipped
);
for (struct criterion_test_stats *ts = ss->tests; ts; ts = ts->next) {
print_test(ts, ss);
}
criterion_important(XML_TESTSUITE_TEMPLATE_END);
}
criterion_important(XML_BASE_TEMPLATE_END);
}
struct criterion_output_provider xml_logging = {
.log_post_all = xml_log_post_all,
};