OSSP CVS Repository

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

ossp-pkg/str/str_test.c
/*
**  OSSP str - String Handling
**  Copyright (c) 1999-2005 Ralf S. Engelschall <rse@engelschall.com>
**  Copyright (c) 1999-2005 The OSSP Project <http://www.ossp.org/>
**
**  This file is part of OSSP str, a string handling and manipulation
**  library which can be found at http://www.ossp.org/pkg/lib/str/.
**
**  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.
**
**  str_test.c: test suite
*/

#include <stdio.h>
#include <stdlib.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#if defined(HAVE_DMALLOC_H) && defined(WITH_DMALLOC)
#include "dmalloc.h"
#endif

#include "str.h"
#include "ts.h"

#define LONG_STRING 1024

/*
 * Test String Length
 */

TS_TEST(test_length)
{
    ts_test_check(TS_CTX, "NULL handling");
    if (str_len(NULL) != 0)
        ts_test_fail(TS_CTX, "unexpected non-zero return");

    ts_test_check(TS_CTX, "empty string handling");
    if (str_len("") != 0)
        ts_test_fail(TS_CTX, "unexpected non-zero return");

    ts_test_check(TS_CTX, "short string handling");
    if (str_len("a") != 1)
        ts_test_fail(TS_CTX, "unexpected return != 1");

    ts_test_check(TS_CTX, "longer string handling");
    if (str_len("foo bar quux") != 12)
        ts_test_fail(TS_CTX, "unexpected return != 12");
    return;
}

/*
 * Test String Locating
 */

struct {
    char *s; str_size_t n; char *p; int o;
} loctab[] = {
    { "foo bar quux", 0, "", 0 },
    { "foo bar quux", 0, "foo", 0 },
    { "foo bar quux", 0, "bar", 4 },
    { "foo bar quux", 0, "quux", 8 },
    { "foo bar quux", 0, "x", 11 },
    { "foo bar quux", 3, "foo", 0 },
    { "foo bar quux", 4, "x", -1 },
    { "foo bar quux", 5, "bar", -1 },
    { "foo bar", 0, "foo bar", 0 },
    { "foo bar", 0, "foo bar quux", -1 },
    { NULL, 0, NULL, 0 }
};

TS_TEST(test_locate)
{
    int i;
    char *rv;

    for (i = 0; loctab[i].s != NULL; i++) {
        rv = str_locate(loctab[i].s, loctab[i].n, loctab[i].p);
        ts_test_check(TS_CTX, "str_locate(\"%s\", %d, \"%s\") = \"%s\"",
                      loctab[i].s, loctab[i].n, loctab[i].p, rv == NULL ? "[NULL]" : rv);
        if (!((rv-loctab[i].s == loctab[i].o) || (rv == NULL && loctab[i].o == -1)))
            ts_test_fail(TS_CTX, "result was \"%s\", expected \"%s\"",
                         rv, loctab[i].s+loctab[i].o);
    }
    return;
}

/*
 * Test String Spanning
 */

struct {
    char *s; str_size_t n; char *cs; int m; int o;
} spantab[] = {
    { "foo bar quux", 0, "", 0, 0 },
    { "foo bar quux", 0, "xyz", 0, 0 },
    { "foo bar quux", 0, "fo ", 0, 4 },
    { "foo bar quux", 0, "b", STR_COMPLEMENT, 4 },
    { "foo bar quux", 0, "", STR_COMPLEMENT, 12 },
    { "foo bar quux", 0, "", STR_RIGHT, 11 },
    { "foo bar quux", 0, "abc", STR_RIGHT, 11 },
    { "foo bar quux", 0, "qux ", STR_RIGHT, 6 },
    { "foo bar quux", 0, "r", STR_RIGHT|STR_COMPLEMENT, 6 },
    { "foo bar quux", 0, "", STR_RIGHT|STR_COMPLEMENT, 0 },
    { "", 0, "", STR_COMPLEMENT, 0 },
    { "", 0, "", STR_RIGHT|STR_COMPLEMENT, 0 },
    { NULL, 0, NULL, 0, 0 }
};

TS_TEST(test_span)
{
    int i;
    char *rv;

    for (i = 0; spantab[i].s != NULL; i++) {
        rv = str_span(spantab[i].s, spantab[i].n, spantab[i].cs, spantab[i].m);
        ts_test_check(TS_CTX, "str_span(\"%s\", %d, \"%s\", %d) = \"%s\"",
                      spantab[i].s, spantab[i].n, spantab[i].cs, spantab[i].m, rv);
        if (rv-spantab[i].s != spantab[i].o)
            ts_test_fail(TS_CTX, "result was \"%s\", expected \"%s\"",
                         rv, spantab[i].s+spantab[i].o);
    }
    return;
}

