Add a unit test for the marshal_UINT32 function.
The code and tests are nearly identical to the unit test for
Marshal_UINT16.
Signed-off-by: Philip Tricca <philip.b.tricca@intel.com>
diff --git a/Makefile.am b/Makefile.am
index b416a98..7e2365b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -45,7 +45,8 @@
test/CommonPreparePrologue_unit \
test/GetNumHandles_unit \
test/CopyCommandHeader_unit \
- test/marshal-UINT16_unit
+ test/marshal-UINT16_unit \
+ test/marshal-UINT32_unit
endif #UNIT
TESTS = $(check_PROGRAMS)
@@ -103,6 +104,15 @@
sysapi/sysapi_util/checkoverflow.c \
sysapi/sysapi_util/marshal_uint16.c \
test/marshal-UINT16_unit.c
+
+test_marshal_UINT32_unit_CFLAGS = $(CMOCKA_CFLAGS) \
+ -I$(srcdir)/include -I$(srcdir)/include/sapi -I$(srcdir)/sysapi/include/
+test_marshal_UINT32_unit_LDADD = $(CMOCKA_LIBS)
+test_marshal_UINT32_unit_SOURCES = \
+ sysapi/sysapi_util/changeEndian.c \
+ sysapi/sysapi_util/checkoverflow.c \
+ sysapi/sysapi_util/marshal_uint32.c \
+ test/marshal-UINT32_unit.c
endif # UNIT
# how to build stuff
diff --git a/test/marshal-UINT32_unit.c b/test/marshal-UINT32_unit.c
new file mode 100644
index 0000000..c65ded3
--- /dev/null
+++ b/test/marshal-UINT32_unit.c
@@ -0,0 +1,191 @@
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+
+#include <setjmp.h>
+#include <cmocka.h>
+#include <tpm20.h>
+
+#include "sys_api_marshalUnmarshal.h"
+#include "sysapi_util.h"
+
+typedef struct {
+ uint8_t *buffer;
+ size_t buffer_size;
+ uint32_t data_host;
+ uint32_t data_net;
+ TSS2_RC rc;
+} marshal_uint32_data_t;
+
+void
+marshal_UINT32_setup (void **state)
+{
+ marshal_uint32_data_t *data;
+
+ data = calloc (1, sizeof (marshal_uint32_data_t));
+ data->buffer = calloc (1, sizeof (uint32_t));
+ data->buffer_size = sizeof (uint32_t);
+ data->data_host = 0xdeadbeef;
+ data->data_net = htonl (data->data_host);
+ data->rc = TSS2_RC_SUCCESS;
+
+ *state = data;
+}
+
+void
+marshal_UINT32_teardown (void **state)
+{
+ marshal_uint32_data_t *data;
+
+ data = (marshal_uint32_data_t*)*state;
+ if (data) {
+ if (data->buffer)
+ free (data->buffer);
+ free (data);
+ }
+}
+/**
+ * Make a call to Marshal_UINT32 function that should succeed. The *_setup
+ * function is expected to have allocated sufficient buffer to hold a
+ * uint32_t. This test just 'marshals' a known uint32_t into this data buffer
+ * and then compares the value to the expected result.
+ * The workings of the Marshal_UINT32 function is a bit complex, so we
+ * assert the expected results as well.
+ */
+void
+marshal_UINT32_good (void **state)
+{
+ marshal_uint32_data_t *data;
+
+ data = (marshal_uint32_data_t*)*state;
+ uint8_t *nextData = data->buffer;
+
+ Marshal_UINT32 (data->buffer,
+ data->buffer_size,
+ &nextData,
+ data->data_host,
+ &data->rc);
+ /**
+ * uint32_t that was marshalled into the data buffer should be equal to
+ * the expected value (data converted from host byte order to network
+ * byte order).
+ */
+ assert_int_equal (*(uint32_t*)(data->buffer), data->data_net);
+ /**
+ * The Marshal_* functions advance the 'nextData' parameter by the size of
+ * the marshalled data.
+ */
+ assert_int_equal (data->buffer, nextData - sizeof (uint32_t));
+ /* Finally the return code should indicate success. */
+ assert_return_code (data->rc, TSS2_RC_SUCCESS);
+}
+/**
+ * Attempt to marshal a uint32_t into a buffer that's only got room for a
+ * uint8_t. The call to the marshalling function should set the TSS2_RC value
+ * to TSS2_SYS_RC_INSUFFICIENT_CONTEXT and the nextData parameter should not
+ * be changed.
+ */
+void
+marshal_UINT32_too_small (void **state)
+{
+ marshal_uint32_data_t *data;
+
+ data = (marshal_uint32_data_t*)*state;
+ /**
+ * Set the locate where data will be marshalled to half way through the
+ * buffer. This only leaves us space for a uint8_t.
+ */
+ uint8_t *nextData = data->buffer + sizeof (uint8_t);
+ data->buffer_size = sizeof (uint8_t);
+
+ Marshal_UINT32 (data->buffer,
+ data->buffer_size,
+ &nextData,
+ data->data_host,
+ &data->rc);
+ /**
+ * The return code should indicate we don't have enough space and the
+ * nextData pointer shouldn't have moved.
+ */
+ assert_return_code (data->rc, TSS2_SYS_RC_INSUFFICIENT_CONTEXT);
+ assert_int_equal (data->buffer, nextData - sizeof (uint8_t));
+}
+void
+marshal_UINT32_under_ptr (void **state)
+{
+ marshal_uint32_data_t *data;
+
+ data = (marshal_uint32_data_t*)*state;
+ /**
+ * Set nextData to a byte *before* the buffer.
+ */
+ uint8_t *nextData = data->buffer - sizeof (uint8_t);
+ Marshal_UINT32 (data->buffer,
+ data->buffer_size,
+ &nextData,
+ data->data_host,
+ &data->rc);
+ /* again, not enough space, and no change to nextData */
+ assert_return_code (data->rc, TSS2_SYS_RC_INSUFFICIENT_CONTEXT);
+ assert_int_equal (data->buffer, nextData - sizeof (uint8_t));
+}
+/**
+ * Test error condition where nextData pointer is already beyond the end
+ * of the data buffer. We set this value to 1 byte past the buffers end.
+ * The expected result is the 'rc' parameter being set to indicate the
+ * size of the buffer is insufficient. The nextData pointer should also
+ * remain unchanged.
+ */
+void
+marshal_UINT32_past_end (void **state)
+{
+ marshal_uint32_data_t *data;
+
+ data = (marshal_uint32_data_t*)*state;
+ /* Set nextData beyond the end of the buffer. */
+ uint8_t *nextData = data->buffer + data->buffer_size + sizeof (uint8_t);
+ Marshal_UINT32 (data->buffer,
+ data->buffer_size,
+ &nextData,
+ data->data_host,
+ &data->rc);
+ /* rc should indicate error and no change to the pointers */
+ assert_return_code (data->rc, TSS2_SYS_RC_INSUFFICIENT_CONTEXT);
+ assert_int_equal (nextData,
+ data->buffer + data->buffer_size + sizeof (uint8_t));
+}
+/**
+ * Test an edge case where the 'rc' parameter is set to something other
+ * than TSS2_RC_SUCCESS. A pattern I see emerging is the use of the TSS2_RC
+ * member of the sapi context structure to skip over large blocks of code.
+ * Many (most?) of the functions in the guts of the serialization logic check
+ * this member data and quickly return when it's set. This is the reason
+ * these fucntions often have no return value: they're using the 'rc' member
+ * in the context structure.
+ */
+void
+marshal_UINT32_rc_previous_fail (void **state)
+{
+ /* Set 'rc' to an error condition. */
+ TSS2_RC rc = TSS2_SYS_RC_BAD_SIZE;
+ /* 'rc' is checked first, all other parameters can be NULL.*/
+ Marshal_UINT32 (NULL, 0, NULL, 0, &rc);
+ assert_return_code (rc, TSS2_SYS_RC_BAD_SIZE);
+}
+int
+main (void)
+{
+ const UnitTest tests [] = {
+ unit_test_setup_teardown (marshal_UINT32_good,
+ marshal_UINT32_setup,
+ marshal_UINT32_teardown),
+ unit_test_setup_teardown (marshal_UINT32_too_small,
+ marshal_UINT32_setup,
+ marshal_UINT32_teardown),
+ unit_test_setup_teardown (marshal_UINT32_past_end,
+ marshal_UINT32_setup,
+ marshal_UINT32_teardown),
+ unit_test (marshal_UINT32_rc_previous_fail),
+ };
+ return run_tests (tests);
+}