OSSP CVS Repository

ossp - Check-in [3152]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 3152
Date: 2003-Feb-06 13:49:16 (local)
2003-Feb-06 12:49:16 (UTC)
User:mlelstv
Branch:
Comment: add BIO(_ssl) test case
Tickets:
Inspections:
Files:
ossp-pkg/sio/sio_test.c      1.14 -> 1.15     527 inserted, 711 deleted

ossp-pkg/sio/sio_test.c 1.14 -> 1.15

--- sio_test.c   2003/02/04 15:07:21     1.14
+++ sio_test.c   2003/02/06 12:49:16     1.15
@@ -38,6 +38,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
+#include <signal.h>
 
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -76,15 +77,15 @@
         ts_test_fail(TS_CTX, "%s -> %d[%s] (expected %d[%s])\n", \
             name, rc, errf(rc), rc0, errf(rc0))
 
-#define EVAL0(name,block) EVAL(name,rc,SIO_OK,block,sio_error)
-#define EVALS(name,block) EVAL(name,rc,SA_OK,block,sa_error)
+#define EVAL0(X) EVAL(#X,rc,SIO_OK,{ rc = X; },sio_error)
+#define EVALS(X) EVAL(#X,rc,SA_OK,{ rc = X; },sa_error)
 
 static sio_rc_t sreadloop(sio_t *, char *, size_t, size_t *);
 static int test_sio_pipe_read(ts_test_t *, int, int);
 static int test_sio_pipe_write(ts_test_t *, int, int);
 
-static int test_sio_hello_client(ts_test_t *, int);
-static int test_sio_hello_server(ts_test_t *, int);
+static int test_sio_hello_client(ts_test_t *, int, int);
+static int test_sio_hello_server(ts_test_t *, int, int);
 
 sio_rc_t sreadloop(sio_t *sio, char *buf, size_t len, size_t *actualp)
 {
@@ -95,6 +96,8 @@
         rc = sio_read(sio, buf, len, &actual);
         if (rc != SIO_OK)
             break;
+        if (actual == 0)
+            break;
         buf   += actual;
         total += actual;
         len   -= actual;
@@ -105,6 +108,57 @@
     return rc;
 }
 
+typedef int (*func)(ts_test_t *, int, int);
+void session(ts_test_t *_t, func client, func server, int duplex)
+{
+    pid_t child;
+    int pd[2];
+    int wcount = 147;
+    int status;
+
+    fflush(stdout);
+    fflush(stderr);
+
+    if (duplex) {
+        if (socketpair(AF_UNIX, SOCK_STREAM, 0, pd) == -1) {
+            ts_test_fail(TS_CTX, "cannot create socketpair (%s)\n",
+                strerror(errno));
+        }
+    } else {
+        if (pipe(pd) == -1) {
+            ts_test_fail(TS_CTX, "cannot create pipe (%s)\n",
+                strerror(errno));
+        }
+    }
+
+    child = fork();
+    if (child == -1) {
+        ts_test_fail(TS_CTX, "cannot fork (%s)\n",
+            strerror(errno));
+        return;
+    }
+
+    if (child == 0) {
+        int result;
+
+        sleep(1);
+
+        close(pd[1]);
+        result = (*server)(NULL, pd[0], wcount);
+        close(pd[0]);
+        exit(result ? 1 : 0);
+    } else {
+        close(pd[0]);
+        (*client)(_t, pd[1], wcount);
+        close(pd[1]);
+        waitpid(child, &status, 0);
+        if (status != 0) {
+            ts_test_fail(TS_CTX, "child returned status %08lx\n",
+                status);
+        }
+    }
+}
+
 TS_TEST(test_sio_buffer)
 {
     sio_rc_t rc;
@@ -115,37 +169,23 @@
     char S[] = "Hello world\n";
     size_t actual, len = strlen(S);
 
-    EVAL0("sio_create", {
-        rc = sio_create(&sio);
-    });
+    EVAL0(sio_create(&sio));
     if (rc != SIO_OK) return;
-    EVAL0("sio_create_stage(&sios_hole)", {
-        rc = sio_create_stage(sio, &sio_module_hole, &sios_hole);
-    });
+    EVAL0(sio_create_stage(sio, &sio_module_hole, &sios_hole));
     if (rc != SIO_OK) return;
-    EVAL0("sio_create_stage(&sios_buffer)", {
-        rc = sio_create_stage(sio, &sio_module_buffer, &sios_buffer);
-    });
+    EVAL0(sio_create_stage(sio, &sio_module_buffer, &sios_buffer));
     if (rc != SIO_OK) return;
 
-    EVAL0("sio_configure_stage(sios_buffer, outputsize)", {
-        rc = sio_configure_stage(sio, sios_buffer, "outputsize", &bufsize);
-    });
+    EVAL0(sio_configure_stage(sio, sios_buffer, "outputsize", &bufsize));
     if (rc != SIO_OK) return;
 
-    EVAL0("sio_attach(sios_hole)", {
-        rc = sio_attach(sio, sios_hole, SIO_MODE_WRITE);
-    });
+    EVAL0(sio_attach(sio, sios_hole, SIO_MODE_WRITE));
     if (rc != SIO_OK) return;
-    EVAL0("sio_attach(sios_buffer)", {
-        rc = sio_attach(sio, sios_buffer, SIO_MODE_WRITE);
-    });
+    EVAL0(sio_attach(sio, sios_buffer, SIO_MODE_WRITE));
     if (rc != SIO_OK) return;
 
     for (i=0; i<wcount; ++i) {
-        EVAL0("sio_write", {
-            rc = sio_write(sio, S, len, &actual);
-        });
+        EVAL0(sio_write(sio, S, len, &actual));
         if (rc != SIO_OK) break;
         if (actual != len) {
             ts_test_fail(TS_CTX, "sio_write result %d (expected %d)\n",
@@ -154,22 +194,11 @@
         }
     }
 
-    EVAL0("sio_detach(sios_hole)", {
-        rc = sio_detach(sio, sios_hole);
-    });
-    EVAL0("sio_detach(sios_buffer)", {
-        rc = sio_detach(sio, sios_buffer);
-    });
-
-    EVAL0("sio_destroy_stage", {
-        rc = sio_destroy_stage(sio, sios_buffer);
-    });
-    EVAL0("sio_destroy_stage(sios_hole)", {
-        rc = sio_destroy_stage(sio, sios_hole);
-    });
-    EVAL0("sio_destroy", {
-        rc = sio_destroy(sio);
-    });
+    EVAL0(sio_detach(sio, sios_hole));
+    EVAL0(sio_detach(sio, sios_buffer));
+    EVAL0(sio_destroy_stage(sio, sios_buffer));
+    EVAL0(sio_destroy_stage(sio, sios_hole));
+    EVAL0(sio_destroy(sio));
 }
 
 TS_TEST(test_sio_fd)
@@ -187,30 +216,17 @@
     char tempfile[] = "./sio_test_tmpfile.XXXXXX";
     int do_unlink = 0;
 
-    EVAL0("sio_create", {
-        rc = sio_create(&sio);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_create_stage(&sios_fd)", {
-        rc = sio_create_stage(sio, &sio_module_fd, &sios_fd);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_create_stage(&sios_buffer)", {
-        rc = sio_create_stage(sio, &sio_module_buffer, &sios_buffer);
-    });
-    if (rc != SIO_OK) return;
-
-    EVAL0("sio_configure_stage(sios_fd, buflen)", {
-        rc = sio_configure_stage(sio, sios_fd, "buflen", &buflen);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(sios_buffer)", {
-        rc = sio_configure_stage(sio, sios_buffer, "outputsize", &bufsize);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(sios_buffer, inputsize)", {
-        rc = sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize);
-    });
+    EVAL0(sio_create(&sio));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_create_stage(sio, &sio_module_fd, &sios_fd));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_create_stage(sio, &sio_module_buffer, &sios_buffer));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(sio, sios_fd, "buflen", &buflen));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(sio, sios_buffer, "outputsize", &bufsize));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize));
     if (rc != SIO_OK) return;
 
     /*
@@ -224,23 +240,15 @@
             tempfile, strerror(errno));
     } else {
         do_unlink = 1;
-        EVAL0("sio_configure_stage(sios_fd, fd)", {
-            rc = sio_configure_stage(sio, sios_fd, "fd", &fd);
-        });
+        EVAL0(sio_configure_stage(sio, sios_fd, "fd", &fd));
         if (rc != SIO_OK) goto badwrite;
-        EVAL0("sio_attach(sios_fd)", {
-            rc = sio_attach(sio, sios_fd, SIO_MODE_READWRITE);
-        });
+        EVAL0(sio_attach(sio, sios_fd, SIO_MODE_READWRITE));
         if (rc != SIO_OK) goto badwrite;
-        EVAL0("sio_attach(sios_buffer)", {
-            rc = sio_attach(sio, sios_buffer, SIO_MODE_READWRITE);
-        });
+        EVAL0(sio_attach(sio, sios_buffer, SIO_MODE_READWRITE));
         if (rc != SIO_OK) goto badwrite2;
 
         for (i=0; i<wcount; ++i) {
-            EVAL0("sio_write", {
-                rc = sio_write(sio, S, len, &actual);
-            });
+            EVAL0(sio_write(sio, S, len, &actual));
             if (rc != SIO_OK) break;
             if (actual != len) {
                 ts_test_fail(TS_CTX, "sio_write result %d (expected %d)\n",
@@ -249,18 +257,11 @@
             }
         }
 
-        EVAL0("sio_push", {
-            rc = sio_push(sio);
-        });
-
-        EVAL0("sio_detach(sios_buffer)", {
-            rc = sio_detach(sio, sios_buffer);
-        });
+        EVAL0(sio_push(sio));
+        EVAL0(sio_detach(sio, sios_buffer));
 
         badwrite2:
-        EVAL0("sio_detach(sios_fd)", {
-            rc = sio_detach(sio, sios_fd);
-        });
+        EVAL0(sio_detach(sio, sios_fd));
 
         badwrite:
         close(fd);
@@ -271,24 +272,15 @@
         ts_test_fail(TS_CTX, "cannot read temporary file \"%s\" (%s)\n",
             tempfile, strerror(errno));
     } else {
-        EVAL0("sio_configure_stage(sios_fd, fd)", {
-            rc = sio_configure_stage(sio, sios_fd, "fd", &fd);
-        });
+        EVAL0(sio_configure_stage(sio, sios_fd, "fd", &fd));
         if (rc != SIO_OK) goto badread;
-
-        EVAL0("sio_attach(sios_fd)", {
-            rc = sio_attach(sio, sios_fd, SIO_MODE_READWRITE);
-        });
+        EVAL0(sio_attach(sio, sios_fd, SIO_MODE_READWRITE));
         if (rc != SIO_OK) goto badread;
-        EVAL0("sio_attach(sios_buffer)", {
-            rc = sio_attach(sio, sios_buffer, SIO_MODE_READWRITE);
-        });
+        EVAL0(sio_attach(sio, sios_buffer, SIO_MODE_READWRITE));
         if (rc != SIO_OK) goto badread2;
 
         for (i=0; i<wcount; ++i) {
-            EVAL0("sio_read", {
-                rc = sreadloop(sio, buf, len, &actual);
-            });
+            EVAL0(sreadloop(sio, buf, len, &actual));
             if (rc != SIO_OK) break;
             if (actual != len) {
                 ts_test_fail(TS_CTX, "sio_read result %d (expected %d)\n",
@@ -303,14 +295,10 @@
             }
         }
 
-        EVAL0("sio_detach(sios_buffer)", {
-            rc = sio_detach(sio, sios_buffer);
-        });
+        EVAL0(sio_detach(sio, sios_buffer));
 
         badread2:
-        EVAL0("sio_detach(sios_fd)", {
-            rc = sio_detach(sio, sios_fd);
-        });
+        EVAL0(sio_detach(sio, sios_fd));
 
         badread:
         close(fd);
@@ -325,15 +313,9 @@
      * common cleanup
      */
 
