commandtest.c 21.9 KB
Newer Older
1 2 3
/*
 * commandtest.c: Test the libCommand API
 *
E
Eric Blake 已提交
4
 * Copyright (C) 2010-2012 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 */

#include <config.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "testutils.h"
#include "internal.h"
#include "nodeinfo.h"
#include "util.h"
#include "memory.h"
#include "command.h"
E
Eric Blake 已提交
37
#include "virfile.h"
E
Eric Blake 已提交
38
#include "virpidfile.h"
39 40 41
#include "virterror_internal.h"

#define VIR_FROM_THIS VIR_FROM_NONE
42 43 44

#ifdef WIN32

45 46
int
main(void)
47
{
48
    return EXIT_AM_SKIP;
49 50 51 52
}

#else

53 54
static int checkoutput(const char *testname)
{
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
    int ret = -1;
    char *expectname = NULL;
    char *expectlog = NULL;
    char *actualname = NULL;
    char *actuallog = NULL;

    if (virAsprintf(&expectname, "%s/commanddata/%s.log", abs_srcdir,
                    testname) < 0)
        goto cleanup;
    if (virAsprintf(&actualname, "%s/commandhelper.log", abs_builddir) < 0)
        goto cleanup;

    if (virFileReadAll(expectname, 1024*64, &expectlog) < 0) {
        fprintf(stderr, "cannot read %s\n", expectname);
        goto cleanup;
    }

    if (virFileReadAll(actualname, 1024*64, &actuallog) < 0) {
        fprintf(stderr, "cannot read %s\n", actualname);
        goto cleanup;
    }

    if (STRNEQ(expectlog, actuallog)) {
        virtTestDifference(stderr, expectlog, actuallog);
        goto cleanup;
    }

    ret = 0;

cleanup:
85 86
    if (actualname)
        unlink(actualname);
87 88 89 90 91 92 93 94 95 96 97 98
    VIR_FREE(actuallog);
    VIR_FREE(actualname);
    VIR_FREE(expectlog);
    VIR_FREE(expectname);
    return ret;
}

/*
 * Run program, no args, inherit all ENV, keep CWD.
 * Only stdin/out/err open
 * No slot for return status must log error.
 */
99 100
static int test0(const void *unused ATTRIBUTE_UNUSED)
{
101 102 103 104 105 106
    virCommandPtr cmd;
    int ret = -1;

    cmd = virCommandNew(abs_builddir "/commandhelper-doesnotexist");
    if (virCommandRun(cmd, NULL) == 0)
        goto cleanup;
107 108

    if (virGetLastError() == NULL)
109
        goto cleanup;
110

111 112 113 114 115 116 117 118 119 120 121 122 123
    virResetLastError();
    ret = 0;

cleanup:
    virCommandFree(cmd);
    return ret;
}

/*
 * Run program, no args, inherit all ENV, keep CWD.
 * Only stdin/out/err open
 * Capturing return status must not log error.
 */
124 125
static int test1(const void *unused ATTRIBUTE_UNUSED)
{
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
    virCommandPtr cmd;
    int ret = -1;
    int status;

    cmd = virCommandNew(abs_builddir "/commandhelper-doesnotexist");
    if (virCommandRun(cmd, &status) < 0)
        goto cleanup;
    if (status == 0)
        goto cleanup;
    ret = 0;

cleanup:
    virCommandFree(cmd);
    return ret;
}

/*
 * Run program (twice), no args, inherit all ENV, keep CWD.
 * Only stdin/out/err open
 */
146 147
static int test2(const void *unused ATTRIBUTE_UNUSED)
{
148 149 150 151 152 153
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
    int ret;

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
154
        virCommandFree(cmd);
155 156 157 158 159 160 161 162 163 164 165
        return -1;
    }

    if ((ret = checkoutput("test2")) != 0) {
        virCommandFree(cmd);
        return ret;
    }

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
166
        virCommandFree(cmd);
167 168 169 170 171 172 173 174 175 176 177 178
        return -1;
    }

    virCommandFree(cmd);

    return checkoutput("test2");
}

/*
 * Run program, no args, inherit all ENV, keep CWD.
 * stdin/out/err + two extra FD open
 */
