aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Selkirk <paul@psgd.org>2019-12-02 15:39:30 -0500
committerPaul Selkirk <paul@psgd.org>2019-12-02 15:39:30 -0500
commit271a1f830acb229c380ae95c6c2e4c4df367fa82 (patch)
treec98c5c8b76642dcdc0dab8163ccc41396160a0f2
parent4fd9d1186efed0de8e3ae1d1e2fa5a0e5c46c2fb (diff)
Beef up XDR unit tests.
-rw-r--r--tests/test-xdr.c426
-rw-r--r--xdr.c22
2 files changed, 391 insertions, 57 deletions
diff --git a/tests/test-xdr.c b/tests/test-xdr.c
index f084e01..6f4eadc 100644
--- a/tests/test-xdr.c
+++ b/tests/test-xdr.c
@@ -42,70 +42,384 @@
#include "hal_internal.h" /* htonl/ntohl */
#include "xdr_internal.h"
-static void hexdump(uint8_t *buf, uint32_t len)
+static int verbose = 0;
+
+/* suppress assert() error messages */
+void hal_log(const hal_log_level_t level, const char *format, ...)
{
- for (uint32_t i = 0; i < len; ++i)
- printf("%02x%c", buf[i], ((i & 0x07) == 0x07) ? '\n' : ' ');
- if ((len & 0x07) != 0)
- printf("\n");
}
-int main(int argc, char *argv[])
+#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)
{
- uint32_t i;
- uint8_t buf[256] = {0};
- uint8_t *bufptr = buf;
- const uint8_t *readptr;
- uint8_t *limit = buf + sizeof(buf);
- hal_error_t ret;
- uint8_t alphabet[] = "abcdefghijklmnopqrstuvwxyz";
- uint8_t readbuf[256] = {0};
-
- printf("hal_xdr_encode_int: work to failure\n");
- for (i = 1; i < 100; ++i) {
- if ((ret = hal_xdr_encode_int(&bufptr, limit, i)) != HAL_OK) {
- printf("%d: %s\n", i, hal_error_string(ret));
- break;
- }
+ for (uint32_t i = 0; i < len; ++i) {
+ printf("%02x", buf[i]);
+ if (i < len - 1)
+ printf(" ");
}
- hexdump(buf, ((uint8_t *)bufptr - buf));
-
- printf("\nhal_xdr_decode_int:\n");
- readptr = buf;
- while (readptr < bufptr) {
- if ((ret = hal_xdr_decode_int(&readptr, limit, &i)) != HAL_OK) {
- printf("%s\n", hal_error_string(ret));
- break;
- }
- printf("%u ", i);
+}
+
+#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; \
}
- printf("\n");
- printf("\nhal_xdr_encode_variable_opaque: work to failure\n");
- memset(buf, 0, sizeof(buf));
- bufptr = buf;
- for (i = 1; ; ++i) {
- if ((ret = hal_xdr_encode_variable_opaque(&bufptr, limit, alphabet, i)) != HAL_OK) {
- printf("%d: %s\n", i, hal_error_string(ret));
- break;
- }
+#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; \
}
- hexdump(buf, ((uint8_t *)bufptr - buf));
-
- printf("\nhal_xdr_decode_variable_opaque:\n");
- readptr = buf;
- while (readptr < bufptr) {
- size_t len;
- if ((ret = hal_xdr_decode_variable_opaque(&readptr, limit, readbuf, &len, bufptr - readptr)) != HAL_OK) {
- printf("%s\n", hal_error_string(ret));
- break;
- }
- printf("%lu: ", len);
- for (size_t j = 0; j < len; ++j)
- putchar(readbuf[j]);
- putchar('\n');
- memset(readbuf, 0, sizeof(readbuf));
+
+#define test_bufptr(bfp, exp) \
+ if (bfp != exp) { \
+ if (!verbose) printf("%s: ", func); \
+ printf("buf ptr = %p, expected %p\n", bfp, exp); \
+ ++nerr; \
}
- return 0;
+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;
}
diff --git a/xdr.c b/xdr.c
index 92c2b64..3c02635 100644
--- a/xdr.c
+++ b/xdr.c
@@ -94,6 +94,9 @@ hal_error_t hal_xdr_encode_fixed_opaque(uint8_t ** const outbuf, const uint8_t *
/* arg checks */
hal_assert(outbuf != NULL && *outbuf != NULL && limit != NULL && limit >= *outbuf && (value != NULL || len == 0));
+ if (len == 0)
+ return HAL_OK;
+
/* buffer overflow check */
/* We need to explicitly check (len > 0xfffffffc) because padding will
* round it up to 0.
@@ -135,11 +138,22 @@ hal_error_t hal_xdr_decode_fixed_opaque(const uint8_t ** const inbuf, const uint
const uint8_t *p;
hal_error_t err;
+ /* arg checks */
+ hal_assert(value != NULL || len == 0);
+
+ if (len == 0)
+ return HAL_OK;
+
/* get and advance the input data pointer */
- if ((err = hal_xdr_decode_fixed_opaque_ptr(inbuf, limit, &p, len)) == HAL_OK)
+ if ((err = hal_xdr_decode_fixed_opaque_ptr(inbuf, limit, &p, len)) == HAL_OK) {
/* read the data */
memcpy(value, p, len);
+ /* pad if necessary */
+ for (size_t i = len; (i & 3) != 0; ++i)
+ value[i] = 0;
+ }
+
return err;
}
@@ -204,8 +218,14 @@ hal_error_t hal_xdr_decode_variable_opaque(const uint8_t ** const inbuf, const u
/* user buffer overflow check */
if (len_max < xdr_len)
return HAL_ERROR_XDR_BUFFER_OVERFLOW;
+
/* read the data */
memcpy(value, p, xdr_len);
+
+ /* pad if necessary */
+ for (size_t i = xdr_len; (i & 3) != 0; ++i)
+ value[i] = 0;
+
*len = xdr_len;
}