-    EVAL0("sio_destroy_stage", {
-        rc = sio_destroy_stage(sio, sios_buffer);
-    });
-    EVAL0("sio_destroy_stage(sios_fd)", {
-        rc = sio_destroy_stage(sio, sios_fd);
-    });
-    EVAL0("sio_destroy", {
-        rc = sio_destroy(sio);
-    });
+    EVAL0(sio_destroy_stage(sio, sios_buffer));
+    EVAL0(sio_destroy_stage(sio, sios_fd));
+    EVAL0(rc = sio_destroy(sio));
 }
 
 static
@@ -350,92 +332,60 @@
     char buf[sizeof(S)];
     size_t actual, len = strlen(S);
 
-    EVAL0("sio_create", {
-        rc = sio_create(&sio);
-    });
+    EVAL0(sio_create(&sio));
     if (rc != SIO_OK) return -1;
-    EVAL0("sio_create_stage(&sios_fd)", {
-        rc = sio_create_stage(sio, &sio_module_fd, &sios_fd);
-    });
+    EVAL0(sio_create_stage(sio, &sio_module_fd, &sios_fd));
     if (rc != SIO_OK) return -1;
-    EVAL0("sio_create_stage(&sios_buffer)", {
-        rc = sio_create_stage(sio, &sio_module_buffer, &sios_buffer);
-    });
+    EVAL0(sio_create_stage(sio, &sio_module_buffer, &sios_buffer));
     if (rc != SIO_OK) return -1;
-
-    EVAL0("sio_configure_stage(sios_fd, buflen)", {
-        rc = sio_configure_stage(sio, sios_fd, "buflen", &buflen);
-    });
+    EVAL0(sio_configure_stage(sio, sios_fd, "buflen", &buflen));
     if (rc != SIO_OK) return -1;
-    EVAL0("sio_configure_stage(sios_buffer)", {
-        rc = sio_configure_stage(sio, sios_buffer, "outputsize", &buflen);
-    });
+    EVAL0(sio_configure_stage(sio, sios_buffer, "outputsize", &bufsize));
     if (rc != SIO_OK) return -1;
-    EVAL0("sio_configure_stage(sios_buffer, inputsize)", {
-        rc = sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize);
-    });
+    EVAL0(sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize));
     if (rc != SIO_OK) return -1;
-
-    EVAL0("sio_configure_stage(sios_fd, fd)", {
-        rc = sio_configure_stage(sio, sios_fd, "fd", &fd);
-    });
+    EVAL0(sio_configure_stage(sio, sios_fd, "fd", &fd));
     if (rc != SIO_OK) goto badread;
