From 62909197d120c01cc86095518aacca9d4ad268dd Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 26 Oct 2011 15:55:29 +0100 Subject: [PATCH] test-user-cancel: Make this test choose smaller cancellation numbers. Use a Gaussian distribution for random numbers so that smaller numbers are chosen more frequently. This also exposes a bug in this test which only happens when small numbers are chosen: If the test thread starts up quickly, it can get to guestfs_user_cancel before the guestfs_upload command has happened in the main thread. This causes the cancel to be ignored (correctly) and we end up in the second loop writing data until the disk runs out of space. Fix this by repeatedly asserting the cancel flag in the second loop. --- capitests/Makefile.am | 2 +- capitests/test-user-cancel.c | 56 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/capitests/Makefile.am b/capitests/Makefile.am index 9802a06..64fc0a1 100644 --- a/capitests/Makefile.am +++ b/capitests/Makefile.am @@ -123,7 +123,7 @@ test_user_cancel_CFLAGS = \ -I$(top_srcdir)/src -I$(top_builddir)/src \ $(WARN_CFLAGS) $(WERROR_CFLAGS) test_user_cancel_LDADD = \ - $(top_builddir)/src/libguestfs.la + $(top_builddir)/src/libguestfs.la -lm test_debug_to_file_SOURCES = test-debug-to-file.c test_debug_to_file_CFLAGS = \ diff --git a/capitests/test-user-cancel.c b/capitests/test-user-cancel.c index 429998e..0cc049a 100644 --- a/capitests/test-user-cancel.c +++ b/capitests/test-user-cancel.c @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -50,6 +51,7 @@ static const off_t filesize = 1024*1024*1024; static void remove_test_img (void); static void *start_test_thread (void *); +static off_t random_cancel_posn (void); struct test_thread_data { guestfs_h *g; /* handle */ @@ -72,7 +74,7 @@ main (int argc, char *argv[]) int fds[2], r, op_error, op_errno, errors = 0; char dev_fd[64]; - srandom (time (NULL)); + srand48 (time (NULL)); g = guestfs_create (); if (g == NULL) { @@ -136,7 +138,7 @@ main (int argc, char *argv[]) data.fd = fds[1]; snprintf (dev_fd, sizeof dev_fd, "/dev/fd/%d", fds[0]); - data.cancel_posn = random () % (filesize/4); + data.cancel_posn = random_cancel_posn (); /* Create the test thread. */ r = pthread_create (&test_thread, NULL, start_test_thread, &data); @@ -197,7 +199,7 @@ main (int argc, char *argv[]) data.fd = fds[0]; snprintf (dev_fd, sizeof dev_fd, "/dev/fd/%d", fds[1]); - data.cancel_posn = random () % (filesize/4); + data.cancel_posn = random_cancel_posn (); /* Create the test thread. */ r = pthread_create (&test_thread, NULL, start_test_thread, &data); @@ -273,13 +275,16 @@ start_test_thread (void *datav) data->transfer_size += r; } - /* Do user cancellation. */ - guestfs_user_cancel (data->g); - /* Keep feeding data after the cancellation point for as long as * the main thread wants it. */ while (1) { + /* Repeatedly assert the cancel flag. We have to do this because + * the guestfs_upload command in the main thread may not have + * started yet. + */ + guestfs_user_cancel (data->g); + r = write (data->fd, buffer, sizeof buffer); if (r == -1) { perror ("test thread: write to pipe after user cancel"); @@ -325,3 +330,42 @@ start_test_thread (void *datav) return NULL; } + +static double random_gauss (double mu, double sd); + +/* Generate a random cancellation position, but skew it towards + * smaller numbers. + */ +static off_t +random_cancel_posn (void) +{ + const double mu = 65536; + const double sd = 65536 * 4; + double r; + + do { + r = random_gauss (mu, sd); + } while (r <= 0); + + return (off_t) r; +} + +/* Generate a random Gaussian distributed number using the Box-Muller + * transformation. (http://www.taygeta.com/random/gaussian.html) + */ +static double +random_gauss (double mu, double sd) +{ + double x1, x2, w, y1; + + do { + x1 = 2. * drand48 () - 1.; + x2 = 2. * drand48 () - 1.; + w = x1 * x1 + x2 * x2; + } while (w >= 1.); + + w = sqrt ((-2. * log (w)) / w); + y1 = x1 * w; + //y2 = x2 * w; + return mu + y1 * sd; +} -- 1.8.3.1