From e52d4246e643cca7f6a3967f91beffdda79a45a0 Mon Sep 17 00:00:00 2001 From: Gediminas Jakutis Date: Fri, 11 Oct 2019 16:14:31 +0300 Subject: test: partial diagnostic subsystem coverage. Add the required bits for most diagnostic testic functions and create tests for rin_err; explicitly skip the rest, for now. Signed-off-by: Gediminas Jakutis --- test/diagnostic.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++- test/meson.build | 8 ++- 2 files changed, 212 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/test/diagnostic.c b/test/diagnostic.c index 7a6670e..640e0d2 100644 --- a/test/diagnostic.c +++ b/test/diagnostic.c @@ -18,11 +18,213 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include +#include +#include +#include #include "test.h" +#include "rin/diagnostic.h" + +struct stdiocap { + int pipefd[2]; + int origfd; + int backupfd; + FILE *pipe; +}; + +static int err_test(void); +static int warn_test(void); +static int fixme_test(void); +static int info_test(void); +static int prefix_test(void); +static int thread_test(void); +static int clean_test(void); +static struct stdiocap capture_stdio_start(FILE *stream); +static void capture_stdio_stop(struct stdiocap *cap); +static char *visible_newlines(const char * const in); +static int test_default_channels(const char * const in, const char * const expected, size_t i, int usearg, void (*func)(const char *, ...)); int diagnostic_test(char *testname) { - (void) testname; - /* basically a NOOP */ - return ok(0, ""); + static const struct test tests[] = { + {"err", err_test}, + {"warn", warn_test}, + {"fixme", fixme_test}, + {"info", info_test}, + {"prefix", prefix_test}, + {"thread", thread_test}, + {"clean", clean_test} }; + size_t i; + + for (i = 0; i < arrlen(tests); ++i) { + if (!strcmp(testname, tests[i].name)) { + return tests[i].testfunc(); + } + } + + return EXIT_FAILURE; +} + +static int err_test(void) +{ + size_t i; + int usearg; + int ret; + + static const char *in[] = {"", "test", "test number is %zu", "%zu tests ran"}; + static const char *expected[] = {"error:\n", "error:test\n", "error:test number is 3\n", "error:4 tests ran\n"}; + + for (i = 0; i < arrlen(in); ++i) { + usearg = i < (arrlen(in) / 2) ? 0 : 1; + ret = test_default_channels(in[i], expected[i], i, usearg, rin_err); + } + + return ret; +} + +static int warn_test(void) +{ + return 77; +} + +static int fixme_test(void) +{ + return 77; +} + +static int info_test(void) +{ + return 77; +} + +static int prefix_test(void) +{ + return 77; +} + +static int thread_test(void) +{ + return 77; +} + +static int clean_test(void) +{ + return 77; +} + +static struct stdiocap capture_stdio_start(FILE *stream) +{ + struct stdiocap ret; + + ret.origfd = fileno(stream); + ret.backupfd = dup(ret.origfd); + + if (pipe(ret.pipefd)) { + close(ret.backupfd); + ret.backupfd = -1; + ret.origfd = -1; + ret.pipefd[0] = -1; + ret.pipefd[1] = -1; + ret.pipe = NULL; + } + + dup2(ret.pipefd[1], ret.origfd); + ret.pipe = fdopen(ret.pipefd[0], "r"); + return ret; +} + +static void capture_stdio_stop(struct stdiocap *cap) +{ + /* restore original fd to the stream */ + dup2(cap->backupfd, cap->origfd); + close(cap->backupfd); + close(cap->pipefd[1]); + close(cap->pipefd[0]); + + /* close everything we opened and invalidate all the descriptors */ + fclose(cap->pipe); + cap->backupfd = -1; + cap->origfd = -1; + cap->pipefd[0] = -1; + cap->pipefd[1] = -1; + cap->pipe = NULL; +} + +static char *visible_newlines(const char * const in) +{ + char *ret; + const char *newline; + const char *readptr; + char *writeptr; + + readptr = in; + ret = malloc(strlen(readptr) * 2 + 1); + writeptr = ret; + newline = strchr(readptr, '\n'); + + while (newline) { + /* write chunk until the next newline */ + memcpy(writeptr, readptr, newline - readptr); + writeptr += newline - readptr; /* advance writing position */ + readptr = newline; + ++readptr; /* skip the newline */ + /* toss in replacement */ + memcpy(writeptr, "\\n", 2); + writeptr += 2; + newline = strchr(readptr, '\n'); + } + + /* write all that remains */ + strcpy(writeptr, readptr); + return ret; +} + +static int test_default_channels(const char * const in, const char * const expected, size_t i, int usearg, void (*func)(const char *, ...)) +{ + char buf[32] = {0}; + struct stdiocap cap; + size_t len; + int ret = 0; + + len = strlen(expected); + ++len; + + cap = capture_stdio_start(stderr); + + if (!cap.pipe) { + ret = -1; + goto fail; + } + + if (usearg) { + func(in, i + 1); + } else { + func(in); + } + + if (!(fgets(buf, sizeof(buf) < len ? sizeof(buf) : len, cap.pipe))) { + ret = 1; + goto fail; + } + +fail: + capture_stdio_stop(&cap); + + if (ret == -1) { + ret = ok(1, "%s: unexpected test program failure on iteration %zu", __func__, i); + } else { + char *tmp[2]; + + ret = strncmp(buf, expected, sizeof(buf) < len ? sizeof(buf) : len); + + tmp[0] = visible_newlines(buf); + tmp[1] = visible_newlines(expected); + + ret = ok(ret, "%s: expected: \"%s\", got: \"%s\"", __func__, tmp[1], tmp[0]); + + free(tmp[0]); + free(tmp[1]); + } + + return ret; } diff --git a/test/meson.build b/test/meson.build index 5e0a100..7864166 100644 --- a/test/meson.build +++ b/test/meson.build @@ -16,7 +16,13 @@ test('flaot to string', test_e, args : ['float', 'floattohexstring']) test('double to string', test_e, args : ['float', 'doubletohexstring']) test('compare floats', test_e, args : ['float', 'comparefloat']) test('compare doubles', test_e, args : ['float', 'comparedouble']) -test('diagnostic', test_e, args : ['diagnostic', 'none']) +test('diagnostic err', test_e, args : ['diagnostic', 'err']) +test('diagnostic warn', test_e, args : ['diagnostic', 'warn']) +test('diagnostic fixme', test_e, args : ['diagnostic', 'fixme']) +test('diagnostic info', test_e, args : ['diagnostic', 'info']) +test('diagnostic prefix', test_e, args : ['diagnostic', 'prefix']) +test('diagnostic thread', test_e, args : ['diagnostic', 'thread']) +test('diagnostic clean', test_e, args : ['diagnostic', 'clean']) test('timespec add', test_e, args : ['time', 'timespec add']) test('timespec subtract', test_e, args : ['time', 'timespec sub']) test('timespec normalize', test_e, args : ['time', 'timespec normalize']) -- cgit v1.2.3