virbuftest.c 14.1 KB
Newer Older
1 2 3 4 5
#include <config.h>


#include "internal.h"
#include "testutils.h"
6
#include "virbuffer.h"
7
#include "viralloc.h"
8
#include "virstring.h"
9

10 11
#define VIR_FROM_THIS VIR_FROM_NONE

12 13 14 15
struct testInfo {
    int doEscape;
};

E
Eric Blake 已提交
16
static int testBufInfiniteLoop(const void *data)
17 18 19 20 21 22
{
    virBuffer bufinit = VIR_BUFFER_INITIALIZER;
    virBufferPtr buf = &bufinit;
    char *addstr = NULL, *bufret = NULL;
    int ret = -1;
    const struct testInfo *info = data;
23
    int len;
24 25 26 27

    virBufferAddChar(buf, 'a');

    /*
E
Eric Blake 已提交
28
     * Infinite loop used to trigger if:
29
     * (strlen + 1 > 1000) && (strlen == buf-size - buf-use - 1)
E
Eric Blake 已提交
30 31
     * 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.
32
     */
33 34
    len = buf->size - buf->use - 1;
    if (virAsprintf(&addstr, "%*s", len, "a") < 0)
35 36 37 38 39
        goto out;

    if (info->doEscape)
        virBufferEscapeString(buf, "%s", addstr);
    else
40
        virBufferAsprintf(buf, "%s", addstr);
41 42

    ret = 0;
43
 out:
44 45
    bufret = virBufferContentAndReset(buf);
    if (!bufret) {
46
        VIR_TEST_DEBUG("Buffer had error set");
47 48 49 50 51 52 53 54
        ret = -1;
    }

    VIR_FREE(addstr);
    VIR_FREE(bufret);
    return ret;
}

E
Eric Blake 已提交
55 56 57 58 59 60 61 62 63 64 65
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) {
66
        VIR_TEST_DEBUG("Wrong indentation");
E
Eric Blake 已提交
67 68 69
        ret = -1;
    }
    virBufferAdjustIndent(buf, 3);
70
    if (STRNEQ(virBufferCurrentContent(buf), "")) {
71
        VIR_TEST_DEBUG("Wrong content");
72 73
        ret = -1;
    }
E
Eric Blake 已提交
74 75 76
    if (virBufferGetIndent(buf, false) != 3 ||
        virBufferGetIndent(buf, true) != 3 ||
        virBufferError(buf)) {
77
        VIR_TEST_DEBUG("Wrong indentation");
E
Eric Blake 已提交
78 79 80 81 82 83
        ret = -1;
    }
    virBufferAdjustIndent(buf, -2);
    if (virBufferGetIndent(buf, false) != 1 ||
        virBufferGetIndent(buf, true) != 1 ||
        virBufferError(buf)) {
84
        VIR_TEST_DEBUG("Wrong indentation");
E
Eric Blake 已提交
85 86 87 88 89 90
        ret = -1;
    }
    virBufferAdjustIndent(buf, -3);
    if (virBufferGetIndent(buf, false) != -1 ||
        virBufferGetIndent(buf, true) != -1 ||
        virBufferError(buf) != -1) {
91
        VIR_TEST_DEBUG("Usage error not flagged");
E
Eric Blake 已提交
92 93 94 95 96 97
        ret = -1;
    }
    virBufferFreeAndReset(buf);
    if (virBufferGetIndent(buf, false) != 0 ||
        virBufferGetIndent(buf, true) != 0 ||
        virBufferError(buf)) {
98
        VIR_TEST_DEBUG("Reset didn't clear indentation");
E
Eric Blake 已提交
99 100 101 102
        ret = -1;
    }
    virBufferAdjustIndent(buf, 2);
    virBufferAddLit(buf, "1");
103
    if (virBufferError(buf)) {
104
        VIR_TEST_DEBUG("Buffer had error");
105 106
        return -1;
    }
107
    if (STRNEQ(virBufferCurrentContent(buf), "  1")) {
108
        VIR_TEST_DEBUG("Wrong content");
109 110
        ret = -1;
    }