-
-    EVAL0("sio_attach(sios_fd)", {
-        rc = sio_attach(sio, sios_fd, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_attach(sio, sios_fd, SIO_MODE_READWRITE));
     if (rc != SIO_OK) goto badread;
-    EVAL0("sio_attach(sios_buffer)", {
-        rc = sio_attach(sio, sios_buffer, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_attach(sio, sios_buffer, SIO_MODE_READWRITE));
     if (rc != SIO_OK) goto badread2;
 
     for (i=0; i<wcount; ++i) {
-        EVAL0("sio_read", {
-            rc = sreadloop(sio, buf, len, &actual);
-        });
-        if (rc != SIO_OK) error = 1;
-        if (rc != SIO_OK) break;
+        EVAL0(sreadloop(sio, buf, len, &actual));
+        if (rc != SIO_OK) {
+            error = 1;
+            break;
+        }
         if (actual != len) {
             ts_test_fail(TS_CTX, "sio_read result %d (expected %d)\n",
                 (int)actual, (int)len);
+            error = 1;
             break;
         }
         buf[actual] = '\0';
         if (strcmp(buf, S)) {
             ts_test_fail(TS_CTX, "sio_read data mismatch at loop %d\n",
                 i);
+            error = 1;
             break;
         }
     }
 
-    EVAL0("sio_detach(sios_buffer)", {
-        rc = sio_detach(sio, sios_buffer);
-    });
+    EVAL0(sio_detach(sio, sios_buffer));
     if (rc != SIO_OK) error = 1;
-
     result = error;
 
     badread2:
-
-    EVAL0("sio_detach(sios_fd)", {
-        rc = sio_detach(sio, sios_fd);
-    });
+    EVAL0(sio_detach(sio, sios_fd));
     if (rc != SIO_OK) result = -1;
 
     badread:
-
-    EVAL0("sio_destroy_stage", {
-        rc = sio_destroy_stage(sio, sios_buffer);
-    });
-    if (rc != SIO_OK) result = -1;
-    EVAL0("sio_destroy_stage(sios_fd)", {
-        rc = sio_destroy_stage(sio, sios_fd);
-    });
-    if (rc != SIO_OK) result = -1;
-    EVAL0("sio_destroy", {
-        rc = sio_destroy(sio);
-    });
+    EVAL0(sio_destroy_stage(sio, sios_buffer));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy_stage(sio, sios_fd));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy(sio));
     if (rc != SIO_OK) result = -1;
 
     return result;
@@ -454,97 +404,61 @@
     char S[] = "Hello world\n";
     size_t actual, len = strlen(S);
 
-    EVAL0("sio_create", {
-        rc = sio_create(&sio);
-    });
-    if (rc != SIO_OK) return -1;
-    EVAL0("sio_create_stage(&sios_fd)", {
-        rc = sio_create_stage(sio, &sio_module_fd, &sios_fd);
-    });
-    if (rc != SIO_OK) return -1;
-    EVAL0("sio_create_stage(&sios_buffer)", {
-        rc = sio_create_stage(sio, &sio_module_buffer, &sios_buffer);
-    });
-    if (rc != SIO_OK) return -1;
-
-    EVAL0("sio_configure_stage(sios_fd, buflen)", {
-        rc = sio_configure_stage(sio, sios_fd, "buflen", &buflen);
-    });
-    if (rc != SIO_OK) return -1;
-    EVAL0("sio_configure_stage(sios_buffer)", {
-        rc = sio_configure_stage(sio, sios_buffer, "outputsize", &buflen);
-    });
-    if (rc != SIO_OK) return -1;
-    EVAL0("sio_configure_stage(sios_buffer, inputsize)", {
-        rc = sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize);
-    });
+    EVAL0(sio_create(&sio));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_create_stage(sio, &sio_module_fd, &sios_fd));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_create_stage(sio, &sio_module_buffer, &sios_buffer));
+    if (rc != SIO_OK) return -1;
+
+    EVAL0(sio_configure_stage(sio, sios_fd, "buflen", &buflen));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_buffer, "outputsize", &bufsize));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize));
     if (rc != SIO_OK) return -1;
 
     /*
      * WRITE phase
      */
 
-    EVAL0("sio_configure_stage(sios_fd, fd)", {
-        rc = sio_configure_stage(sio, sios_fd, "fd", &fd);
-    });
+    EVAL0(sio_configure_stage(sio, sios_fd, "fd", &fd));
     if (rc != SIO_OK) goto badwrite;
-    EVAL0("sio_attach(sios_fd)", {
-        rc = sio_attach(sio, sios_fd, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_attach(sio, sios_fd, SIO_MODE_READWRITE));
     if (rc != SIO_OK) goto badwrite;
-    EVAL0("sio_attach(sios_buffer)", {
-        rc = sio_attach(sio, sios_buffer, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_attach(sio, sios_buffer, SIO_MODE_READWRITE));
     if (rc != SIO_OK) goto badwrite2;
 
     for (i=0; i<wcount; ++i) {
-        EVAL0("sio_write", {
-            rc = sio_write(sio, S, len, &actual);
-        });
-        if (rc != SIO_OK) error = 1;
-        if (rc != SIO_OK) break;
+        EVAL0(sio_write(sio, S, len, &actual));
+        if (rc != SIO_OK) {
+            error = 1;
+            break;
+        } 
         if (actual != len) {
             ts_test_fail(TS_CTX, "sio_write result %d (expected %d)\n",
                 (int)actual, (int)len);
+            error = 1;
             break;
         }
     }
 
-    EVAL0("sio_push", {
-        rc = sio_push(sio);
-    });
+    EVAL0(sio_push(sio));
     if (rc != SIO_OK) error = 1;
-
-    EVAL0("sio_detach(sios_buffer)", {
-        rc = sio_detach(sio, sios_buffer);
-    });
+    EVAL0(sio_detach(sio, sios_buffer));
     if (rc != SIO_OK) error = 1;
-
     result = error;
 
     badwrite2:
-    EVAL0("sio_detach(sios_fd)", {
-        rc = sio_detach(sio, sios_fd);
-    });
+    EVAL0(sio_detach(sio, sios_fd));
     if (rc != SIO_OK) result = -1;
 
     badwrite:
-
-    /*
-     * common cleanup
-     */
-
-    EVAL0("sio_destroy_stage", {
-        rc = sio_destroy_stage(sio, sios_buffer);
-    });
-    if (rc != SIO_OK) result = -1;
-    EVAL0("sio_destroy_stage(sios_fd)", {
-        rc = sio_destroy_stage(sio, sios_fd);
-    });
-    if (rc != SIO_OK) result = -1;
-    EVAL0("sio_destroy", {
-        rc = sio_destroy(sio);
-    });
+    EVAL0(sio_destroy_stage(sio, sios_buffer));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy_stage(sio, sios_fd));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy(sio));
     if (rc != SIO_OK) result = -1;
 
     return result;
@@ -552,44 +466,7 @@
 
 TS_TEST(test_sio_pipe)
 {
-    pid_t child;
-    int pd[2];
-    int wcount = 147;
-    int status;
-
-    fflush(stdout);
-    fflush(stderr);
-
-    if (pipe(pd) == -1) {
-        ts_test_fail(TS_CTX, "cannot create pipe (%s)\n",
-            strerror(errno));
-    }
-
-    child = fork();
-    if (child == -1) {
-        ts_test_fail(TS_CTX, "cannot fork (%s)\n",
-            strerror(errno));
-    }
-
-    if (child == 0) {
-        int result;
-
-        sleep(1);
-
-        close(pd[1]);
-        result = test_sio_pipe_write(NULL, pd[0], wcount);
-        close(pd[0]);
-        exit(result ? 1 : 0);
-    } else {
-        close(pd[0]);
-        test_sio_pipe_read(_t, pd[1], wcount);
-        close(pd[1]);
-        waitpid(child, &status, 0);
-        if (status != 0) {
-            ts_test_fail(TS_CTX, "child returned status %08lx\n",
-                status);
-        }
-    }
+    session(_t, test_sio_pipe_read, test_sio_pipe_write, 0);
 }
 
 TS_TEST(test_sio_sio)
@@ -642,89 +519,51 @@
     /*
      * create MUX stream
      */
-    EVAL0("sio_create(&A_sio)", {
-        rc = sio_create(&A_sio);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_create_stage(&A_sios_fd)", {
-        rc = sio_create_stage(A_sio, &sio_module_fd, &A_sios_fd);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(A_sios_fd, fd)", {
-        rc = sio_configure_stage(A_sio, A_sios_fd, "fd", &fd);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(A_sios_fd, buflen)", {
-        rc = sio_configure_stage(A_sio, A_sios_fd, "buflen", &buflen);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_create_stage(&A_sios_sillymux)", {
-        rc = sio_create_stage(A_sio, &sio_module_sillymux, &A_sios_sillymux);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(A_sios_sillymux, oddlabel)", {
-        rc = sio_configure_stage(A_sio, A_sios_sillymux, "oddlabel", ODD);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(A_sios_sillymux, evenlabel)", {
-        rc = sio_configure_stage(A_sio, A_sios_sillymux, "evenlabel", EVEN);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_attach(A_sios_fd)", {
-        rc = sio_attach(A_sio, A_sios_fd, SIO_MODE_READWRITE);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_attach(A_sios_sillymux)", {
-        rc = sio_attach(A_sio, A_sios_sillymux, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_create(&A_sio));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_create_stage(A_sio, &sio_module_fd, &A_sios_fd));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(A_sio, A_sios_fd, "fd", &fd));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(A_sio, A_sios_fd, "buflen", &buflen));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_create_stage(A_sio, &sio_module_sillymux, &A_sios_sillymux));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(A_sio, A_sios_sillymux, "oddlabel", ODD));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(A_sio, A_sios_sillymux, "evenlabel", EVEN));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_attach(A_sio, A_sios_fd, SIO_MODE_READWRITE));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_attach(A_sio, A_sios_sillymux, SIO_MODE_READWRITE));
     if (rc != SIO_OK) return;
 
     /*
      * create ODD stream
      */