/*
 * Test String Tokenization
 */

struct {
    char *s; char *d; char *q; char *c; int f; char *r[4];
} toktab[] = {
    { "foo bar quux", " \t", "\"'", "#", 0, { "foo", "bar", "quux", NULL } },
    { " foo \t \"bar \t b'az\" quux#vwxyz", " \t", "\"'", "#", STR_STRIPQUOTES, { "foo", "bar \t b'az", "quux", NULL } },
    { NULL, NULL, NULL, NULL, 0, { NULL, NULL, NULL, NULL } }
};

static char *prstr_tab[200];
static int prstr_idx = 0;

static char *prstr(char *s)
{
    char *cp;
    char *p, *q;

    if (s == NULL)
         return "NULL";
    if ((cp = malloc(strlen(s)+20)) == NULL)
         return "ERROR";
    prstr_tab[prstr_idx++] = cp;
    q = cp;
    p = s;
    *q++ = '"';
    while (*p != NUL) {
        switch (*p) {
            case '\t': *q++ = '\\'; *q++ = 't'; p++; break;
            case '\n': *q++ = '\\'; *q++ = 'n'; p++; break;
            case '\r': *q++ = '\\'; *q++ = 'r'; p++; break;
            case '"': *q++ = '\\'; *q++ = '"'; p++; break;
            default:   *q++ = *p++;
        }
    }
    *q++ = '"';
    *q = NUL;
    return cp;
}

static void prstr_free(void)
{
    while (prstr_idx > 0)
        free(prstr_tab[--prstr_idx]);
    return;
}

TS_TEST(test_tokenize)
{
    char *cp;
    char *cp2;
    char *cp3;
    char *rc;
    int i, j;

    for (i = 0; toktab[i].s != NULL; i++) {
        ts_test_check(TS_CTX, "tokenization of \"%s\"\n", prstr(toktab[i].s));
        prstr_free();
        cp2 = cp = strdup(toktab[i].s);
        for (j = 0; j < 4; j++) {
            cp3 = strdup(cp);
            rc = str_token(&cp, toktab[i].d, toktab[i].q, toktab[i].c, toktab[i].f);
            ts_test_check(TS_CTX, "str_token(&%s, %s, %s, %s, %d) = %s",
                          prstr(cp3), prstr(toktab[i].d),
                          prstr(toktab[i].q), prstr(toktab[i].c),
                          toktab[i].f, prstr(rc)), prstr_free();
            free(cp3);
            if (!(   (rc == NULL && toktab[i].r[j] == NULL)
                  || (rc != NULL && toktab[i].r[j] != NULL && strcmp(rc, toktab[i].r[j]) == 0))) {
                ts_test_fail(TS_CTX, "expected result is \"%s\"", prstr(toktab[i].r[j]));
                prstr_free();
            }
        }
        free(cp2);
    }
    return;
}

/*
 * Test String Parsing
 */

struct {
    char *s; char *p; char *r1; char *r2; char *r3; char *r4; int rv;
} test2_tab[] = {
    { "foobar", "foobar", NULL, NULL, NULL, NULL, 1 },
    { "foobar", "m/^foobar$/", NULL, NULL, NULL, NULL, 1 },
    { "foobar", "foobarquux", NULL, NULL, NULL, NULL, 0 },
    { "foobar", "foo", NULL, NULL, NULL, NULL, 1 },
    { "foobar", "?", NULL, NULL, NULL, NULL, -1 },
    { "foobar", "m/(foo|bar)(bar|foo)/", "foo", "bar", NULL, NULL, 1 },
    { "foobar", "m&(?:foo|bar)(?:bar|foo)&", NULL, NULL, NULL, NULL, 1 },
    { "foobar", "m/(?:foo|bar)(?:bar|foo)/o", NULL, NULL, NULL, NULL, 1 },
    { "foobar", "m/(?:FOO|BAR)(?:bar|foo)/io", NULL, NULL, NULL, NULL, 1 },
    { "foobar", "((f(.)\\3)(b.*))", "foobar", "foo", "o", "bar", 1 },
    { "foobar", "s/((f(.)\\3)(b.*))/$2-$4/io", "foo-bar", NULL, NULL, NULL, 1 },
    { "foobar", "s/((f(.)\\3)(b.*))/$2-%s-$4/io", "foo-quux-bar", "quux", NULL, NULL, 1 },
    { "foobar", "s/((f(.)\\3)(b.*))/$2-%s-%s-%s-$4/io", "foo-quux-baz-0815-bar", "quux", "baz", "0815", 1 },
    { "foo:bar", "m/^(f[^:]+):(.*)$/", "foo", "bar", NULL, NULL, 1 },
    { "foo:bar", "s/^([^:]+):(.*)$/$1-%s-$2/o", "foo-quux-bar", "quux", NULL, NULL, 1 },
    { NULL, NULL, NULL, NULL, NULL, NULL, 0 }
};