179 180
static int test3(const void *unused ATTRIBUTE_UNUSED)
{
181 182 183 184
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
    int newfd1 = dup(STDERR_FILENO);
    int newfd2 = dup(STDERR_FILENO);
    int newfd3 = dup(STDERR_FILENO);
E
Eric Blake 已提交
185
    int ret = -1;
186 187 188 189 190 191 192

    virCommandPreserveFD(cmd, newfd1);
    virCommandTransferFD(cmd, newfd3);

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
193
        goto cleanup;
194 195 196 197 198 199
    }

    if (fcntl(newfd1, F_GETFL) < 0 ||
        fcntl(newfd2, F_GETFL) < 0 ||
        fcntl(newfd3, F_GETFL) >= 0) {
        puts("fds in wrong state");
E
Eric Blake 已提交
200
        goto cleanup;
201 202
    }

E
Eric Blake 已提交
203 204 205
    ret = checkoutput("test3");

cleanup:
206 207 208
    virCommandFree(cmd);
    VIR_FORCE_CLOSE(newfd1);
    VIR_FORCE_CLOSE(newfd2);
E
Eric Blake 已提交
209
    return ret;
210 211 212 213 214 215 216 217
}


/*
 * Run program, no args, inherit all ENV, CWD is /
 * Only stdin/out/err open.
 * Daemonized
 */
218 219
static int test4(const void *unused ATTRIBUTE_UNUSED)
{
220
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
E
Eric Blake 已提交
221
    char *pidfile = virPidFileBuildPath(abs_builddir, "commandhelper");
E
Eric Blake 已提交
222 223 224 225 226
    pid_t pid;
    int ret = -1;

    if (!pidfile)
        goto cleanup;
227 228 229 230 231 232 233

    virCommandSetPidFile(cmd, pidfile);
    virCommandDaemonize(cmd);

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
234
        goto cleanup;
235 236
    }

E
Eric Blake 已提交
237
    if (virPidFileRead(abs_builddir, "commandhelper", &pid) < 0) {
238
        printf("cannot read pidfile\n");
E
Eric Blake 已提交
239
        goto cleanup;
240 241 242 243
    }
    while (kill(pid, 0) != -1)
        usleep(100*1000);

E
Eric Blake 已提交
244
    ret = checkoutput("test4");
245

E
Eric Blake 已提交
246 247
cleanup:
    virCommandFree(cmd);
248 249
    if (pidfile)
        unlink(pidfile);
250
    VIR_FREE(pidfile);
E
Eric Blake 已提交
251
    return ret;
252 253 254 255 256 257 258
}


/*
 * Run program, no args, inherit filtered ENV, keep CWD.
 * Only stdin/out/err open
 */
259 260
static int test5(const void *unused ATTRIBUTE_UNUSED)
{
261 262 263 264 265 266 267
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");

    virCommandAddEnvPassCommon(cmd);

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
268
        virCommandFree(cmd);
269 270 271 272 273 274 275 276 277 278 279 280 281
        return -1;
    }

    virCommandFree(cmd);

    return checkoutput("test5");
}


/*
 * Run program, no args, inherit filtered ENV, keep CWD.
 * Only stdin/out/err open
 */
282 283
static int test6(const void *unused ATTRIBUTE_UNUSED)
{
284 285 286 287 288 289 290 291
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");

    virCommandAddEnvPass(cmd, "DISPLAY");
    virCommandAddEnvPass(cmd, "DOESNOTEXIST");

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
292
        virCommandFree(cmd);
293 294 295 296 297 298 299 300 301 302 303 304 305
        return -1;
    }

    virCommandFree(cmd);

    return checkoutput("test6");
}


/*
 * Run program, no args, inherit filtered ENV, keep CWD.
 * Only stdin/out/err open
 */
306 307
static int test7(const void *unused ATTRIBUTE_UNUSED)
{
308 309 310 311 312 313 314 315 316
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");

    virCommandAddEnvPassCommon(cmd);
    virCommandAddEnvPass(cmd, "DISPLAY");
    virCommandAddEnvPass(cmd, "DOESNOTEXIST");

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
317
        virCommandFree(cmd);
318 319 320 321 322 323 324 325 326 327 328 329
        return -1;
    }

    virCommandFree(cmd);

    return checkoutput("test7");
}

/*
 * Run program, no args, inherit filtered ENV, keep CWD.
 * Only stdin/out/err open
 */