-    EVAL0("sio_create(&B_sio)", {
-        rc = sio_create(&B_sio);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_create_stage(&B_sios_sio)", {
-        rc = sio_create_stage(B_sio, &sio_module_sio, &B_sios_sio);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(B_sios_sio, upstream)", {
-        rc = sio_configure_stage(B_sio, B_sios_sio, "upstream", A_sio);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(B_sios_sio, mydatalabel)", {
-        rc = sio_configure_stage(B_sio, B_sios_sio, "mydatalabel", ODD);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_attach(B_sios_sio)", {
-        rc = sio_attach(B_sio, B_sios_sio, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_create(&B_sio));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_create_stage(B_sio, &sio_module_sio, &B_sios_sio));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(B_sio, B_sios_sio, "upstream", A_sio));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(B_sio, B_sios_sio, "mydatalabel", ODD));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_attach(B_sio, B_sios_sio, SIO_MODE_READWRITE));
     if (rc != SIO_OK) return;
 
     /*
      * create EVEN stream
      */
-    EVAL0("sio_create(&C_sio)", {
-        rc = sio_create(&C_sio);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_create_stage(&C_sios_sio)", {
-        rc = sio_create_stage(C_sio, &sio_module_sio, &C_sios_sio);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(C_sios_sio, upstream)", {
-        rc = sio_configure_stage(C_sio, C_sios_sio, "upstream", A_sio);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(C_sios_sio, mydatalabel)", {
-        rc = sio_configure_stage(C_sio, C_sios_sio, "mydatalabel", EVEN);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_attach(C_sios_sio)", {
-        rc = sio_attach(C_sio, C_sios_sio, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_create(&C_sio));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_create_stage(C_sio, &sio_module_sio, &C_sios_sio));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(C_sio, C_sios_sio, "upstream", A_sio));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(C_sio, C_sios_sio, "mydatalabel", EVEN));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_attach(C_sio, C_sios_sio, SIO_MODE_READWRITE));
     if (rc != SIO_OK) return;
 
     /*
@@ -746,13 +585,10 @@
         char buf[17], *p;
         int nstreams = 2;
 
-        EVAL0("sio_read(B_sio)", {
-            rc = sreadloop(B_sio, buf, sizeof(buf), &actual);
-            if (rc == SIO_ERR_EOF) {
-                --nstreams;
-                rc = SIO_OK;
-            }
-        });
+        EVAL0(
+            ( (rc = sreadloop(B_sio, buf, sizeof(buf), &actual)),
+              rc == SIO_ERR_EOF ? (--nstreams, SIO_OK) : rc )
+        );
         if (rc != SIO_OK)
             break;
         p = buf;
@@ -776,13 +612,10 @@
         if (actual > 0)
             break;
 
-        EVAL0("sio_read(C_sio)", {
-            rc = sreadloop(C_sio, buf, sizeof(buf), &actual);
-            if (rc == SIO_ERR_EOF) {
-                --nstreams;
-                rc = SIO_OK;
-            }
-        });
+        EVAL0(
+            ( (rc = sreadloop(C_sio, buf, sizeof(buf), &actual)),
+              rc == SIO_ERR_EOF ? (--nstreams, SIO_OK) : rc )
+        );
         if (rc != SIO_OK)
             break;
         p = buf;
@@ -821,47 +654,25 @@
     /*
      * destroy EVEN stream
      */
-    EVAL0("sio_detach(C_sios_sio)", {
-        rc = sio_detach(C_sio, C_sios_sio);
-    });
-    EVAL0("sio_destroy_stage(C_sios_sio)", {
-        rc = sio_destroy_stage(C_sio, C_sios_sio);
-    });
-    EVAL0("sio_destroy(C_sio)", {
-        rc = sio_destroy(C_sio);
-    });
+    EVAL0(sio_detach(C_sio, C_sios_sio));
+    EVAL0(sio_destroy_stage(C_sio, C_sios_sio));
+    EVAL0(rc = sio_destroy(C_sio));
 
     /*
      * destroy ODD stream
      */
-    EVAL0("sio_detach(B_sios_sio)", {
-        rc = sio_detach(B_sio, B_sios_sio);
-    });
-    EVAL0("sio_destroy_stage(B_sios_sio)", {
-        rc = sio_destroy_stage(B_sio, B_sios_sio);
-    });
-    EVAL0("sio_destroy(B_sio)", {
-        rc = sio_destroy(B_sio);
-    });
+    EVAL0(sio_detach(B_sio, B_sios_sio));
+    EVAL0(sio_destroy_stage(B_sio, B_sios_sio));
+    EVAL0(sio_destroy(B_sio));
 
     /*
      * destroy MUX stream
      */
-    EVAL0("sio_detach(A_sios_sillymux)", {
-        rc = sio_detach(A_sio, A_sios_sillymux);
-    });
-    EVAL0("sio_detach(A_sios_fd)", {
-        rc = sio_detach(A_sio, A_sios_fd);
-    });
-    EVAL0("sio_destroy_stage(A_sios_sillymux)", {
-        rc = sio_destroy_stage(A_sio, A_sios_sillymux);
-    });
-    EVAL0("sio_destroy_stage(A_sios_fd)", {
-        rc = sio_destroy_stage(A_sio, A_sios_fd);
-    });
-    EVAL0("sio_destroy(A_sio)", {
-        rc = sio_destroy(A_sio);
-    });
+    EVAL0(sio_detach(A_sio, A_sios_sillymux));
+    EVAL0(sio_detach(A_sio, A_sios_fd));
+    EVAL0(sio_destroy_stage(A_sio, A_sios_sillymux));
+    EVAL0(sio_destroy_stage(A_sio, A_sios_fd));
+    EVAL0(sio_destroy(A_sio));
 
 close_and_cleanup:
     close(fd);
@@ -872,7 +683,7 @@
 }
 
 static
-int test_sio_hello_client(ts_test_t *_t, int fd)
+int test_sio_hello_client(ts_test_t *_t, int fd, int dummy)
 {
     FILE *f;
     char buf[81];
@@ -929,7 +740,7 @@
 }
 
 static
