aboutsummaryrefslogblamecommitdiff
path: root/tests/test-xdr.c
blob: 6f4eadcb0ec6332dc798c0ec1c4b760d1ed73555 (plain) (tree)











































                                                                           



                                                                  
 

 




                                                 
 



                                        
     







                                                                 
     
 






















                                                         
     





                                                                 

     































































































































































































































































































































                                                                                                                                    
 
/*
 * xdr.c
 * -----
 * Serialization/deserialization routines, using XDR (RFC 4506) encoding.
 * These functions are not part of the public libhal API.
 *
 * Copyright (c) 2016-2018, NORDUnet A/S All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of the NORDUnet nor the names of its contributors may
 *   be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS 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 COPYRIGHT
 * HOLDER OR 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.
 */

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>		/* ptrdiff_t */
#include <string.h>             /* memcpy, memset */

#include "hal.h"
#include "hal_internal.h"	/* htonl/ntohl */
#include "xdr_internal.h"

static int verbose = 0;

/* suppress assert() error messages */
void hal_log(const hal_log_level_t level, const char *format, ...)
{
}

#define DEFINE_HAL_ERROR(_code_,_text_)  #_code_,
static char *err_name[] = { HAL_ERROR_LIST };
#undef  DEFINE_HAL_ERROR

static void hexdump(uint8_t *buf, uint32_t len)
{
    for (uint32_t i = 0; i < len; ++i) {
        printf("%02x", buf[i]);
        if (i < len - 1)
            printf(" ");
    }
}

#define test(name, result, expected)                            \
    if ((err = result) != expected) {                           \
        if (!verbose) printf("%s: ", func);                     \
        printf("%s test returned %s, expected %s\n",            \
               name, err_name[err], err_name[expected]);        \
        ++nerr;                                                 \
    }

#define test_value(val, exp)                            \
    if (val != exp) {                                   \
        if (!verbose) printf("%s: ", func);             \
        printf("value = %u, expected %u\n", val, exp);  \
        ++nerr;                                         \
    }

#define test_len(len, exp)                              \
    if (len != exp) {                                   \
        if (!verbose) printf("%s: ", func);             \
        printf("len = %lu, expected %u\n", len, exp);   \
        ++nerr;                                         \
    }

#define test_memcmp(buf, exp, len)              \
    if (memcmp(buf, exp, len) != 0) {           \
        if (!verbose) printf("%s: ", func);     \
        printf("buffer = [");                   \
        hexdump(buf, len);                      \
        printf("], expected [");                \
        hexdump(exp, len);                      \
        printf("]\n");                          \
        ++nerr;                                 \
    }

#define test_bufptr(bfp, exp)                                   \
    if (bfp != exp) {                                           \
        if (!verbose) printf("%s: ", func);                     \
        printf("buf ptr = %p, expected %p\n", bfp, exp);        \
        ++nerr;                                                 \
    }

static int test_hal_xdr_encode_int(void)
{
    hal_error_t err = HAL_OK;
    int nerr = 0;
    uint8_t *null = NULL;
    uint8_t buf[4] = {0};
    uint8_t *bufptr = buf;
    uint8_t *limit = buf + sizeof(buf);
    uint8_t exp[4] = { 0x00, 0x11, 0x22, 0x33 };
    uint32_t value = 0x00112233;
    const char *func = "hal_xdr_encode_int";

    if (verbose)
        printf("%s... ", func);

    test("null outbuf", hal_xdr_encode_int(NULL, limit, value), HAL_ERROR_ASSERTION_FAILED);
    test("null outbuf", hal_xdr_encode_int(&null, limit, value), HAL_ERROR_ASSERTION_FAILED);
    test("null limit", hal_xdr_encode_int(&bufptr, NULL, value), HAL_ERROR_ASSERTION_FAILED);
    test("outbuf overflow", hal_xdr_encode_int(&bufptr, buf, value), HAL_ERROR_XDR_BUFFER_OVERFLOW);
    test("outbuf overflow", hal_xdr_encode_int(&bufptr, buf + 3, value), HAL_ERROR_XDR_BUFFER_OVERFLOW);

    test("valid write", hal_xdr_encode_int(&bufptr, limit, value), HAL_OK);
    test_memcmp(buf, exp, sizeof(exp));
    test_bufptr(bufptr, buf + 4);

    if (verbose && nerr == 0)
        printf("PASS\n");

    return nerr;
}

