Formatted test results across multiple lines in the same way as in Go. Also prettyprinted diffs in initmain.c.

This commit is contained in:
Pietro Gagliardi 2019-05-04 21:13:47 -04:00
parent 4c097f93f7
commit 98093ed46e
3 changed files with 99 additions and 16 deletions

View File

@ -31,7 +31,8 @@ testingTestBefore(Init)
if (ret != 0)
testingTErrorf(t, "uiInit() with non-NULL options succeeded with return value %d; expected failure", err);
if (strcmp(err.Message, errInvalidOptions) != 0)
testingTErrorf(t, "uiInit() with non-NULL options returned bad error message: got %s, want %s", err.Message, errInvalidOptions);
diff(t, "uiInit() with non-NULL options returned bad error message", "%s",
err.Message, errInvalidOptions);
memset(&err, 0, sizeof (uiInitError));
err.Size = sizeof (uiInitError);
@ -45,7 +46,8 @@ testingTestBefore(Init)
if (ret != 0)
testingTErrorf(t, "uiInit() after a previous successful call succeeded with return value %d; expected failure", ret);
if (strcmp(err.Message, errAlreadyInitialized) != 0)
testingTErrorf(t, "uiInit() after a previous successful call returned bad error message: got %s, want %s", err.Message, errAlreadyInitialized);
diff(t, "uiInit() after a previous successful call returned bad error message", "%s",
err.Message, errAlreadyInitialized);
}
struct testParams {
@ -70,7 +72,8 @@ testingTest(QueueMain)
uiQueueMain(queued, &p);
timeout_uiMain(t, 5 * timerSecond);
if (p.flag != 1)
testingTErrorf(t, "uiQueueMain() didn't set flag properly: got %d, want 1", p.flag);
diff(t, "uiQueueMain() didn't set flag properly", "%d",
p.flag, 1);
}
#define queueOp(name, expr) \
@ -118,10 +121,14 @@ static void checkOrder(testingT *t, uint32_t flag)
return;
for (i = 1; i < 6; i++)
if (flag == orders[i].result) {
testingTErrorf(t, "got %" PRIu32 " (%s), want %" PRIu32 " (%s)", flag, orders[i].order, orders[0].result, orders[0].order);
diff2(t, "wrong order", "%" PRIu32 " (%s)",
flag, orders[i].order,
orders[0].result, orders[0].order);
return;
}
testingTErrorf(t, "got %" PRIu32 " (unknown order), want %" PRIu32 " (%s)", flag, orders[0].result, orders[0].order);
diff2(t, "wrong result", "%" PRIu32 " (%s)",
flag, "unknown order",
orders[0].result, orders[0].order);
}
testingTest(QueueMain_Sequence)
@ -160,7 +167,8 @@ testingTest(QueueMain_DifferentThread)
if (p.err != 0)
testingTErrorf(t, "error sleeping in thread to ensure a high likelihood the uiQueueMain() is run after uiMain() starts: " timerSysErrorFmt, timerSysErrorFmtArg(p.err));
if (p.flag != 1)
testingTErrorf(t, "uiQueueMain() didn't set flag properly: got %d, want 1", p.flag);
diff(t, "uiQueueMain() didn't set flag properly", "%d",
p.flag, 1);
}
static void queueOrderThread(void *data)

View File