-int test_sio_hello_server(ts_test_t *_t, int fd)
+int test_sio_hello_server(ts_test_t *_t, int fd, int dummy)
 {
     int error = 0, result = -1;
     sio_rc_t rc;
@@ -939,57 +750,33 @@
     char S[] = "Welcome to the real world\r\n";
     size_t actual, len = strlen(S);
 
-    EVAL0("sio_create", {
-        rc = sio_create(&sio);
-    });
+    EVAL0(sio_create(&sio));
     if (rc != SIO_OK) return -1;
-    EVAL0("sio_create_stage(&sios_fd)", {
-        rc = sio_create_stage(sio, &sio_module_fd, &sios_fd);
-    });
+    EVAL0(sio_create_stage(sio, &sio_module_fd, &sios_fd));
     if (rc != SIO_OK) return -1;
-    EVAL0("sio_create_stage(&sios_hello)", {
-        rc = sio_create_stage(sio, &sio_module_hello, &sios_hello);
-    });
+    EVAL0(sio_create_stage(sio, &sio_module_hello, &sios_hello));
     if (rc != SIO_OK) return -1;
-
-    EVAL0("sio_configure_stage(sios_fd, buflen)", {
-        rc = sio_configure_stage(sio, sios_fd, "buflen", &buflen);
-    });
+    EVAL0(sio_configure_stage(sio, sios_fd, "buflen", &buflen));
     if (rc != SIO_OK) return -1;
 
-    EVAL0("sio_configure_stage(sios_fd, fd)", {
-        rc = sio_configure_stage(sio, sios_fd, "fd", &fd);
-    });
+    EVAL0(sio_configure_stage(sio, sios_fd, "fd", &fd));
     if (rc != SIO_OK) goto badwrite;
-    EVAL0("sio_attach(sios_fd)", {
-        rc = sio_attach(sio, sios_fd, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_attach(sio, sios_fd, SIO_MODE_READWRITE));
     if (rc != SIO_OK) goto badwrite;
-    EVAL0("sio_attach(sios_hello)", {
-        rc = sio_attach(sio, sios_hello, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_attach(sio, sios_hello, SIO_MODE_READWRITE));
     if (rc != SIO_OK) goto badwrite2;
+    EVAL0(sio_write(sio, S, len, &actual));
 
-    EVAL0("sio_write", {
-        rc = sio_write(sio, S, len, &actual);
-    });
     if (rc != SIO_OK) error = 1;
-    EVAL0("sio_push", {
-        rc = sio_push(sio);
-    });
+    EVAL0(sio_push(sio));
     if (rc != SIO_OK) error = 1;
-
-    EVAL0("sio_detach(sios_hello)", {
-        rc = sio_detach(sio, sios_hello);
-    });
+    EVAL0(sio_detach(sio, sios_hello));
     if (rc != SIO_OK) error = 1;
 
     result = error;
 
     badwrite2:
-    EVAL0("sio_detach(sios_fd)", {
-        rc = sio_detach(sio, sios_fd);
-    });
+    EVAL0(sio_detach(sio, sios_fd));
     if (rc != SIO_OK) result = -1;
 
     badwrite:
@@ -998,17 +785,11 @@
      * common cleanup
      */
 
-    EVAL0("sio_destroy_stage", {
-        rc = sio_destroy_stage(sio, sios_hello);
-    });
-    if (rc != SIO_OK) result = -1;
-    EVAL0("sio_destroy_stage(sios_fd)", {
-        rc = sio_destroy_stage(sio, sios_fd);
-    });
-    if (rc != SIO_OK) result = -1;
-    EVAL0("sio_destroy", {
-        rc = sio_destroy(sio);
-    });
+    EVAL0(sio_destroy_stage(sio, sios_hello));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy_stage(sio, sios_fd));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy(sio));
     if (rc != SIO_OK) result = -1;
 
     return result;
@@ -1016,46 +797,9 @@
 
 TS_TEST(test_sio_hello)
 {
-    pid_t child;
-    int pd[2];
-    int status;
-
-    fflush(stdout);
-    fflush(stderr);
-
-    if (socketpair(AF_UNIX, SOCK_STREAM, 0, pd) == -1) {
-        ts_test_fail(TS_CTX, "cannot create pipe (%s)\n",
-            strerror(errno));
-    }
-
-    child = fork();
-    if (child == -1) {
-        ts_test_fail(TS_CTX, "cannot fork (%s)\n",
-            strerror(errno));
-    }
-
-    if (child == 0) {
-        int result;
-
-        sleep(1);
-
-        close(pd[1]);
-        result = test_sio_hello_client(NULL, pd[0]);
-        close(pd[0]);
-        exit(result ? 1 : 0);
-    } else {
-        close(pd[0]);
-        test_sio_hello_server(_t, pd[1]);
-        close(pd[1]);
-        waitpid(child, &status, 0);
-        if (status != 0) {
-            ts_test_fail(TS_CTX, "child returned status %08lx\n",
-                status);
-        }
-    }
+    session(_t, test_sio_hello_server, test_sio_hello_client, 1);
 }
 
-
 #if ENABLE_ZLIB
 TS_TEST(test_sio_zlib)
 {
@@ -1074,38 +818,21 @@
     char tempfile[] = "./sio_test_tmpfile.XXXXXX";
     int do_unlink = 0;
 
-    EVAL0("sio_create", {
-        rc = sio_create(&sio);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_create_stage(&sios_fd)", {
-        rc = sio_create_stage(sio, &sio_module_fd, &sios_fd);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_create_stage(&sios_zlib)", {
-        rc = sio_create_stage(sio, &sio_module_zlib, &sios_zlib);
-    });
-    if (rc != SIO_OK) return;
-
-    EVAL0("sio_configure_stage(sios_fd, buflen)", {
-        rc = sio_configure_stage(sio, sios_fd, "buflen", &buflen);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(sios_zlib)", {
-        rc = sio_configure_stage(sio, sios_zlib, "outputsize", &bufsize);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(sios_zlib, inputsize)", {
-        rc = sio_configure_stage(sio, sios_zlib, "inputsize", &bufsize);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(sios_zlib, outputlevel)", {
-        rc = sio_configure_stage(sio, sios_zlib, "outputlevel", &zoutlevel);
-    });
-    if (rc != SIO_OK) return;
-    EVAL0("sio_configure_stage(sios_zlib, inputlevel)", {
-        rc = sio_configure_stage(sio, sios_zlib, "inputlevel", &zinlevel);
-    });
+    EVAL0(sio_create(&sio));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_create_stage(sio, &sio_module_fd, &sios_fd));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_create_stage(sio, &sio_module_zlib, &sios_zlib));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(sio, sios_fd, "buflen", &buflen));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(sio, sios_zlib, "outputsize", &bufsize));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(sio, sios_zlib, "inputsize", &bufsize));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(sio, sios_zlib, "outputlevel", &zoutlevel));
+    if (rc != SIO_OK) return;
+    EVAL0(sio_configure_stage(sio, sios_zlib, "inputlevel", &zinlevel));
     if (rc != SIO_OK) return;
 
     /*
@@ -1119,23 +846,15 @@
             tempfile, strerror(errno));
     } else {
         do_unlink = 1;
-        EVAL0("sio_configure_stage(sios_fd, fd)", {
-            rc = sio_configure_stage(sio, sios_fd, "fd", &fd);
-        });
+        EVAL0(sio_configure_stage(sio, sios_fd, "fd", &fd));
         if (rc != SIO_OK) goto badwrite;
-        EVAL0("sio_attach(sios_fd)", {
-            rc = sio_attach(sio, sios_fd, SIO_MODE_READWRITE);
-        });
+        EVAL0(sio_attach(sio, sios_fd, SIO_MODE_READWRITE));
         if (rc != SIO_OK) goto badwrite;
-        EVAL0("sio_attach(sios_zlib)", {
-            rc = sio_attach(sio, sios_zlib, SIO_MODE_READWRITE);
-        });
+        EVAL0(sio_attach(sio, sios_zlib, SIO_MODE_READWRITE));
         if (rc != SIO_OK) goto badwrite2;
 
         for (i=0; i<wcount; ++i) {
-            EVAL0("sio_write", {
-                rc = sio_write(sio, S, len, &actual);
-            });
+            EVAL0(sio_write(sio, S, len, &actual));
             if (rc != SIO_OK) break;
             if (actual != len) {
                 ts_test_fail(TS_CTX, "sio_write result %d (expected %d)\n",
@@ -1144,18 +863,11 @@
             }
         }
 
-        EVAL0("sio_push", {
-            rc = sio_push(sio);
-        });
-
-        EVAL0("sio_detach(sios_zlib)", {
-            rc = sio_detach(sio, sios_zlib);
-        });
+        EVAL0(sio_push(sio));
+        EVAL0(sio_detach(sio, sios_zlib));
 
         badwrite2:
-        EVAL0("sio_detach(sios_fd)", {
-            rc = sio_detach(sio, sios_fd);
-        });
+        EVAL0(sio_detach(sio, sios_fd));
 
         badwrite:
         close(fd);
@@ -1166,24 +878,15 @@
         ts_test_fail(TS_CTX, "cannot read temporary file \"%s\" (%s)\n",
             tempfile, strerror(errno));
     } else {
-        EVAL0("sio_configure_stage(sios_fd, fd)", {
-            rc = sio_configure_stage(sio, sios_fd, "fd", &fd);
-        });
+        EVAL0(sio_configure_stage(sio, sios_fd, "fd", &fd));
         if (rc != SIO_OK) goto badread;
-
-        EVAL0("sio_attach(sios_fd)", {
-            rc = sio_attach(sio, sios_fd, SIO_MODE_READWRITE);
-        });
+        EVAL0(sio_attach(sio, sios_fd, SIO_MODE_READWRITE));
         if (rc != SIO_OK) goto badread;
-        EVAL0("sio_attach(sios_zlib)", {
-            rc = sio_attach(sio, sios_zlib, SIO_MODE_READWRITE);
-        });
+        EVAL0(sio_attach(sio, sios_zlib, SIO_MODE_READWRITE));
         if (rc != SIO_OK) goto badread2;
 
         for (i=0; i<wcount; ++i) {
-            EVAL0("sio_read", {
-                rc = sreadloop(sio, buf, len, &actual);
-            });
+            EVAL0(sreadloop(sio, buf, len, &actual));
             if (rc != SIO_OK) break;
             if (actual != len) {
                 ts_test_fail(TS_CTX, "sio_read result %d (expected %d)\n",
@@ -1198,14 +901,10 @@
             }
         }
 
-        EVAL0("sio_detach(sios_zlib)", {
-            rc = sio_detach(sio, sios_zlib);
-        });
+        EVAL0(sio_detach(sio, sios_zlib));
 
         badread2:
-        EVAL0("sio_detach(sios_fd)", {
-            rc = sio_detach(sio, sios_fd);
-        });
+        EVAL0(sio_detach(sio, sios_fd));
 
         badread:
         close(fd);
@@ -1220,15 +919,9 @@
      * common cleanup
      */
 
