head 1.10; access; symbols SIO_0_9_3:1.10 AL_0_9_3:1.10 AL_0_9_2:1.10 SIO_0_9_2:1.9 SIO_0_9_1:1.9 SIO_0_9_0:1.9 AL_0_9_0:1.4; locks; strict; comment @ * @; 1.10 date 2005.10.03.08.43.04; author rse; state Exp; branches; next 1.9; 1.9 date 2003.01.22.16.37.48; author mlelstv; state Exp; branches; next 1.8; 1.8 date 2003.01.06.13.49.24; author rse; state Exp; branches; next 1.7; 1.7 date 2002.12.16.15.03.18; author mlelstv; state Exp; branches; next 1.6; 1.6 date 2002.12.16.15.02.14; author rse; state Exp; branches; next 1.5; 1.5 date 2002.12.16.14.46.52; author mlelstv; state Exp; branches; next 1.4; 1.4 date 2002.12.16.14.02.45; author rse; state Exp; branches; next 1.3; 1.3 date 2002.12.16.13.35.58; author mlelstv; state Exp; branches; next 1.2; 1.2 date 2002.12.16.13.33.23; author mlelstv; state Exp; branches; next 1.1; 1.1 date 2002.12.16.12.24.52; author mlelstv; state Exp; branches; next ; desc @@ 1.10 log @o Upgraded build environment to GNU autoconf 2.59, GNU libtool 1.5.20 and GNU shtool 2.0.3 o Provide Autoconf check (AC_CHECK_VA_COPY) for va_copy(d,s) macro and fallback implementations and now that we can be sure that va_copy() exists for us, use it in var_formatv() and ts.c instead of the direct assignments (which are not sufficiently portable). o Adjusted copyright messages for year 2005. @ text @/* ** OSSP al - Assembly Line ** Copyright (c) 2002-2005 Ralf S. Engelschall ** Copyright (c) 2002-2005 The OSSP Project ** Copyright (c) 2002-2005 Cable & Wireless ** Copyright (c) 2002-2005 Michael van Elst ** ** This file is part of OSSP al, an abstract datatype of a data buffer ** that can assemble, move and truncate data but avoids actual copying ** and which can be found at http://www.ossp.org/pkg/lib/al/. ** ** 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. ** ** al_test.c: assembly line library test suite */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "ts.h" #include "al.h" static char label, label2, label3; #define LABEL ((al_label_t)&label) #define LABEL2 ((al_label_t)&label2) #define LABEL3 ((al_label_t)&label3) #define S(s) s, strlen(s) #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, al_error(rc), rc0, al_error(rc0)) #define CHECKLEN(name, al) \ do { \ size_t good, bad; \ if (checklen(al, &good, &bad)) \ ts_test_fail(TS_CTX, "%s -> corrupted length %d (expected %d)\n", \ name, good, bad); \ } while (0) #define EVAL0(name,block) EVAL(name,rc,AL_OK,block) #define EVAL1(name,al,block) EVAL(name,rc,AL_OK,block); CHECKLEN(name, al); #define CHECKLEN1(name, al, n) \ do { \ CHECKLEN(name, al); \ if (al_bytes(al) != (n)) \ ts_test_fail(TS_CTX, "%s -> invalid length %d (expected %d)\n", \ al_bytes(al), (n)); \ } while (0) static int checklen(al_t *al, size_t *goodp, size_t *badp) { al_rc_t rc; al_tx_t *tx; al_chunk_t *cur; size_t total, total2; total = 0; rc = al_txalloc(al, &tx); if (rc != AL_OK) return -1; rc = al_traverse(al, 0, al_bytes(al), AL_FORWARD, NULL, tx); if (rc != AL_OK) { al_txfree(al, tx); return -1; } while (al_traverse_next(al, tx, &cur) == AL_OK) total += al_chunk_len(cur); al_traverse_end(al, tx, 1); al_txfree(al, tx); total2 = al_bytes(al); if (total != total2) { *goodp = total; *badp = total2; return -1; } return 0; } /* test: data copy */ TS_TEST(test_al_data) { al_rc_t rc; al_t *al; EVAL0("al_create", { rc = al_create(&al); }); if (rc != AL_OK) return; EVAL1("al_append_bytes", al, { rc = al_append_bytes(al, S("Hello world\n"), NULL); }); EVAL0("al_destroy", { rc = al_destroy(al); }); } /* test: splicing */ TS_TEST(test_al_splice) { al_rc_t rc; al_t *src, *ins, *dst; int i; EVAL0("al_create(&src)", { rc = al_create(&src); }); if (rc != AL_OK) return; EVAL0("al_create(&ins)", { rc = al_create(&ins); }); if (rc != AL_OK) return; EVAL0("al_create(&dst)", { rc = al_create(&dst); }); if (rc != AL_OK) return; for (i=0; i<500; ++i) { EVAL1("al_append_bytes(&src)", src, { rc = al_append_bytes(src, S("Huhu world\n"), LABEL); }); } EVAL1("al_append_bytes(src)", src, { rc = al_append_bytes(src, S("Goodbye world\n"), LABEL); }); EVAL1("al_append_bytes(src)", src, { rc = al_append_bytes(src, S("Goodbye world\n"), LABEL2); }); EVAL1("al_prepend_byts(src)", src, { rc = al_prepend_bytes(src, S("Hello world\n"), LABEL2); }); EVAL1("al_prepend_bytes(src)", src, { rc = al_prepend_bytes(src, S("Hello world\n"), LABEL); }); EVAL1("al_prepend_bytes(ins)", ins, { rc = al_prepend_bytes(ins, S("KICK "), LABEL3); }); EVAL1("al_append_bytes(ins)", ins, { rc = al_append_bytes(ins, S("ME\n"), LABEL3); }); EVAL0("al_splice", { rc = al_splice(src, 4, 80, ins, dst); }); CHECKLEN1("al_splice(src)",src, 5480); CHECKLEN1("al_splice(ins)",ins, 0); CHECKLEN1("al_splice(dst)",dst, 80); EVAL0("al_destroy(dst)", { rc = al_destroy(dst); }); EVAL0("al_destroy(ins)", { rc = al_destroy(ins); }); EVAL0("al_destroy(src)", { rc = al_destroy(src); }); } /* test: labelling */ TS_TEST(test_al_label) { al_rc_t rc; al_t *al; al_tx_t *tx; al_chunk_t *cur; int i, k; static struct { size_t len; int ln; } chunks[] = { { 5, 1 }, { 2, 2 }, { 2, 3 }, { 5, 2 }, { 14, 1 }, { 0, 0 } }; static al_label_t labels[] = { NULL, LABEL, LABEL2, LABEL3 }; EVAL0("al_create", { rc = al_create(&al); }); if (rc != AL_OK) return; EVAL0("al_append_bytes", { rc = al_append_bytes(al, S("Hello world. Goodbye world.\n"), LABEL); }); /* * 28 chars LABEL */ EVAL1("al_setlabel", al, { rc = al_setlabel(al, 7, 2, NULL, LABEL3); }); /* * 7 chars LABEL * 2 chars LABEL3 * 19 chars LABEL */ EVAL1("al_setlabel", al, { rc = al_setlabel(al, 5, 9, LABEL, LABEL2); }); /* * 5 chars LABEL * 2 chars LABEL2 * 2 chars LABEL3 * 5 chars LABEL2 * 14 chars LABEL */ EVAL0("al_txalloc", { rc = al_txalloc(al, &tx); }); EVAL0("al_traverse", { rc = al_traverse(al, 0, al_bytes(al), AL_FORWARD, NULL, tx); }); i = 0; ts_test_check(TS_CTX, "al_traverse_next"); while (al_traverse_next(al, tx, &cur) == AL_OK) { size_t n = al_chunk_len(cur); al_label_t l = al_chunk_label(cur); for (k=3; k>0; --k) if (labels[k] == l) break; if (chunks[i].len == 0) { ts_test_fail(TS_CTX, "al_traverse_next: found chunk %d[L%d] (none expected)\n", n, k); continue; } if (n != chunks[i].len || k != chunks[i].ln) { ts_test_fail(TS_CTX, "al_traverse_next: found chunk %d[L%d] (expected %d[L%d])\n", n, k, chunks[i].len, chunks[i].ln); } ++i; } EVAL0("al_traverse_end", { rc = al_traverse_end(al, tx, 1); }); EVAL0("al_txfree", { rc = al_txfree(al, tx); }); EVAL0("al_destroy", { rc = al_destroy(al); }); } /* test: attach */ static char *reclaim_ptr = NULL; static size_t reclaim_size = 0; static void *reclaim_u = NULL; static int reclaim_count = 0; static void reclaim(char *p, size_t n, void *u) { ++reclaim_count; if (reclaim_ptr != NULL || reclaim_size != 0 || reclaim_u != NULL) return; reclaim_ptr = p; reclaim_size = n; reclaim_u = u; } static const char *reclaim_result(const char *p, size_t n, void *u) { if (reclaim_count == 0) return "reclaim never called"; if (reclaim_count > 1) return "repeated call"; if (p != reclaim_ptr || n != reclaim_size || u != reclaim_u) return "bad data for free"; return NULL; } TS_TEST(test_al_attach) { al_rc_t rc; al_t *al; char baf[] = "Mittendrin\n"; char *context = "CONTEXT"; const char *mess; EVAL0("al_create", { rc = al_create(&al); }); if (rc != AL_OK) return; EVAL1("al_append_bytes", al, { rc = al_append_bytes(al, S("Hello world\n"), NULL); }); EVAL1("al_attach_buffer", al, { rc = al_attach_buffer(al, S(baf), NULL, reclaim, context); }); EVAL1("al_append_bytes", al, { rc = al_append_bytes(al, S("Goodbye world\n"), NULL); }); EVAL0("al_destroy", { rc = al_destroy(al); }); mess = reclaim_result(S(baf), context); if (mess != NULL) ts_test_fail(TS_CTX,"buffer reclaim failed: %s\n",mess); } /* test: exception handling */ #ifdef WITH_EX #include "ex.h" TS_TEST(test_al_ex) { volatile al_t *al; ex_t ex; int caught; ts_test_check(TS_CTX, "exception handling"); caught = 0; al = NULL; ex_try { al_create(&al); al_append_bytes(al, S("DUMMYDUMMY"), NULL); al_splice(al, 50, 1, NULL, NULL); } ex_cleanup { if (al != NULL) al_destroy(al); } ex_catch (ex) { if ((al_rc_t)ex.ex_value != AL_ERR_EOF) ts_test_fail(TS_CTX, "unexpected exception: %d\n", (al_rc_t)ex.ex_value); caught = 1; } if (!caught) ts_test_fail(TS_CTX, "expected exception not caught\n"); } #endif int main(int argc, char *argv[]) { ts_suite_t *ts; int n; ts = ts_suite_new("OSSP al (Assembly Line)"); ts_suite_test(ts, test_al_data, "assembly line data copying"); ts_suite_test(ts, test_al_splice, "assembly line splicing"); ts_suite_test(ts, test_al_label, "assembly line labelling"); ts_suite_test(ts, test_al_attach, "assembly line buffer attach"); #ifdef WITH_EX ts_suite_test(ts, test_al_ex, "exception handling"); #endif n = ts_suite_run(ts); ts_suite_free(ts); return n; } @ 1.9 log @fixed broken error output @ text @d3 4 a6 4 ** Copyright (c) 2002-2003 Ralf S. Engelschall ** Copyright (c) 2002-2003 The OSSP Project ** Copyright (c) 2002-2003 Cable & Wireless Deutschland ** Copyright (c) 2002-2003 Michael van Elst @ 1.8 log @Adjust copyright messages for new year 2003 @ text @d57 1 a57 1 rc, al_error(rc), rc0, al_error(rc0)) d64 1 a64 1 good, bad); \ @ 1.7 log @more fixes for WITH_EX case @ text @d3 4 a6 4 ** Copyright (c) 2002 Ralf S. Engelschall ** Copyright (c) 2002 The OSSP Project ** Copyright (c) 2002 Cable & Wireless Deutschland ** Copyright (c) 2002 Michael van Elst @ 1.6 log @do not touch disclaimer messages in any way @ text @d379 1 a380 1 al = NULL; d382 1 a382 1 al_append_bytes(&al, S("DUMMYDUMMY"), NULL); d386 1 a386 1 if (al != NULL) al_destroy(&al); @ 1.5 log @fix cut&paste error for WITH_EX case @ text @d17 1 a17 1 ** THIS SOFTWARE IS PROVIDED ``AS IS"" AND ANY EXPRESSED OR IMPLIED @ 1.4 log @post-adjustments to source tree @ text @d371 1 a371 1 TS_TEST(test_sa_ex) d389 1 a389 1 if ((sa_rc_t)ex.ex_value != AL_ERR_EOF) @ 1.3 log @bail out of test if al_create fails (who said memory leak ?) @ text @d9 2 a10 1 ** that can assemble, move and truncate data but avoids actual copying. @ 1.2 log @make it work @ text @d123 1 d144 1 d148 1 d152 1 d225 2 d347 2 @ 1.1 log @initial snapshot for OSSP al @ text @d16 1 a16 1 ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED d38 2 a39 7 #include #include #include #include #include #include #include d50 4 a53 1 #define RCHK(name, rc, rc0) \ d56 3 a58 2 rc, al_error(al), rc0, al_error(rc0)) #define CCHK(name, al) \ d61 1 a61 1 if (chklen(al, &good, &bad)) { \ a63 1 } \ d66 2 a67 19 static const char *fill(char *p, int n) { static char buf[4 * 80 + 1]; int max = sizeof(buf)-5; int k; k=0; while (n > 0 && k < max) { if (isprint(*p)) { buf[k] = *p; k += 1; } else { sprintf(buf+k,"<%2.2x>",*p); k += 4; } ++p; --n; } buf[k] = '\0'; d69 7 a75 2 return (const char *)buf; } d79 1 d86 10 a95 2 al_txalloc(al, &tx); al_traverse(al, 0, al_bytes(al), AL_FORWARD, NULL, tx); d98 1 d120 11 a130 7 rc = al_create(&al); RCHK('al_create',rc,AL_OK); rc = al_append_bytes(al, S("Hello world\n")); RCHK('al_append_bytes',rc,AL_OK); CCHK('al_append_bytes', al); rc = al_destroy(&al); RCHK('al_destroy',rc,AL_OK); d140 9 a148 6 rc = al_create(&src); RCHK('al_create(&src)',rc,AL_OK); rc = al_create(&ins); RCHK('al_create(&ins)',rc,AL_OK); rc = al_create(&dst); RCHK('al_create(&dst)',rc,AL_OK); d151 3 a153 2 rc = al_append_bytes(src, S("Huhu world\n"), LABEL); RCHK('al_append_bytes(src)',rc,AL_OK); d155 38 a192 32 rc = al_append_bytes(src, S("Goodbye world\n"), LABEL); RCHK('al_append_bytes(src)',rc,AL_OK); CCHK('al_append_bytes(src)',src); rc = al_append_bytes(src, S("Goodbye world\n"), LABEL2); RCHK('al_append_bytes(src)',rc,AL_OK); CCHK('al_append_bytes(src)',src); rc = al_prepend_bytes(src, S("Hello world\n"), LABEL2); RCHK('al_prepend_bytes(src)',rc,AL_OK); CCHK('al_prepend_bytes(src)',src); rc = al_prepend_bytes(src, S("Hello world\n"), LABEL); RCHK('al_prepend_bytes(src)',rc,AL_OK); CCHK('al_prepend_bytes(src)',src); rc = al_prepend_bytes(ins, S("KICK "), LABEL3); RCHK('al_prepend_bytes(ins)',rc,AL_OK); CCHK('al_prepend_bytes(ins)',ins); rc = al_append_bytes(ins, S("ME\n"), LABEL3); RCHK('al_append_bytes(ins)',rc,AL_OK); CCHK('al_append_bytes(ins)',ins); rc = al_splice(src, 4, 80, ins, dst); RCHK('al_splice',rc,AL_OK); CCHK('al_splice(src)',src); CCHK('al_splice(ins)',ins); CCHK('al_splice(dst)',dst); rc = al_destroy(dst); RCHK('al_destroy(dst)',rc,AL_OK); rc = al_destroy(ins); RCHK('al_destroy(ins)',rc,AL_OK); rc = al_destroy(src); RCHK('al_destroy(src)',rc,AL_OK); d200 75 d276 7 a282 10 rc = al_create(&al); RCHK('al_create',rc,AL_OK); rc = al_append_bytes(&al, S("Hello world\n"), LABEL); RCHK('al_create',rc,AL_OK); rc = al_setlabel(al, 7, 2, NULL, LABEL3); RCHK('al_setlabel',rc,AL_OK); CCHK('al_setlabel',al); rc = al_setlabel(al, 5, 9, NULL, LABEL2); CCHK('al_setlabel',al); d284 11 a294 2 rc = al_destroy(al); RCHK('al_destroy(al)',rc,AL_OK); d299 1 a299 1 static size_t *reclaim_size = 0; d315 1 a315 1 static const char *reclaim_result(char *p, size_t n, void *u) d319 1 a319 1 if (reclaim_count > 0) d336 1 a336 1 char *mess; d338 15 a352 13 rc = al_create(&al); RCHK('al_create', rc, AL_OK); rc = al_append_bytes(al, S("Hello world\n"), NULL); RCHK('al_append_bytes', rc, AL_OK); CCHK('al_append_bytes', al); rc = al_attach_buffer(al, S(baf), NULL, reclaim, context); RCHK('al_attach_buffer', rc, AL_OK); CCHK('al_attach_buffer', al); rc = al_append_bytes(al, S("Goodbye world\n"), NULL); RCHK('al_append_bytes', rc, AL_OK); CCHK('al_append_bytes', al); rc = al_destroy(&al); RCHK('al_destroy', rc, AL_OK); @