#include #include #include #include #include "internal.h" #include "util.h" #include "testutils.h" #include "buf.h" #include "memory.h" #define TEST_ERROR(...) \ do { \ if (virTestGetDebug()) \ fprintf(stderr, __VA_ARGS__); \ } while (0) struct testInfo { int doEscape; }; static int testBufInfiniteLoop(const void *data) { virBuffer bufinit = VIR_BUFFER_INITIALIZER; virBufferPtr buf = &bufinit; char *addstr = NULL, *bufret = NULL; int ret = -1; const struct testInfo *info = data; virBufferAddChar(buf, 'a'); /* * Infinite loop used to trigger if: * (strlen + 1 > 1000) && (strlen == buf-size - buf-use - 1) * which was the case after the above addchar at the time of the bug. * This test is a bit fragile, since it relies on virBuffer internals. */ if (virAsprintf(&addstr, "%*s", buf->a - buf->b - 1, "a") < 0) { goto out; } if (info->doEscape) virBufferEscapeString(buf, "%s", addstr); else virBufferAsprintf(buf, "%s", addstr); ret = 0; out: bufret = virBufferContentAndReset(buf); if (!bufret) { TEST_ERROR("Buffer had error set"); ret = -1; } VIR_FREE(addstr); VIR_FREE(bufret); return ret; } static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) { virBuffer bufinit = VIR_BUFFER_INITIALIZER; virBufferPtr buf = &bufinit; const char expected[] = " 1\n 2\n 3\n 4\n 5\n 6\n 7\n &\n 8\n 9\n 10\n ' 11'\n"; char *result = NULL; int ret = 0; if (virBufferGetIndent(buf, false) != 0 || virBufferGetIndent(buf, true) != 0) { TEST_ERROR("Wrong indentation"); ret = -1; } virBufferAdjustIndent(buf, 3); if (STRNEQ(virBufferCurrentContent(buf), "")) { TEST_ERROR("Wrong content"); ret = -1; } if (virBufferGetIndent(buf, false) != 3 || virBufferGetIndent(buf, true) != 3 || virBufferError(buf)) { TEST_ERROR("Wrong indentation"); ret = -1; } virBufferAdjustIndent(buf, -2); if (virBufferGetIndent(buf, false) != 1 || virBufferGetIndent(buf, true) != 1 || virBufferError(buf)) { TEST_ERROR("Wrong indentation"); ret = -1; } virBufferAdjustIndent(buf, -3); if (virBufferGetIndent(buf, false) != -1 || virBufferGetIndent(buf, true) != -1 || virBufferError(buf) != -1) { TEST_ERROR("Usage error not flagged"); ret = -1; } virBufferFreeAndReset(buf); if (virBufferGetIndent(buf, false) != 0 || virBufferGetIndent(buf, true) != 0 || virBufferError(buf)) { TEST_ERROR("Reset didn't clear indentation"); ret = -1; } virBufferAdjustIndent(buf, 2); virBufferAddLit(buf, "1"); if (STRNEQ(virBufferCurrentContent(buf), " 1")) { TEST_ERROR("Wrong content"); ret = -1; } if (virBufferGetIndent(buf, false) != 2 || virBufferGetIndent(buf, true) != 0) { TEST_ERROR("Wrong indentation"); ret = -1; } virBufferAddLit(buf, "\n"); virBufferAdd(buf, "" "2\n", -1); /* Extra "" appeases syntax-check */ virBufferAddChar(buf, '3'); virBufferAddChar(buf, '\n'); virBufferAsprintf(buf, "%d", 4); virBufferAsprintf(buf, "%c", '\n'); virBufferStrcat(buf, "5", "\n", "6\n", NULL); virBufferEscapeString(buf, "%s\n", "7"); virBufferEscapeString(buf, "%s\n", "&"); virBufferEscapeSexpr(buf, "%s", "8\n"); virBufferURIEncodeString(buf, "9"); virBufferAddChar(buf, '\n'); virBufferEscapeShell(buf, "10"); virBufferAddChar(buf, '\n'); virBufferEscapeShell(buf, " 11"); virBufferAddChar(buf, '\n'); result = virBufferContentAndReset(buf); if (!result || STRNEQ(result, expected)) { virtTestDifference(stderr, expected, result); ret = -1; } VIR_FREE(result); return ret; } static int testBufTrim(const void *data ATTRIBUTE_UNUSED) { virBuffer bufinit = VIR_BUFFER_INITIALIZER; virBufferPtr buf = NULL; char *result = NULL; const char *expected = "a,b"; int ret = -1; int i = 1; #define ACT(str, len, result) \ do { \ if (virBufferTrim(buf, str, len) != result) { \ TEST_ERROR("trim %d failed", i); \ goto cleanup; \ } \ i++; \ } while (0); if (virBufferTrim(buf, "", 0) != -1) { TEST_ERROR("Wrong failure detection 1"); goto cleanup; } buf = &bufinit; if (virBufferTrim(buf, NULL, -1) != -1) { TEST_ERROR("Wrong failure detection 2"); goto cleanup; } virBufferAddLit(buf, "a;"); ACT("", 0, 1); ACT("", -1, 1); ACT(NULL, 1, 1); ACT(NULL, 5, 0); ACT("a", 2, 0); virBufferAddLit(buf, ",b,,"); ACT("b", -1, 0); ACT("b,,", 1, 1); ACT(",", -1, 1); result = virBufferContentAndReset(buf); if (!result || STRNEQ(result, expected)) { virtTestDifference(stderr, expected, result); goto cleanup; } ret = 0; cleanup: virBufferFreeAndReset(buf); VIR_FREE(result); return ret; } static int mymain(void) { int ret = 0; #define DO_TEST(msg, cb, data) \ do { \ struct testInfo info = { data }; \ if (virtTestRun("Buf: " msg, 1, cb, &info) < 0) \ ret = -1; \ } while (0) DO_TEST("EscapeString infinite loop", testBufInfiniteLoop, 1); DO_TEST("VSprintf infinite loop", testBufInfiniteLoop, 0); DO_TEST("Auto-indentation", testBufAutoIndent, 0); DO_TEST("Trim", testBufTrim, 0); return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; } VIRT_TEST_MAIN(mymain)