virbuftest.c 13.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 23 24 25 26
{
    virBuffer bufinit = VIR_BUFFER_INITIALIZER;
    virBufferPtr buf = &bufinit;
    char *addstr = NULL, *bufret = NULL;
    int ret = -1;
    const struct testInfo *info = data;

    virBufferAddChar(buf, 'a');

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

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

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

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

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

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

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

145 146 147 148 149 150 151
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 已提交
152 153

    virBufferTrim(buf, "", 0);
154 155 156
    buf = &bufinit;

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

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

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

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

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

185 186
    ret = 0;

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

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

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

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

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

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

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

    virBufferAddBuffer(&buf2, &buf3);

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

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

    virBufferAddBuffer(&buf1, &buf2);

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

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

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

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

304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
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))) {
324
        VIR_TEST_DEBUG("buf is empty");
325 326 327 328
        goto cleanup;
    }

    if (STRNEQ_NULLABLE(actual, data->expect)) {
329
        VIR_TEST_DEBUG("testBufAddStr(): Strings don't match:\n");
330
        virTestDifference(stderr, data->expect, actual);
331 332 333 334 335 336 337 338 339 340
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(actual);
    return ret;
}

341

342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
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))) {
357
        VIR_TEST_DEBUG("buf is empty");
358 359 360 361
        goto cleanup;
    }

    if (STRNEQ_NULLABLE(actual, data->expect)) {
362
        VIR_TEST_DEBUG("testBufEscapeStr(): Strings don't match:\n");
363
        virTestDifference(stderr, data->expect, actual);
364 365 366 367 368 369 370 371 372 373 374
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(actual);
    return ret;
}


375 376 377 378 379 380 381 382 383 384 385
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))) {
386
        VIR_TEST_DEBUG("testBufEscapeRegex: buf is empty");
387 388 389 390
        goto cleanup;
    }

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

    ret = 0;

 cleanup:
    VIR_FREE(actual);
    return ret;
}


404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
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")) {
        VIR_TEST_DEBUG("testBufSetIndent: expected indent not set\n");
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(actual);
    return ret;
}


432
static int
E
Eric Blake 已提交
433
mymain(void)
434 435 436 437
{
    int ret = 0;


438 439 440 441 442
#define DO_TEST(msg, cb, data) \
    do { \
        struct testInfo info = { data }; \
        if (virTestRun("Buf: " msg, cb, &info) < 0) \
            ret = -1; \
443 444 445 446
    } while (0)

    DO_TEST("EscapeString infinite loop", testBufInfiniteLoop, 1);
    DO_TEST("VSprintf infinite loop", testBufInfiniteLoop, 0);
E
Eric Blake 已提交
447
    DO_TEST("Auto-indentation", testBufAutoIndent, 0);
448
    DO_TEST("Trim", testBufTrim, 0);
449
    DO_TEST("AddBuffer", testBufAddBuffer, 0);
450
    DO_TEST("set indent", testBufSetIndent, 0);
451

452 453 454 455 456
#define DO_TEST_ADD_STR(DATA, EXPECT) \
    do { \
        struct testBufAddStrData info = { DATA, EXPECT }; \
        if (virTestRun("Buf: AddStr", testBufAddStr, &info) < 0) \
            ret = -1; \
457 458 459 460 461 462 463
    } 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>");

464 465 466
#define DO_TEST_ESCAPE(data, expect) \
    do { \
        struct testBufAddStrData info = { data, expect }; \
467
        if (virTestRun("Buf: EscapeStr", testBufEscapeStr, &info) < 0) \
468
            ret = -1; \
469 470 471 472 473 474 475 476 477 478 479
    } 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>");

480 481 482 483 484
#define DO_TEST_ESCAPE_REGEX(data, expect) \
    do { \
        struct testBufAddStrData info = { data, expect }; \
        if (virTestRun("Buf: EscapeRegex", testBufEscapeRegex, &info) < 0) \
            ret = -1; \
485 486 487 488 489 490
    } while (0)

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

491
    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
492 493
}

494
VIR_TEST_MAIN(mymain)