[libvirt] [PATCH v7 14/19] tests: Extend command test to transfer large data to process on multiple fds
John Ferlan
jferlan at redhat.com
Fri Jul 26 10:46:05 UTC 2019
On 7/25/19 2:22 PM, Stefan Berger wrote:
> Add a test case to commandtest.c to test the transfer of data to a
> process who received the read-end of pipes' file descriptors. Transfer
> large (128 kb) byte streams.
>
> Extend the commandhelper.c with support for --readfd <fd> command line
> parameter and convert the data receive loop to use poll and receive data
> on multiple file descriptors (up to 3) and read data into distinct buffers
> that we grow while adding more (string) data.
>
> Signed-off-by: Stefan Berger <stefanb at linux.ibm.com>
> Reviewed-by: Daniel P. Berrangé <berrange at redhat.com>
> ---
> tests/commandhelper.c | 70 +++++++++++++++++++++++---
> tests/commandtest.c | 113 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 177 insertions(+), 6 deletions(-)
>
[...]
> diff --git a/tests/commandtest.c b/tests/commandtest.c
> index ce0832fb0c..991c0572b0 100644
> --- a/tests/commandtest.c
> +++ b/tests/commandtest.c
> @@ -1139,6 +1139,118 @@ static int test26(const void *unused ATTRIBUTE_UNUSED)
> return ret;
> }
>
> +static int test27(const void *unused ATTRIBUTE_UNUSED)
> +{
> + virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
> + int pipe1[2];
> + int pipe2[2];
> + int ret = -1;
> + size_t buflen = 1024 * 128;
> + char *buffer0 = NULL;
> + char *buffer1 = NULL;
> + char *buffer2 = NULL;
> + char *outactual = NULL;
> + char *erractual = NULL;
> + char *outexpect = NULL;
> +# define TEST27_OUTEXPECT_TEMP "BEGIN STDOUT\n" \
> + "%s%s%s" \
> + "END STDOUT\n"
> + char *errexpect = NULL;
> +# define TEST27_ERREXPECT_TEMP "BEGIN STDERR\n" \
> + "%s%s%s" \
> + "END STDERR\n"
> +
> + if (VIR_ALLOC_N(buffer0, buflen) < 0 ||
> + VIR_ALLOC_N(buffer1, buflen) < 0 ||
> + VIR_ALLOC_N(buffer2, buflen) < 0)
> + goto cleanup;
> +
> + 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;
> +
> + if (virAsprintf(&outexpect, TEST27_OUTEXPECT_TEMP,
> + buffer0, buffer1, buffer2) < 0 ||
> + virAsprintf(&errexpect, TEST27_ERREXPECT_TEMP,
> + buffer0, buffer1, buffer2) < 0) {
> + printf("Could not virAsprintf expected output\n");
> + goto cleanup;
> + }
> +
> + if (pipe(pipe1) < 0 || pipe(pipe2) < 0) {
> + printf("Could not create pipe: %s\n", strerror(errno));
> + goto cleanup;
> + }
> +
> + if (virCommandSetSendBuffer(cmd, pipe1[1],
> + (unsigned char *)buffer1, buflen - 1) < 0 ||
> + virCommandSetSendBuffer(cmd, pipe2[1],
> + (unsigned char *)buffer2, buflen - 1) < 0) {
> + printf("Could not set send buffers\n");
> + goto cleanup;
> + }
> + pipe1[1] = 0;
> + pipe2[1] = 0;
> + buffer1 = NULL;
> + buffer2 = NULL;
> +
> + virCommandAddArg(cmd, "--readfd");
> + virCommandAddArgFormat(cmd, "%d", pipe1[0]);
> + virCommandPassFD(cmd, pipe1[0], 0);
> +
> + virCommandAddArg(cmd, "--readfd");
> + virCommandAddArgFormat(cmd, "%d", pipe2[0]);
> + virCommandPassFD(cmd, pipe2[0], 0);
> +
> + virCommandSetInputBuffer(cmd, buffer0);
> + virCommandSetOutputBuffer(cmd, &outactual);
> + virCommandSetErrorBuffer(cmd, &erractual);
> +
> + if (virCommandRun(cmd, NULL) < 0) {
> + printf("Cannot run child %s\n", virGetLastErrorMessage());
> + goto cleanup;
> + }
> +
> + virCommandFree(cmd);
This should be in the cleanup section; otherwise, Coverity considers
@cmd as leaked for any other path above where @cmd is allocated and we
go to cleanup.
John
> +
> + if (!outactual || !erractual)
> + goto cleanup;
> +
> + if (STRNEQ(outactual, outexpect)) {
> + virTestDifference(stderr, outexpect, outactual);
> + goto cleanup;
> + }
> + if (STRNEQ(erractual, errexpect)) {
> + virTestDifference(stderr, errexpect, erractual);
> + goto cleanup;
> + }
> +
> + ret = 0;
> +
> + cleanup:
> + VIR_FORCE_CLOSE(pipe1[0]);
> + VIR_FORCE_CLOSE(pipe2[0]);
> + VIR_FORCE_CLOSE(pipe1[1]);
> + VIR_FORCE_CLOSE(pipe2[1]);
> + VIR_FREE(buffer0);
> + VIR_FREE(buffer1);
> + VIR_FREE(buffer2);
> + VIR_FREE(outactual);
> + VIR_FREE(erractual);
> + VIR_FREE(outexpect);
> + VIR_FREE(errexpect);
> +
> + return ret;
> +}
> +
> static void virCommandThreadWorker(void *opaque)
> {
> virCommandTestDataPtr test = opaque;
> @@ -1292,6 +1404,7 @@ mymain(void)
> DO_TEST(test23);
> DO_TEST(test25);
> DO_TEST(test26);
> + DO_TEST(test27);
>
> virMutexLock(&test->lock);
> if (test->running) {
>
More information about the libvir-list
mailing list