Introduce a test case which ensures that a daemonized process can work with virCommandSetSendBuffer() when async IO is enabled. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- tests/commanddata/test29.log | 19 ++++++++ tests/commandtest.c | 84 ++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 tests/commanddata/test29.log diff --git a/tests/commanddata/test29.log b/tests/commanddata/test29.log new file mode 100644 index 0000000000..49993a4947 --- /dev/null +++ b/tests/commanddata/test29.log @@ -0,0 +1,19 @@ +ARG:--close-stdin +ARG:--readfd +ARG:3 +ENV:DISPLAY=:0.0 +ENV:HOME=/home/test +ENV:HOSTNAME=test +ENV:LANG=C +ENV:LOGNAME=test +ENV:PATH=/usr/bin:/bin +ENV:TMPDIR=/tmp +ENV:USER=test +FD:0 +FD:1 +FD:2 +FD:3 +FD:6 +DAEMON:yes +CWD:/ +UMASK:0022 diff --git a/tests/commandtest.c b/tests/commandtest.c index 10a051124d..573a4f250d 100644 --- a/tests/commandtest.c +++ b/tests/commandtest.c @@ -25,6 +25,7 @@ #include <sys/stat.h> #ifndef WIN32 # include <sys/wait.h> +# include <poll.h> #endif #include <fcntl.h> @@ -1157,6 +1158,88 @@ test28(const void *unused G_GNUC_UNUSED) } +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, "--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 }; + int rc = 0; + + rc = read(outfd, buf, sizeof(buf)); + if (rc < 0) { + fprintf(stderr, "cannot read from output pipe: errno=%d\n", errno); + goto cleanup; + } + + if (rc == 0) + break; + + outactual = g_renew(char, outactual, outactuallen + rc + 1); + memcpy(outactual + outactuallen, buf, rc); + outactuallen += rc; + outactual[outactuallen] = '\0'; + } + + if (STRNEQ_NULLABLE(outactual, outexpect)) { + virTestDifference(stderr, outexpect, outactual); + goto cleanup; + } + + ret = checkoutput("test29"); + + cleanup: + if (pidfile) + unlink(pidfile); + + return ret; +} + + static int mymain(void) { @@ -1254,6 +1337,7 @@ mymain(void) DO_TEST(test26); DO_TEST(test27); DO_TEST(test28); + DO_TEST(test29); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 2.34.1