#include #include "internal.h" #include "testutils.h" #include "virbuffer.h" #include "viralloc.h" #include "virstring.h" #define VIR_FROM_THIS VIR_FROM_NONE struct testBufAddStrData { const char *data; const char *expect; }; static int testBufAutoIndent(const void *data G_GNUC_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"; g_autofree char *result = NULL; int ret = 0; if (virBufferGetIndent(buf) != 0 || virBufferGetEffectiveIndent(buf) != 0) { VIR_TEST_DEBUG("Wrong indentation"); ret = -1; } virBufferAdjustIndent(buf, 3); if (STRNEQ(virBufferCurrentContent(buf), "")) { VIR_TEST_DEBUG("Wrong content"); ret = -1; } if (virBufferGetIndent(buf) != 3 || virBufferGetEffectiveIndent(buf) != 3) { VIR_TEST_DEBUG("Wrong indentation"); ret = -1; } virBufferAdjustIndent(buf, -2); if (virBufferGetIndent(buf) != 1 || virBufferGetEffectiveIndent(buf) != 1) { VIR_TEST_DEBUG("Wrong indentation"); ret = -1; } virBufferAdjustIndent(buf, -3); if (virBufferGetIndent(buf) != 0 || virBufferGetEffectiveIndent(buf) != 0) { VIR_TEST_DEBUG("Indentation level not truncated"); ret = -1; } virBufferAdjustIndent(buf, 3); virBufferFreeAndReset(buf); if (virBufferGetIndent(buf) != 0 || virBufferGetEffectiveIndent(buf) != 0) { VIR_TEST_DEBUG("Reset didn't clear indentation"); ret = -1; } virBufferAdjustIndent(buf, 2); virBufferAddLit(buf, "1"); if (STRNEQ(virBufferCurrentContent(buf), " 1")) { VIR_TEST_DEBUG("Wrong content"); ret = -1; } if (virBufferGetIndent(buf) != 2 || virBufferGetEffectiveIndent(buf) != 0) { VIR_TEST_DEBUG("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)) { virTestDifference(stderr, expected, result); ret = -1; } return ret; } static int testBufTrim(const void *data G_GNUC_UNUSED) { virBuffer bufinit = VIR_BUFFER_INITIALIZER; virBufferPtr buf = NULL; g_autofree char *result = NULL; const char *expected = "a,b"; int ret = -1; virBufferTrim(buf, "", 0); buf = &bufinit; virBufferAddLit(buf, "a;"); virBufferTrim(buf, "", 0); virBufferTrim(buf, "", -1); virBufferTrim(buf, NULL, 1); virBufferTrim(buf, NULL, 5); virBufferTrim(buf, "a", 2); virBufferAddLit(buf, ",b,,"); virBufferTrim(buf, NULL, -1); virBufferTrim(buf, "b", -1); virBufferTrim(buf, "b,,", 1); virBufferTrim(buf, ",", -1); result = virBufferContentAndReset(buf); if (!result || STRNEQ(result, expected)) { virTestDifference(stderr, expected, result); goto cleanup; } ret = 0; cleanup: virBufferFreeAndReset(buf); return ret; } static int testBufAddBuffer(const void *data G_GNUC_UNUSED) { virBuffer buf1 = VIR_BUFFER_INITIALIZER; virBuffer buf2 = VIR_BUFFER_INITIALIZER; virBuffer buf3 = VIR_BUFFER_INITIALIZER; int ret = -1; g_autofree char *result = NULL; const char *expected = \ " A long time ago, in a galaxy far,\n" \ " far away...\n" \ " It is a period of civil war.\n" \ " Rebel spaceships, striking\n" \ " from a hidden base, have won\n" \ " their first victory against\n" \ " the evil Galactic Empire.\n" \ " During the battle, rebel\n" \ " spies managed to steal secret\n" \ " plans to the Empire's\n" \ " ultimate weapon, the DEATH\n" \ " STAR, an armored space\n" \ " station with enough power to\n" \ " destroy an entire planet.\n"; if (virBufferUse(&buf1)) { VIR_TEST_DEBUG("buf1 already in use"); goto cleanup; } if (virBufferUse(&buf2)) { VIR_TEST_DEBUG("buf2 already in use"); goto cleanup; } if (virBufferUse(&buf3)) { VIR_TEST_DEBUG("buf3 already in use"); goto cleanup; } virBufferAdjustIndent(&buf1, 2); virBufferAddLit(&buf1, "A long time ago, in a galaxy far,\n"); virBufferAddLit(&buf1, "far away...\n"); virBufferAdjustIndent(&buf2, 4); virBufferAddLit(&buf2, "It is a period of civil war.\n"); virBufferAddLit(&buf2, "Rebel spaceships, striking\n"); virBufferAddLit(&buf2, "from a hidden base, have won\n"); virBufferAddLit(&buf2, "their first victory against\n"); virBufferAddLit(&buf2, "the evil Galactic Empire.\n"); virBufferAdjustIndent(&buf3, 2); virBufferAddLit(&buf3, "During the battle, rebel\n"); virBufferAddLit(&buf3, "spies managed to steal secret\n"); virBufferAddLit(&buf3, "plans to the Empire's\n"); virBufferAddLit(&buf3, "ultimate weapon, the DEATH\n"); virBufferAddLit(&buf3, "STAR, an armored space\n"); virBufferAddLit(&buf3, "station with enough power to\n"); virBufferAddLit(&buf3, "destroy an entire planet.\n"); if (!virBufferUse(&buf1)) { VIR_TEST_DEBUG("Error adding to buf1"); goto cleanup; } if (!virBufferUse(&buf2)) { VIR_TEST_DEBUG("Error adding to buf2"); goto cleanup; } if (!virBufferUse(&buf3)) { VIR_TEST_DEBUG("Error adding to buf3"); goto cleanup; } virBufferAddBuffer(&buf2, &buf3); if (!virBufferUse(&buf2)) { VIR_TEST_DEBUG("buf2 cleared mistakenly"); goto cleanup; } if (virBufferUse(&buf3)) { VIR_TEST_DEBUG("buf3 is not clear even though it should be"); goto cleanup; } virBufferAddBuffer(&buf1, &buf2); if (!virBufferUse(&buf1)) { VIR_TEST_DEBUG("buf1 cleared mistakenly"); goto cleanup; } if (virBufferUse(&buf2)) { VIR_TEST_DEBUG("buf2 is not clear even though it should be"); goto cleanup; } result = virBufferContentAndReset(&buf1); if (STRNEQ_NULLABLE(result, expected)) { virTestDifference(stderr, expected, result); goto cleanup; } ret = 0; cleanup: virBufferFreeAndReset(&buf1); virBufferFreeAndReset(&buf2); return ret; } static int testBufAddStr(const void *opaque) { const struct testBufAddStrData *data = opaque; virBuffer buf = VIR_BUFFER_INITIALIZER; g_autofree char *actual = NULL; virBufferAddLit(&buf, "\n"); virBufferAdjustIndent(&buf, 2); virBufferAddStr(&buf, data->data); virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, ""); if (!(actual = virBufferContentAndReset(&buf))) { VIR_TEST_DEBUG("buf is empty"); return -1; } if (STRNEQ_NULLABLE(actual, data->expect)) { VIR_TEST_DEBUG("testBufAddStr(): Strings don't match:"); virTestDifference(stderr, data->expect, actual); return -1; } return 0; } static int testBufEscapeStr(const void *opaque) { const struct testBufAddStrData *data = opaque; virBuffer buf = VIR_BUFFER_INITIALIZER; g_autofree char *actual = NULL; virBufferAddLit(&buf, "\n"); virBufferAdjustIndent(&buf, 2); virBufferEscapeString(&buf, "%s\n", data->data); virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, ""); if (!(actual = virBufferContentAndReset(&buf))) { VIR_TEST_DEBUG("buf is empty"); return -1; } if (STRNEQ_NULLABLE(actual, data->expect)) { VIR_TEST_DEBUG("testBufEscapeStr(): Strings don't match:"); virTestDifference(stderr, data->expect, actual); return -1; } return 0; } static int testBufEscapeRegex(const void *opaque) { const struct testBufAddStrData *data = opaque; virBuffer buf = VIR_BUFFER_INITIALIZER; g_autofree char *actual = NULL; virBufferEscapeRegex(&buf, "%s", data->data); if (!(actual = virBufferContentAndReset(&buf))) { VIR_TEST_DEBUG("testBufEscapeRegex: buf is empty"); return -1; } if (STRNEQ_NULLABLE(actual, data->expect)) { VIR_TEST_DEBUG("testBufEscapeRegex: Strings don't match:"); virTestDifference(stderr, data->expect, actual); return -1; } return 0; } static int testBufSetIndent(const void *opaque G_GNUC_UNUSED) { virBuffer buf = VIR_BUFFER_INITIALIZER; g_autofree char *actual = NULL; virBufferSetIndent(&buf, 11); virBufferAddLit(&buf, "test\n"); virBufferSetIndent(&buf, 2); virBufferAddLit(&buf, "test2\n"); if (!(actual = virBufferContentAndReset(&buf))) return -1; if (STRNEQ(actual, " test\n test2\n")) { VIR_TEST_DEBUG("testBufSetIndent: expected indent not set"); return -1; } return 0; } /* Result of this shows up only in valgrind or similar */ static int testBufferAutoclean(const void *opaque G_GNUC_UNUSED) { g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; virBufferAddLit(&buf, "test test test\n"); return 0; } static int mymain(void) { int ret = 0; #define DO_TEST(msg, cb) \ do { \ if (virTestRun("Buf: " msg, cb, NULL) < 0) \ ret = -1; \ } while (0) DO_TEST("Auto-indentation", testBufAutoIndent); DO_TEST("Trim", testBufTrim); DO_TEST("AddBuffer", testBufAddBuffer); DO_TEST("set indent", testBufSetIndent); DO_TEST("autoclean", testBufferAutoclean); #define DO_TEST_ADD_STR(_data, _expect) \ do { \ struct testBufAddStrData info = { .data = _data, .expect = _expect }; \ if (virTestRun("Buf: AddStr", testBufAddStr, &info) < 0) \ ret = -1; \ } while (0) DO_TEST_ADD_STR("", "\n"); DO_TEST_ADD_STR("", "\n "); DO_TEST_ADD_STR("\n", "\n \n"); DO_TEST_ADD_STR("\n \n\n", "\n \n \n \n"); #define DO_TEST_ESCAPE(_data, _expect) \ do { \ struct testBufAddStrData info = { .data = _data, .expect = _expect }; \ if (virTestRun("Buf: EscapeStr", testBufEscapeStr, &info) < 0) \ ret = -1; \ } while (0) DO_TEST_ESCAPE("", "\n <td></td><td></td>\n"); DO_TEST_ESCAPE("\007\"&&\"\x15", "\n "&&"\n"); DO_TEST_ESCAPE(",,'..',,", "\n ,,'..',,\n"); DO_TEST_ESCAPE("\x01\x01\x02\x03\x05\x08", "\n \n"); #define DO_TEST_ESCAPE_REGEX(_data, _expect) \ do { \ struct testBufAddStrData info = { .data = _data, .expect = _expect }; \ if (virTestRun("Buf: EscapeRegex", testBufEscapeRegex, &info) < 0) \ ret = -1; \ } while (0) DO_TEST_ESCAPE_REGEX("noescape", "noescape"); DO_TEST_ESCAPE_REGEX("^$.|?*+()[]{}\\", "\\^\\$\\.\\|\\?\\*\\+\\(\\)\\[\\]\\{\\}\\\\"); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } VIR_TEST_MAIN(mymain)