ossp-pkg/sio/sio_test.c
1.9
/*
** OSSP sio - Stream I/O
** Copyright (c) 2002-2003 Cable & Wireless Deutschland <http://www.cw.com/de/>
** Copyright (c) 2002-2003 The OSSP Project <http://www.ossp.org/>
** Copyright (c) 2002-2003 Ralf S. Engelschall <rse@engelschall.com>
**
** This file is part of OSSP sio, a layered stream I/O library
** which can be found at http://www.ossp.org/pkg/lib/sio/.
**
** Permission to use, copy, modify, and distribute this software for
** any purpose with or without fee is hereby granted, provided that
** the above copyright notice and this permission notice appear in all
** copies.
**
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
** sio_test.c: stream I/O library test suite
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "ts.h"
#include "al.h"
#include "sio.h"
#if ENABLE_BIO
#include <openssl/ssl.h>
#include <openssl/bio.h>
extern BIO_METHOD *BIO_s_socket();
extern sio_module_t sio_module_bio;
#endif
#if ENABLE_SA
#include "sa.h"
extern sio_module_t sio_module_sa;
#endif
extern sio_module_t sio_module_null;
extern sio_module_t sio_module_hole;
extern sio_module_t sio_module_buffer;
extern sio_module_t sio_module_zlib;
extern sio_module_t sio_module_sio;
extern sio_module_t sio_module_fd;
extern sio_module_t sio_module_hello;
extern sio_module_t sio_module_sillymux;
#define EVAL(name,rc,rc0,block) \
ts_test_check(TS_CTX, name); \
block \
if (rc != rc0) \
ts_test_fail(TS_CTX, "%s -> %d[%s] (expected %d[%s])\n", \
name, rc, sio_error(rc), rc0, sio_error(rc0))
#define EVAL0(name,block) EVAL(name,rc,SIO_OK,block)
sio_rc_t readloop(sio_t *, char *, size_t, size_t *);
int test_sio_pipe_read(ts_test_t *, int, int);
int test_sio_pipe_write(ts_test_t *, int, int);
sio_rc_t readloop(sio_t *sio, char *buf, size_t len, size_t *actualp)
{
sio_rc_t rc = SIO_OK;
size_t actual, total = 0;
while (len > 0) {
rc = sio_read(sio, buf, len, &actual);
if (rc != SIO_OK)
break;
buf += actual;
total += actual;
len -= actual;
}
*actualp = total;
return rc;
}
TS_TEST(test_sio_buffer)
{
sio_rc_t rc;
sio_t *sio;
sio_stage_t *sios_buffer, *sios_hole;
size_t bufsize = 1000; /* output/input buffer size */
int i,wcount = 100;
char S[] = "Hello world\n";
size_t actual, len = strlen(S);
EVAL0("sio_create", {
rc = sio_create(&sio);
});
if (rc != SIO_OK) return;
EVAL0("sio_create_stage(&sios_hole)", {
rc = 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);
});
if (rc != SIO_OK) return;
EVAL0("sio_configure_stage(sios_buffer, outputsize)", {
rc = 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);
});
if (rc != SIO_OK) return;
EVAL0("sio_attach(sios_buffer)", {
rc = 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);
});
if (rc != SIO_OK) break;
if (actual != len) {
ts_test_fail(TS_CTX, "sio_write result %d (expected %d)\n",
(int)actual, (int)len);
break;
}
}
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);
});
}
TS_TEST(test_sio_fd)
{
sio_rc_t rc;
sio_t *sio;
sio_stage_t *sios_buffer, *sios_fd;
size_t bufsize = 1000; /* output buffer size */
size_t buflen = 81; /* fd input buffer size */
int fd;
int i,wcount = 100;
char S[] = "Hello world\n";
char buf[sizeof(S)];
size_t actual, len = strlen(S);
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", &buflen);
});
if (rc != SIO_OK) return;
EVAL0("sio_configure_stage(sios_buffer, inputsize)", {
rc = sio_configure_stage(sio, sios_buffer, "inputsize", &bufsize);
});
if (rc != SIO_OK) return;
/*
* WRITE phase
*/
mktemp(tempfile);
fd = open(tempfile, O_CREAT|O_EXCL|O_WRONLY, 0600);
if (fd < 0) {
ts_test_fail(TS_CTX, "cannot create temporary file \"%s\" (%s)\n",
tempfile, strerror(errno));
} else {
do_unlink = 1;
EVAL0("sio_configure_stage(sios_fd, fd)", {
rc = 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);
});
if (rc != SIO_OK) goto badwrite;
EVAL0("sio_attach(sios_buffer)", {
rc = 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) break;
if (actual != len) {
ts_test_fail(TS_CTX, "sio_write result %d (expected %d)\n",
(int)actual, (int)len);
break;
}
}
EVAL0("sio_push", {
rc = sio_push(sio);
});
EVAL0("sio_detach(sios_buffer)", {
rc = sio_detach(sio, sios_buffer);
});
badwrite2:
EVAL0("sio_detach(sios_fd)", {
rc = sio_detach(sio, sios_fd);
});
badwrite:
close(fd);
}
fd = open(tempfile, O_RDONLY);
if (fd < 0) {
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);
});
if (rc != SIO_OK) goto badread;
EVAL0("sio_attach(sios_fd)", {
rc = 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);
});
if (rc != SIO_OK) goto badread2;
for (i=0; i<wcount; ++i) {
EVAL0("sio_read", {
rc = readloop(sio, buf, len, &actual);
});
if (rc != SIO_OK) break;
if (actual != len) {
ts_test_fail(TS_CTX, "sio_read result %d (expected %d)\n",
(int)actual, (int)len);
break;
}
buf[actual] = '\0';
if (strcmp(buf, S)) {
ts_test_fail(TS_CTX, "sio_read data mismatch at loop %d\n",
i);
break;
}
}
EVAL0("sio_detach(sios_buffer)", {
rc = sio_detach(sio, sios_buffer);
});
badread2:
EVAL0("sio_detach(sios_fd)", {
rc = sio_detach(sio, sios_fd);
});
badread:
close(fd);
}
if (do_unlink && unlink(tempfile) < 0) {
ts_test_fail(TS_CTX, "cannot unlink temporary file \"%s\" (%s)\n",
tempfile, strerror(errno));
}
/*
* 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);
});
}
int test_sio_pipe_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_buffer, *sios_fd;
size_t bufsize = 987; /* output buffer size */
size_t buflen = 64; /* fd input buffer size */
int i;
char S[] = "Hello world\n";
char buf[sizeof(S)];
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);
});
if (rc != SIO_OK) return -1;
EVAL0("sio_configure_stage(sios_fd, fd)", {
rc = 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);
});
if (rc != SIO_OK) goto badread;
EVAL0("sio_attach(sios_buffer)", {
rc = sio_attach(sio, sios_buffer, SIO_MODE_READWRITE);
});
if (rc != SIO_OK) goto badread2;
for (i=0; i<wcount; ++i) {
EVAL0("sio_read", {
rc = readloop(sio, buf, len, &actual);
});
if (rc != SIO_OK) error = 1;
if (rc != SIO_OK) break;
if (actual != len) {
ts_test_fail(TS_CTX, "sio_read result %d (expected %d)\n",
(int)actual, (int)len);
break;
}
buf[actual] = '\0';
if (strcmp(buf, S)) {
ts_test_fail(TS_CTX, "sio_read data mismatch at loop %d\n",
i);
break;
}
}
EVAL0("sio_detach(sios_buffer)", {
rc = 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);
});
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);
});
if (rc != SIO_OK) result = -1;
return result;
}
int test_sio_pipe_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_buffer, *sios_fd;
size_t bufsize = 1003; /* output buffer size */
size_t buflen = 47; /* fd input buffer size */
int i;
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);
});
if (rc != SIO_OK) return -1;
/*
* WRITE phase
*/
EVAL0("sio_configure_stage(sios_fd, fd)", {
rc = 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);
});
if (rc != SIO_OK) goto badwrite;
EVAL0("sio_attach(sios_buffer)", {
rc = 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;
if (actual != len) {
ts_test_fail(TS_CTX, "sio_write result %d (expected %d)\n",
(int)actual, (int)len);
break;
}
}
EVAL0("sio_push", {
rc = sio_push(sio);
});
if (rc != SIO_OK) error = 1;
EVAL0("sio_detach(sios_buffer)", {
rc = 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);
});
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);
});
if (rc != SIO_OK) result = -1;
return result;
}
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;
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);
}
}
}
TS_TEST(test_sio_sio)
{
sio_rc_t rc;
sio_t *A_sio;
sio_stage_t *A_sios_sillymux;
sio_stage_t *A_sios_fd;
sio_t *B_sio;
sio_stage_t *B_sios_sio;
sio_t *C_sio;
sio_stage_t *C_sios_sio;
size_t buflen = 53;
int i,wcount = 100;
char SO[] = "Hello world\n";
size_t lenodd = strlen(SO);
char SE[] = "Goodbye cruel world\n";
size_t leneven = strlen(SE);
size_t actual;
al_label_t ODD = (al_label_t)1;
al_label_t EVEN = (al_label_t)2;
char tempfile[] = "./sio_test_tmpfile.XXXXXX";
int fd;
int neven, nodd;
int ceven, codd;
mktemp(tempfile);
fd = open(tempfile, O_CREAT|O_EXCL|O_RDWR, 0600);
if (fd < 0) {
ts_test_fail(TS_CTX, "cannot create temporary file \"%s\" (%s)\n",
tempfile, strerror(errno));
return;
}
for (i=0; i<wcount; ++i) {
if (write(fd, SO, lenodd) != lenodd ||
write(fd, SE, leneven) != leneven) {
ts_test_fail(TS_CTX, "cannot write temporary file \"%s\" (%s)\n",
tempfile, strerror(errno));
goto close_and_cleanup;
}
}
if (lseek(fd, (off_t)0, SEEK_SET) == -1) {
ts_test_fail(TS_CTX, "cannot rewind temporary file \"%s\" (%s)\n",
tempfile, strerror(errno));
goto close_and_cleanup;
}
/*
* 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);
});
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);
});
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);
});
if (rc != SIO_OK) return;
/*
* read from both streams
*/
nodd = neven = 0;
codd = ceven = 0;
while (nodd < wcount || neven < wcount) {
char buf[17], *p;
int nstreams = 2;
EVAL0("sio_read(B_sio)", {
rc = readloop(B_sio, buf, sizeof(buf), &actual);
if (rc == SIO_ERR_EOF) {
--nstreams;
rc = SIO_OK;
}
});
if (rc != SIO_OK)
break;
p = buf;
while (actual > 0) {
int n = lenodd - codd;
if (n > actual) n = actual;
if (memcmp(p, SO + codd, n) != 0) {
ts_test_fail(TS_CTX, "data mismatch on odd stream\n");
break;
}
actual -= n;
p += n;
codd += n;
if (codd >= lenodd) {
codd = 0;
++nodd;
}
}
if (actual > 0)
break;
EVAL0("sio_read(C_sio)", {
rc = readloop(C_sio, buf, sizeof(buf), &actual);
if (rc == SIO_ERR_EOF) {
--nstreams;
rc = SIO_OK;
}
});
if (rc != SIO_OK)
break;
p = buf;
while (actual > 0) {
int n = leneven - ceven;
if (n > actual) n = actual;
if (memcmp(p, SE + ceven, n) != 0) {
ts_test_fail(TS_CTX, "data mismatch on even stream\n");
break;
}
actual -= n;
p += n;
ceven += n;
if (ceven >= leneven) {
ceven = 0;
++neven;
}
}
if (actual > 0)
break;
if (nstreams == 0) {
if (neven != wcount ||
ceven != 0 ||
nodd != wcount ||
codd != 0) {
ts_test_fail(TS_CTX, "data missing from streams\n");
}
break;
}
}
/*
* 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);
});
/*
* 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);
});
/*
* 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);
});
close_and_cleanup:
close(fd);
if (unlink(tempfile) < 0) {
ts_test_fail(TS_CTX, "cannot unlink temporary file \"%s\" (%s)\n",
tempfile, strerror(errno));
}
}
TS_TEST(test_sio_hello)
{
}
#if ENABLE_ZLIB
TS_TEST(test_sio_zlib)
{
}
#endif
#if ENABLE_SA
TS_TEST(test_sio_sa)
{
}
#endif
#if ENABLE_BIO
TS_TEST(test_sio_bio)
{
}
#endif
int main(int argc, char *argv[])
{
ts_suite_t *ts;
int n;
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");
ts_suite_test(ts, test_sio_pipe, "stream I/O pipe");
ts_suite_test(ts, test_sio_sio, "stream I/O multiplexing");
ts_suite_test(ts, test_sio_hello, "stream I/O hello protocol");
#if ENABLE_ZLIB
ts_suite_test(ts, test_sio_zlib, "stream I/O zlib compression");
#endif
#if ENABLE_SA
ts_suite_test(ts, test_sio_sa, "stream I/O socket abstraction");
#endif
#if ENABLE_BIO
ts_suite_test(ts, test_sio_bio, "stream I/O ssl adapter");
#endif
n = ts_suite_run(ts);
ts_suite_free(ts);
return n;
}