OSSP CVS Repository

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

ossp-pkg/xds/xds_test_lib.c
/*
**  OSSP xds - Extensible Data Serialization
**  Copyright (c) 2001-2005 Ralf S. Engelschall <rse@engelschall.com>
**  Copyright (c) 2001-2005 The OSSP Project <http://www.ossp.org/>
**  Copyright (c) 2001-2005 Cable & Wireless <http://www.cw.com/>
**
**  This file is part of OSSP xds, an extensible data serialization
**  library which can be found at http://www.ossp.org/pkg/lib/xds/.
**
**  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.
**
**  xds_test_lib.c: test suite for library framework
*/

#include <string.h>
#include <errno.h>
#include <stdio.h>
#include "xds_p.h"

#ifdef XDS_TEST_XDS_CORE

int main(int argc, char *argv[])
{
    xds_t *ctx[50];
    size_t i;

    /* Open a bunch of contextes and close them again. */
    for (i = 0; i < sizeof (ctx) / sizeof (xds_t *); ++i) {
        if (i % 2 == 0)
            xds_init(&ctx[i], XDS_ENCODE);
        else
            xds_init(&ctx[i], XDS_DECODE);

        if (ctx[i] == 0) {
            printf("Failed to initialize xds context: i = %d\n", i);
            return 1;
        }
    }

    for (i = 0; i < sizeof (ctx) / sizeof (xds_t *); ++i)
        xds_destroy(ctx[i]);

#ifdef NDEBUG
    /* Check how the library deals with errorneous arguments. */
    if (xds_init(NULL, (xds_mode_t)42) != NULL || errno != EINVAL) {
        printf
            ("Called xds_init() with invalid mode but didn't get EINVAL.\n");
        return 1;
    }

    /* Call xds_destroy() with an invalid context and see whether we survive
       that. */
    xds_destroy(NULL);
#endif

    /* Everything went fine. */
    return 0;
}

#endif /* XDS_TEST_XDS_CORE */

#ifdef XDS_TEST_XDS_REGISTER

static int dummy_engine(xds_t *xds, void *engine_context,
                        void *buffer, size_t buffer_size,
                        size_t *used_buffer_size, va_list *args)
{
    return 0;
}

int main(int argc, char *argv[])
{
    const char *test_names[] = {
        "foo",
        "bar",
        "zarah",
        "caesar",
        "claus",
        "heinz",
    };
    size_t test_names_len = sizeof (test_names) / sizeof (char *);
    xds_t *xds;
    size_t i;

    /* Create context. */
    if (xds_init(&xds, XDS_ENCODE) != XDS_OK) {
        printf("Failed to initialize XDS context.\n");
        return 1;
    }

    /* Register the dummy callback under an invalid name to see whether the
       routine fails correctly. */
    if (xds_register(xds, "abcdefh1230#", &dummy_engine, NULL) !=
        XDS_ERR_INVALID_ARG) {
        printf
            ("xds_register() illegally accepted an invalid name for the engine.\n");
        return 1;
    }

    /* Register the dummy callback under multiple names. */
    for (i = 0; i < test_names_len; ++i) {
        if (xds_register(xds, test_names[i], &dummy_engine, NULL) != XDS_OK) {
            printf("Failed to register engine for '%s'.\n", test_names[i]);
            return 1;
        }
    }

    /* Register the callback again, overwriting an existing entry. */
    if (xds_register(xds, "claus", &dummy_engine, NULL) != XDS_OK) {
        printf("Failed to re-register engine for 'claus'.\n");
        return 1;
    }

    /* Ensure that everything is in alphabetical order. */
    for (i = 1; i < xds->engines_len; ++i) {
        assert(xds->engines[i - 1].name != NULL);
        assert(xds->engines[i].name != NULL);
        if (strcmp(xds->engines[i - 1].name, xds->engines[i].name) >= 0) {
            printf("xds->engines is not in alphabetical order!\n");
            exit(1);
        }
    }

    /* Try to remove an unknown entry. */
    if (xds_unregister(xds, "abacadabra") != XDS_ERR_UNKNOWN_ENGINE) {
        printf("xds_unregister() succeeded at removing 'abacadabra' even though it is not there.\n");
        exit(1);
    }

    /* Remove an entry from the middle. */
    if (xds_unregister(xds, test_names[test_names_len / 2]) != XDS_OK) {
        printf("xds_unregister() failed to remove '%s'.\n",
               test_names[test_names_len / 2]);
        exit(1);
    }

    /* Remove the last entry. */
    assert(test_names_len > 0);
    if (xds_unregister(xds, test_names[test_names_len - 1]) != XDS_OK) {
        printf("xds_unregister() failed to remove '%s'.\n",
               test_names[test_names_len - 1]);
        exit(1);
    }

    /* Remove the first entry. */
    if (xds_unregister(xds, test_names[0]) != XDS_OK) {
        printf("xds_unregister() failed to remove '%s'.\n", test_names[0]);
        exit(1);
    }

    /* Clean up. */
    xds_destroy(xds);

    /* Everything went fine. */
    return 0;
}