330 331
static int test8(const void *unused ATTRIBUTE_UNUSED)
{
332 333 334 335 336 337 338 339
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");

    virCommandAddEnvString(cmd, "LANG=C");
    virCommandAddEnvPair(cmd, "USER", "test");

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
340
        virCommandFree(cmd);
341 342 343 344 345 346 347 348 349 350 351 352 353
        return -1;
    }

    virCommandFree(cmd);

    return checkoutput("test8");
}


/*
 * Run program, some args, inherit all ENV, keep CWD.
 * Only stdin/out/err open
 */
354 355
static int test9(const void *unused ATTRIBUTE_UNUSED)
{
356 357
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
    const char* const args[] = { "arg1", "arg2", NULL };
358
    virBuffer buf = VIR_BUFFER_INITIALIZER;
359 360 361 362

    virCommandAddArg(cmd, "-version");
    virCommandAddArgPair(cmd, "-log", "bar.log");
    virCommandAddArgSet(cmd, args);
363 364 365 366 367 368 369 370 371 372 373
    virCommandAddArgBuffer(cmd, &buf);
    virBufferAddLit(&buf, "arg4");
    virCommandAddArgBuffer(cmd, &buf);
    virCommandAddArgList(cmd, "arg5", "arg6", NULL);

    if (virBufferUse(&buf)) {
        printf("Buffer not transferred\n");
        virBufferFreeAndReset(&buf);
        virCommandFree(cmd);
        return -1;
    }
374 375 376 377

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
378
        virCommandFree(cmd);
379 380 381 382 383 384 385 386 387 388 389 390 391
        return -1;
    }

    virCommandFree(cmd);

    return checkoutput("test9");
}


/*
 * Run program, some args, inherit all ENV, keep CWD.
 * Only stdin/out/err open
 */
392 393
static int test10(const void *unused ATTRIBUTE_UNUSED)
{
394 395 396 397 398 399 400 401 402 403
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
    const char *const args[] = {
        "-version", "-log=bar.log", NULL,
    };

    virCommandAddArgSet(cmd, args);

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
404
        virCommandFree(cmd);
405 406 407 408 409 410 411 412 413 414 415 416
        return -1;
    }

    virCommandFree(cmd);

    return checkoutput("test10");
}

/*
 * Run program, some args, inherit all ENV, keep CWD.
 * Only stdin/out/err open
 */
417 418
static int test11(const void *unused ATTRIBUTE_UNUSED)
{
419 420 421 422 423 424 425 426 427
    const char *args[] = {
        abs_builddir "/commandhelper",
        "-version", "-log=bar.log", NULL,
    };
    virCommandPtr cmd = virCommandNewArgs(args);

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
428
        virCommandFree(cmd);
429 430 431 432 433 434 435 436 437 438 439 440
        return -1;
    }

    virCommandFree(cmd);

    return checkoutput("test11");
}

/*
 * Run program, no args, inherit all ENV, keep CWD.
 * Only stdin/out/err open. Set stdin data
 */
441 442
static int test12(const void *unused ATTRIBUTE_UNUSED)
{
443 444 445 446 447 448 449
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");

    virCommandSetInputBuffer(cmd, "Hello World\n");

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
450
        virCommandFree(cmd);
451 452 453 454 455 456 457 458 459 460 461 462
        return -1;
    }

    virCommandFree(cmd);

    return checkoutput("test12");
}

/*
 * Run program, no args, inherit all ENV, keep CWD.
 * Only stdin/out/err open. Set stdin data
 */
463 464
static int test13(const void *unused ATTRIBUTE_UNUSED)
{
465 466 467 468 469 470 471 472 473 474 475 476 477
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
    char *outactual = NULL;
    const char *outexpect = "BEGIN STDOUT\n"
        "Hello World\n"
        "END STDOUT\n";
    int ret = -1;

    virCommandSetInputBuffer(cmd, "Hello World\n");
    virCommandSetOutputBuffer(cmd, &outactual);

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
478
        goto cleanup;
479
    }
E
Eric Blake 已提交
480 481
    if (!outactual)
        goto cleanup;
482 483

    virCommandFree(cmd);
E
Eric Blake 已提交
484
    cmd = NULL;
485 486

    if (!STREQ(outactual, outexpect)) {
E
Eric Blake 已提交
487
        virtTestDifference(stderr, outexpect, outactual);
488 489 490
        goto cleanup;
    }

E
Eric Blake 已提交
491
    ret = checkoutput("test13");
492 493

cleanup:
E
Eric Blake 已提交
494
    virCommandFree(cmd);
