libvirt/tests/virbuftest.c
Michal Privoznik 83c5467ee9 util: Introduce virBufferAddBuffer
This API joins the following two lines:

char *s = virBufferContentAndReset(buf1);
virBufferAdd(buf2, s, -1);

into one:

virBufferAddBuffer(buf2, buf1);

With one exception: there's no re-indentation applied to @buf1.
The idea is, that in general both can have different indentation
(like the test I'm adding proves)

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2015-02-25 09:23:42 +01:00

337 lines
9.3 KiB
C

#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "internal.h"
#include "testutils.h"
#include "virbuffer.h"
#include "viralloc.h"
#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_NONE
#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 &amp;\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 (virBufferError(buf)) {
TEST_ERROR("Buffer had error");
return -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');
if (virBufferError(buf)) {
TEST_ERROR("Buffer had error");
return -1;
}
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;
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, "b", -1);
virBufferTrim(buf, "b,,", 1);
virBufferTrim(buf, ",", -1);
if (virBufferError(buf)) {
TEST_ERROR("Buffer had error");
return -1;
}
result = virBufferContentAndReset(buf);
if (!result || STRNEQ(result, expected)) {
virtTestDifference(stderr, expected, result);
goto cleanup;
}
virBufferTrim(buf, NULL, -1);
if (virBufferError(buf) != -1) {
TEST_ERROR("Usage error not flagged");
goto cleanup;
}
ret = 0;
cleanup:
virBufferFreeAndReset(buf);
VIR_FREE(result);
return ret;
}
static int testBufAddBuffer(const void *data ATTRIBUTE_UNUSED)
{
virBuffer buf1 = VIR_BUFFER_INITIALIZER;
virBuffer buf2 = VIR_BUFFER_INITIALIZER;
virBuffer buf3 = VIR_BUFFER_INITIALIZER;
int ret = -1;
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)) {
TEST_ERROR("buf1 already in use");
goto cleanup;
}
if (virBufferUse(&buf2)) {
TEST_ERROR("buf2 already in use");
goto cleanup;
}
if (virBufferUse(&buf3)) {
TEST_ERROR("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)) {
TEST_ERROR("Error adding to buf1");
goto cleanup;
}
if (!virBufferUse(&buf2)) {
TEST_ERROR("Error adding to buf2");
goto cleanup;
}
if (!virBufferUse(&buf3)) {
TEST_ERROR("Error adding to buf3");
goto cleanup;
}
virBufferAddBuffer(&buf2, &buf3);
if (!virBufferUse(&buf2)) {
TEST_ERROR("buf2 cleared mistakenly");
goto cleanup;
}
if (virBufferUse(&buf3)) {
TEST_ERROR("buf3 is not clear even though it should be");
goto cleanup;
}
virBufferAddBuffer(&buf1, &buf2);
if (!virBufferUse(&buf1)) {
TEST_ERROR("buf1 cleared mistakenly");
goto cleanup;
}
if (virBufferUse(&buf2)) {
TEST_ERROR("buf2 is not clear even though it should be");
goto cleanup;
}
result = virBufferContentAndReset(&buf1);
if (STRNEQ_NULLABLE(result, expected)) {
virtTestDifference(stderr, expected, result);
goto cleanup;
}
ret = 0;
cleanup:
virBufferFreeAndReset(&buf1);
virBufferFreeAndReset(&buf2);
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, 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);
DO_TEST("AddBuffer", testBufAddBuffer, 0);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
VIRT_TEST_MAIN(mymain)