E
Eric Blake 已提交
111 112
    if (virBufferGetIndent(buf, false) != 2 ||
        virBufferGetIndent(buf, true) != 0) {
113
        VIR_TEST_DEBUG("Wrong indentation");
E
Eric Blake 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
        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');

133
    if (virBufferError(buf)) {
134
        VIR_TEST_DEBUG("Buffer had error");
135 136 137
        return -1;
    }

E
Eric Blake 已提交
138 139
    result = virBufferContentAndReset(buf);
    if (!result || STRNEQ(result, expected)) {
140
        virTestDifference(stderr, expected, result);
E
Eric Blake 已提交
141 142 143 144 145 146
        ret = -1;
    }
    VIR_FREE(result);
    return ret;
}

147 148 149 150 151 152 153
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;
J
Ján Tomko 已提交
154 155

    virBufferTrim(buf, "", 0);
156 157 158
    buf = &bufinit;

    virBufferAddLit(buf, "a;");
J
Ján Tomko 已提交
159 160 161 162 163
    virBufferTrim(buf, "", 0);
    virBufferTrim(buf, "", -1);
    virBufferTrim(buf, NULL, 1);
    virBufferTrim(buf, NULL, 5);
    virBufferTrim(buf, "a", 2);
164 165

    virBufferAddLit(buf, ",b,,");
J
Ján Tomko 已提交
166 167 168
    virBufferTrim(buf, "b", -1);
    virBufferTrim(buf, "b,,", 1);
    virBufferTrim(buf, ",", -1);
169

170
    if (virBufferError(buf)) {
171
        VIR_TEST_DEBUG("Buffer had error");
172 173 174
        return -1;
    }

175 176
    result = virBufferContentAndReset(buf);
    if (!result || STRNEQ(result, expected)) {
177
        virTestDifference(stderr, expected, result);
178 179 180
        goto cleanup;
    }

J
Ján Tomko 已提交
181 182
    virBufferTrim(buf, NULL, -1);
    if (virBufferError(buf) != -1) {
183
        VIR_TEST_DEBUG("Usage error not flagged");
J
Ján Tomko 已提交
184 185 186
        goto cleanup;
    }

187 188
    ret = 0;

189
 cleanup:
190 191 192 193 194
    virBufferFreeAndReset(buf);
    VIR_FREE(result);
    return ret;
}

195 196 197 198 199 200 201 202 203
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" \
204 205 206 207 208 209 210 211 212 213 214 215
"  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" \
216 217 218
"  destroy an entire planet.\n";

    if (virBufferUse(&buf1)) {
219
        VIR_TEST_DEBUG("buf1 already in use");
220 221 222 223
        goto cleanup;
    }

    if (virBufferUse(&buf2)) {
224
        VIR_TEST_DEBUG("buf2 already in use");
225 226 227 228
        goto cleanup;
    }

    if (virBufferUse(&buf3)) {
229
        VIR_TEST_DEBUG("buf3 already in use");
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
        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)) {
254
        VIR_TEST_DEBUG("Error adding to buf1");
255 256 257 258
        goto cleanup;
    }

    if (!virBufferUse(&buf2)) {
259
        VIR_TEST_DEBUG("Error adding to buf2");
260 261 262 263
        goto cleanup;
    }

    if (!virBufferUse(&buf3)) {
264
        VIR_TEST_DEBUG("Error adding to buf3");
265 266 267 268 269 270
        goto cleanup;
    }

    virBufferAddBuffer(&buf2, &buf3);

    if (!virBufferUse(&buf2)) {
271
        VIR_TEST_DEBUG("buf2 cleared mistakenly");
272 273 274 275
        goto cleanup;
    }

    if (virBufferUse(&buf3)) {
276
        VIR_TEST_DEBUG("buf3 is not clear even though it should be");
277 278 279 280 281 282
        goto cleanup;
    }

    virBufferAddBuffer(&buf1, &buf2);

    if (!virBufferUse(&buf1)) {
283
        VIR_TEST_DEBUG("buf1 cleared mistakenly");
284 285 286 287
        goto cleanup;
    }

    if (virBufferUse(&buf2)) {
288
        VIR_TEST_DEBUG("buf2 is not clear even though it should be");
289 290 291 292 293
        goto cleanup;
    }

    result = virBufferContentAndReset(&buf1);
    if (STRNEQ_NULLABLE(result, expected)) {
294
        virTestDifference(stderr, expected, result);
295 296 297 298 299 300 301 302 303 304 305
        goto cleanup;
    }

    ret = 0;
 cleanup:
    virBufferFreeAndReset(&buf1);
    virBufferFreeAndReset(&buf2);
    VIR_FREE(result);
    return ret;
}

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
static int
testBufAddBuffer2(const void *opaque ATTRIBUTE_UNUSED)
{
    VIR_AUTOCLEAN(virBuffer) buf1 = VIR_BUFFER_INITIALIZER;
    VIR_AUTOCLEAN(virBuffer) buf2 = VIR_BUFFER_INITIALIZER;

    /* Intent of this test is to demonstrate a memleak that happen with
     * virBufferAddBuffer */

    virBufferAddLit(&buf1, "Hello world!\n");
    virBufferAddLit(&buf2, "Hello world!\n");

    /* Intentional usage error */
    virBufferAdjustIndent(&buf2, -2);

    virBufferAddBuffer(&buf1, &buf2);

    if (virBufferCurrentContent(&buf1) ||
        !virBufferCurrentContent(&buf2)) {
        VIR_TEST_DEBUG("Unexpected buffer content");
        return -1;
    }

    return 0;
}

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
struct testBufAddStrData {
    const char *data;
    const char *expect;
};

