OSSP CVS Repository

ossp - ossp-pkg/al/al_test.c 1.1
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/al/al_test.c 1.1
/*
**  OSSP al - Assembly Line
**  Copyright (c) 2002 Ralf S. Engelschall <rse@engelschall.com>
**  Copyright (c) 2002 The OSSP Project <http://www.ossp.org/>
**  Copyright (c) 2002 Cable & Wireless Deutschland <http://www.cw.com/de/>
**  Copyright (c) 2002 Michael van Elst <mlelstv@dev.de.cw.net>
**
**  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.
**
**  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 <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

#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 RCHK(name, rc, rc0) \
    if (rc != rc0) \
        ts_test_fail(TS_CTX, "%s -> %d[%s] (expected %d[%s])\n", \
            rc, al_error(al), rc0, al_error(rc0))
#define CCHK(name, al) \
    do { \
        size_t good, bad; \
        if (chklen(al, &good, &bad)) { \
            ts_test_fail(TS_CTX, "%s -> corrupted length %d (expected %d)\n", \
                good, bad); \
        } \
    } while (0)

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';

    return (const char *)buf;
}

static int checklen(al_t *al, size_t *goodp, size_t *badp)
{
    al_tx_t *tx;
    al_chunk_t *cur;
    size_t total, total2;

    total = 0;

    al_txalloc(al, &tx);
    al_traverse(al, 0, al_bytes(al), AL_FORWARD, NULL, tx);
    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;

    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);
}

/* test: splicing */
TS_TEST(test_al_splice)
{
    al_rc_t rc;
    al_t *src, *ins, *dst;
    int i;

    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);

    for (i=0; i<500; ++i) {
        rc = al_append_bytes(src, S("Huhu world\n"), LABEL);
        RCHK('al_append_bytes(src)',rc,AL_OK);
    }
    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);
}

/* test: labelling */
TS_TEST(test_al_label)
{
    al_rc_t rc;
    al_t *al;

    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);

    rc = al_destroy(al);
    RCHK('al_destroy(al)',rc,AL_OK);
}

/* 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(char *p, size_t n, void *u)
{
    if (reclaim_count == 0)
        return "reclaim never called";
    if (reclaim_count > 0)
        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";
    char *mess;

    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);

    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_sa_ex)
{
    volatile al_t *al;
    ex_t ex;
    int caught;

    ts_test_check(TS_CTX, "exception handling");
    caught = 0;
    ex_try {
        al = NULL;
        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 ((sa_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;
}


CVSTrac 2.0.1