495 496 497 498 499 500 501 502
    VIR_FREE(outactual);
    return ret;
}

/*
 * Run program, no args, inherit all ENV, keep CWD.
 * Only stdin/out/err open. Set stdin data
 */
503 504
static int test14(const void *unused ATTRIBUTE_UNUSED)
{
505 506 507 508 509 510 511 512 513
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
    char *outactual = NULL;
    const char *outexpect = "BEGIN STDOUT\n"
        "Hello World\n"
        "END STDOUT\n";
    char *erractual = NULL;
    const char *errexpect = "BEGIN STDERR\n"
        "Hello World\n"
        "END STDERR\n";
514 515 516 517 518 519 520 521

    char *jointactual = NULL;
    const char *jointexpect = "BEGIN STDOUT\n"
        "BEGIN STDERR\n"
        "Hello World\n"
        "Hello World\n"
        "END STDOUT\n"
        "END STDERR\n";
522 523 524 525 526 527 528 529 530
    int ret = -1;

    virCommandSetInputBuffer(cmd, "Hello World\n");
    virCommandSetOutputBuffer(cmd, &outactual);
    virCommandSetErrorBuffer(cmd, &erractual);

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
E
Eric Blake 已提交
531
        goto cleanup;
532
    }
E
Eric Blake 已提交
533 534
    if (!outactual || !erractual)
        goto cleanup;
535 536

    virCommandFree(cmd);
537 538 539 540 541 542 543 544 545 546 547 548

    cmd = virCommandNew(abs_builddir "/commandhelper");
    virCommandSetInputBuffer(cmd, "Hello World\n");
    virCommandSetOutputBuffer(cmd, &jointactual);
    virCommandSetErrorBuffer(cmd, &jointactual);
    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
        goto cleanup;
    }
    if (!jointactual)
        goto cleanup;
549 550

    if (!STREQ(outactual, outexpect)) {
E
Eric Blake 已提交
551
        virtTestDifference(stderr, outexpect, outactual);
552 553 554
        goto cleanup;
    }
    if (!STREQ(erractual, errexpect)) {
E
Eric Blake 已提交
555
        virtTestDifference(stderr, errexpect, erractual);
556 557
        goto cleanup;
    }
558 559 560 561
    if (!STREQ(jointactual, jointexpect)) {
        virtTestDifference(stderr, jointexpect, jointactual);
        goto cleanup;
    }
562

E
Eric Blake 已提交
563
    ret = checkoutput("test14");
564 565

cleanup:
E
Eric Blake 已提交
566
    virCommandFree(cmd);
567 568
    VIR_FREE(outactual);
    VIR_FREE(erractual);
569
    VIR_FREE(jointactual);
570 571 572 573 574 575 576 577
    return ret;
}


/*
 * Run program, no args, inherit all ENV, change CWD.
 * Only stdin/out/err open
 */
578 579
static int test15(const void *unused ATTRIBUTE_UNUSED)
{
580
    virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
581 582
    char *cwd = NULL;
    int ret = -1;
583

584 585 586
    if (virAsprintf(&cwd, "%s/commanddata", abs_srcdir) < 0)
        goto cleanup;
    virCommandSetWorkingDirectory(cmd, cwd);
587 588 589 590

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
591
        goto cleanup;
592 593
    }

594 595 596 597
    ret = checkoutput("test15");

cleanup:
    VIR_FREE(cwd);
598 599
    virCommandFree(cmd);

600
    return ret;
601 602 603 604 605
}

/*
 * Don't run program; rather, log what would be run.
 */
606 607
static int test16(const void *unused ATTRIBUTE_UNUSED)
{
608
    virCommandPtr cmd = virCommandNew("true");
609
    char *outactual = NULL;
610
    const char *outexpect = "A=B true C";
611 612 613 614 615 616 617 618 619
    int ret = -1;
    int fd = -1;

    virCommandAddEnvPair(cmd, "A", "B");
    virCommandAddArg(cmd, "C");

    if ((outactual = virCommandToString(cmd)) == NULL) {
        virErrorPtr err = virGetLastError();
        printf("Cannot convert to string: %s\n", err->message);
E
Eric Blake 已提交
620
        goto cleanup;
621 622 623 624 625 626 627 628 629 630 631 632 633
    }
    if ((fd = open(abs_builddir "/commandhelper.log",
                   O_CREAT | O_TRUNC | O_WRONLY, 0600)) < 0) {
        printf("Cannot open log file: %s\n", strerror (errno));
        goto cleanup;
    }
    virCommandWriteArgLog(cmd, fd);
    if (VIR_CLOSE(fd) < 0) {
        printf("Cannot close log file: %s\n", strerror (errno));
        goto cleanup;
    }

    if (!STREQ(outactual, outexpect)) {
E
Eric Blake 已提交
634
        virtTestDifference(stderr, outexpect, outactual);
635 636
        goto cleanup;
    }
E
Eric Blake 已提交
637 638

    ret = checkoutput("test16");
639 640

cleanup:
E
Eric Blake 已提交
641
    virCommandFree(cmd);
642 643 644 645 646
    VIR_FORCE_CLOSE(fd);
    VIR_FREE(outactual);
    return ret;
}

