Files
libvirt/tests/commandtest.c
T

1341 lines
34 KiB
C
Raw Normal View History

2010-05-25 12:14:06 +01:00
/*
* commandtest.c: Test the libCommand API
*
* Copyright (C) 2010-2014 Red Hat, Inc.
2010-05-25 12:14:06 +01:00
*
* 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, see
2012-07-21 18:06:23 +08:00
* <http://www.gnu.org/licenses/>.
2010-05-25 12:14:06 +01:00
*/
#include <config.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
2020-01-16 11:38:18 +00:00
#ifndef WIN32
# include <sys/wait.h>
# include <poll.h>
2020-01-16 11:38:18 +00:00
#endif
2010-05-25 12:14:06 +01:00
#include <fcntl.h>
#include "testutils.h"
#include "internal.h"
2012-12-12 18:06:53 +00:00
#include "viralloc.h"
2012-12-12 16:27:01 +00:00
#include "vircommand.h"
2011-07-19 12:32:58 -06:00
#include "virfile.h"
2011-08-12 15:54:49 -06:00
#include "virpidfile.h"
#include "virerror.h"
#include "virprocess.h"
2020-02-16 22:59:28 +01:00
#include "virutil.h"
2012-05-31 15:50:07 -06:00
#define VIR_FROM_THIS VIR_FROM_NONE
2010-05-25 12:14:06 +01:00
#ifdef WIN32
2011-07-28 17:48:12 +02:00
int
main(void)
2010-05-25 12:14:06 +01:00
{
2011-07-28 17:48:12 +02:00
return EXIT_AM_SKIP;
2010-05-25 12:14:06 +01:00
}
#else
2020-01-07 16:16:19 +00:00
/* Some UNIX lack it in headers & it doesn't hurt to redeclare */
extern char **environ;
static int checkoutput(const char *testname)
2010-12-06 11:51:41 +01:00
{
2010-05-25 12:14:06 +01:00
int ret = -1;
2020-07-28 02:30:59 +02:00
g_autofree char *expectname = NULL;
g_autofree char *actualname = NULL;
g_autofree char *actuallog = NULL;
2010-05-25 12:14:06 +01:00
expectname = g_strdup_printf("%s/commanddata/%s.log", abs_srcdir, testname);
actualname = g_strdup_printf("%s/commandhelper.log", abs_builddir);
2010-05-25 12:14:06 +01:00
if (virFileReadAll(actualname, 1024*64, &actuallog) < 0) {
fprintf(stderr, "cannot read %s\n", actualname);
goto cleanup;
}
ret = virTestCompareToFile(actuallog, expectname);
2010-05-25 12:14:06 +01:00
cleanup:
2011-05-03 10:37:13 -06:00
if (actualname)
unlink(actualname);
2010-05-25 12:14:06 +01:00
return ret;
}
/*
* Run program, no args, inherit all ENV, keep CWD.
* Only stdin/out/err open
* No slot for return status must log error.
*/
2019-10-14 14:45:03 +02:00
static int test0(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = NULL;
2010-05-25 12:14:06 +01:00
cmd = virCommandNew(abs_builddir "/commandhelper-doesnotexist");
if (virCommandRun(cmd, NULL) == 0)
2020-07-28 02:51:27 +02:00
return -1;
2010-12-06 12:58:56 +01:00
if (virGetLastErrorCode() == VIR_ERR_OK)
2020-07-28 02:51:27 +02:00
return -1;
2010-12-06 12:58:56 +01:00
2010-05-25 12:14:06 +01:00
virResetLastError();
2020-07-28 02:51:27 +02:00
return 0;
2010-05-25 12:14:06 +01:00
}
/*
* Run program, no args, inherit all ENV, keep CWD.
* Only stdin/out/err open
* Capturing return status must not log error.
*/
2019-10-14 14:45:03 +02:00
static int test1(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = NULL;
2010-05-25 12:14:06 +01:00
int status;
cmd = virCommandNew(abs_builddir "/commandhelper-doesnotexist");
if (virCommandRun(cmd, &status) < 0)
2020-07-28 02:51:27 +02:00
return -1;
if (status != EXIT_ENOENT)
2020-07-28 02:51:27 +02:00
return -1;
virCommandRawStatus(cmd);
2010-05-25 12:14:06 +01:00
if (virCommandRun(cmd, &status) < 0)
2020-07-28 02:51:27 +02:00
return -1;
if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_ENOENT)
2020-07-28 02:51:27 +02:00
return -1;
2010-05-25 12:14:06 +01:00
2020-07-28 02:51:27 +02:00
return 0;
2010-05-25 12:14:06 +01:00
}
/*
* Run program (twice), no args, inherit all ENV, keep CWD.
* Only stdin/out/err open
*/
2019-10-14 14:45:03 +02:00
static int test2(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2010-05-25 12:14:06 +01:00
int ret;
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-05-25 12:14:06 +01:00
return -1;
}
if ((ret = checkoutput("test2")) != 0)
2010-05-25 12:14:06 +01:00
return ret;
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-05-25 12:14:06 +01:00
return -1;
}
return checkoutput("test2");
2010-05-25 12:14:06 +01:00
}
/*
* Run program, no args, inherit all ENV, keep CWD.
* stdin/out/err + two extra FD open
*/
2019-10-14 14:45:03 +02:00
static int test3(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2020-07-28 02:42:01 +02:00
VIR_AUTOCLOSE newfd1 = dup(STDERR_FILENO);
VIR_AUTOCLOSE newfd2 = dup(STDERR_FILENO);
2010-05-25 12:14:06 +01:00
int newfd3 = dup(STDERR_FILENO);
2020-01-17 10:52:46 +00:00
struct stat before, after;
2010-05-25 12:14:06 +01:00
2020-01-17 10:52:46 +00:00
if (fstat(newfd3, &before) < 0) {
perror("fstat");
2020-07-28 02:51:27 +02:00
return -1;
2020-01-17 10:52:46 +00:00
}
virCommandPassFD(cmd, newfd1, 0);
virCommandPassFD(cmd, newfd3,
VIR_COMMAND_PASS_FD_CLOSE_PARENT);
2010-05-25 12:14:06 +01:00
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2020-07-28 02:51:27 +02:00
return -1;
2010-05-25 12:14:06 +01:00
}
if (fcntl(newfd1, F_GETFL) < 0 ||
2020-01-17 10:52:46 +00:00
fcntl(newfd2, F_GETFL) < 0) {
puts("fds 1/2 were not open");
2020-07-28 02:51:27 +02:00
return -1;
2010-05-25 12:14:06 +01:00
}
2020-01-17 10:52:46 +00:00
/* We expect newfd3 to be closed, but the
* fd might have already been reused by
* the event loop. So if it is open, we
* check if it matches the stat info we
* got earlier
*/
if (fcntl(newfd3, F_GETFL) >= 0 &&
fstat(newfd3, &after) >= 0) {
if (before.st_ino == after.st_ino &&
before.st_dev == after.st_dev &&
before.st_mode == after.st_mode) {
puts("fd 3 should not be open");
2020-07-28 02:51:27 +02:00
return -1;
2020-01-17 10:52:46 +00:00
}
}
2020-07-28 02:51:27 +02:00
return checkoutput("test3");
2010-05-25 12:14:06 +01:00
}
/*
* Run program, no args, inherit all ENV, CWD is /
* Only stdin/out/err open.
* Daemonized
*/
2019-10-14 14:45:03 +02:00
static int test4(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNewArgList(abs_builddir "/commandhelper",
"--check-daemonize", NULL);
2020-07-28 02:30:59 +02:00
g_autofree char *pidfile = virPidFileBuildPath(abs_builddir, "commandhelper");
2010-12-06 14:48:11 -07:00
pid_t pid;
int ret = -1;
if (!pidfile)
goto cleanup;
2010-05-25 12:14:06 +01:00
virCommandSetPidFile(cmd, pidfile);
virCommandDaemonize(cmd);
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-12-06 14:48:11 -07:00
goto cleanup;
2010-05-25 12:14:06 +01:00
}
2011-08-12 15:54:49 -06:00
if (virPidFileRead(abs_builddir, "commandhelper", &pid) < 0) {
2010-05-25 12:14:06 +01:00
printf("cannot read pidfile\n");
2010-12-06 14:48:11 -07:00
goto cleanup;
2010-05-25 12:14:06 +01:00
}
while (kill(pid, 0) != -1)
g_usleep(100*1000);
2010-05-25 12:14:06 +01:00
ret = checkoutput("test4");
2010-05-25 12:14:06 +01:00
cleanup:
2011-05-03 10:37:13 -06:00
if (pidfile)
unlink(pidfile);
2010-12-06 14:48:11 -07:00
return ret;
2010-05-25 12:14:06 +01:00
}
/*
* Run program, no args, inherit filtered ENV, keep CWD.
* Only stdin/out/err open
*/
2019-10-14 14:45:03 +02:00
static int test5(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2010-05-25 12:14:06 +01:00
virCommandAddEnvPassCommon(cmd);
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-05-25 12:14:06 +01:00
return -1;
}
return checkoutput("test5");
2010-05-25 12:14:06 +01:00
}
/*
* Run program, no args, inherit filtered ENV, keep CWD.
* Only stdin/out/err open
*/
2019-10-14 14:45:03 +02:00
static int test6(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2010-05-25 12:14:06 +01:00
virCommandAddEnvPass(cmd, "DISPLAY");
virCommandAddEnvPass(cmd, "DOESNOTEXIST");
2010-05-25 12:14:06 +01:00
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-05-25 12:14:06 +01:00
return -1;
}
return checkoutput("test6");
2010-05-25 12:14:06 +01:00
}
/*
* Run program, no args, inherit filtered ENV, keep CWD.
* Only stdin/out/err open
*/
2019-10-14 14:45:03 +02:00
static int test7(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2010-05-25 12:14:06 +01:00
virCommandAddEnvPassCommon(cmd);
virCommandAddEnvPass(cmd, "DISPLAY");
virCommandAddEnvPass(cmd, "DOESNOTEXIST");
2010-05-25 12:14:06 +01:00
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-05-25 12:14:06 +01:00
return -1;
}
return checkoutput("test7");
2010-05-25 12:14:06 +01:00
}
/*
* Run program, no args, inherit filtered ENV, keep CWD.
* Only stdin/out/err open
*/
2019-10-14 14:45:03 +02:00
static int test8(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2010-05-25 12:14:06 +01:00
2012-09-24 17:04:46 -06:00
virCommandAddEnvString(cmd, "USER=bogus");
2010-05-25 12:14:06 +01:00
virCommandAddEnvString(cmd, "LANG=C");
2012-09-24 17:04:46 -06:00
virCommandAddEnvPair(cmd, "USER", "also bogus");
2010-05-25 12:14:06 +01:00
virCommandAddEnvPair(cmd, "USER", "test");
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-05-25 12:14:06 +01:00
return -1;
}
return checkoutput("test8");
2010-05-25 12:14:06 +01:00
}
/*
* Run program, some args, inherit all ENV, keep CWD.
* Only stdin/out/err open
*/
2019-10-14 14:45:03 +02:00
static int test9(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2010-05-25 12:14:06 +01:00
const char* const args[] = { "arg1", "arg2", NULL };
2020-07-02 19:35:41 -04:00
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
2010-05-25 12:14:06 +01:00
virCommandAddArg(cmd, "-version");
virCommandAddArgPair(cmd, "-log", "bar.log");
virCommandAddArgSet(cmd, args);
virCommandAddArgBuffer(cmd, &buf);
virBufferAddLit(&buf, "arg4");
virCommandAddArgBuffer(cmd, &buf);
virCommandAddArgList(cmd, "arg5", "arg6", NULL);
if (virBufferUse(&buf)) {
printf("Buffer not transferred\n");
return -1;
}
2010-05-25 12:14:06 +01:00
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-05-25 12:14:06 +01:00
return -1;
}
return checkoutput("test9");
2010-05-25 12:14:06 +01:00
}
/*
* Run program, some args, inherit all ENV, keep CWD.
* Only stdin/out/err open
*/
2019-10-14 14:45:03 +02:00
static int test10(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2010-05-25 12:14:06 +01:00
const char *const args[] = {
"-version", "-log=bar.log", NULL,
};
virCommandAddArgSet(cmd, args);
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-05-25 12:14:06 +01:00
return -1;
}
return checkoutput("test10");
2010-05-25 12:14:06 +01:00
}
/*
* Run program, some args, inherit all ENV, keep CWD.
* Only stdin/out/err open
*/
2019-10-14 14:45:03 +02:00
static int test11(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
2010-05-25 12:14:06 +01:00
const char *args[] = {
abs_builddir "/commandhelper",
"-version", "-log=bar.log", NULL,
};
g_autoptr(virCommand) cmd = virCommandNewArgs(args);
2010-05-25 12:14:06 +01:00
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-05-25 12:14:06 +01:00
return -1;
}
return checkoutput("test11");
2010-05-25 12:14:06 +01:00
}
/*
* Run program, no args, inherit all ENV, keep CWD.
* Only stdin/out/err open. Set stdin data
*/
2019-10-14 14:45:03 +02:00
static int test12(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2010-05-25 12:14:06 +01:00
virCommandSetInputBuffer(cmd, "Hello World\n");
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-05-25 12:14:06 +01:00
return -1;
}
return checkoutput("test12");
2010-05-25 12:14:06 +01:00
}
/*
* Run program, no args, inherit all ENV, keep CWD.
* Only stdin/out/err open. Set stdin data
*/
2019-10-14 14:45:03 +02:00
static int test13(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
2021-03-11 08:16:13 +01:00
virCommand *cmd = virCommandNew(abs_builddir "/commandhelper");
2020-07-28 02:30:59 +02:00
g_autofree char *outactual = NULL;
2010-05-25 12:14:06 +01:00
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) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-12-06 14:48:11 -07:00
goto cleanup;
2010-05-25 12:14:06 +01:00
}
2010-12-06 14:48:11 -07:00
if (!outactual)
goto cleanup;
2010-05-25 12:14:06 +01:00
2022-01-28 18:42:45 +01:00
g_clear_pointer(&cmd, virCommandFree);
2010-05-25 12:14:06 +01:00
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(outexpect, outactual) < 0) {
2010-05-25 12:14:06 +01:00
goto cleanup;
}
ret = checkoutput("test13");
2010-05-25 12:14:06 +01:00
cleanup:
2010-12-06 14:48:11 -07:00
virCommandFree(cmd);
2010-05-25 12:14:06 +01:00
return ret;
}
/*
* Run program, no args, inherit all ENV, keep CWD.
* Only stdin/out/err open. Set stdin data
*/
2019-10-14 14:45:03 +02:00
static int test14(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
2021-03-11 08:16:13 +01:00
virCommand *cmd = virCommandNew(abs_builddir "/commandhelper");
2020-07-28 02:30:59 +02:00
g_autofree char *outactual = NULL;
2010-05-25 12:14:06 +01:00
const char *outexpect = "BEGIN STDOUT\n"
"Hello World\n"
"END STDOUT\n";
2020-07-28 02:30:59 +02:00
g_autofree char *erractual = NULL;
2010-05-25 12:14:06 +01:00
const char *errexpect = "BEGIN STDERR\n"
"Hello World\n"
"END STDERR\n";
2020-07-28 02:30:59 +02:00
g_autofree char *jointactual = NULL;
const char *jointexpect = "BEGIN STDOUT\n"
"BEGIN STDERR\n"
"Hello World\n"
"Hello World\n"
"END STDOUT\n"
"END STDERR\n";
2010-05-25 12:14:06 +01:00
int ret = -1;
virCommandSetInputBuffer(cmd, "Hello World\n");
virCommandSetOutputBuffer(cmd, &outactual);
virCommandSetErrorBuffer(cmd, &erractual);
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-12-06 14:48:11 -07:00
goto cleanup;
2010-05-25 12:14:06 +01:00
}
2010-12-06 14:48:11 -07:00
if (!outactual || !erractual)
goto cleanup;
2010-05-25 12:14:06 +01:00
virCommandFree(cmd);
cmd = virCommandNew(abs_builddir "/commandhelper");
virCommandSetInputBuffer(cmd, "Hello World\n");
virCommandSetOutputBuffer(cmd, &jointactual);
virCommandSetErrorBuffer(cmd, &jointactual);
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
goto cleanup;
}
if (!jointactual)
goto cleanup;
2010-05-25 12:14:06 +01:00
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(outexpect, outactual) < 0) {
2010-05-25 12:14:06 +01:00
goto cleanup;
}
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(errexpect, erractual) < 0) {
2010-05-25 12:14:06 +01:00
goto cleanup;
}
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(jointexpect, jointactual) < 0) {
goto cleanup;
}
2010-05-25 12:14:06 +01:00
ret = checkoutput("test14");
2010-05-25 12:14:06 +01:00
cleanup:
2010-12-06 14:48:11 -07:00
virCommandFree(cmd);
2010-05-25 12:14:06 +01:00
return ret;
}
/*
* Run program, no args, inherit all ENV, change CWD.
* Only stdin/out/err open
*/
2019-10-14 14:45:03 +02:00
static int test15(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2020-07-28 02:30:59 +02:00
g_autofree char *cwd = NULL;
2010-05-25 12:14:06 +01:00
cwd = g_strdup_printf("%s/commanddata", abs_srcdir);
2010-12-06 13:03:26 +01:00
virCommandSetWorkingDirectory(cmd, cwd);
2014-09-03 09:13:21 -06:00
virCommandSetUmask(cmd, 002);
2010-05-25 12:14:06 +01:00
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2020-07-28 02:51:27 +02:00
return -1;
2010-05-25 12:14:06 +01:00
}
2020-07-28 02:51:27 +02:00
return checkoutput("test15");
2010-05-25 12:14:06 +01:00
}
/*
* Don't run program; rather, log what would be run.
*/
2019-10-14 14:45:03 +02:00
static int test16(const void *unused G_GNUC_UNUSED)
2010-12-06 11:51:41 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew("true");
2020-07-28 02:30:59 +02:00
g_autofree char *outactual = NULL;
2012-08-28 11:11:45 -07:00
const char *outexpect = "A=B C='D E' true F 'G H'";
2020-07-28 02:42:01 +02:00
VIR_AUTOCLOSE fd = -1;
2010-05-25 12:14:06 +01:00
virCommandAddEnvPair(cmd, "A", "B");
2012-08-28 11:11:45 -07:00
virCommandAddEnvPair(cmd, "C", "D E");
virCommandAddArg(cmd, "F");
virCommandAddArg(cmd, "G H");
2010-05-25 12:14:06 +01:00
if ((outactual = virCommandToString(cmd, false)) == NULL) {
printf("Cannot convert to string: %s\n", virGetLastErrorMessage());
2020-07-28 02:51:27 +02:00
return -1;
2010-05-25 12:14:06 +01:00
}
if ((fd = open(abs_builddir "/commandhelper.log",
O_CREAT | O_TRUNC | O_WRONLY, 0600)) < 0) {
printf("Cannot open log file: %s\n", g_strerror(errno));
2020-07-28 02:51:27 +02:00
return -1;
2010-05-25 12:14:06 +01:00
}
virCommandWriteArgLog(cmd, fd);
if (VIR_CLOSE(fd) < 0) {
printf("Cannot close log file: %s\n", g_strerror(errno));
2020-07-28 02:51:27 +02:00
return -1;
2010-05-25 12:14:06 +01:00
}
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(outexpect, outactual) < 0) {
2020-07-28 02:51:27 +02:00
return -1;
2010-05-25 12:14:06 +01:00
}
2010-12-06 14:48:11 -07:00
2020-07-28 02:51:27 +02:00
return checkoutput("test16");
2010-05-25 12:14:06 +01:00
}
2010-12-03 14:14:16 -07:00
/*
* Test string handling when no output is present.
*/
2019-10-14 14:45:03 +02:00
static int test17(const void *unused G_GNUC_UNUSED)
2010-12-03 14:14:16 -07:00
{
g_autoptr(virCommand) cmd = virCommandNew("true");
2010-12-03 14:14:16 -07:00
int ret = -1;
2020-07-28 02:30:59 +02:00
char *outbuf = NULL;
g_autofree char *errbuf = NULL;
2010-12-03 14:14:16 -07:00
virCommandSetOutputBuffer(cmd, &outbuf);
if (outbuf != NULL) {
puts("buffer not sanitized at registration");
goto cleanup;
}
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-12-03 14:14:16 -07:00
goto cleanup;
}
if (*outbuf) {
2010-12-03 14:14:16 -07:00
puts("output buffer is not an allocated empty string");
goto cleanup;
}
VIR_FREE(outbuf);
2019-10-20 13:49:46 +02:00
outbuf = g_strdup("should not be leaked");
2010-12-03 14:14:16 -07:00
virCommandSetErrorBuffer(cmd, &errbuf);
if (errbuf != NULL) {
puts("buffer not sanitized at registration");
goto cleanup;
}
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-12-03 14:14:16 -07:00
goto cleanup;
}
if (*outbuf || *errbuf) {
2010-12-03 14:14:16 -07:00
puts("output buffers are not allocated empty strings");
goto cleanup;
}
ret = 0;
cleanup:
2010-12-03 14:14:16 -07:00
VIR_FREE(outbuf);
return ret;
}
2010-12-21 11:49:49 -07:00
/*
* Run long-running daemon, to ensure no hang.
*/
2019-10-14 14:45:03 +02:00
static int test18(const void *unused G_GNUC_UNUSED)
2010-12-21 11:49:49 -07:00
{
2021-03-11 08:16:13 +01:00
virCommand *cmd = virCommandNewArgList("sleep", "100", NULL);
2020-07-28 02:30:59 +02:00
g_autofree char *pidfile = virPidFileBuildPath(abs_builddir, "commandhelper");
2010-12-21 11:49:49 -07:00
pid_t pid;
int ret = -1;
if (!pidfile)
goto cleanup;
virCommandSetPidFile(cmd, pidfile);
virCommandDaemonize(cmd);
alarm(5);
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2010-12-21 11:49:49 -07:00
goto cleanup;
}
alarm(0);
2011-08-12 15:54:49 -06:00
if (virPidFileRead(abs_builddir, "commandhelper", &pid) < 0) {
2010-12-21 11:49:49 -07:00
printf("cannot read pidfile\n");
goto cleanup;
}
2022-01-28 18:42:45 +01:00
g_clear_pointer(&cmd, virCommandFree);
if (kill(pid, 0) != 0) {
printf("daemon should still be running\n");
goto cleanup;
}
2010-12-21 11:49:49 -07:00
while (kill(pid, SIGINT) != -1)
g_usleep(100*1000);
2010-12-21 11:49:49 -07:00
ret = 0;
cleanup:
2010-12-21 11:49:49 -07:00
virCommandFree(cmd);
2011-05-03 10:37:13 -06:00
if (pidfile)
unlink(pidfile);
2010-12-21 11:49:49 -07:00
return ret;
}
/*
* Asynchronously run long-running daemon, to ensure no hang.
*/
2019-10-14 14:45:03 +02:00
static int test19(const void *unused G_GNUC_UNUSED)
{
g_autoptr(virCommand) cmd = virCommandNewArgList("sleep", "100", NULL);
pid_t pid;
alarm(5);
if (virCommandRunAsync(cmd, &pid) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2020-07-28 02:51:27 +02:00
return -1;
}
if (kill(pid, 0) != 0) {
printf("Child should still be running");
2020-07-28 02:51:27 +02:00
return -1;
}
virCommandAbort(cmd);
if (kill(pid, 0) == 0) {
printf("Child should be aborted");
2020-07-28 02:51:27 +02:00
return -1;
}
alarm(0);
2020-07-28 02:51:27 +02:00
return 0;
}
2010-12-21 11:49:49 -07:00
2012-05-31 15:50:07 -06:00
/*
* Run program, no args, inherit all ENV, keep CWD.
* Ignore huge stdin data, to provoke SIGPIPE or EPIPE in parent.
*/
2019-10-14 14:45:03 +02:00
static int test20(const void *unused G_GNUC_UNUSED)
2012-05-31 15:50:07 -06:00
{
g_autoptr(virCommand) cmd = virCommandNewArgList(abs_builddir "/commandhelper",
"--close-stdin", NULL);
2020-07-28 02:30:59 +02:00
g_autofree char *buf = NULL;
2012-05-31 15:50:07 -06:00
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);
buf = g_strdup_printf("1\n%100000d\n", 2);
2012-05-31 15:50:07 -06:00
virCommandSetInputBuffer(cmd, buf);
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2020-07-28 02:51:27 +02:00
return -1;
2012-05-31 15:50:07 -06:00
}
2020-07-28 02:51:27 +02:00
return checkoutput("test20");
2012-05-31 15:50:07 -06:00
}
2011-05-11 09:51:30 -06:00
static const char *const newenv[] = {
"PATH=/usr/bin:/bin",
"HOSTNAME=test",
"LANG=C",
"HOME=/home/test",
"USER=test",
2017-11-17 16:17:38 +03:00
"LOGNAME=test",
2011-05-11 09:51:30 -06:00
"TMPDIR=/tmp",
"DISPLAY=:0.0",
NULL
};
2019-10-14 14:45:03 +02:00
static int test21(const void *unused G_GNUC_UNUSED)
2013-01-16 18:55:06 +01:00
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
2013-01-16 18:55:06 +01:00
const char *wrbuf = "Hello world\n";
2020-07-28 02:30:59 +02:00
g_autofree char *outbuf = NULL;
g_autofree char *errbuf = NULL;
const char *outbufExpected = "BEGIN STDOUT\n"
2013-01-16 18:55:06 +01:00
"Hello world\n"
"END STDOUT\n";
const char *errbufExpected = "BEGIN STDERR\n"
2013-01-16 18:55:06 +01:00
"Hello world\n"
"END STDERR\n";
virCommandSetInputBuffer(cmd, wrbuf);
virCommandSetOutputBuffer(cmd, &outbuf);
virCommandSetErrorBuffer(cmd, &errbuf);
virCommandDoAsyncIO(cmd);
if (virCommandRunAsync(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
2020-07-28 02:51:27 +02:00
return -1;
2013-01-16 18:55:06 +01:00
}
if (virCommandWait(cmd, NULL) < 0)
2020-07-28 02:51:27 +02:00
return -1;
2013-01-16 18:55:06 +01:00
if (virTestGetVerbose())
printf("STDOUT:%s\nSTDERR:%s\n", NULLSTR(outbuf), NULLSTR(errbuf));
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(outbufExpected, outbuf) < 0) {
2020-07-28 02:51:27 +02:00
return -1;
2013-01-16 18:55:06 +01:00
}
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(errbufExpected, errbuf) < 0) {
2020-07-28 02:51:27 +02:00
return -1;
2013-01-16 18:55:06 +01:00
}
2020-07-28 02:51:27 +02:00
return checkoutput("test21");
2013-01-16 18:55:06 +01:00
}
static int
2019-10-14 14:45:03 +02:00
test22(const void *unused G_GNUC_UNUSED)
{
int ret = -1;
2021-03-11 08:16:13 +01:00
virCommand *cmd;
int status = -1;
cmd = virCommandNewArgList("/bin/sh", "-c", "exit 3", NULL);
if (virCommandRun(cmd, &status) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
goto cleanup;
}
if (status != 3) {
printf("Unexpected status %d\n", status);
goto cleanup;
}
virCommandRawStatus(cmd);
if (virCommandRun(cmd, &status) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
goto cleanup;
}
if (!WIFEXITED(status) || WEXITSTATUS(status) != 3) {
printf("Unexpected status %d\n", status);
goto cleanup;
}
virCommandFree(cmd);
cmd = virCommandNewArgList("/bin/sh", "-c", "kill -9 $$", NULL);
if (virCommandRun(cmd, &status) == 0) {
printf("Death by signal not detected, status %d\n", status);
goto cleanup;
}
virCommandRawStatus(cmd);
if (virCommandRun(cmd, &status) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
goto cleanup;
}
if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL) {
printf("Unexpected status %d\n", status);
goto cleanup;
}
ret = 0;
cleanup:
virCommandFree(cmd);
return ret;
}
static int
2019-10-14 14:45:03 +02:00
test23(const void *unused G_GNUC_UNUSED)
{
/* Not strictly a virCommand test, but this is the easiest place
* to test this lower-level interface. It takes a double fork to
* test virProcessExitWithStatus. */
int status = -1;
pid_t pid;
2013-12-21 17:54:33 -07:00
if ((pid = virFork()) < 0)
2019-11-12 17:46:29 -03:00
return -1;
if (pid == 0) {
2013-12-21 17:54:33 -07:00
if ((pid = virFork()) < 0)
_exit(EXIT_FAILURE);
if (pid == 0)
_exit(42);
if (virProcessWait(pid, &status, true) < 0)
_exit(EXIT_FAILURE);
virProcessExitWithStatus(status);
_exit(EXIT_FAILURE);
}
if (virProcessWait(pid, &status, true) < 0)
2019-11-12 17:46:29 -03:00
return -1;
if (!WIFEXITED(status) || WEXITSTATUS(status) != 42) {
printf("Unexpected status %d\n", status);
2019-11-12 17:46:29 -03:00
return -1;
}
2013-12-21 17:54:33 -07:00
if ((pid = virFork()) < 0)
2019-11-12 17:46:29 -03:00
return -1;
if (pid == 0) {
2013-12-21 17:54:33 -07:00
if ((pid = virFork()) < 0)
_exit(EXIT_FAILURE);
if (pid == 0) {
raise(SIGKILL);
_exit(EXIT_FAILURE);
}
if (virProcessWait(pid, &status, true) < 0)
_exit(EXIT_FAILURE);
virProcessExitWithStatus(status);
_exit(EXIT_FAILURE);
}
if (virProcessWait(pid, &status, true) < 0)
2019-11-12 17:46:29 -03:00
return -1;
if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL) {
printf("Unexpected status %d\n", status);
2019-11-12 17:46:29 -03:00
return -1;
}
2019-11-12 17:46:29 -03:00
return 0;
}
2019-10-14 14:45:03 +02:00
static int test25(const void *unused G_GNUC_UNUSED)
{
int ret = -1;
int pipeFD[2] = { -1, -1};
2016-07-13 18:53:22 +02:00
int rv = 0;
ssize_t tries = 100;
pid_t pid;
2020-07-28 02:30:59 +02:00
g_autofree gid_t *groups = NULL;
2017-10-09 21:14:56 +02:00
int ngroups;
g_autoptr(virCommand) cmd = virCommandNew("some/nonexistent/binary");
2020-01-24 15:22:12 +00:00
if (virPipeQuiet(pipeFD) < 0) {
fprintf(stderr, "Unable to create pipe\n");
goto cleanup;
}
if (virSetNonBlock(pipeFD[0]) < 0) {
fprintf(stderr, "Unable to make read end of pipe nonblocking\n");
goto cleanup;
}
2017-10-09 21:14:56 +02:00
if ((ngroups = virGetGroupList(virCommandGetUID(cmd), virCommandGetGID(cmd),
&groups)) < 0)
goto cleanup;
/* Now, fork and try to exec a nonexistent binary. */
pid = virFork();
if (pid < 0) {
fprintf(stderr, "Unable to spawn child\n");
goto cleanup;
}
if (pid == 0) {
/* Child */
2017-10-09 21:14:56 +02:00
rv = virCommandExec(cmd, groups, ngroups);
2017-04-09 13:28:07 +02:00
if (safewrite(pipeFD[1], &rv, sizeof(rv)) < 0)
fprintf(stderr, "Unable to write to pipe\n");
_exit(EXIT_FAILURE);
}
/* Parent */
while (--tries) {
if (saferead(pipeFD[0], &rv, sizeof(rv)) < 0) {
if (errno != EWOULDBLOCK) {
fprintf(stderr, "Unable to read from pipe\n");
goto cleanup;
}
g_usleep(10 * 1000);
} else {
break;
}
}
if (!tries) {
fprintf(stderr, "Child hasn't returned anything\n");
goto cleanup;
}
if (rv >= 0) {
fprintf(stderr, "Child should have returned an error\n");
goto cleanup;
}
ret = 0;
cleanup:
VIR_FORCE_CLOSE(pipeFD[0]);
VIR_FORCE_CLOSE(pipeFD[1]);
return ret;
}
/*
* Don't run program; rather, log what would be run.
*/
2019-10-14 14:45:03 +02:00
static int test26(const void *unused G_GNUC_UNUSED)
{
g_autoptr(virCommand) cmd = virCommandNew("true");
2020-07-28 02:30:59 +02:00
g_autofree char *outactual = NULL;
const char *outexpect =
"A=B \\\n"
"C='D E' \\\n"
"true \\\n"
"--foo bar \\\n"
"--oooh \\\n"
"-f \\\n"
"--wizz 'eek eek' \\\n"
"--m-m-m-multiarg arg arg2 \\\n"
"-w \\\n"
"-z \\\n"
"-l \\\n"
"--mmm flash \\\n"
"bang \\\n"
"wallop";
2020-07-28 02:42:01 +02:00
VIR_AUTOCLOSE fd = -1;
virCommandAddEnvPair(cmd, "A", "B");
virCommandAddEnvPair(cmd, "C", "D E");
virCommandAddArgList(cmd, "--foo", "bar", "--oooh", "-f",
"--wizz", "eek eek",
"--m-m-m-multiarg", "arg", "arg2",
"-w", "-z", "-l",
"--mmm", "flash", "bang", "wallop",
NULL);
if ((outactual = virCommandToString(cmd, true)) == NULL) {
printf("Cannot convert to string: %s\n", virGetLastErrorMessage());
2020-07-28 02:51:27 +02:00
return -1;
}
if ((fd = open(abs_builddir "/commandhelper.log",
O_CREAT | O_TRUNC | O_WRONLY, 0600)) < 0) {
printf("Cannot open log file: %s\n", g_strerror(errno));
2020-07-28 02:51:27 +02:00
return -1;
}
virCommandWriteArgLog(cmd, fd);
if (VIR_CLOSE(fd) < 0) {
printf("Cannot close log file: %s\n", g_strerror(errno));
2020-07-28 02:51:27 +02:00
return -1;
}
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(outexpect, outactual) < 0) {
2020-07-28 02:51:27 +02:00
return -1;
}
2020-07-28 02:51:27 +02:00
return checkoutput("test26");
}
2019-10-14 14:45:03 +02:00
static int test27(const void *unused G_GNUC_UNUSED)
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
int buf1fd;
int buf2fd;
size_t buflen = 1024 * 128;
2020-07-28 02:30:59 +02:00
g_autofree char *buffer0 = NULL;
2022-03-22 12:11:44 +01:00
g_autofree unsigned char *buffer1 = NULL;
g_autofree unsigned char *buffer2 = NULL;
2020-07-28 02:30:59 +02:00
g_autofree char *outactual = NULL;
g_autofree char *erractual = NULL;
g_autofree char *outexpect = NULL;
# define TEST27_OUTEXPECT_TEMP "BEGIN STDOUT\n" \
"%s%s%s" \
"END STDOUT\n"
2020-07-28 02:30:59 +02:00
g_autofree char *errexpect = NULL;
# define TEST27_ERREXPECT_TEMP "BEGIN STDERR\n" \
"%s%s%s" \
"END STDERR\n"
2020-09-23 01:04:17 +02:00
buffer0 = g_new0(char, buflen);
2022-03-22 12:11:44 +01:00
buffer1 = g_new0(unsigned char, buflen);
buffer2 = g_new0(unsigned char, buflen);
memset(buffer0, 'H', buflen - 2);
buffer0[buflen - 2] = '\n';
buffer0[buflen - 1] = 0;
memset(buffer1, '1', buflen - 2);
buffer1[buflen - 2] = '\n';
buffer1[buflen - 1] = 0;
memset(buffer2, '2', buflen - 2);
buffer2[buflen - 2] = '\n';
buffer2[buflen - 1] = 0;
outexpect = g_strdup_printf(TEST27_OUTEXPECT_TEMP,
buffer0, buffer1, buffer2);
errexpect = g_strdup_printf(TEST27_ERREXPECT_TEMP,
buffer0, buffer1, buffer2);
buf1fd = virCommandSetSendBuffer(cmd, &buffer1, buflen - 1);
buf2fd = virCommandSetSendBuffer(cmd, &buffer2, buflen - 1);
virCommandAddArg(cmd, "--readfd");
virCommandAddArgFormat(cmd, "%d", buf1fd);
virCommandAddArg(cmd, "--readfd");
virCommandAddArgFormat(cmd, "%d", buf2fd);
virCommandSetInputBuffer(cmd, buffer0);
virCommandSetOutputBuffer(cmd, &outactual);
virCommandSetErrorBuffer(cmd, &erractual);
if (virCommandRun(cmd, NULL) < 0) {
printf("Cannot run child %s\n", virGetLastErrorMessage());
return -1;
}
if (!outactual || !erractual)
return -1;
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(outexpect, outactual) < 0) {
return -1;
}
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(errexpect, erractual) < 0) {
return -1;
}
if (checkoutput("test27") < 0)
return -1;
return 0;
}
2013-01-16 11:58:00 +01:00
static int
test28Callback(pid_t pid G_GNUC_UNUSED,
void *opaque G_GNUC_UNUSED)
{
virReportSystemError(ENODATA, "%s", "some error message");
return -1;
}
static int
test28(const void *unused G_GNUC_UNUSED)
{
/* Not strictly a virCommand test, but this is the easiest place
* to test this lower-level interface. */
virErrorPtr err;
2020-03-24 13:48:58 +01:00
g_autofree char *msg = g_strdup_printf("some error message: %s", g_strerror(ENODATA));
if (virProcessRunInFork(test28Callback, NULL) != -1) {
fprintf(stderr, "virProcessRunInFork did not fail\n");
return -1;
}
if (!(err = virGetLastError())) {
fprintf(stderr, "Expected error but got nothing\n");
return -1;
}
if (!(err->code == VIR_ERR_SYSTEM_ERROR &&
err->domain == 0 &&
2020-03-24 13:48:58 +01:00
STREQ(err->message, msg) &&
err->level == VIR_ERR_ERROR &&
STREQ(err->str1, "%s") &&
2020-03-24 13:48:58 +01:00
STREQ(err->str2, msg) &&
err->int1 == ENODATA &&
err->int2 == -1)) {
fprintf(stderr, "Unexpected error object\n");
return -1;
}
return 0;
}
static int
test29(const void *unused G_GNUC_UNUSED)
{
g_autoptr(virCommand) cmd = virCommandNew(abs_builddir "/commandhelper");
g_autofree char *pidfile = virPidFileBuildPath(abs_builddir, "commandhelper");
pid_t pid;
int buffd;
VIR_AUTOCLOSE outfd = -1;
size_t buflen = 1024 * 10;
g_autofree unsigned char *buffer = NULL;
g_autofree char *outactual = NULL;
g_autofree char *outexpect = NULL;
size_t i;
size_t outactuallen = 0;
int ret = -1;
if (!pidfile)
return -1;
buffer = g_new0(unsigned char, buflen + 1);
for (i = 0; i < buflen; i++) {
buffer[i] = 'a' + i % ('z' - 'a' + 1);
}
buffer[buflen] = '\0';
outexpect = g_strdup_printf("BEGIN STDOUT\n%sEND STDOUT\n", buffer);
buffd = virCommandSetSendBuffer(cmd, &buffer, buflen);
virCommandAddArg(cmd, "--close-stdin");
virCommandAddArg(cmd, "--check-daemonize");
virCommandAddArg(cmd, "--readfd");
virCommandAddArgFormat(cmd, "%d", buffd);
virCommandSetOutputFD(cmd, &outfd);
virCommandSetPidFile(cmd, pidfile);
virCommandDaemonize(cmd);
virCommandDoAsyncIO(cmd);
if (virCommandRun(cmd, NULL) < 0) {
fprintf(stderr, "Cannot run child %s\n", virGetLastErrorMessage());
goto cleanup;
}
if (virPidFileReadPath(pidfile, &pid) < 0) {
fprintf(stderr, "cannot read pidfile: %s\n", pidfile);
goto cleanup;
}
while (1) {
char buf[1024] = { 0 };
struct pollfd pfd = {.fd = outfd, .events = POLLIN, .revents = 0};
int rc = 0;
rc = poll(&pfd, 1, 1000);
if (rc < 0) {
if (errno == EINTR)
continue;
fprintf(stderr, "poll() returned errno = %d\n", errno);
goto cleanup;
}
if (pfd.revents & POLLIN) {
rc = read(outfd, buf, sizeof(buf));
if (rc < 0) {
fprintf(stderr, "cannot read from output pipe: errno=%d\n", errno);
goto cleanup;
}
2022-12-01 16:23:55 +01:00
if (rc == 0)
break;
outactual = g_renew(char, outactual, outactuallen + rc + 1);
memcpy(outactual + outactuallen, buf, rc);
outactuallen += rc;
outactual[outactuallen] = '\0';
} else if (pfd.revents & POLLERR ||
pfd.revents & POLLHUP) {
break;
}
}
2022-11-30 09:57:49 +01:00
if (virTestCompareToString(outexpect, outactual) < 0) {
goto cleanup;
}
ret = checkoutput("test29");
cleanup:
if (pidfile)
unlink(pidfile);
return ret;
}
2010-05-25 12:14:06 +01:00
static int
2011-04-29 10:21:20 -06:00
mymain(void)
2010-05-25 12:14:06 +01:00
{
int ret = 0;
2011-01-28 14:22:39 -07:00
int fd;
int virinitret;
2013-01-16 11:58:00 +01:00
2010-05-25 12:14:06 +01:00
if (chdir("/tmp") < 0)
return EXIT_FAILURE;
2010-05-25 12:14:06 +01:00
2014-09-03 09:13:21 -06:00
umask(022);
setpgid(0, 0);
2012-04-27 17:25:35 -04:00
ignore_value(setsid());
2012-01-06 14:07:23 -07:00
/* 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 ||
2013-02-05 09:15:20 -07:00
dup2(fd, 6) < 0 ||
dup2(fd, 7) < 0 ||
dup2(fd, 8) < 0 ||
(fd > 8 && VIR_CLOSE(fd) < 0)) {
VIR_FORCE_CLOSE(fd);
2012-01-06 14:07:23 -07:00
return EXIT_FAILURE;
}
/* Prime the debug/verbose settings from the env vars,
* since we're about to reset 'environ' */
2012-04-27 17:25:35 -04:00
ignore_value(virTestGetDebug());
ignore_value(virTestGetVerbose());
ignore_value(virTestGetRegenerate());
/* Make sure to not leak fd's */
virinitret = virInitialize();
2012-01-06 14:07:23 -07:00
/* Phase two of killing interfering fds; see above. */
2011-01-28 14:22:39 -07:00
fd = 3;
VIR_FORCE_CLOSE(fd);
fd = 4;
VIR_FORCE_CLOSE(fd);
fd = 5;
VIR_FORCE_CLOSE(fd);
2013-02-05 09:15:20 -07:00
fd = 6;
VIR_FORCE_CLOSE(fd);
fd = 7;
VIR_FORCE_CLOSE(fd);
fd = 8;
VIR_FORCE_CLOSE(fd);
2010-12-10 15:30:56 -07:00
if (virinitret < 0)
return EXIT_FAILURE;
2010-05-25 12:14:06 +01:00
environ = (char **)newenv;
2017-11-03 13:09:47 +01:00
# define DO_TEST(NAME) \
if (virTestRun("Command Exec " #NAME " test", \
NAME, NULL) < 0) \
2010-05-25 12:14:06 +01:00
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);
2010-12-03 14:14:16 -07:00
DO_TEST(test17);
2010-12-21 11:49:49 -07:00
DO_TEST(test18);
DO_TEST(test19);
2012-05-31 15:50:07 -06:00
DO_TEST(test20);
2013-01-16 18:55:06 +01:00
DO_TEST(test21);
DO_TEST(test22);
DO_TEST(test23);
DO_TEST(test25);
DO_TEST(test26);
DO_TEST(test27);
DO_TEST(test28);
DO_TEST(test29);
2010-05-25 12:14:06 +01:00
2014-03-17 10:38:38 +01:00
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
2010-05-25 12:14:06 +01:00
}
VIR_TEST_MAIN(mymain)
2011-07-28 17:48:12 +02:00
#endif /* !WIN32 */