#endif /* XDS_TEST_XDS_REGISTER */

#ifdef XDS_TEST_XDS_SETBUFFER

static int dummy_engine(xds_t *xds, void *engine_context,
                        void *buffer, size_t buffer_size,
                        size_t *used_buffer_size, va_list *args)
{
    assert(xds != NULL);
    assert(buffer != NULL);
    assert(buffer_size != 0);
    assert(used_buffer_size != NULL);
    assert(args != NULL);
    if (buffer_size < 64)
        return XDS_ERR_OVERFLOW;
    else
        *used_buffer_size = 64;
    memset(buffer, 'a', 64);
    return XDS_OK;
}

int main(int argc, char *argv[])
{
    xds_t *xds;
    char *buffer;
    size_t buffer_size;

    /* Create XDS context. */
    if (xds_init(&xds, XDS_ENCODE) != XDS_OK) {
        printf("Failed to initialize XDS context.\n");
        return 1;
    }

    /* Register the callback. */
    if (xds_register(xds, "dummy", &dummy_engine, NULL) != XDS_OK) {
        printf("Failed to register my encoding engine.\n");
        return 1;
    }

    /* Give the library a buffer of 32 byte, call the engine once, get the
       buffer back and see whether it has been enlarged or not. */
    buffer_size = 32;
    buffer = malloc(buffer_size);
    if (buffer == NULL) {
        printf("Failed to allocate my memory.\n");
        return 1;
    }
    if (xds_setbuffer(xds, XDS_GIFT, buffer, buffer_size) != XDS_OK) {
        printf("xds_setbuffer() failed!\n");
        return 1;
    }
    if (xds_encode(xds, "dummy") != XDS_OK) {
        printf("xds_encode() failed!\n");
        return 1;
    }
    if (xds_getbuffer(xds, XDS_GIFT, (void **)&buffer, &buffer_size) != XDS_OK) {
        printf("xds_getbuffer() failed!\n");
        return 1;
    }
    if (buffer_size < 64) {
        printf("xds_encode() did not enlarge the buffer after processing the callback\n");
        printf("even though all capacity was used up!\n");
        return 1;
    }

    /* Loan the library a buffer we own, call the engine once to exceed the
       buffer's capacity and check, whether the library returns the correct
       error code. */
    buffer = malloc(32);
    if (buffer == NULL) {
        printf("Failed to allocate my memory.\n");
        return 1;
    }
    buffer_size = 32;
    if (xds_setbuffer(xds, XDS_LOAN, buffer, buffer_size) != XDS_OK) {
        printf("xds_setbuffer() failed!\n");
        return 1;
    }
    if (xds_encode(xds, "dummy") != XDS_ERR_OVERFLOW) {
        printf("xds_encode() was supposed to fail with XDS_ERR_OVERFLOW!\n");
        return 1;
    }
    free(buffer);

    /* Clean up. */
    xds_destroy(xds);

    /* Everything went fine. */
    return 0;
}