647 648 649 650 651
/*
 * Test string handling when no output is present.
 */
static int test17(const void *unused ATTRIBUTE_UNUSED)
{
652
    virCommandPtr cmd = virCommandNew("true");
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
    int ret = -1;
    char *outbuf;
    char *errbuf;

    virCommandSetOutputBuffer(cmd, &outbuf);
    if (outbuf != NULL) {
        puts("buffer not sanitized at registration");
        goto cleanup;
    }

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
        goto cleanup;
    }

    if (!outbuf || *outbuf) {
        puts("output buffer is not an allocated empty string");
        goto cleanup;
    }
    VIR_FREE(outbuf);
    if ((outbuf = strdup("should not be leaked")) == NULL) {
        puts("test framework failure");
        goto cleanup;
    }

    virCommandSetErrorBuffer(cmd, &errbuf);
    if (errbuf != NULL) {
        puts("buffer not sanitized at registration");
        goto cleanup;
    }

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
        goto cleanup;
    }

    if (!outbuf || *outbuf || !errbuf || *errbuf) {
        puts("output buffers are not allocated empty strings");
        goto cleanup;
    }

    ret = 0;
cleanup:
    virCommandFree(cmd);
    VIR_FREE(outbuf);
    VIR_FREE(errbuf);
    return ret;
}

704 705 706 707 708 709
/*
 * Run long-running daemon, to ensure no hang.
 */
static int test18(const void *unused ATTRIBUTE_UNUSED)
{
    virCommandPtr cmd = virCommandNewArgList("sleep", "100", NULL);
E
Eric Blake 已提交
710
    char *pidfile = virPidFileBuildPath(abs_builddir, "commandhelper");
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727
    pid_t pid;
    int ret = -1;

    if (!pidfile)
        goto cleanup;

    virCommandSetPidFile(cmd, pidfile);
    virCommandDaemonize(cmd);

    alarm(5);
    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
        goto cleanup;
    }
    alarm(0);

E
Eric Blake 已提交
728
    if (virPidFileRead(abs_builddir, "commandhelper", &pid) < 0) {
729 730 731
        printf("cannot read pidfile\n");
        goto cleanup;
    }
732 733 734 735 736 737 738 739

    virCommandFree(cmd);
    cmd = NULL;
    if (kill(pid, 0) != 0) {
        printf("daemon should still be running\n");
        goto cleanup;
    }

740 741 742 743 744 745 746
    while (kill(pid, SIGINT) != -1)
        usleep(100*1000);

    ret = 0;

cleanup:
    virCommandFree(cmd);
747 748
    if (pidfile)
        unlink(pidfile);
749 750 751 752
    VIR_FREE(pidfile);
    return ret;
}

753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
/*
 * Asynchronously run long-running daemon, to ensure no hang.
 */
static int test19(const void *unused ATTRIBUTE_UNUSED)
{
    virCommandPtr cmd = virCommandNewArgList("sleep", "100", NULL);
    pid_t pid;
    int ret = -1;

    alarm(5);
    if (virCommandRunAsync(cmd, &pid) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
        goto cleanup;
    }

    if (kill(pid, 0) != 0) {
        printf("Child should still be running");
        goto cleanup;
    }

    virCommandAbort(cmd);

    if (kill(pid, 0) == 0) {
        printf("Child should be aborted");
        goto cleanup;
    }

    alarm(0);

    ret = 0;

cleanup:
    virCommandFree(cmd);
    return ret;
}
789

790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
/*
 * Run program, no args, inherit all ENV, keep CWD.
 * Ignore huge stdin data, to provoke SIGPIPE or EPIPE in parent.
 */
