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@xxxxxxxxxxxxx> > Reviewed-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> > --- > 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) { > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list