#endif /* XDS_TEST_XDS_SETBUFFER */

#ifdef XDS_TEST_XDS_GETBUFFER

static int dummy_engine(xds_t *xds, void *engine_context,
                        void *buffer, size_t buffer_size,
                        size_t *used_buffer_size, va_list *args)
{
    if (buffer_size < 6)
        return XDS_ERR_OVERFLOW;
    else
        *used_buffer_size = 6;
    memmove(buffer, "Hallo!", 6);
    return XDS_OK;
}

int main(int argc, char *argv[])
{
    xds_t *xds;
    char *old;
    size_t old_len;
    char *new;
    size_t new_len;

    /* Create XDS context. */
    if (xds_init(&xds, XDS_ENCODE) != XDS_OK) {
        printf("Failed to initialize XDS context.\n");
        return 1;
    }

    /* Register the dummy callback under multiple names. */
    if (xds_register(xds, "text", &dummy_engine, (void *)42) != XDS_OK) {
        printf("Failed to register my encoding engine.\n");
        return 1;
    }

    /* Encode something, then flush the buffer by calling xds_getbuffer(),
       then encode something new and verify that the old buffer hasn't ben
       overwritten and that the new one contains the correct string. */
    if (xds_encode(xds, "text text") != XDS_OK) {
        printf("xds_encode() failed!\n");
        return 1;
    }
    if (xds_getbuffer(xds, XDS_GIFT, (void **)&old, &old_len) != XDS_OK) {
        printf("xds_getbuffer() failed for the first buffer!\n");
        return 1;
    }
    if (xds_encode(xds, "text") != XDS_OK) {
        printf("xds_encode() failed!\n");
        return 1;
    }
    if (xds_getbuffer(xds, XDS_GIFT, (void **)&new, &new_len) != XDS_OK) {
        printf("xds_getbuffer() failed for the second buffer!\n");
        return 1;
    }
    if ((memcmp(old, "Hallo!Hallo!", 12) != 0 || old_len != 12) &&
        (memcmp(new, "Hallo!", 6) != 0 || new_len != 6)) {
        printf("xds_encode() did not yield the expected result.\n");
        return 1;
    }
    free(old);
    free(new);

    /* Encode somthing, then get the buffer via XDS_LOAN and verify the
       contents. Encode something new and compare the new content with what
       we expect. */
    if (xds_encode(xds, "text text") != XDS_OK) {
        printf("xds_encode() failed!\n");
        return 1;
    }
    if (xds_getbuffer(xds, XDS_LOAN, (void **)&old, &old_len) != XDS_OK) {
        printf("xds_getbuffer() failed for the first buffer!\n");
        return 1;
    }
    if (memcmp(old, "Hallo!Hallo!", 12) != 0 || old_len != 12) {
        printf("xds_encode() did not yield the expected result.\n");
        return 1;
    }
    if (xds_encode(xds, "text") != XDS_OK) {
        printf("xds_encode() failed!\n");
        return 1;
    }
    if (xds_getbuffer(xds, XDS_LOAN, (void **)&new, &new_len) != XDS_OK) {
        printf("xds_getbuffer() failed for the second buffer!\n");
        return 1;
    }
    if (old != new) {
        printf
            ("xds_encode() allocated a new buffer even though we used XDS_LOAN.\n");
        return 1;
    }
    if (memcmp(new, "Hallo!", 6) != 0 || new_len != 6) {
        printf("xds_encode() did not yield the expected result.\n");
        return 1;
    }

    /* Clean up. */
    xds_destroy(xds);

    /* Everything went fine. */
    return 0;
}

