read_write_all: don't rely on write to pipe blocking in tests.
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 20 Oct 2010 02:20:18 +0000 (12:50 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 20 Oct 2010 02:20:18 +0000 (12:50 +1030)
Instead, directly control write().

ccan/read_write_all/test/run-write_all.c

index 5b310688aea6283ec178515c92ed81d2e4474a18..6dbd9c29f92f1ad6358db75a4e12976c63c560aa 100644 (file)
@@ -1,7 +1,4 @@
-/* FIXME: Do something tricky to ensure we really do loop in write_all. */
-
 #include <ccan/read_write_all/read_write_all.h>
 #include <ccan/read_write_all/read_write_all.h>
-#include <ccan/read_write_all/read_write_all.c>
 #include <ccan/tap/tap.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <ccan/tap/tap.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <string.h>
 #include <stdio.h>
 
 #include <string.h>
 #include <stdio.h>
 
-static volatile int sigcount;
-static void got_signal(int sig)
+static ssize_t test_write(int fd, const void *buf, size_t count);
+#define write test_write
+#include <ccan/read_write_all/read_write_all.c>
+#undef write
+
+static ssize_t write_return;
+
+static ssize_t test_write(int fd, const void *buf, size_t count)
 {
 {
-       sigcount++;
+       if (write_return == 0) {
+               errno = ENOSPC;
+               return 0;
+       }
+
+       if (write_return < 0) {
+               errno = -write_return;
+               /* Don't return EINTR more than once! */
+               if (errno == EINTR)
+                       write_return = count;
+               return -1;
+       }
+
+       if (write_return < count)
+               return write_return;
+       return count;
 }
 
 }
 
-/* < PIPE_BUF *will* be atomic.  But > PIPE_BUF only *might* be non-atomic. */
-#define BUFSZ (1024*1024)
+#define BUFSZ 1024
 
 int main(int argc, char *argv[])
 {
        char *buffer;
 
 int main(int argc, char *argv[])
 {
        char *buffer;
-       int p2c[2];
-       int status;
-       pid_t child;
 
 
-       buffer = calloc(BUFSZ, 1);
-       plan_tests(4);
+       buffer = malloc(BUFSZ);
+       plan_tests(8);
 
 
-       /* We fork and torture parent. */
-       if (pipe(p2c) != 0)
-               err(1, "pipe");
-       child = fork();
+       write_return = -ENOSPC;
+       ok1(!write_all(100, buffer, BUFSZ));
+       ok1(errno == ENOSPC);
 
 
-       if (!child) {
-               close(p2c[1]);
-               /* Make sure they started writing. */
-               if (read(p2c[0], buffer, 1) != 1)
-                       exit(1);
-               if (kill(getppid(), SIGUSR1) != 0)
-                       exit(2);
-               if (!read_all(p2c[0], buffer+1, BUFSZ-1))
-                       exit(3);
-               if (memchr(buffer, 0, BUFSZ)) {
-                       fprintf(stderr, "buffer has 0 at offset %ti\n",
-                               memchr(buffer, 0, BUFSZ) - (void *)buffer);
-                       exit(4);
-               }
-               exit(0);
-       }
-       if (child == -1)
-               err(1, "forking");
+       write_return = -EINTR;
+       ok1(write_all(100, buffer, BUFSZ));
+       ok1(errno == EINTR);
+
+       write_return = 1;
+       errno = 0;
+       ok1(write_all(100, buffer, BUFSZ));
+       ok1(errno == 0);
+
+       write_return = BUFSZ;
+       ok1(write_all(100, buffer, BUFSZ));
+       ok1(errno == 0);
 
 
-       close(p2c[0]);
-       memset(buffer, 0xff, BUFSZ);
-       signal(SIGUSR1, got_signal);
-       ok1(write_all(p2c[1], buffer, BUFSZ));
-       ok1(sigcount == 1);
-       ok1(wait(&status) == child);
-       ok(WIFEXITED(status) && WEXITSTATUS(status) == 0,
-          "WIFEXITED(status) = %u, WEXITSTATUS(status) = %u",
-          WIFEXITED(status), WEXITSTATUS(status));
        return exit_status();
 }
        return exit_status();
 }