Rewrote testing.c to use testingprivOutbuf. It doesn't quite work yet...
This commit is contained in:
parent
9bec2005a1
commit
a4c6817d33
|
@ -11,104 +11,6 @@
|
||||||
#include "testing.h"
|
#include "testing.h"
|
||||||
#include "testingpriv.h"
|
#include "testingpriv.h"
|
||||||
|
|
||||||
// a struct outbuf of NULL writes directly to stdout
|
|
||||||
struct outbuf {
|
|
||||||
char *buf;
|
|
||||||
size_t len;
|
|
||||||
size_t cap;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define nOutbufGrow 32
|
|
||||||
|
|
||||||
static void outbufCopyStr(struct outbuf *o, const char *str, size_t len)
|
|
||||||
{
|
|
||||||
size_t grow;
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
return;
|
|
||||||
if (o == NULL) {
|
|
||||||
printf("%s", str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
grow = len + 1;
|
|
||||||
if (grow < nOutbufGrow)
|
|
||||||
grow = nOutbufGrow;
|
|
||||||
if ((o->len + grow) >= o->cap) {
|
|
||||||
size_t prevcap;
|
|
||||||
|
|
||||||
prevcap = o->cap;
|
|
||||||
o->cap += grow;
|
|
||||||
o->buf = testingprivResizeArray(o->buf, char, prevcap, o->cap);
|
|
||||||
}
|
|
||||||
memmove(o->buf + o->len, str, len * sizeof (char));
|
|
||||||
o->len += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define outbufAddNewline(o) outbufCopyStr(o, "\n", 1)
|
|
||||||
|
|
||||||
static void outbufAddIndent(struct outbuf *o, int n)
|
|
||||||
{
|
|
||||||
for (; n != 0; n--)
|
|
||||||
outbufCopyStr(o, " ", 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void outbufVprintf(struct outbuf *o, 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 = testingprivVsnprintf(NULL, 0, format, ap2);
|
|
||||||
va_end(ap2);
|
|
||||||
buf = testingprivNewArray(char, n + 1);
|
|
||||||
testingprivVsnprintf(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';
|
|
||||||
outbufAddIndent(o, indent);
|
|
||||||
outbufCopyStr(o, lineStart, lineEnd - lineStart);
|
|
||||||
outbufAddNewline(o);
|
|
||||||
lineStart = lineEnd + 1;
|
|
||||||
if (firstLine) {
|
|
||||||
// subsequent lines are indented twice
|
|
||||||
indent++;
|
|
||||||
firstLine = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// print the last line
|
|
||||||
outbufAddIndent(o, indent);
|
|
||||||
outbufCopyStr(o, lineStart, strlen(lineStart));
|
|
||||||
outbufAddNewline(o);
|
|
||||||
|
|
||||||
testingprivFree(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void outbufPrintf(struct outbuf *o, int indent, const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, format);
|
|
||||||
outbufVprintf(o, indent, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void outbufCopy(struct outbuf *o, const struct outbuf *from)
|
|
||||||
{
|
|
||||||
outbufCopyStr(o, from->buf, from->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct defer {
|
struct defer {
|
||||||
void (*f)(testingT *, void *);
|
void (*f)(testingT *, void *);
|
||||||
void *data;
|
void *data;
|
||||||
|
@ -141,9 +43,8 @@ struct testingT {
|
||||||
int defersRun;
|
int defersRun;
|
||||||
|
|
||||||
// output
|
// output
|
||||||
int indent;
|
|
||||||
int verbose;
|
int verbose;
|
||||||
struct outbuf output;
|
testingprivOutbuf *outbuf;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -215,42 +116,54 @@ static const testingOptions defaultOptions = {
|
||||||
.Verbose = 0,
|
.Verbose = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void testingprivSetRun(testingSet *set, const testingOptions *options, int indent, int *anyFailed)
|
static int testingprivTRun(testingT *t, const testingOptions *options, testingprivOutbuf *parentbuf)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
testingT *t;
|
|
||||||
const char *status;
|
const char *status;
|
||||||
timerTime start, end;
|
timerTime start, end;
|
||||||
char timerstr[timerDurationStringLen];
|
char timerstr[timerDurationStringLen];
|
||||||
int printStatus;
|
int printStatus;
|
||||||
|
|
||||||
|
if (options->Verbose)
|
||||||
|
testingprivOutbufPrintf(parentbuf, "=== RUN %s\n", t->name);
|
||||||
|
t->verbose = options->Verbose;
|
||||||
|
t->outbuf = testingprivNewOutbuf();
|
||||||
|
|
||||||
|
start = timerMonotonicNow();
|
||||||
|
if (setjmp(t->returnNowBuf) == 0)
|
||||||
|
(*(t->f))(t);
|
||||||
|
end = timerMonotonicNow();
|
||||||
|
t->returned = 1;
|
||||||
|
runDefers(t);
|
||||||
|
|
||||||
|
printStatus = t->verbose;
|
||||||
|
status = "PASS";
|
||||||
|
if (t->failed) {
|
||||||
|
status = "FAIL";
|
||||||
|
printStatus = 1; // always print status on failure
|
||||||
|
} else if (t->skipped)
|
||||||
|
// note that failed overrides skipped
|
||||||
|
status = "SKIP";
|
||||||
|
timerDurationString(timerTimeSub(end, start), timerstr);
|
||||||
|
if (printStatus) {
|
||||||
|
testingprivOutbufPrintf(parentbuf, "--- %s: %s (%s)\n", status, t->name, timerstr);
|
||||||
|
testingprivOutbufAppendOutbuf(parentbuf, t->outbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
testingprivOutbufFree(t->outbuf);
|
||||||
|
t->outbuf = NULL;
|
||||||
|
return t->failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testingprivSetRun(testingSet *set, const testingOptions *options, testingprivOutbuf *outbuf, int *anyFailed)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
testingT *t;
|
||||||
|
|
||||||
testingprivArrayQsort(&(set->tests), testcmp);
|
testingprivArrayQsort(&(set->tests), testcmp);
|
||||||
t = (testingT *) (set->tests.buf);
|
t = (testingT *) (set->tests.buf);
|
||||||
for (i = 0; i < set->tests.len; i++) {
|
for (i = 0; i < set->tests.len; i++) {
|
||||||
if (options->Verbose)
|
if (!testingprivTRun(t, options, outbuf))
|
||||||
outbufPrintf(NULL, indent, "=== RUN %s", t->name);
|
|
||||||
t->indent = indent + 1;
|
|
||||||
t->verbose = options->Verbose;
|
|
||||||
start = timerMonotonicNow();
|
|
||||||
if (setjmp(t->returnNowBuf) == 0)
|
|
||||||
(*(t->f))(t);
|
|
||||||
end = timerMonotonicNow();
|
|
||||||
t->returned = 1;
|
|
||||||
runDefers(t);
|
|
||||||
printStatus = t->verbose;
|
|
||||||
status = "PASS";
|
|
||||||
if (t->failed) {
|
|
||||||
status = "FAIL";
|
|
||||||
printStatus = 1; // always print status on failure
|
|
||||||
*anyFailed = 1;
|
*anyFailed = 1;
|
||||||
} else if (t->skipped)
|
|
||||||
// note that failed overrides skipped
|
|
||||||
status = "SKIP";
|
|
||||||
timerDurationString(timerTimeSub(end, start), timerstr);
|
|
||||||
if (printStatus) {
|
|
||||||
outbufPrintf(NULL, indent, "--- %s: %s (%s)", status, t->name, timerstr);
|
|
||||||
outbufCopy(NULL, &(t->output));
|
|
||||||
}
|
|
||||||
t++;
|
t++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,7 +178,7 @@ void testingSetRun(testingSet *set, const struct testingOptions *options, int *a
|
||||||
options = &defaultOptions;
|
options = &defaultOptions;
|
||||||
if (set->tests.len == 0)
|
if (set->tests.len == 0)
|
||||||
return;
|
return;
|
||||||
testingprivSetRun(set, options, 0, anyFailed);
|
testingprivSetRun(set, options, NULL, anyFailed);
|
||||||
*anyRun = 1;
|
*anyRun = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,22 +193,9 @@ 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)
|
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
|
// TODO extract filename from file
|
||||||
n = testingprivSnprintf(NULL, 0, "%s:%ld: ", file, line);
|
testingprivOutbufPrintf(t->outbuf, "%s:%ld: ", file, line);
|
||||||
// TODO handle n < 0 case
|
testingprivOutbufPrintf(t->outbuf, format, ap);
|
||||||
va_copy(ap2, ap);
|
|
||||||
n2 = testingprivVsnprintf(NULL, 0, format, ap2);
|
|
||||||
// TODO handle n2 < 0 case
|
|
||||||
va_end(ap2);
|
|
||||||
buf = testingprivNewArray(char, n + n2 + 1);
|
|
||||||
testingprivSnprintf(buf, n + 1, "%s:%ld: ", file, line);
|
|
||||||
testingprivVsnprintf(buf + n, n2 + 1, format, ap);
|
|
||||||
outbufPrintf(&(t->output), t->indent, "%s", buf);
|
|
||||||
testingprivFree(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void testingTFail(testingT *t)
|
void testingTFail(testingT *t)
|
||||||
|
|
|
@ -217,16 +217,13 @@ void testingprivOutbufPrintf(testingprivOutbuf *o, const char *fmt, ...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO right now this assumes the last character in o before calling this is a newline
|
// TODO right now this assumes the last character in o before calling this is a newline
|
||||||
void testingprivOutbufAppendOutbuf(testingprivOutbuf *o, testingprivOutbuf *src, int indent)
|
void testingprivOutbufAppendOutbuf(testingprivOutbuf *o, testingprivOutbuf *src)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t n;
|
size_t n;
|
||||||
int hasTrailingBlankLine;
|
int hasTrailingBlankLine;
|
||||||
size_t trailingBlankLinePos;
|
size_t trailingBlankLinePos;
|
||||||
char *lineStart, *lineEnd;
|
char *lineStart, *lineEnd;
|
||||||
int firstLine;
|
|
||||||
char *indentstr;
|
|
||||||
int indentoff;
|
|
||||||
|
|
||||||
buf = src->buf.buf;
|
buf = src->buf.buf;
|
||||||
n = src->buf.len;
|
n = src->buf.len;
|
||||||
|
@ -250,34 +247,19 @@ void testingprivOutbufAppendOutbuf(testingprivOutbuf *o, testingprivOutbuf *src,
|
||||||
buf[trailingBlankLinePos] = '\0';
|
buf[trailingBlankLinePos] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
// precompute the indent string so we don't have to repeatedly print four spaces each time
|
|
||||||
// the + 4 is because lines after the first have one extra level of indent; indentoff is used to control that
|
|
||||||
indentstr = (char *) testingprivAlloc((indent * 4 + 4 + 1) * sizeof (char), "indent string");
|
|
||||||
// the NUL was added by testingprivAlloc()
|
|
||||||
memset(indentstr, ' ', (indent * 4 + 4) * sizeof (char));
|
|
||||||
firstLine = 1;
|
|
||||||
indentoff = 4;
|
|
||||||
|
|
||||||
lineStart = buf;
|
lineStart = buf;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
lineEnd = strchr(lineStart, '\n');
|
lineEnd = strchr(lineStart, '\n');
|
||||||
if (lineEnd == NULL) // last line
|
if (lineEnd == NULL) // last line
|
||||||
break;
|
break;
|
||||||
*lineEnd = '\0';
|
*lineEnd = '\0';
|
||||||
testingprivOutbufPrintf(o, "%s%s\n", indentstr + indentoff, lineStart);
|
testingprivOutbufPrintf(o, " %s\n", lineStart);
|
||||||
// be sure to restore src to its original state
|
// be sure to restore src to its original state
|
||||||
*lineEnd = '\n';
|
*lineEnd = '\n';
|
||||||
lineStart = lineEnd + 1;
|
lineStart = lineEnd + 1;
|
||||||
if (firstLine) {
|
|
||||||
// subsequent lines are indented twice
|
|
||||||
firstLine = 0;
|
|
||||||
indentoff = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// print the last line
|
// print the last line
|
||||||
testingprivOutbufPrintf(o, "%s%s\n", indentstr + indentoff, lineStart);
|
testingprivOutbufPrintf(o, " %s\n", lineStart);
|
||||||
|
|
||||||
testingprivFree(indentstr);
|
|
||||||
|
|
||||||
// restore src to its original state
|
// restore src to its original state
|
||||||
if (hasTrailingBlankLine)
|
if (hasTrailingBlankLine)
|
||||||
|
|
|
@ -47,4 +47,4 @@ extern testingprivOutbuf *testingprivNewOutbuf(void);
|
||||||
extern void testingprivOutbufFree(testingprivOutbuf *o);
|
extern void testingprivOutbufFree(testingprivOutbuf *o);
|
||||||
extern void testingprivOutbufVprintf(testingprivOutbuf *o, const char *fmt, va_list ap);
|
extern void testingprivOutbufVprintf(testingprivOutbuf *o, const char *fmt, va_list ap);
|
||||||
extern void testingprivOutbufPrintf(testingprivOutbuf *o, const char *fmt, ...);
|
extern void testingprivOutbufPrintf(testingprivOutbuf *o, const char *fmt, ...);
|
||||||
extern void testingprivOutbufAppendOutbuf(testingprivOutbuf *o, testingprivOutbuf *src, int indent);
|
extern void testingprivOutbufAppendOutbuf(testingprivOutbuf *o, testingprivOutbuf *src);
|
||||||
|
|
Loading…
Reference in New Issue