#endif /* XDS_TEST_XDS_GETBUFFER */

#ifdef XDS_TEST_XDS_ENCODE

static int dummy_engine(xds_t *xds, void *engine_context,
                        void *buffer, size_t buffer_size,
                        size_t *used_buffer_size, va_list *args)
{
    if (xds == NULL) {
        printf("XDS context isn't passed through to registered engine.\n");
        exit(1);
    }
    if (engine_context != (void *)42) {
        printf("Engine context isn't passed through to registered engine.\n");
        exit(1);
    }
    if (buffer == NULL) {
        printf("Buffer passed to engine is NULL.\n");
        exit(1);
    }
    if (buffer_size == 0) {
        printf("buffer_size passed to engine is zero!\n");
        exit(1);
    }
    if (used_buffer_size == NULL) {
        printf("used_buffer_size pointer passed to engine is NULL!\n");
        exit(1);
    }
    if (args == NULL) {
        printf("args pointer passed to engine is NULL!\n");
        exit(1);
    }
    *used_buffer_size = 6;
    if (buffer_size < 6)
        return XDS_ERR_OVERFLOW;
    memmove(buffer, "Hallo ", 6);
    return XDS_OK;
}

int main(int argc, char *argv[])
{
    xds_t *xds;

    /* Create XDS context. */
    if (xds_init(&xds, XDS_ENCODE) != XDS_OK) {
        printf("Failed to initialize XDS context.\n");
        return 1;
    }

    /* Register the dummy callback under multiple names. */
    if (xds_register(xds, "int", &dummy_engine, (void *)42) != XDS_OK ||
        xds_register(xds, "float", &dummy_engine, (void *)42) != XDS_OK ||
        xds_register(xds, "double", &dummy_engine, (void *)42) != XDS_OK ||
        xds_register(xds, "text", &dummy_engine, (void *)42) != XDS_OK) {
        printf("Failed to register my encoding engines.\n");
        return 1;
    }

    /* Let's go and encode something. */
    if (xds_encode(xds, "int:text    double double float") != XDS_OK) {
        printf("xds_encode() failed!\n");
        return 1;
    }
    if (memcmp(xds->buffer, "Hallo Hallo Hallo Hallo Hallo ", 30) != 0) {
        printf("xds_encode() did not yield the expected result.\n");
        return 1;
    }

    /* Clean up. */
    xds_destroy(xds);

    /* Everything went fine. */
    return 0;
}

#endif /* XDS_TEST_XDS_ENCODE */

#ifdef XDS_TEST_XDS_DECODE

static int dummy_engine(xds_t *xds, void *engine_context,
                        void *buffer, size_t buffer_size,
                        size_t *used_buffer_size, va_list *args)
{
    if (xds == NULL) {
        printf("XDS context isn't passed through to registered engine.\n");
        exit(1);
    }
    if (engine_context != (void *)42) {
        printf("Engine context isn't passed through to registered engine.\n");
        exit(1);
    }
    if (buffer == NULL) {
        printf("Buffer passed to engine is NULL.\n");
        exit(1);
    }
    if (buffer_size == 0) {
        printf("Buffer size passed to engine is zero!\n");
        exit(1);
    }
    if (used_buffer_size == NULL) {
        printf("used_buffer_size passed to engine is zero!\n");
        exit(1);
    }
    if (args == NULL) {
        printf("args pointer passed to engine is NULL!\n");
        exit(1);
    }
    if (buffer_size < 6) {
        printf("The buffer is too small; can't verify my encoded string.\n");
        exit(1);
    }
    if (memcmp(buffer, "Hallo!", 6) != 0) {
        printf("The contents of the decode buffer are not what we expected.\n");
        exit(1);
    }
    *used_buffer_size = 6;
    return XDS_OK;
}

