/* ** OSSP sio - Stream I/O ** Copyright (c) 2002-2003 Cable & Wireless Deutschland ** Copyright (c) 2002-2003 The OSSP Project ** Copyright (c) 2002-2003 Ralf S. Engelschall ** ** 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 #include #include #include #include #include #include #include #include "ts.h" #include "al.h" #include "sio.h" #if ENABLE_BIO #include #include 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 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 (nodd > wcount) ts_test_fail(TS_CTX, "excess data on odd stream\n"); } } 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 (neven > wcount) ts_test_fail(TS_CTX, "excess data on even stream\n"); } } if (actual > 0) break; if (nstreams == 0) break; } if (nodd < wcount) ts_test_fail(TS_CTX, "missing data on odd stream %d vs %d\n",nodd,wcount); if (neven < wcount) ts_test_fail(TS_CTX, "missing data on even stream %d vs %d\n",neven,wcount); if (codd != 0) ts_test_fail(TS_CTX, "extra chars on odd stream\n"); if (ceven != 0) ts_test_fail(TS_CTX, "extra chars on even stream\n"); /* * 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; }