static int test_hal_xdr_decode_int(void)
{
    hal_error_t err = HAL_OK;
    int nerr = 0;
    const uint8_t *null = NULL;
    const uint8_t buf[4] = { 0x00, 0x11, 0x22, 0x33 };
    const uint8_t *bufptr = buf;
    const uint8_t * const limit = buf + sizeof(buf);
    uint32_t value = 0;
    const uint32_t exp = 0x00112233;
    const char *func = "hal_xdr_decode_int"; 

    if (verbose)
        printf("%s... ", func);

    test("null inbuf", hal_xdr_decode_int(NULL, limit, &value), HAL_ERROR_ASSERTION_FAILED);
    test("null inbuf", hal_xdr_decode_int(&null, limit, &value), HAL_ERROR_ASSERTION_FAILED);
    test("null limit", hal_xdr_decode_int(&bufptr, NULL, &value), HAL_ERROR_ASSERTION_FAILED);
    test("null value", hal_xdr_decode_int(&bufptr, limit, NULL), HAL_ERROR_ASSERTION_FAILED);

    test("inbuf overflow", hal_xdr_decode_int(&bufptr, buf, &value), HAL_ERROR_XDR_BUFFER_OVERFLOW);
    test("inbuf overflow", hal_xdr_decode_int(&bufptr, buf + 3, &value), HAL_ERROR_XDR_BUFFER_OVERFLOW);

    test("valid read", hal_xdr_decode_int(&bufptr, limit, &value), HAL_OK);
    test_value(value, exp);
    test_bufptr(bufptr, buf + 4);

    if (verbose && nerr == 0)
        printf("PASS\n");

    return nerr;
}

static int test_hal_xdr_decode_int_peek(void)
{
    hal_error_t err = HAL_OK;
    int nerr = 0;
    const uint8_t buf[4] = { 0x00, 0x11, 0x22, 0x33 };
    const uint8_t *bufptr = buf;
    const uint8_t * const limit = buf + sizeof(buf);
    uint32_t value = 0;
    const uint32_t exp = 0x00112233;
    const char *func = "hal_xdr_decode_int_peek";

    if (verbose)
        printf("%s... ", func);

    test("valid read", hal_xdr_decode_int_peek(&bufptr, limit, &value), HAL_OK);
    test_value(value, exp);
    test_bufptr(bufptr, buf);

    if (verbose && nerr == 0)
        printf("PASS\n");

    return nerr;
}