@ -73,6 +73,7 @@ struct testingT {
jmp_buf returnNowBuf;
struct defer *defers;
int defersRun;
int indent;
};
#ifdef _MSC_VER
@ -150,6 +151,63 @@ static void testsetSort(struct testset *set)
qsort(set->tests, set->len, sizeof (testingT), testcmp);
}
static void printIndent(int n)
{
for (; n != 0; n--)
printf(" ");
}
static void vprintfIndented(int indent, const char *format, va_list ap)
{
va_list ap2;
char *buf;
int n;
char *lineStart, *lineEnd;
int firstLine = 1;
va_copy(ap2, ap);
n = vsnprintf(NULL, 0, format, ap2);
// TODO handle n < 0 case
va_end(ap2);
buf = testingprivNewArray(char, n + 1);
vsnprintf(buf, n + 1, format, ap);
// strip trailing blank lines
while (buf[n - 1] == '\n')
n--;
buf[n] = '\0';
lineStart = buf;
for (;;) {
lineEnd = strchr(lineStart, '\n');
if (lineEnd == NULL) // last line
break;
*lineEnd = '\0';
printIndent(indent);
printf("%s\n", lineStart);
lineStart = lineEnd + 1;
if (firstLine) {
// subsequent lines are indented twice
indent++;
firstLine = 0;
}
}
// print the last line
printIndent(indent);
printf("%s\n", lineStart);
testingprivFree(buf);
}
static void printfIndented(int indent, const char *format, ...)
{
va_list ap;
va_start(ap, format);
vprintfIndented(indent, format, ap);
va_end(ap);
}
static void runDefers(testingT *t)
{
struct defer *d;
@ -161,7 +219,7 @@ static void runDefers(testingT *t)
(*(d->f))(t, d->data);
}
static void testsetRun(struct testset *set, int *anyFailed)
static void testsetRun(struct testset *set, int indent, int *anyFailed)
{
size_t i;
testingT *t;
@ -171,7 +229,8 @@ static void testsetRun(struct testset *set, int *anyFailed)
t = set->tests;
for (i = 0; i < set->len; i++) {
printf("=== RUN %s\n", t->name);
printfIndented(indent, "=== RUN %s\n", t->name);
t->indent = indent + 1;
start = timerMonotonicNow();
if (setjmp(t->returnNowBuf) == 0)
(*(t->f))(t);
@ -186,7 +245,7 @@ static void testsetRun(struct testset *set, int *anyFailed)
// note that failed overrides skipped
status = "SKIP";
timerDurationString(timerTimeSub(end, start), timerstr);
printf("--- %s: %s (%s)\n", status, t->name, timerstr);
printfIndented(indent, "--- %s: %s (%s)\n", status, t->name, timerstr);
t++;
}
}
@ -207,13 +266,13 @@ int testingMain(void)
testsetSort(&testsAfter);
anyFailed = 0;
testsetRun(&testsBefore, &anyFailed);
testsetRun(&testsBefore, 0, &anyFailed);
// TODO print a warning that we skip the next stages if a prior stage failed?
if (!anyFailed)
testsetRun(&tests, &anyFailed);
testsetRun(&tests, 0, &anyFailed);
// TODO should we unconditionally run these tests if before succeeded but the main tests failed?
if (!anyFailed)
testsetRun(&testsAfter, &anyFailed);
testsetRun(&testsAfter, 0, &anyFailed);
if (anyFailed) {
printf("FAIL\n");
return 1;
@ -233,11 +292,22 @@ void testingprivTLogfFull(testingT *t, const char *file, long line, const char *
void testingprivTLogvfFull(testingT *t, const char *file, long line, const char *format, va_list ap)
{
va_list ap2;
char *buf;
int n, n2;
// TODO extract filename from file
printf("\t%s:%ld: ", file, line);
// TODO split into lines separated by \n\t\t and trimming trailing empty lines
vprintf(format, ap);
printf("\n");
n = snprintf(NULL, 0, "%s:%ld: ", file, line);
// TODO handle n < 0 case
va_copy(ap2, ap);
n2 = vsnprintf(NULL, 0, format, ap2);
// TODO handle n2 < 0 case
va_end(ap2);
buf = testingprivNewArray(char, n + n2 + 1);
snprintf(buf, n + 1, "%s:%ld: ", file, line);
vsnprintf(buf + n, n2 + 1, format, ap);
printfIndented(t->indent, "%s", buf);
testingprivFree(buf);
}
void testingTFail(testingT *t)

View File

@ -3,6 +3,11 @@
#include "lib/testing.h"
#include "lib/timer.h"
#define diff(t, clause, fmt, got, want) testingTErrorf(t, "%s:\ngot " fmt "\nwant " fmt, clause, got, want)
#define diff2(t, clause, fmts, got1, got2, want1, want2) testingTErrorf(t, "%s:\ngot " fmts "\nwant " fmts, clause, got1, got2, want1, want2)
#define diffFatal(t, clause, fmt, got, want) testingTFatalf(t, "%s:\ngot " fmt "\nwant " fmt, clause, got, want)
#define diff2Fatal(t, clause, fmts, got1, got2, want1, want2) testingTFatalf(t, "%s:\ngot " fmts "\nwant " fmts, clause, got1, got2, want1, want2)
// main.c
extern void timeoutMain(void *data);
#define timeout_uiMain(t, d) { \