static int
testBufAddStr(const void *opaque ATTRIBUTE_UNUSED)
{
    const struct testBufAddStrData *data = opaque;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *actual;
    int ret = -1;

    virBufferAddLit(&buf, "<c>\n");
    virBufferAdjustIndent(&buf, 2);
    virBufferAddStr(&buf, data->data);
    virBufferAdjustIndent(&buf, -2);
    virBufferAddLit(&buf, "</c>");

    if (!(actual = virBufferContentAndReset(&buf))) {
352
        VIR_TEST_DEBUG("buf is empty");
353 354 355 356
        goto cleanup;
    }

    if (STRNEQ_NULLABLE(actual, data->expect)) {
357
        VIR_TEST_DEBUG("testBufAddStr(): Strings don't match:");
358
        virTestDifference(stderr, data->expect, actual);
359 360 361 362 363 364 365 366 367 368
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(actual);
    return ret;
}

369

370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
static int
testBufEscapeStr(const void *opaque ATTRIBUTE_UNUSED)
{
    const struct testBufAddStrData *data = opaque;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *actual;
    int ret = -1;

    virBufferAddLit(&buf, "<c>\n");
    virBufferAdjustIndent(&buf, 2);
    virBufferEscapeString(&buf, "<el>%s</el>\n", data->data);
    virBufferAdjustIndent(&buf, -2);
    virBufferAddLit(&buf, "</c>");

    if (!(actual = virBufferContentAndReset(&buf))) {
385
        VIR_TEST_DEBUG("buf is empty");
386 387 388 389
        goto cleanup;
    }

    if (STRNEQ_NULLABLE(actual, data->expect)) {
390
        VIR_TEST_DEBUG("testBufEscapeStr(): Strings don't match:");
391
        virTestDifference(stderr, data->expect, actual);
392 393 394 395 396 397 398 399 400 401 402
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(actual);
    return ret;
}


403 404 405 406 407 408 409 410 411 412 413
static int
testBufEscapeRegex(const void *opaque)
{
    const struct testBufAddStrData *data = opaque;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *actual;
    int ret = -1;

    virBufferEscapeRegex(&buf, "%s", data->data);

    if (!(actual = virBufferContentAndReset(&buf))) {
414
        VIR_TEST_DEBUG("testBufEscapeRegex: buf is empty");
415 416 417 418
        goto cleanup;
    }

    if (STRNEQ_NULLABLE(actual, data->expect)) {
419
        VIR_TEST_DEBUG("testBufEscapeRegex: Strings don't match:");
420 421 422 423 424 425 426 427 428 429 430 431
        virTestDifference(stderr, data->expect, actual);
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(actual);
    return ret;
}


432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
static int
testBufSetIndent(const void *opaque ATTRIBUTE_UNUSED)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *actual;
    int ret = -1;

    virBufferSetIndent(&buf, 11);
    virBufferAddLit(&buf, "test\n");
    virBufferSetIndent(&buf, 2);
    virBufferAddLit(&buf, "test2\n");

    if (!(actual = virBufferContentAndReset(&buf)))
        goto cleanup;

    if (STRNEQ(actual, "           test\n  test2\n")) {
448
        VIR_TEST_DEBUG("testBufSetIndent: expected indent not set");
449 450 451 452 453 454 455 456 457 458 459
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(actual);
    return ret;
}


460 461 462 463 464 465 466 467 468 469 470
/* Result of this shows up only in valgrind or similar */
static int
testBufferAutoclean(const void *opaque ATTRIBUTE_UNUSED)
{
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;

    virBufferAddLit(&buf, "test test test\n");
    return 0;
}


471
static int
E
Eric Blake 已提交
472
mymain(void)
473 474 475 476
{
    int ret = 0;


477 478 479 480 481
#define DO_TEST(msg, cb, data) \
    do { \
        struct testInfo info = { data }; \
        if (virTestRun("Buf: " msg, cb, &info) < 0) \
            ret = -1; \
482 483 484 485
    } while (0)

    DO_TEST("EscapeString infinite loop", testBufInfiniteLoop, 1);
    DO_TEST("VSprintf infinite loop", testBufInfiniteLoop, 0);
E
Eric Blake 已提交
486
    DO_TEST("Auto-indentation", testBufAutoIndent, 0);
487
    DO_TEST("Trim", testBufTrim, 0);
488
    DO_TEST("AddBuffer", testBufAddBuffer, 0);
489
    DO_TEST("AddBuffer2", testBufAddBuffer2, 0);
490
    DO_TEST("set indent", testBufSetIndent, 0);
491
    DO_TEST("autoclean", testBufferAutoclean, 0);
492

493 494 495 496 497
#define DO_TEST_ADD_STR(DATA, EXPECT) \
    do { \
        struct testBufAddStrData info = { DATA, EXPECT }; \
        if (virTestRun("Buf: AddStr", testBufAddStr, &info) < 0) \
            ret = -1; \
498 499 500 501 502 503 504
    } while (0)

    DO_TEST_ADD_STR("", "<c>\n</c>");
    DO_TEST_ADD_STR("<a/>", "<c>\n  <a/></c>");
    DO_TEST_ADD_STR("<a/>\n", "<c>\n  <a/>\n</c>");
    DO_TEST_ADD_STR("<b>\n  <a/>\n</b>\n", "<c>\n  <b>\n    <a/>\n  </b>\n</c>");

505 506 507
#define DO_TEST_ESCAPE(data, expect) \
    do { \
        struct testBufAddStrData info = { data, expect }; \
508
        if (virTestRun("Buf: EscapeStr", testBufEscapeStr, &info) < 0) \
509
            ret = -1; \
510 511 512 513 514 515 516 517 518 519 520
    } while (0)

    DO_TEST_ESCAPE("<td></td><td></td>",
                   "<c>\n  <el>&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;</el>\n</c>");
    DO_TEST_ESCAPE("\007\"&&\"\x15",
                   "<c>\n  <el>&quot;&amp;&amp;&quot;</el>\n</c>");
    DO_TEST_ESCAPE(",,'..',,",
                   "<c>\n  <el>,,&apos;..&apos;,,</el>\n</c>");
    DO_TEST_ESCAPE("\x01\x01\x02\x03\x05\x08",
                   "<c>\n  <el></el>\n</c>");

521 522 523 524 525
#define DO_TEST_ESCAPE_REGEX(data, expect) \
    do { \
        struct testBufAddStrData info = { data, expect }; \
        if (virTestRun("Buf: EscapeRegex", testBufEscapeRegex, &info) < 0) \
            ret = -1; \
526 527 528 529 530 531
    } while (0)

    DO_TEST_ESCAPE_REGEX("noescape", "noescape");
    DO_TEST_ESCAPE_REGEX("^$.|?*+()[]{}\\",
                         "\\^\\$\\.\\|\\?\\*\\+\\(\\)\\[\\]\\{\\}\\\\");

532
    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
533 534
}

535
VIR_TEST_MAIN(mymain)