static int test_hal_xdr_encode_fixed_opaque(void)
{
    hal_error_t err = HAL_OK;
    int nerr = 0;
    uint8_t *null = NULL;
    uint8_t buf[8];
    uint8_t *bufptr = buf;
    uint8_t *limit = buf + sizeof(buf);
    uint8_t src[8]  = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
    uint8_t exp3[4] = { 0x00, 0x11, 0x22, 0x00 };
    uint8_t exp4[4] = { 0x00, 0x11, 0x22, 0x33 };
    uint8_t exp5[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00 };
    const char *func = "hal_xdr_encode_fixed_opaque";

    if (verbose)
        printf("%s... ", func);

    test("null outbuf", hal_xdr_encode_fixed_opaque(NULL, limit, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED);
    test("null outbuf", hal_xdr_encode_fixed_opaque(&null, limit, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED); 
    test("null limit", hal_xdr_encode_fixed_opaque(&bufptr, NULL, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED);
   test("null value", hal_xdr_encode_fixed_opaque(&bufptr, limit, NULL, sizeof(src)), HAL_ERROR_ASSERTION_FAILED);
    test("outbuf overflow", hal_xdr_encode_fixed_opaque(&bufptr, buf, src, sizeof(src)), HAL_ERROR_XDR_BUFFER_OVERFLOW);

    memset(buf, 0xff, sizeof(buf));
    test("write 3", hal_xdr_encode_fixed_opaque(&bufptr, limit, src, 3), HAL_OK);
    test_memcmp(buf, exp3, sizeof(exp3));
    test_bufptr(bufptr, buf + 4);

    bufptr = buf;
    memset(buf, 0xff, sizeof(buf));
    test("write 4", hal_xdr_encode_fixed_opaque(&bufptr, limit, src, 4), HAL_OK);
    test_memcmp(buf, exp4, sizeof(exp4));
    test_bufptr(bufptr, buf + 4)
    
    bufptr = buf;
    memset(buf, 0xff, sizeof(buf));
    test("write 5", hal_xdr_encode_fixed_opaque(&bufptr, limit, src, 5), HAL_OK);
    test_memcmp(buf, exp5, sizeof(exp5));
    test_bufptr(bufptr, buf + 8);

    bufptr = buf;
    memset(buf, 0xff, sizeof(buf));
    test("write 8", hal_xdr_encode_fixed_opaque(&bufptr, limit, src, 8), HAL_OK);
    test_memcmp(buf, src, sizeof(src));
    test_bufptr(bufptr, buf + 8)

    if (verbose && nerr == 0)
        printf("PASS\n");

    return nerr;
}

static int test_hal_xdr_decode_fixed_opaque(void)
{
    hal_error_t err = HAL_OK;
    int nerr = 0;
    const uint8_t *null = NULL;
    const uint8_t buf[8]  = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
    const uint8_t *bufptr = buf;
    const uint8_t *limit = buf + sizeof(buf);
    uint8_t value[8];
    uint8_t exp3[4] = { 0x00, 0x11, 0x22, 0x00 };
    uint8_t exp4[4] = { 0x00, 0x11, 0x22, 0x33 };
    uint8_t exp5[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00 };
    const char *func = "hal_xdr_decode_fixed_opaque";

    if (verbose)
        printf("%s... ", func);

    test("null inbuf", hal_xdr_decode_fixed_opaque(NULL, limit, value, sizeof(value)), HAL_ERROR_ASSERTION_FAILED);
    test("null inbuf", hal_xdr_decode_fixed_opaque(&null, limit, value, sizeof(value)), HAL_ERROR_ASSERTION_FAILED);
    test("null limit", hal_xdr_decode_fixed_opaque(&bufptr, NULL, value, sizeof(value)), HAL_ERROR_ASSERTION_FAILED);
    test("null value", hal_xdr_decode_fixed_opaque(&bufptr, limit, NULL, sizeof(value)), HAL_ERROR_ASSERTION_FAILED);
    test("inbuf overflow", hal_xdr_decode_fixed_opaque(&bufptr, buf, value, sizeof(value)), HAL_ERROR_XDR_BUFFER_OVERFLOW);

    memset(value, 0xff, sizeof(value));
    test("read 3", hal_xdr_decode_fixed_opaque(&bufptr, limit, value, 3), HAL_OK);
    test_memcmp(value, exp3, sizeof(exp3));
    test_bufptr(bufptr, buf + 4);

    bufptr = buf;
    memset(value, 0xff, sizeof(value));
    test("read 4", hal_xdr_decode_fixed_opaque(&bufptr, limit, value, 4), HAL_OK);
    test_memcmp(value, exp4, sizeof(exp4));
    test_bufptr(bufptr, buf + 4);

    bufptr = buf;
    memset(value, 0xff, sizeof(value));
    test("read 5", hal_xdr_decode_fixed_opaque(&bufptr, limit, value, 5), HAL_OK);
    test_memcmp(value, exp5, sizeof(exp5));
    test_bufptr(bufptr, buf + 8);

    if (verbose && nerr == 0)
        printf("PASS\n");

    return nerr;
}

static int test_hal_xdr_encode_variable_opaque(void)
{
    hal_error_t err = HAL_OK;
    int nerr = 0;
    uint8_t *null = NULL;
    uint8_t buf[12];
    uint8_t *bufptr = buf;
    uint8_t *limit = buf + sizeof(buf);
    uint8_t src[8]  = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
    uint8_t exp3[8] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x11, 0x22, 0x00 };
    uint8_t exp4[8] = { 0x00, 0x00, 0x00, 0x04, 0x00, 0x11, 0x22, 0x33 };
    uint8_t exp5[12] = { 0x00, 0x00, 0x00, 0x05, 0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00 };
    uint8_t exp8[12] = { 0x00, 0x00, 0x00, 0x08, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
    const char *func = "hal_xdr_encode_variable_opaque";

    if (verbose)
        printf("%s... ", func);

    test("null outbuf", hal_xdr_encode_variable_opaque(NULL, limit, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED);
    test("null outbuf", hal_xdr_encode_variable_opaque(&null, limit, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED); 
    test("null limit", hal_xdr_encode_variable_opaque(&bufptr, NULL, src, sizeof(src)), HAL_ERROR_ASSERTION_FAILED);
   test("null value", hal_xdr_encode_variable_opaque(&bufptr, limit, NULL, sizeof(src)), HAL_ERROR_ASSERTION_FAILED);
    test("outbuf overflow", hal_xdr_encode_variable_opaque(&bufptr, buf, src, sizeof(src)), HAL_ERROR_XDR_BUFFER_OVERFLOW);

    memset(buf, 0xff, sizeof(buf));
    test("write 3", hal_xdr_encode_variable_opaque(&bufptr, limit, src, 3), HAL_OK);
    test_memcmp(buf, exp3, sizeof(exp3));
    test_bufptr(bufptr, buf + 8);

    bufptr = buf;
    memset(buf, 0xff, sizeof(buf));
    test("write 4", hal_xdr_encode_variable_opaque(&bufptr, limit, src, 4), HAL_OK);
    test_memcmp(buf, exp4, sizeof(exp4));
    test_bufptr(bufptr, buf + 8)
    
    bufptr = buf;
    memset(buf, 0xff, sizeof(buf));
    test("write 5", hal_xdr_encode_variable_opaque(&bufptr, limit, src, 5), HAL_OK);
    test_memcmp(buf, exp5, sizeof(exp5));
    test_bufptr(bufptr, buf + 12);

    bufptr = buf;
    memset(buf, 0xff, sizeof(buf));
    test("write 8", hal_xdr_encode_variable_opaque(&bufptr, limit, src, 8), HAL_OK);
    test_memcmp(buf, exp8, sizeof(exp8));
    test_bufptr(bufptr, buf + 12)

    if (verbose && nerr == 0)
        printf("PASS\n");

    return nerr;
}

static int test_hal_xdr_decode_variable_opaque(void)
{
    hal_error_t err = HAL_OK;
    int nerr = 0;
    const uint8_t *null = NULL;
    uint8_t buf[12]  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
    const uint8_t *bufptr = buf;
    const uint8_t *limit = buf + sizeof(buf);
    uint8_t value[12];
    size_t len;
    uint8_t exp3[4] = { 0x00, 0x11, 0x22, 0x00 };
    uint8_t exp4[4] = { 0x00, 0x11, 0x22, 0x33 };
    uint8_t exp5[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x00, 0x00 };
    uint8_t exp8[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
    const char *func = "hal_xdr_decode_variable_opaque";

    if (verbose)
        printf("%s... ", func);

    test("null inbuf", hal_xdr_decode_variable_opaque(NULL, limit, value, &len, sizeof(value)), HAL_ERROR_ASSERTION_FAILED);
    test("null inbuf", hal_xdr_decode_variable_opaque(&null, limit, value, &len, sizeof(value)), HAL_ERROR_ASSERTION_FAILED);
    test("null limit", hal_xdr_decode_variable_opaque(&bufptr, NULL, value, &len, sizeof(value)), HAL_ERROR_ASSERTION_FAILED);
    test("null value", hal_xdr_decode_variable_opaque(&bufptr, limit, NULL, &len, sizeof(value)), HAL_ERROR_ASSERTION_FAILED);
    test("inbuf overflow", hal_xdr_decode_variable_opaque(&bufptr, buf, value, &len, sizeof(value)), HAL_ERROR_XDR_BUFFER_OVERFLOW);

    buf[3] = 0x03;
    memset(value, 0xff, sizeof(value));
    test("read 3", hal_xdr_decode_variable_opaque(&bufptr, limit, value, &len, sizeof(value)), HAL_OK);
    test_len(len, 3);
    test_memcmp(value, exp3, sizeof(exp3));
    test_bufptr(bufptr, buf + 8);

    bufptr = buf;
    buf[3] = 0x04;
    memset(value, 0xff, sizeof(value));
    test("read 4", hal_xdr_decode_variable_opaque(&bufptr, limit, value, &len, sizeof(value)), HAL_OK);
    test_len(len, 4);
    test_memcmp(value, exp4, sizeof(exp4));
    test_bufptr(bufptr, buf + 8);

    bufptr = buf;
    buf[3] = 0x05;
    memset(value, 0xff, sizeof(value));
    test("read 5", hal_xdr_decode_variable_opaque(&bufptr, limit, value, &len, sizeof(value)), HAL_OK);
    test_len(len, 5);
    test_memcmp(value, exp5, sizeof(exp5));
    test_bufptr(bufptr, buf + 12);

    bufptr = buf;
    buf[3] = 0x08;
    memset(value, 0xff, sizeof(value));
    test("read 8", hal_xdr_decode_variable_opaque(&bufptr, limit, value, &len, sizeof(value)), HAL_OK);
    test_len(len, 8);
    test_memcmp(value, exp8, sizeof(exp8));
    test_bufptr(bufptr, buf + 12);

    if (verbose && nerr == 0)
        printf("PASS\n");

    return nerr;
}


int main(int argc, char *argv[])
{
    if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'v')
        verbose = 1;

    int nerr = 0;
    nerr += test_hal_xdr_encode_int();
    nerr += test_hal_xdr_decode_int();
    nerr += test_hal_xdr_decode_int_peek();
    nerr += test_hal_xdr_encode_fixed_opaque();
    nerr += test_hal_xdr_decode_fixed_opaque();
    nerr += test_hal_xdr_encode_variable_opaque();
    nerr += test_hal_xdr_decode_variable_opaque();

    if (nerr)
        printf("%d failures\n", nerr);

    return nerr;
}