static int test20(const void *unused ATTRIBUTE_UNUSED)
{
    virCommandPtr cmd = virCommandNewArgList(abs_builddir "/commandhelper",
                                             "--close-stdin", NULL);
    char *buf;
    int ret = -1;

    struct sigaction sig_action;

    sig_action.sa_handler = SIG_IGN;
    sig_action.sa_flags = 0;
    sigemptyset(&sig_action.sa_mask);

    sigaction(SIGPIPE, &sig_action, NULL);

    if (virAsprintf(&buf, "1\n%100000d\n", 2) < 0) {
        virReportOOMError();
        goto cleanup;
    }
    virCommandSetInputBuffer(cmd, buf);

    if (virCommandRun(cmd, NULL) < 0) {
        virErrorPtr err = virGetLastError();
        printf("Cannot run child %s\n", err->message);
        goto cleanup;
    }

    ret = checkoutput("test20");
cleanup:
    virCommandFree(cmd);
    VIR_FREE(buf);
    return ret;
}

828 829 830 831 832 833 834 835 836 837 838 839
static const char *const newenv[] = {
    "PATH=/usr/bin:/bin",
    "HOSTNAME=test",
    "LANG=C",
    "HOME=/home/test",
    "USER=test",
    "LOGNAME=test"
    "TMPDIR=/tmp",
    "DISPLAY=:0.0",
    NULL
};

840
static int
E
Eric Blake 已提交
841
mymain(void)
842 843
{
    int ret = 0;
E
Eric Blake 已提交
844
    int fd;
845 846

    if (chdir("/tmp") < 0)
847
        return EXIT_FAILURE;
848

849
    setpgid(0, 0);
S
Stefan Berger 已提交
850
    ignore_value(setsid());
851

852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
    /* Our test expects particular fd values; to get that, we must not
     * leak fds that we inherited from a lazy parent.  At the same
     * time, virInitialize may open some fds (perhaps via third-party
     * libraries that it uses), and we must not kill off an fd that
     * this process opens as it might break expectations of a
     * pthread_atfork handler, as well as interfering with our tests
     * trying to ensure we aren't leaking to our children.  The
     * solution is to do things in two phases - reserve the fds we
     * want by overwriting any externally inherited fds, then
     * initialize, then clear the slots for testing.  */
    if ((fd = open("/dev/null", O_RDONLY)) < 0 ||
        dup2(fd, 3) < 0 ||
        dup2(fd, 4) < 0 ||
        dup2(fd, 5) < 0 ||
        (fd > 5 && VIR_CLOSE(fd) < 0))
        return EXIT_FAILURE;
868 869 870

    /* Prime the debug/verbose settings from the env vars,
     * since we're about to reset 'environ' */
S
Stefan Berger 已提交
871 872
    ignore_value(virTestGetDebug());
    ignore_value(virTestGetVerbose());
873

S
Stefan Berger 已提交
874 875
    if (virInitialize() < 0)
        return EXIT_FAILURE;
876 877

    /* Phase two of killing interfering fds; see above.  */
E
Eric Blake 已提交
878 879 880 881 882 883
    fd = 3;
    VIR_FORCE_CLOSE(fd);
    fd = 4;
    VIR_FORCE_CLOSE(fd);
    fd = 5;
    VIR_FORCE_CLOSE(fd);
884

885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908
    environ = (char **)newenv;

# define DO_TEST(NAME)                                                \
    if (virtTestRun("Command Exec " #NAME " test",                    \
                    1, NAME, NULL) < 0)                               \
        ret = -1

    DO_TEST(test0);
    DO_TEST(test1);
    DO_TEST(test2);
    DO_TEST(test3);
    DO_TEST(test4);
    DO_TEST(test5);
    DO_TEST(test6);
    DO_TEST(test7);
    DO_TEST(test8);
    DO_TEST(test9);
    DO_TEST(test10);
    DO_TEST(test11);
    DO_TEST(test12);
    DO_TEST(test13);
    DO_TEST(test14);
    DO_TEST(test15);
    DO_TEST(test16);
909
    DO_TEST(test17);
910
    DO_TEST(test18);
911
    DO_TEST(test19);
912
    DO_TEST(test20);
913

914
    return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
915 916 917
}

VIRT_TEST_MAIN(mymain)
918 919

#endif /* !WIN32 */