TS_TEST(test_parsing)
{
    int i;
    int rv;
    char *r1, *r2, *r3, *r4;

    for (i = 0; test2_tab[i].s != NULL; i++) {
        ts_test_check(TS_CTX, "str_parse(\"%s\", \"%s\", ...)", test2_tab[i].s, test2_tab[i].p);
        if (*(test2_tab[i].p) == 's') {
            r1 = NULL;
            r2 = test2_tab[i].r2;
            r3 = test2_tab[i].r3;
            r4 = test2_tab[i].r4;
            rv = str_parse(test2_tab[i].s, test2_tab[i].p, &r1, r2, r3, r4);
        }
        else {
            r1 = r2 = r3 = r4 = NULL;
            rv = str_parse(test2_tab[i].s, test2_tab[i].p, &r1, &r2, &r3, &r4);
        }
        if (rv != test2_tab[i].rv ||
            ((r1 == NULL && test2_tab[i].r1 != NULL) ||
             (r1 != NULL && test2_tab[i].r1 == NULL) ||
             (r1 != NULL && test2_tab[i].r1 != NULL && strcmp(r1, test2_tab[i].r1) != 0)) ||
            ((r2 == NULL && test2_tab[i].r2 != NULL) ||
             (r2 != NULL && test2_tab[i].r2 == NULL) ||
             (r2 != NULL && test2_tab[i].r2 != NULL && strcmp(r2, test2_tab[i].r2) != 0)) ||
            ((r3 == NULL && test2_tab[i].r3 != NULL) ||
             (r3 != NULL && test2_tab[i].r3 == NULL) ||
             (r3 != NULL && test2_tab[i].r3 != NULL && strcmp(r3, test2_tab[i].r3) != 0)) ||
            ((r4 == NULL && test2_tab[i].r4 != NULL) ||
             (r4 != NULL && test2_tab[i].r4 == NULL) ||
             (r4 != NULL && test2_tab[i].r4 != NULL && strcmp(r4, test2_tab[i].r4) != 0))) {
            ts_test_fail(TS_CTX, "expected result: %d + <%s><%s><%s><%s>",
                         test2_tab[i].rv,
                         test2_tab[i].r1 == NULL ? "NULL" : test2_tab[i].r1,
                         test2_tab[i].r2 == NULL ? "NULL" : test2_tab[i].r2,
                         test2_tab[i].r3 == NULL ? "NULL" : test2_tab[i].r3,
                         test2_tab[i].r4 == NULL ? "NULL" : test2_tab[i].r4);
        }
        if (*(test2_tab[i].p) == 's') {
            if (r1 != NULL) free(r1);
        }
        else {
            if (r1 != NULL) free(r1);
            if (r2 != NULL) free(r2);
            if (r3 != NULL) free(r3);
            if (r4 != NULL) free(r4);
        }
    }
    str_parse(NULL, NULL);
    return;
}

/*
 * Test String Formatting
 */

