X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=capitests%2Ftest-user-cancel.c;h=0cc049a02d66a4b747d3c4cb5895dbf8b4fbeedf;hb=99ec97dcdfaf242ba0683a230ba51e4a87f7458b;hp=429998e76130df52d24725b4d2e52171fb9307f0;hpb=9ec9c97ce2ba46e56b304d3a367c86adc703160d;p=libguestfs.git 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; +}