-    EVAL0("sio_destroy_stage", {
-        rc = sio_destroy_stage(sio, sios_zlib);
-    });
-    EVAL0("sio_destroy_stage(sios_fd)", {
-        rc = sio_destroy_stage(sio, sios_fd);
-    });
-    EVAL0("sio_destroy", {
-        rc = sio_destroy(sio);
-    });
+    EVAL0(sio_destroy_stage(sio, sios_zlib));
+    EVAL0(sio_destroy_stage(sio, sios_fd));
+    EVAL0(sio_destroy(sio));
 }
 #endif
 
@@ -1247,92 +940,62 @@
     char buf[sizeof(S)];
     size_t actual, len = strlen(S);
 
-    EVAL0("sio_create", {
-        rc = sio_create(&sio);
-    });
+    EVAL0(sio_create(&sio));
     if (rc != SIO_OK) return -1;
-    EVAL0("sio_create_stage(&sios_sa)", {
-        rc = sio_create_stage(sio, &sio_module_sa, &sios_sa);
-    });
+    EVAL0(sio_create_stage(sio, &sio_module_sa, &sios_sa));
     if (rc != SIO_OK) return -1;
-    EVAL0("sio_create_stage(&sios_buffer)", {
-        rc = sio_create_stage(sio, &sio_module_buffer, &sios_buffer);
-    });
+    EVAL0(sio_create_stage(sio, &sio_module_buffer, &sios_buffer));
     if (rc != SIO_OK) return -1;
-
-    EVAL0("sio_configure_stage(sios_sa, buflen)", {
-        rc = sio_configure_stage(sio, sios_sa, "buflen", &buflen);
-    });
+    EVAL0(sio_configure_stage(sio, sios_sa, "buflen", &buflen));
     if (rc != SIO_OK) return -1;
-    EVAL0("sio_configure_stage(sios_buffer)", {
-        rc = sio_configure_stage(sio, sios_buffer, "outputsize", &buflen);
-    });
+    EVAL0(sio_configure_stage(sio, sios_buffer, "outputsize", &bufsize));
     if (rc != SIO_OK) return -1;
-    EVAL0("sio_configure_stage(sios_buffer, inputsize)", {
-        rc = sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize);
-    });
+    EVAL0(sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize));
     if (rc != SIO_OK) return -1;
 
-    EVAL0("sio_configure_stage(sios_sa, sa)", {
-        rc = sio_configure_stage(sio, sios_sa, "sa", sa);
-    });
+    EVAL0(sio_configure_stage(sio, sios_sa, "sa", sa));
     if (rc != SIO_OK) goto badread;
-
-    EVAL0("sio_attach(sios_sa)", {
-        rc = sio_attach(sio, sios_sa, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_attach(sio, sios_sa, SIO_MODE_READWRITE));
     if (rc != SIO_OK) goto badread;
-    EVAL0("sio_attach(sios_buffer)", {
-        rc = sio_attach(sio, sios_buffer, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_attach(sio, sios_buffer, SIO_MODE_READWRITE));
     if (rc != SIO_OK) goto badread2;
 
     for (i=0; i<wcount; ++i) {
-        EVAL0("sio_read", {
-            rc = sreadloop(sio, buf, len, &actual);
-        });
-        if (rc != SIO_OK) error = 1;
-        if (rc != SIO_OK) break;
+        EVAL0(sreadloop(sio, buf, len, &actual));
+        if (rc != SIO_OK) {
+            error = 1;
+            break;
+        }
         if (actual != len) {
             ts_test_fail(TS_CTX, "sio_read result %d (expected %d)\n",
                 (int)actual, (int)len);
+            error = 1;
             break;
         }
         buf[actual] = '\0';
         if (strcmp(buf, S)) {
             ts_test_fail(TS_CTX, "sio_read data mismatch at loop %d\n",
                 i);
+            error = 1;
             break;
         }
     }
 
-    EVAL0("sio_detach(sios_buffer)", {
-        rc = sio_detach(sio, sios_buffer);
-    });
+    EVAL0(sio_detach(sio, sios_buffer));
     if (rc != SIO_OK) error = 1;
 
     result = error;
 
     badread2:
-
-    EVAL0("sio_detach(sios_sa)", {
-        rc = sio_detach(sio, sios_sa);
-    });
+    EVAL0(sio_detach(sio, sios_sa));
     if (rc != SIO_OK) result = -1;
 
     badread:
-
-    EVAL0("sio_destroy_stage", {
-        rc = sio_destroy_stage(sio, sios_buffer);
-    });
-    if (rc != SIO_OK) result = -1;
-    EVAL0("sio_destroy_stage(sios_sa)", {
-        rc = sio_destroy_stage(sio, sios_sa);
-    });
-    if (rc != SIO_OK) result = -1;
-    EVAL0("sio_destroy", {
-        rc = sio_destroy(sio);
-    });
+    EVAL0(sio_destroy_stage(sio, sios_buffer));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy_stage(sio, sios_sa));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy(sio));
     if (rc != SIO_OK) result = -1;
 
     return result;
@@ -1351,78 +1014,52 @@
     char S[] = "Hello world\n";
     size_t actual, len = strlen(S);
 
-    EVAL0("sio_create", {
-        rc = sio_create(&sio);
-    });
-    if (rc != SIO_OK) return -1;
-    EVAL0("sio_create_stage(&sios_sa)", {
-        rc = sio_create_stage(sio, &sio_module_sa, &sios_sa);
-    });
-    if (rc != SIO_OK) return -1;
-    EVAL0("sio_create_stage(&sios_buffer)", {
-        rc = sio_create_stage(sio, &sio_module_buffer, &sios_buffer);
-    });
-    if (rc != SIO_OK) return -1;
-
-    EVAL0("sio_configure_stage(sios_sa, buflen)", {
-        rc = sio_configure_stage(sio, sios_sa, "buflen", &buflen);
-    });
-    if (rc != SIO_OK) return -1;
-    EVAL0("sio_configure_stage(sios_buffer)", {
-        rc = sio_configure_stage(sio, sios_buffer, "outputsize", &buflen);
-    });
-    if (rc != SIO_OK) return -1;
-    EVAL0("sio_configure_stage(sios_buffer, inputsize)", {
-        rc = sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize);
-    });
+    EVAL0(sio_create(&sio));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_create_stage(sio, &sio_module_sa, &sios_sa));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_create_stage(sio, &sio_module_buffer, &sios_buffer));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_sa, "buflen", &buflen));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_buffer, "outputsize", &bufsize));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize));
     if (rc != SIO_OK) return -1;
 
     /*
      * WRITE phase
      */
 