TS_TEST(test_formatting)
{
    char buf1[LONG_STRING];
    char buf2[LONG_STRING];
    char *fp_fmt[] = {
        "%-1.5f", "%1.5f", "%123.9f", "%10.5f", "% 10.5f",
        "%+22.9f", "%+4.9f", "%01.3f", "%4f",
        "%3.1f", "%3.2f", "%.0f", "%.1f",
        NULL
    };
    double fp_nums[] = {
        -1.5, 134.21, 91340.2, 341.1234, 0203.9,
        0.96, 0.996, 0.9996, 1.996, 4.136,
        0
    };
    char *int_fmt[] = {
        "%-1.5d", "%1.5d", "%123.9d", "%5.5d", "%10.5d",
        "% 10.5d", "%+22.33d", "%01.3d", "%4d",
#if defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG > 0)
        "%12qd",
#endif
        NULL
    };
#if defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG > 0)
    long long
#else
    long
#endif
        int_nums[] = {
        -1, 134, 91340, 341, 0203,
        4294967290UL, /* less than 2^32 */
#if defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG > 0)
        4294967297ULL, /* more than 2^32 (actually 2^32 + 1) */
#endif
        0
    };
    int x, y;
    int len;

    ts_test_check(TS_CTX, "str_format vs. vendor sprintf comparison");

    for (x = 0; fp_fmt[x] != NULL; x++) {
        ts_test_check(TS_CTX, "str_format(..,..,\"%s\",..)", fp_fmt[x]);
        for (y = 0; fp_nums[y] != 0; y++) {
            len = str_format(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
            sprintf(buf2, fp_fmt[x], fp_nums[y]);
            if (strcmp(buf1, buf2) != 0)
                ts_test_fail(TS_CTX, "mismatch: str_format: \"%s\", snprintf: \"%s\"", buf1, buf2);
        }
    }

    for (x = 0; int_fmt[x] != NULL; x++) {
        ts_test_check(TS_CTX, "str_format(..,..,\"%s\",..)", int_fmt[x]);
        for (y = 0; int_nums[y] != 0; y++) {
            len = str_format(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
            sprintf(buf2, int_fmt[x], int_nums[y]);
            if (strcmp(buf1, buf2) != 0)
                ts_test_fail(TS_CTX, "mismatch: str_format: \"%s\", snprintf: \"%s\"", buf1, buf2);
        }
    }
    return;
}

/*
 * Test Base64 Encoding/Decoding
 */

static void test_base64_do(ts_test_t *_t, unsigned char *ucp, int ulen, int mode)
{
    unsigned char ucp2[1024];
    char cp[1024];
    int n1, n2, n3, n4;
    int i;

    n1 = str_base64(NULL, 0, ucp, ulen, STR_BASE64_ENCODE|mode);
    n2 = str_base64(cp, sizeof(cp), ucp, ulen, STR_BASE64_ENCODE|mode);
    if (n1 != n2)
        ts_test_fail(TS_CTX, "encoding length mismatch: %d vs. %d\n", n1, n2);
    n3 = str_base64(cp, n2, NULL, 0, STR_BASE64_DECODE|mode);
    if (n3 != ulen)
        ts_test_fail(TS_CTX, "decoding check length mismatch: %d vs. %d\n", n3, ulen);
    n4 = str_base64(cp, n2, ucp2, ulen, STR_BASE64_DECODE|mode);
    if (n3 != n4)
        ts_test_fail(TS_CTX, "decoding length mismatch: %d vs. %d\n", n3, n4);
    for (i = 0; i < 256; i++) {
        if (ucp[i] != ucp2[i]) {
            ts_test_fail(TS_CTX, "decoding contents mismatch\n");
            break;
        }
    }
    return;
}

TS_TEST(test_base64)
{
    unsigned char ucp[256];
    int i;

    ts_test_check(TS_CTX, "encode/decode of 0 bytes");
    for (i = 0; i < 256; i++)
        ucp[i] = 0x55;
    test_base64_do(_t, ucp, 256, STR_BASE64_STRICT);

    ts_test_check(TS_CTX, "encode/decode of increasing bytes\n");
    for (i = 0; i < 256; i++)
        ucp[i] = i;
    test_base64_do(_t, ucp, 256, STR_BASE64_STRICT);

    ts_test_check(TS_CTX, "encode/decode of distributed bytes\n");
    for (i = 0; i < 256; i++)
        ucp[i] = i*31;
    test_base64_do(_t, ucp, 256, STR_BASE64_STRICT);

    return;
}

/*
 * Main Test Suite Procedure
 */

int main(int argc, char *argv[])
{
    ts_suite_t *ts;
    int n;

    ts = ts_suite_new("OSSP str (String Handling)");
    ts_suite_test(ts, test_length,     "String Length Determination");
    ts_suite_test(ts, test_locate,     "String Locating");
    ts_suite_test(ts, test_span,       "String Spanning");
    ts_suite_test(ts, test_tokenize,   "String Tokenizing");
    ts_suite_test(ts, test_parsing,    "String Parsing");
    ts_suite_test(ts, test_formatting, "String Formatting");
    ts_suite_test(ts, test_base64,     "String Encoding/Decoding");
    n = ts_suite_run(ts);
    ts_suite_free(ts);
    return n;
}


CVSTrac 2.0.1