Update clar from:
- 1516124 (Merge pull request #97 from pks-t/pks-whitespace-fixes, 2024-08-15).
To:
- 206accb (Merge pull request #108 from pks-t/pks-uclibc-without-wchar, 2024-10-21)
This update includes a bunch of fixes and improvements that we have
discussed in Git when initial support for clar was merged:
- There is a ".editorconfig" file now.
- Compatibility with Windows has been improved so that the clar
compiles on this platform without an issue. This has been tested
with Cygwin, MinGW and Microsoft Visual Studio.
- clar now uses CMake. This does not impact us at all as we wire up
the clar into our own build infrastructure anyway. This conversion
was done such that we can easily run CI jobs against Windows.
- Allocation failures are now checked for consistently.
- We now define feature test macros in "clar.c", which fixes
compilation on some platforms that didn't previously pull in
non-standard functions like lstat(3p) or strdup(3p). This was
reported by a user of OpenSUSE Leap.
- We stop using `struct timezone`, which is undefined behaviour
nowadays and results in a compilation error on some platforms.
- We now use the combination of mktemp(3) and mkdir(3) on SunOS, same
as we do on NonStop.
- We now support uClibc without support for <wchar.h>.
The most important bits here are the improved platform compatibility
with Windows, OpenSUSE, SunOS and uClibc.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
140 lines
3.4 KiB
C
140 lines
3.4 KiB
C
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
|
|
static int clar_summary_close_tag(
|
|
struct clar_summary *summary, const char *tag, int indent)
|
|
{
|
|
const char *indt;
|
|
|
|
if (indent == 0) indt = "";
|
|
else if (indent == 1) indt = "\t";
|
|
else indt = "\t\t";
|
|
|
|
return fprintf(summary->fp, "%s</%s>\n", indt, tag);
|
|
}
|
|
|
|
static int clar_summary_testsuites(struct clar_summary *summary)
|
|
{
|
|
return fprintf(summary->fp, "<testsuites>\n");
|
|
}
|
|
|
|
static int clar_summary_testsuite(struct clar_summary *summary,
|
|
int idn, const char *name, time_t timestamp,
|
|
int test_count, int fail_count, int error_count)
|
|
{
|
|
struct tm *tm = localtime(×tamp);
|
|
char iso_dt[20];
|
|
|
|
if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", tm) == 0)
|
|
return -1;
|
|
|
|
return fprintf(summary->fp, "\t<testsuite"
|
|
" id=\"%d\""
|
|
" name=\"%s\""
|
|
" hostname=\"localhost\""
|
|
" timestamp=\"%s\""
|
|
" tests=\"%d\""
|
|
" failures=\"%d\""
|
|
" errors=\"%d\">\n",
|
|
idn, name, iso_dt, test_count, fail_count, error_count);
|
|
}
|
|
|
|
static int clar_summary_testcase(struct clar_summary *summary,
|
|
const char *name, const char *classname, double elapsed)
|
|
{
|
|
return fprintf(summary->fp,
|
|
"\t\t<testcase name=\"%s\" classname=\"%s\" time=\"%.2f\">\n",
|
|
name, classname, elapsed);
|
|
}
|
|
|
|
static int clar_summary_failure(struct clar_summary *summary,
|
|
const char *type, const char *message, const char *desc)
|
|
{
|
|
return fprintf(summary->fp,
|
|
"\t\t\t<failure type=\"%s\"><![CDATA[%s\n%s]]></failure>\n",
|
|
type, message, desc);
|
|
}
|
|
|
|
static int clar_summary_skipped(struct clar_summary *summary)
|
|
{
|
|
return fprintf(summary->fp, "\t\t\t<skipped />\n");
|
|
}
|
|
|
|
struct clar_summary *clar_summary_init(const char *filename)
|
|
{
|
|
struct clar_summary *summary;
|
|
FILE *fp;
|
|
|
|
if ((fp = fopen(filename, "w")) == NULL)
|
|
clar_abort("Failed to open the summary file '%s': %s.\n",
|
|
filename, strerror(errno));
|
|
|
|
if ((summary = malloc(sizeof(struct clar_summary))) == NULL)
|
|
clar_abort("Failed to allocate summary.\n");
|
|
|
|
summary->filename = filename;
|
|
summary->fp = fp;
|
|
|
|
return summary;
|
|
}
|
|
|
|
int clar_summary_shutdown(struct clar_summary *summary)
|
|
{
|
|
struct clar_report *report;
|
|
const char *last_suite = NULL;
|
|
|
|
if (clar_summary_testsuites(summary) < 0)
|
|
goto on_error;
|
|
|
|
report = _clar.reports;
|
|
while (report != NULL) {
|
|
struct clar_error *error = report->errors;
|
|
|
|
if (last_suite == NULL || strcmp(last_suite, report->suite) != 0) {
|
|
if (clar_summary_testsuite(summary, 0, report->suite,
|
|
report->start, _clar.tests_ran, _clar.total_errors, 0) < 0)
|
|
goto on_error;
|
|
}
|
|
|
|
last_suite = report->suite;
|
|
|
|
clar_summary_testcase(summary, report->test, report->suite, report->elapsed);
|
|
|
|
while (error != NULL) {
|
|
if (clar_summary_failure(summary, "assert",
|
|
error->error_msg, error->description) < 0)
|
|
goto on_error;
|
|
|
|
error = error->next;
|
|
}
|
|
|
|
if (report->status == CL_TEST_SKIP)
|
|
clar_summary_skipped(summary);
|
|
|
|
if (clar_summary_close_tag(summary, "testcase", 2) < 0)
|
|
goto on_error;
|
|
|
|
report = report->next;
|
|
|
|
if (!report || strcmp(last_suite, report->suite) != 0) {
|
|
if (clar_summary_close_tag(summary, "testsuite", 1) < 0)
|
|
goto on_error;
|
|
}
|
|
}
|
|
|
|
if (clar_summary_close_tag(summary, "testsuites", 0) < 0 ||
|
|
fclose(summary->fp) != 0)
|
|
goto on_error;
|
|
|
|
printf("written summary file to %s\n", summary->filename);
|
|
|
|
free(summary);
|
|
return 0;
|
|
|
|
on_error:
|
|
fclose(summary->fp);
|
|
free(summary);
|
|
return -1;
|
|
}
|