-    EVAL0("sio_configure_stage(sios_sa, sa)", {
-        rc = sio_configure_stage(sio, sios_sa, "sa", sa);
-    });
+    EVAL0(sio_configure_stage(sio, sios_sa, "sa", sa));
     if (rc != SIO_OK) goto badwrite;
-    EVAL0("sio_attach(sios_sa)", {
-        rc = sio_attach(sio, sios_sa, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_attach(sio, sios_sa, SIO_MODE_READWRITE));
     if (rc != SIO_OK) goto badwrite;
-    EVAL0("sio_attach(sios_buffer)", {
-        rc = sio_attach(sio, sios_buffer, SIO_MODE_READWRITE);
-    });
+    EVAL0(sio_attach(sio, sios_buffer, SIO_MODE_READWRITE));
     if (rc != SIO_OK) goto badwrite2;
 
     for (i=0; i<wcount; ++i) {
-        EVAL0("sio_write", {
-            rc = sio_write(sio, S, len, &actual);
-        });
-        if (rc != SIO_OK) error = 1;
-        if (rc != SIO_OK) break;
+        EVAL0(sio_write(sio, S, len, &actual));
+        if (rc != SIO_OK) {
+           error = 1;
+           break;
+        }
         if (actual != len) {
             ts_test_fail(TS_CTX, "sio_write result %d (expected %d)\n",
                 (int)actual, (int)len);
+            error = 1;
             break;
         }
     }
 
-    EVAL0("sio_push", {
-        rc = sio_push(sio);
-    });
+    EVAL0(sio_push(sio));
     if (rc != SIO_OK) error = 1;
-
-    EVAL0("sio_detach(sios_buffer)", {
-        rc = sio_detach(sio, sios_buffer);
-    });
+    EVAL0(sio_detach(sio, sios_buffer));
     if (rc != SIO_OK) error = 1;
-
     result = error;
 
     badwrite2:
-    EVAL0("sio_detach(sios_sa)", {
-        rc = sio_detach(sio, sios_sa);
-    });
+    EVAL0(sio_detach(sio, sios_sa));
     if (rc != SIO_OK) result = -1;
 
     badwrite:
@@ -1431,17 +1068,11 @@
      * common cleanup
      */
 
-    EVAL0("sio_destroy_stage", {
-        rc = sio_destroy_stage(sio, sios_buffer);
-    });
-    if (rc != SIO_OK) result = -1;
-    EVAL0("sio_destroy_stage(sios_sa)", {
-        rc = sio_destroy_stage(sio, sios_sa);
-    });
-    if (rc != SIO_OK) result = -1;
-    EVAL0("sio_destroy", {
-        rc = sio_destroy(sio);
-    });
+    EVAL0(sio_destroy_stage(sio, sios_buffer));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy_stage(sio, sios_sa));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy(sio));
     if (rc != SIO_OK) result = -1;
 
     return result;
@@ -1459,51 +1090,32 @@
     fflush(stdout);
     fflush(stderr);
 
-    EVALS("sa_create(sa_server)", {
-        rc = sa_create(&sa_server);
-    });
+    EVALS(sa_create(&sa_server));
     if (rc != SA_OK) goto sa_bail;
-    EVALS("sa_timeout(sa_server, SA_TIMEOUT_ALL, 5, 0)", {
-        rc = sa_timeout(sa_server, SA_TIMEOUT_ALL, 5, 0);
-    });
+    EVALS(sa_timeout(sa_server, SA_TIMEOUT_ALL, 5, 0));
     if (rc != SA_OK) goto sa_bail1;
-    EVALS("sa_option(sa_server, SA_OPTION_REUSEADDR, 1)", {
-        rc = sa_option(sa_server, SA_OPTION_REUSEADDR, 1);
-    });
+    EVALS(sa_option(sa_server, SA_OPTION_REUSEADDR, 1));
     if (rc != SA_OK) goto sa_bail1;
-    EVALS("sa_addr_create(&saa_b)", {
-        rc = sa_addr_create(&saa_b);
-    });
+    EVALS(sa_addr_create(&saa_b));
     if (rc != SA_OK) goto sa_bail1;
-    EVALS("sa_addr_u2a(saa_b, uri)", {
-        rc = sa_addr_u2a(saa_b, "inet://127.0.0.1:0");
-    });
+    EVALS(sa_addr_u2a(saa_b, "inet://127.0.0.1:0"));
     if (rc != SA_OK) goto sa_bail1;
-    EVALS("sa_bind(sa_server, saa_b)", {
-        rc = sa_bind(sa_server, saa_b);
-    });
+    EVALS(sa_bind(sa_server, saa_b));
     if (rc != SA_OK) goto sa_bail2;
-    EVALS("sa_listen(sa_server, 128)", {
-        rc = sa_listen(sa_server, 128);
-    });
+    EVALS(sa_listen(sa_server, 128));
     if (rc != SA_OK) goto sa_bail2;
-    EVALS("sa_getlocal(sa_server, &saa_p)", {
-        rc = sa_getlocal(sa_server, &saa_p);
-    });
+    EVALS(sa_getlocal(sa_server, &saa_p));
     if (rc != SA_OK) goto sa_bail2;
-    EVALS("sa_create(sa_client)", {
-        rc = sa_create(&sa_client);
-    });
+    EVALS(sa_create(&sa_client));
     if (rc != SA_OK) goto sa_bail3;
-    EVALS("sa_timeout(sa_client, SA_TIMEOUT_ALL, 5, 0)", {
-        rc = sa_timeout(sa_client, SA_TIMEOUT_ALL, 5, 0);
-    });
+    EVALS(sa_timeout(sa_client, SA_TIMEOUT_ALL, 5, 0));
     if (rc != SA_OK) goto sa_bail4;
 
     child = fork();
     if (child == -1) {
         ts_test_fail(TS_CTX, "cannot fork (%s)\n",
             strerror(errno));
+        return;
     }
 
     if (child == 0) {
@@ -1523,9 +1135,7 @@
         rc = sa_shutdown(sa_conn, "w");
         exit(result ? 1 : 0);
     } else {
-        EVALS("sa_connect(sa_client, saa_p)", {
-            rc = sa_connect(sa_client, saa_p);
-        });
+        EVALS(sa_connect(sa_client, saa_p));
         rc = sa_shutdown(sa_server, "w");
         test_sio_sa_read(_t, sa_client, wcount);
         rc = sa_shutdown(sa_server, "r");
@@ -1537,13 +1147,13 @@
     }
 
 sa_bail4:
-    sa_destroy(sa_client);
+    EVALS(sa_destroy(sa_client));
 sa_bail3:
-    sa_addr_destroy(saa_p);
+    EVALS(sa_addr_destroy(saa_p));
 sa_bail2:
-    sa_addr_destroy(saa_b);
+    EVALS(sa_addr_destroy(saa_b));
 sa_bail1:
-    sa_destroy(sa_server);
+    EVALS(sa_destroy(sa_server));
 sa_bail:
     return;
 }
@@ -1551,8 +1161,212 @@
 #endif
 
 #if ENABLE_BIO
+static
+BIO *get_server_bio()
+{
+    SSL_CTX *ctx;
+    BIO *bio;
+
+    ERR_load_BIO_strings();
+    OpenSSL_add_ssl_algorithms();
+    ctx = SSL_CTX_new(SSLv23_server_method());
+    if (!SSL_CTX_use_certificate_file(ctx, "sio_test.cer", SSL_FILETYPE_PEM) ||
+        !SSL_CTX_use_PrivateKey_file(ctx, "sio_test.key", SSL_FILETYPE_PEM)) {
+        SSL_CTX_free(ctx);
+        return NULL;
+    }
+    bio = BIO_new_ssl(ctx,0);
+    if (bio == NULL)
+        SSL_CTX_free(ctx);
+    return bio;
+}
+
+static
+BIO *get_client_bio()
+{
+    SSL_CTX *ctx;
+    BIO *bio;
+
+    ERR_load_BIO_strings();
+    OpenSSL_add_ssl_algorithms();
+    ctx = SSL_CTX_new(SSLv23_client_method());
+    if (ctx == NULL)
+        return NULL;
+    bio = BIO_new_ssl(ctx,1);
+    if (bio == NULL)
+        SSL_CTX_free(ctx);
+    return bio;
+}
+
+static
+int test_sio_bio_read(ts_test_t *_t, int fd, int wcount)
+{
+    int error = 0, result = -1;
+    sio_rc_t rc;
+    sio_t *sio;
+    sio_stage_t *sios_bio, *sios_fd;
+    BIO *bio;
+    int yes = 1;
+    size_t buflen  =   99;     /* fd input buffer size */
+    size_t bufsize =  343;     /* BIO input buffer size */
+    int i;
+    char S[] = "Hello world\n";
+    char buf[sizeof(S)];
+    size_t actual, len = strlen(S);
+
+    bio = get_client_bio();
+    if (bio == NULL) {
+            ts_test_fail(TS_CTX, "cannot create client BIO\n");
+            return;
+    }
+
+    EVAL0(sio_create(&sio));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_create_stage(sio, &sio_module_fd, &sios_fd));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_create_stage(sio, &sio_module_bio, &sios_bio));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_fd, "buflen", &buflen));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_bio, "bio", bio));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_bio, "freebio", &yes));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_bio, "inputsize", &bufsize));
+    if (rc != SIO_OK) return -1;
+
+    EVAL0(sio_configure_stage(sio, sios_fd, "fd", &fd));
+    if (rc != SIO_OK) goto badread;
+    EVAL0(sio_attach(sio, sios_fd, SIO_MODE_READWRITE));
+    if (rc != SIO_OK) goto badread;
+    EVAL0(sio_attach(sio, sios_bio, SIO_MODE_READWRITE));
+    if (rc != SIO_OK) goto badread2;
+
+    for (i=0; i<wcount; ++i) {
+        EVAL0(sreadloop(sio, buf, len, &actual));
+        if (rc != SIO_OK) {
+            error = 1;
+            break;
+        }
+        if (actual != len) {
+            ts_test_fail(TS_CTX, "sio_read result %d (expected %d)\n",
+                (int)actual, (int)len);
+            error = 1;
+            break;
+        }
+        buf[actual] = '\0';
+        if (strcmp(buf, S)) {
+            ts_test_fail(TS_CTX, "sio_read data mismatch at loop %d\n",
+                i);
+            error = 1;
+            break;
+        }
+    }
+
+    EVAL0(sio_detach(sio, sios_bio));
+    if (rc != SIO_OK) error = 1;
+    result = error;
+
+    badread2:
+    EVAL0(sio_detach(sio, sios_fd));
+    if (rc != SIO_OK) result = -1;
+
+    badread:
+    EVAL0(sio_destroy_stage(sio, sios_bio));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy_stage(sio, sios_fd));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy(sio));
+    if (rc != SIO_OK) result = -1;
+
+    return result;
+}
+
+static
+int test_sio_bio_write(ts_test_t *_t, int fd, int wcount)
+{
+    int error = 0, result = -1;
+    sio_rc_t rc;
+    sio_t *sio;
+    sio_stage_t *sios_bio, *sios_fd;
+    BIO *bio;
+    int yes = 1;
+    size_t buflen  =   256;     /* fd input buffer size */
+    size_t bufsize =    73;     /* BIO input buffer size */
+    int i;
+    char S[] = "Hello world\n";
+    size_t actual, len = strlen(S);
+
+    bio = get_server_bio();
+    if (bio == NULL) {
+            ts_test_fail(TS_CTX, "cannot create server BIO\n");
+            return;
+    }
+
+    EVAL0(sio_create(&sio));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_create_stage(sio, &sio_module_fd, &sios_fd));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_create_stage(sio, &sio_module_bio, &sios_bio));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_fd, "buflen", &buflen));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_bio, "bio", bio));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_bio, "freebio", &yes));
+    if (rc != SIO_OK) return -1;
+    EVAL0(sio_configure_stage(sio, sios_bio, "inputsize", &bufsize));
+    if (rc != SIO_OK) return -1;
+
+    /*
+     * WRITE phase
+     */
+
+    EVAL0(sio_configure_stage(sio, sios_fd, "fd", &fd));
+    if (rc != SIO_OK) goto badwrite;
+    EVAL0(sio_attach(sio, sios_fd, SIO_MODE_READWRITE));
+    if (rc != SIO_OK) goto badwrite;
+    EVAL0(sio_attach(sio, sios_bio, SIO_MODE_READWRITE));
+    if (rc != SIO_OK) goto badwrite2;
+
+    for (i=0; i<wcount; ++i) {
+        EVAL0(sio_write(sio, S, len, &actual));
+        if (rc != SIO_OK) {
+            error = 1;
+            break;
+        } 
+        if (actual != len) {
+            ts_test_fail(TS_CTX, "sio_write result %d (expected %d)\n",
+                (int)actual, (int)len);
+            error = 1;
+            break;
+        }
+    }
+
+    EVAL0(sio_push(sio));
+    if (rc != SIO_OK) error = 1;
+    EVAL0(sio_detach(sio, sios_bio));
+    if (rc != SIO_OK) error = 1;
+    result = error;
+
+    badwrite2:
+    EVAL0(sio_detach(sio, sios_fd));
+    if (rc != SIO_OK) result = -1;
+
+    badwrite:
+    EVAL0(sio_destroy_stage(sio, sios_bio));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy_stage(sio, sios_fd));
+    if (rc != SIO_OK) result = -1;
+    EVAL0(sio_destroy(sio));
+    if (rc != SIO_OK) result = -1;
+
+    return result;
+}
+
 TS_TEST(test_sio_bio)
 {
+    session(_t, test_sio_bio_read, test_sio_bio_write, 1);
 }
 #endif
 
@@ -1561,6 +1375,8 @@
     ts_suite_t *ts;
     int n;
 
+    signal(SIGPIPE, SIG_IGN);
+
     ts = ts_suite_new("OSSP sio (Stream I/O)");
     ts_suite_test(ts, test_sio_buffer, "stream I/O buffering");
     ts_suite_test(ts, test_sio_fd, "stream I/O file");

CVSTrac 2.0.1