int main(int argc, char *argv[])
{
    xds_t *xds;
    char buffer[] = "Hallo!Hallo!Hallo!";

    /* Create XDS context. */
    if (xds_init(&xds, XDS_DECODE) != XDS_OK) {
        printf("Failed to initialize XDS context.\n");
        return 1;
    }

    /* Register the dummy callback under multiple names. */
    if (xds_register(xds, "text", &dummy_engine, (void *)42) != XDS_OK) {
        printf("Failed to register my decoding engines.\n");
        return 1;
    }

    /* Decode the buffer and have the callback report when something is wrong. */
    if (xds_setbuffer(xds, XDS_LOAN, buffer, sizeof (buffer) - 1) != XDS_OK) {
        printf("xds_decode() failed!");
        return 1;
    }
    if (xds_decode(xds, "text::text text") != XDS_OK) {
        printf("xds_decode() failed!");
        return 1;
    }

    /* Clean up. */
    xds_destroy(xds);

    /* Everything went fine. */

    return 0;
}

#endif /* XDS_TEST_XDS_DECODE */

#ifdef XDS_TEST_XDS_ENGINE_RESTART

static int dummy_engine(xds_t *xds, void *engine_context,
                        void *buffer, size_t buffer_size,
                        size_t *used_buffer_size, va_list *args)
{
    if (xds == NULL) {
        printf("XDS context isn't passed through to registered engine.\n");
        exit(1);
    }
    if (engine_context != (void *)42) {
        printf("Engine context isn't passed through to registered engine.\n");
        exit(1);
    }
    if (buffer == NULL) {
        printf("Buffer passed to engine is NULL.\n");
        exit(1);
    }
    if (buffer_size == 0) {
        printf("Buffer size passed to engine is zero!\n");
        exit(1);
    }
    if (used_buffer_size == NULL) {
        printf("used_buffer_size pointer passed to engine is NULL!\n");
        exit(1);
    }
    if (args == NULL) {
        printf("args pointer passed to engine is NULL!\n");
        exit(1);
    }
    if (va_arg(*args, int) != 42) {
        printf("The varadic argument is not what the engine expected!\n");
        exit(1);
    }
    if (buffer_size < 64)
        return XDS_ERR_OVERFLOW;
    else
        *used_buffer_size = 64;
    return XDS_OK;
}

int main(int argc, char *argv[])
{
    xds_t *xds;
    char *buffer;
    size_t buffer_size;

    /* Create an XDS context and set a buffer that's too small for the first
       encode() call. Then call encode() with two parameters: the one the
       engine is expecting and a different one after that. The engine will
       complain if it sees the second value -- what would mean that the args
       parameter was not resetted to the original value before the engine is
       restarted after buffer enlargement. */
    if (xds_init(&xds, XDS_ENCODE) != XDS_OK) {
        printf("Failed to initialize XDS context.\n");
        return 1;
    }
    if (xds_register(xds, "int", &dummy_engine, (void *)42) != XDS_OK) {
        printf("Failed to register my encoding engines.\n");
        return 1;
    }
    buffer = malloc(32);
    if (buffer == NULL) {
        printf("malloc() failed!\n");
        return 1;
    }
    buffer_size = 32;
    if (xds_setbuffer(xds, XDS_GIFT, buffer, buffer_size) != XDS_OK) {
        printf("xds_setbuffer() failed!\n");
        return 1;
    }
    if (xds_encode(xds, "int", 42, 13) != XDS_OK) {
        printf("xds_encode() failed!");
        return 1;
    }
    xds_destroy(xds);
    return 0;
}

#endif /* XDS_TEST_XDS_ENGINE_RESTART */

#ifdef XDS_TEST_XDS_MYSTRUCT

struct mystruct {
    xds_int32_t small;
    xds_uint32_t positive;
};

