summaryrefslogtreecommitdiffstats
path: root/capitests/test-user-cancel.c
diff options
context:
space:
mode:
Diffstat (limited to 'capitests/test-user-cancel.c')
-rw-r--r--capitests/test-user-cancel.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/capitests/test-user-cancel.c b/capitests/test-user-cancel.c
index 429998e7..0cc049a0 100644
--- a/capitests/test-user-cancel.c
+++ b/capitests/test-user-cancel.c
@@ -40,6 +40,7 @@
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
+#include <math.h>
#include <pthread.h>
@@ -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;
+}