static int encode_mystruct_engine(xds_t *xds, void *engine_context,
                                  void *buffer, size_t buffer_size,
                                  size_t *used_buffer_size, va_list *args)
{
    struct mystruct *ms;

    assert(xds != NULL);
    assert(buffer != NULL);
    assert(buffer_size != 0);
    assert(used_buffer_size != NULL);
    assert(args != NULL);

    ms = va_arg(*args, struct mystruct *);
    return xds_encode(xds, "int32 uint32", ms->small, ms->positive);
}

static int decode_mystruct_engine(xds_t *xds, void *engine_context,
                                  void *buffer, size_t buffer_size,
                                  size_t *used_buffer_size, va_list *args)
{
    struct mystruct *ms;

    assert(xds != NULL);
    assert(buffer != NULL);
    assert(buffer_size != 0);
    assert(used_buffer_size != NULL);
    assert(args != NULL);

    ms = va_arg(*args, struct mystruct *);
    return xds_decode(xds, "int32 uint32", &(ms->small), &(ms->positive));
}

int main(int argc, char *argv[])
{
    xds_t *xds;
    char *buffer;
    size_t buffer_size;

    struct mystruct ms, new_ms;
    ms.small = -0x1234567;
    ms.positive = 42;

    /* Encode our copy of mystruct using our encoding callback. Then get a
       the buffer and destroy the context again. */
    if (xds_init(&xds, XDS_ENCODE) != XDS_OK) {
        printf("Failed to initialize XDS context.\n");
        return 1;
    }
    if (   xds_register(xds, "mystruct", &encode_mystruct_engine, NULL) != XDS_OK
        || xds_register(xds, "int32", &xdr_encode_int32, NULL) != XDS_OK
        || xds_register(xds, "uint32", &xdr_encode_uint32, NULL) != XDS_OK) {
        printf("Failed to register my encoding engines.\n");
        return 1;
    }
    buffer_size = 4;
    buffer = malloc(buffer_size);
    if (buffer == NULL) {
        printf("Failed to allocate memory for buffer.\n");
        return 1;
    }
    if (xds_setbuffer(xds, XDS_GIFT, buffer, buffer_size) != XDS_OK) {
        printf("xds_setbuffer() failed!\n");
        return 1;
    }
    if (xds_encode(xds, "mystruct", &ms) != XDS_OK) {
        printf("xds_encode() failed!\n");
        return 1;
    }
    if (xds->buffer_capacity <= buffer_size) {
        printf("Buffer should have been enlarged after xds_encode()!\n");
        return 1;
    }
    if (xds_getbuffer(xds, XDS_GIFT, (void **)&buffer, &buffer_size) !=
        XDS_OK) {
        printf("xds_getbuffer() failed!\n");
        return 1;
    }
    xds_destroy(xds);

    /* Now create a decoding context and decode the whole thing again. */
    if (xds_init(&xds, XDS_DECODE) != XDS_OK) {
        printf("Failed to initialize XDS context.\n");
        return 1;
    }
    if (xds_register(xds, "mystruct", &decode_mystruct_engine, NULL) != XDS_OK
        || xds_register(xds, "int32", &xdr_decode_int32, NULL) != XDS_OK
        || xds_register(xds, "uint32", &xdr_decode_uint32, NULL) != XDS_OK) {
        printf("Failed to register my decoding engines.\n");
        return 1;
    }
    if (xds_setbuffer(xds, XDS_GIFT, buffer, buffer_size) != XDS_OK) {
        printf("xds_setbuffer() failed!\n");
        return 1;
    }
    if (xds_decode(xds, "mystruct", &new_ms) != XDS_OK) {
        printf("xds_decode() failed!\n");
        return 1;
    }
    xds_destroy(xds);

    /* Both structures must be identical. */
    if (ms.small != new_ms.small
        || ms.positive != new_ms.positive) {
        printf("Decoded data does not match the original!\n");
        return 1;
    }

    /* Everything went fine. */
    return 0;
}

#endif /* XDS_TEST_XDS_MYSTRUCT */

CVSTrac 2.0.1