/* * Copyright (c) 2015-2016 Nicholas Fraser * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "test-node.h" #if MPACK_NODE mpack_error_t test_tree_error = mpack_ok; void test_tree_error_handler(mpack_tree_t* tree, mpack_error_t error) { TEST_TRUE(test_tree_error == mpack_ok, "error handler was called multiple times"); TEST_TRUE(error != mpack_ok, "error handler was called with mpack_ok"); TEST_TRUE(mpack_tree_error(tree) == error, "tree error does not match given error"); test_tree_error = error; } // tests the example on the messagepack homepage static void test_example_node() { // add a junk byte at the end to test mpack_tree_size() static const char test[] = "\x82\xA7""compact\xC3\xA6""schema\x00\xC1"; mpack_tree_t tree; // this is a node pool test even if we have malloc. the rest of the // non-simple tests use paging unless malloc is unavailable. mpack_node_data_t pool[128]; mpack_tree_init_pool(&tree, test, sizeof(test) - 1, pool, sizeof(pool) / sizeof(*pool)); TEST_TRUE(mpack_tree_error(&tree) == mpack_ok); mpack_node_t map = mpack_tree_root(&tree); TEST_TRUE(true == mpack_node_bool(mpack_node_map_cstr(map, "compact"))); TEST_TRUE(0 == mpack_node_u8(mpack_node_map_cstr(map, "schema"))); TEST_TRUE(mpack_tree_size(&tree) == sizeof(test) - 2); TEST_TREE_DESTROY_NOERROR(&tree); } static void test_node_read_uint_fixnum() { mpack_node_data_t pool[128]; // positive fixnums with u8 TEST_SIMPLE_TREE_READ("\x00", 0 == mpack_node_u8(node)); TEST_SIMPLE_TREE_READ("\x01", 1 == mpack_node_u8(node)); TEST_SIMPLE_TREE_READ("\x02", 2 == mpack_node_u8(node)); TEST_SIMPLE_TREE_READ("\x0f", 0x0f == mpack_node_u8(node)); TEST_SIMPLE_TREE_READ("\x10", 0x10 == mpack_node_u8(node)); TEST_SIMPLE_TREE_READ("\x7f", 0x7f == mpack_node_u8(node)); // positive fixnums with u16 TEST_SIMPLE_TREE_READ("\x00", 0 == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\x01", 1 == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\x02", 2 == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\x0f", 0x0f == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\x10", 0x10 == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\x7f", 0x7f == mpack_node_u16(node)); // positive fixnums with u32 TEST_SIMPLE_TREE_READ("\x00", 0 == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\x01", 1 == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\x02", 2 == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\x0f", 0x0f == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\x10", 0x10 == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\x7f", 0x7f == mpack_node_u32(node)); // positive fixnums with u64 TEST_SIMPLE_TREE_READ("\x00", 0 == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\x01", 1 == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\x02", 2 == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\x0f", 0x0f == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\x10", 0x10 == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\x7f", 0x7f == mpack_node_u64(node)); // positive fixnums with uint TEST_SIMPLE_TREE_READ("\x00", 0 == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\x01", 1 == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\x02", 2 == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\x0f", 0x0f == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\x10", 0x10 == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\x7f", 0x7f == mpack_node_uint(node)); } static void test_node_read_uint_signed_fixnum() { mpack_node_data_t pool[128]; // positive fixnums with i8 TEST_SIMPLE_TREE_READ("\x00", 0 == mpack_node_i8(node)); TEST_SIMPLE_TREE_READ("\x01", 1 == mpack_node_i8(node)); TEST_SIMPLE_TREE_READ("\x02", 2 == mpack_node_i8(node)); TEST_SIMPLE_TREE_READ("\x0f", 0x0f == mpack_node_i8(node)); TEST_SIMPLE_TREE_READ("\x10", 0x10 == mpack_node_i8(node)); TEST_SIMPLE_TREE_READ("\x7f", 0x7f == mpack_node_i8(node)); // positive fixnums with i16 TEST_SIMPLE_TREE_READ("\x00", 0 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\x01", 1 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\x02", 2 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\x0f", 0x0f == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\x10", 0x10 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\x7f", 0x7f == mpack_node_i16(node)); // positive fixnums with i32 TEST_SIMPLE_TREE_READ("\x00", 0 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\x01", 1 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\x02", 2 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\x0f", 0x0f == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\x10", 0x10 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\x7f", 0x7f == mpack_node_i32(node)); // positive fixnums with i64 TEST_SIMPLE_TREE_READ("\x00", 0 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\x01", 1 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\x02", 2 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\x0f", 0x0f == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\x10", 0x10 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\x7f", 0x7f == mpack_node_i64(node)); // positive fixnums with int TEST_SIMPLE_TREE_READ("\x00", 0 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\x01", 1 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\x02", 2 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\x0f", 0x0f == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\x10", 0x10 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\x7f", 0x7f == mpack_node_int(node)); } static void test_node_read_negative_fixnum() { mpack_node_data_t pool[128]; // negative fixnums with i8 TEST_SIMPLE_TREE_READ("\xff", -1 == mpack_node_i8(node)); TEST_SIMPLE_TREE_READ("\xfe", -2 == mpack_node_i8(node)); TEST_SIMPLE_TREE_READ("\xf0", -16 == mpack_node_i8(node)); TEST_SIMPLE_TREE_READ("\xe0", -32 == mpack_node_i8(node)); // negative fixnums with i16 TEST_SIMPLE_TREE_READ("\xff", -1 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\xfe", -2 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\xf0", -16 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\xe0", -32 == mpack_node_i16(node)); // negative fixnums with i32 TEST_SIMPLE_TREE_READ("\xff", -1 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xfe", -2 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xf0", -16 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xe0", -32 == mpack_node_i32(node)); // negative fixnums with i64 TEST_SIMPLE_TREE_READ("\xff", -1 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xfe", -2 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xf0", -16 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xe0", -32 == mpack_node_i64(node)); // negative fixnums with int TEST_SIMPLE_TREE_READ("\xff", -1 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xfe", -2 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xf0", -16 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xe0", -32 == mpack_node_int(node)); } static void test_node_read_uint() { mpack_node_data_t pool[128]; // positive signed into u8 TEST_SIMPLE_TREE_READ("\xd0\x7f", 0x7f == mpack_node_u8(node)); TEST_SIMPLE_TREE_READ("\xd0\x7f", 0x7f == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\xd0\x7f", 0x7f == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\xd0\x7f", 0x7f == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\xd0\x7f", 0x7f == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\xd1\x7f\xff", 0x7fff == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\xd1\x7f\xff", 0x7fff == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\xd1\x7f\xff", 0x7fff == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\xd1\x7f\xff", 0x7fff == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\xd2\x7f\xff\xff\xff", 0x7fffffff == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\xd2\x7f\xff\xff\xff", 0x7fffffff == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\xd2\x7f\xff\xff\xff", 0x7fffffff == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\xd3\x7f\xff\xff\xff\xff\xff\xff\xff", 0x7fffffffffffffff == mpack_node_u64(node)); // positive unsigned into u8 TEST_SIMPLE_TREE_READ("\xcc\x80", 0x80 == mpack_node_u8(node)); TEST_SIMPLE_TREE_READ("\xcc\x80", 0x80 == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\xcc\x80", 0x80 == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\xcc\x80", 0x80 == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\xcc\x80", 0x80 == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\xcc\xff", 0xff == mpack_node_u8(node)); TEST_SIMPLE_TREE_READ("\xcc\xff", 0xff == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\xcc\xff", 0xff == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\xcc\xff", 0xff == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\xcc\xff", 0xff == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\xcd\x01\x00", 0x100 == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\xcd\x01\x00", 0x100 == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\xcd\x01\x00", 0x100 == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\xcd\x01\x00", 0x100 == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\xcd\xff\xff", 0xffff == mpack_node_u16(node)); TEST_SIMPLE_TREE_READ("\xcd\xff\xff", 0xffff == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\xcd\xff\xff", 0xffff == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\xcd\xff\xff", 0xffff == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\xce\x00\x01\x00\x00", 0x10000 == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\xce\x00\x01\x00\x00", 0x10000 == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\xce\x00\x01\x00\x00", 0x10000 == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\xce\xff\xff\xff\xff", 0xffffffff == mpack_node_u32(node)); TEST_SIMPLE_TREE_READ("\xce\xff\xff\xff\xff", 0xffffffff == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\xce\xff\xff\xff\xff", 0xffffffff == mpack_node_uint(node)); TEST_SIMPLE_TREE_READ("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", 0x100000000 == mpack_node_u64(node)); TEST_SIMPLE_TREE_READ("\xcf\xff\xff\xff\xff\xff\xff\xff\xff", 0xffffffffffffffff == mpack_node_u64(node)); } static void test_node_read_uint_signed() { mpack_node_data_t pool[128]; TEST_SIMPLE_TREE_READ("\xcc\x80", 0x80 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\xcc\x80", 0x80 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xcc\x80", 0x80 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xcc\x80", 0x80 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xcc\xff", 0xff == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\xcc\xff", 0xff == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xcc\xff", 0xff == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xcc\xff", 0xff == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xcd\x01\x00", 0x100 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\xcd\x01\x00", 0x100 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xcd\x01\x00", 0x100 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xcd\x01\x00", 0x100 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xcd\xff\xff", 0xffff == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xcd\xff\xff", 0xffff == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xcd\xff\xff", 0xffff == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xce\x00\x01\x00\x00", 0x10000 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xce\x00\x01\x00\x00", 0x10000 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xce\x00\x01\x00\x00", 0x10000 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xce\xff\xff\xff\xff", 0xffffffff == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", 0x100000000 == mpack_node_i64(node)); } static void test_node_read_int() { mpack_node_data_t pool[128]; TEST_SIMPLE_TREE_READ("\xd0\xdf", -33 == mpack_node_i8(node)); TEST_SIMPLE_TREE_READ("\xd0\xdf", -33 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\xd0\xdf", -33 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xd0\xdf", -33 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xd0\xdf", -33 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xd0\x80", INT8_MIN == mpack_node_i8(node)); TEST_SIMPLE_TREE_READ("\xd0\x80", INT8_MIN == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\xd0\x80", INT8_MIN == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xd0\x80", INT8_MIN == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xd0\x80", INT8_MIN == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xd1\xff\x7f", INT8_MIN - 1 == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\xd1\xff\x7f", INT8_MIN - 1 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xd1\xff\x7f", INT8_MIN - 1 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xd1\xff\x7f", INT8_MIN - 1 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xd1\x80\x00", INT16_MIN == mpack_node_i16(node)); TEST_SIMPLE_TREE_READ("\xd1\x80\x00", INT16_MIN == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xd1\x80\x00", INT16_MIN == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xd1\x80\x00", INT16_MIN == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xd2\xff\xff\x7f\xff", INT16_MIN - 1 == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xd2\xff\xff\x7f\xff", INT16_MIN - 1 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xd2\xff\xff\x7f\xff", INT16_MIN - 1 == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xd2\x80\x00\x00\x00", INT32_MIN == mpack_node_i32(node)); TEST_SIMPLE_TREE_READ("\xd2\x80\x00\x00\x00", INT32_MIN == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xd2\x80\x00\x00\x00", INT32_MIN == mpack_node_int(node)); TEST_SIMPLE_TREE_READ("\xd3\xff\xff\xff\xff\x7f\xff\xff\xff", (int64_t)INT32_MIN - 1 == mpack_node_i64(node)); TEST_SIMPLE_TREE_READ("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", INT64_MIN == mpack_node_i64(node)); } static void test_node_read_ints_dynamic_int() { mpack_node_data_t pool[128]; // we don't bother to test with different signed/unsigned value // functions; they are tested for equality in test-value.c // positive fixnums TEST_SIMPLE_TREE_READ("\x00", mpack_tag_equal(mpack_tag_uint(0), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\x01", mpack_tag_equal(mpack_tag_uint(1), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\x02", mpack_tag_equal(mpack_tag_uint(2), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\x0f", mpack_tag_equal(mpack_tag_uint(0x0f), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\x10", mpack_tag_equal(mpack_tag_uint(0x10), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\x7f", mpack_tag_equal(mpack_tag_uint(0x7f), mpack_node_tag(node))); // negative fixnums TEST_SIMPLE_TREE_READ("\xff", mpack_tag_equal(mpack_tag_int(-1), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xfe", mpack_tag_equal(mpack_tag_int(-2), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xf0", mpack_tag_equal(mpack_tag_int(-16), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xe0", mpack_tag_equal(mpack_tag_int(-32), mpack_node_tag(node))); // uints TEST_SIMPLE_TREE_READ("\xcc\x80", mpack_tag_equal(mpack_tag_uint(0x80), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xcc\xff", mpack_tag_equal(mpack_tag_uint(0xff), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xcd\x01\x00", mpack_tag_equal(mpack_tag_uint(0x100), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xcd\xff\xff", mpack_tag_equal(mpack_tag_uint(0xffff), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xce\x00\x01\x00\x00", mpack_tag_equal(mpack_tag_uint(0x10000), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xce\xff\xff\xff\xff", mpack_tag_equal(mpack_tag_uint(0xffffffff), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", mpack_tag_equal(mpack_tag_uint(UINT64_C(0x100000000)), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xcf\xff\xff\xff\xff\xff\xff\xff\xff", mpack_tag_equal(mpack_tag_uint(UINT64_C(0xffffffffffffffff)), mpack_node_tag(node))); // ints TEST_SIMPLE_TREE_READ("\xd0\xdf", mpack_tag_equal(mpack_tag_int(-33), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xd0\x80", mpack_tag_equal(mpack_tag_int(INT8_MIN), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xd1\xff\x7f", mpack_tag_equal(mpack_tag_int(INT8_MIN - 1), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xd1\x80\x00", mpack_tag_equal(mpack_tag_int(INT16_MIN), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xd2\xff\xff\x7f\xff", mpack_tag_equal(mpack_tag_int(INT16_MIN - 1), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xd2\x80\x00\x00\x00", mpack_tag_equal(mpack_tag_int(INT32_MIN), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xd3\xff\xff\xff\xff\x7f\xff\xff\xff", mpack_tag_equal(mpack_tag_int((int64_t)INT32_MIN - 1), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", mpack_tag_equal(mpack_tag_int(INT64_MIN), mpack_node_tag(node))); } static void test_node_read_int_bounds() { mpack_node_data_t pool[128]; TEST_SIMPLE_TREE_READ_ERROR("\xd1\xff\x7f", 0 == mpack_node_i8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd1\x80\x00", 0 == mpack_node_i8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd2\xff\xff\x7f\xff", 0 == mpack_node_i8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd2\xff\xff\x7f\xff", 0 == mpack_node_i16(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd2\x80\x00\x00\x00", 0 == mpack_node_i8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd2\x80\x00\x00\x00", 0 == mpack_node_i16(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd3\xff\xff\xff\xff\x7f\xff\xff\xff", 0 == mpack_node_i8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd3\xff\xff\xff\xff\x7f\xff\xff\xff", 0 == mpack_node_i16(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd3\xff\xff\xff\xff\x7f\xff\xff\xff", 0 == mpack_node_i32(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", 0 == mpack_node_i8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", 0 == mpack_node_i16(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", 0 == mpack_node_i32(node), mpack_error_type); } static void test_node_read_uint_bounds() { mpack_node_data_t pool[128]; TEST_SIMPLE_TREE_READ_ERROR("\xcd\x01\x00", 0 == mpack_node_u8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xcd\xff\xff", 0 == mpack_node_u8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xce\x00\x01\x00\x00", 0 == mpack_node_u8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xce\x00\x01\x00\x00", 0 == mpack_node_u16(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xce\xff\xff\xff\xff", 0 == mpack_node_u8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xce\xff\xff\xff\xff", 0 == mpack_node_u16(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", 0 == mpack_node_u8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", 0 == mpack_node_u16(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", 0 == mpack_node_u32(node), mpack_error_type); } static void test_node_read_misc() { mpack_node_data_t pool[128]; TEST_SIMPLE_TREE_READ("\xc0", (mpack_node_nil(node), true)); TEST_SIMPLE_TREE_READ("\xc2", false == mpack_node_bool(node)); TEST_SIMPLE_TREE_READ("\xc2", (mpack_node_false(node), true)); TEST_SIMPLE_TREE_READ("\xc3", true == mpack_node_bool(node)); TEST_SIMPLE_TREE_READ("\xc3", (mpack_node_true(node), true)); TEST_SIMPLE_TREE_READ_ERROR("\xc2", (mpack_node_true(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc3", (mpack_node_false(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ("\xc0", mpack_tag_equal(mpack_tag_nil(), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xc2", mpack_tag_equal(mpack_tag_false(), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xc3", mpack_tag_equal(mpack_tag_true(), mpack_node_tag(node))); // test missing space for cstr null-terminator mpack_tree_t tree; mpack_tree_init_pool(&tree, "\xa0", 1, pool, sizeof(pool) / sizeof(*pool)); #if MPACK_DEBUG char buf[1]; TEST_ASSERT(mpack_node_copy_cstr(mpack_tree_root(&tree), buf, 0)); #endif #ifdef MPACK_MALLOC TEST_BREAK(NULL == mpack_node_cstr_alloc(mpack_tree_root(&tree), 0)); TEST_TREE_DESTROY_ERROR(&tree, mpack_error_bug); #else TEST_TREE_DESTROY_NOERROR(&tree); #endif // test pool too small mpack_node_data_t small_pool[1]; mpack_tree_init_pool(&tree, "\x91\xc0", 2, small_pool, 1); TEST_TREE_DESTROY_ERROR(&tree, mpack_error_too_big); TEST_BREAK((mpack_tree_init_pool(&tree, "\xc0", 1, small_pool, 0), true)); TEST_TREE_DESTROY_ERROR(&tree, mpack_error_bug); } static void test_node_read_floats() { mpack_node_data_t pool[128]; // these are some very simple floats that don't really test IEEE 742 conformance; // this section could use some improvement TEST_SIMPLE_TREE_READ("\x00", 0.0f == mpack_node_float(node)); TEST_SIMPLE_TREE_READ("\xd0\x00", 0.0f == mpack_node_float(node)); TEST_SIMPLE_TREE_READ("\xca\x00\x00\x00\x00", 0.0f == mpack_node_float(node)); TEST_SIMPLE_TREE_READ("\xcb\x00\x00\x00\x00\x00\x00\x00\x00", 0.0f == mpack_node_float(node)); TEST_SIMPLE_TREE_READ("\x00", 0.0 == mpack_node_double(node)); TEST_SIMPLE_TREE_READ("\xd0\x00", 0.0 == mpack_node_double(node)); TEST_SIMPLE_TREE_READ("\xca\x00\x00\x00\x00", 0.0 == mpack_node_double(node)); TEST_SIMPLE_TREE_READ("\xcb\x00\x00\x00\x00\x00\x00\x00\x00", 0.0 == mpack_node_double(node)); TEST_SIMPLE_TREE_READ("\xca\x00\x00\x00\x00", 0.0f == mpack_node_float_strict(node)); TEST_SIMPLE_TREE_READ("\xca\x00\x00\x00\x00", mpack_tag_equal(mpack_tag_float(0.0f), mpack_node_tag(node))); TEST_SIMPLE_TREE_READ("\xca\x00\x00\x00\x00", 0.0 == mpack_node_double_strict(node)); TEST_SIMPLE_TREE_READ("\xcb\x00\x00\x00\x00\x00\x00\x00\x00", mpack_tag_equal(mpack_tag_double(0.0), mpack_node_tag(node))); // when -ffinite-math-only is enabled, isnan() can always return false. // TODO: we should probably add at least a reader option to // generate an error on non-finite reals. #if !MPACK_FINITE_MATH TEST_SIMPLE_TREE_READ("\xca\xff\xff\xff\xff", isnanf(mpack_node_float(node)) != 0); TEST_SIMPLE_TREE_READ("\xcb\xff\xff\xff\xff\xff\xff\xff\xff", isnanf(mpack_node_float(node)) != 0); TEST_SIMPLE_TREE_READ("\xca\xff\xff\xff\xff", isnan(mpack_node_double(node)) != 0); TEST_SIMPLE_TREE_READ("\xcb\xff\xff\xff\xff\xff\xff\xff\xff", isnan(mpack_node_double(node)) != 0); TEST_SIMPLE_TREE_READ("\xca\xff\xff\xff\xff", isnanf(mpack_node_float_strict(node)) != 0); TEST_SIMPLE_TREE_READ("\xca\xff\xff\xff\xff", isnan(mpack_node_double_strict(node)) != 0); TEST_SIMPLE_TREE_READ("\xcb\xff\xff\xff\xff\xff\xff\xff\xff", isnan(mpack_node_double_strict(node)) != 0); #endif TEST_SIMPLE_TREE_READ_ERROR("\x00", 0.0f == mpack_node_float_strict(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd0\x00", 0.0f == mpack_node_float_strict(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xcb\x00\x00\x00\x00\x00\x00\x00\x00", 0.0f == mpack_node_float_strict(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", 0.0 == mpack_node_double_strict(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xd0\x00", 0.0 == mpack_node_double_strict(node), mpack_error_type); } static void test_node_read_bad_type() { mpack_node_data_t pool[128]; // test that non-compound node functions correctly handle badly typed data TEST_SIMPLE_TREE_READ_ERROR("\xc2", (mpack_node_nil(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", false == mpack_node_bool(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_u8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_u16(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_u32(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_u64(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_uint(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_i8(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_i16(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_i32(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_i64(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_int(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0.0f == mpack_node_float(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0.0 == mpack_node_double(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0.0f == mpack_node_float_strict(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0.0 == mpack_node_double_strict(node), mpack_error_type); } static void test_node_read_possible() { // test early exit for data that contains impossible node numbers mpack_node_data_t pool[128]; TEST_SIMPLE_TREE_READ_ERROR("\xcc", (MPACK_UNUSED(node), true), mpack_error_invalid); // truncated u8 TEST_SIMPLE_TREE_READ_ERROR("\xcd", (MPACK_UNUSED(node), true), mpack_error_invalid); // truncated u16 TEST_SIMPLE_TREE_READ_ERROR("\xce", (MPACK_UNUSED(node), true), mpack_error_invalid); // truncated u32 TEST_SIMPLE_TREE_READ_ERROR("\xcf", (MPACK_UNUSED(node), true), mpack_error_invalid); // truncated u64 #ifdef MPACK_MALLOC // this is an example of a potential denial-of-service attack against // MessagePack implementations that allocate storage up-front. this // should be handled safely without allocating huge amounts of memory. const char* attack = "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff" "\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff\xdd\xff\xff\xff\xff"; size_t allocation_count = test_malloc_total_count(); mpack_tree_t tree; mpack_tree_init(&tree, attack, strlen(attack)); allocation_count = test_malloc_total_count() - allocation_count; TEST_TRUE(allocation_count <= 2, "too many allocations! %i calls to malloc()", (int)allocation_count); TEST_TREE_DESTROY_ERROR(&tree, mpack_error_invalid); #endif } static void test_node_read_pre_error() { mpack_node_data_t pool[128]; char buf[1]; // test that all node functions correctly handle pre-existing errors TEST_SIMPLE_TREE_READ_ERROR("\xc1", mpack_type_nil == mpack_node_tag(node).type, mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", (mpack_node_nil(node), true), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", false == mpack_node_bool(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_u8(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_u16(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_u32(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_u64(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_uint(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_i8(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_i16(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_i32(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_i64(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_int(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0.0f == mpack_node_float(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0.0 == mpack_node_double(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0.0f == mpack_node_float_strict(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0.0 == mpack_node_double_strict(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_array_length(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", &tree.nil_node == mpack_node_array_at(node, 0).data, mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_map_count(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", &tree.nil_node == mpack_node_map_key_at(node, 0).data, mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", &tree.nil_node == mpack_node_map_value_at(node, 0).data, mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", &tree.nil_node == mpack_node_map_uint(node, 1).data, mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", &tree.nil_node == mpack_node_map_int(node, -1).data, mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", &tree.nil_node == mpack_node_map_str(node, "test", 4).data, mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", &tree.nil_node == mpack_node_map_cstr(node, "test").data, mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", false == mpack_node_map_contains_str(node, "test", 4), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", false == mpack_node_map_contains_cstr(node, "test"), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_exttype(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_data_len(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_strlen(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", NULL == mpack_node_data(node), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", 0 == mpack_node_copy_data(node, NULL, 0), mpack_error_invalid); buf[0] = 1; TEST_SIMPLE_TREE_READ_ERROR("", (mpack_node_copy_cstr(node, buf, sizeof(buf)), true), mpack_error_invalid); TEST_TRUE(buf[0] == 0); #ifdef MPACK_MALLOC TEST_SIMPLE_TREE_READ_ERROR("", NULL == mpack_node_data_alloc(node, 0), mpack_error_invalid); TEST_SIMPLE_TREE_READ_ERROR("", NULL == mpack_node_cstr_alloc(node, 0), mpack_error_invalid); #endif } static void test_node_read_strings() { char buf[256]; mpack_node_data_t pool[128]; #ifdef MPACK_MALLOC char* test = NULL; #endif // these are copied from test-expect.c // the first byte of each of these is the MessagePack object header const char utf8_null[] = "\xa1\x00"; const char utf8_valid[] = "\xac \xCF\x80 \xe4\xb8\xad \xf0\xa0\x80\xb6"; const char utf8_trimmed[] = "\xa4\xf0\xa0\x80\xb6"; const char utf8_invalid[] = "\xa3 \x80 "; const char utf8_invalid_trimmed[] = "\xa1\xa0"; const char utf8_truncated[] = "\xa2\xf0\xa0"; // we don't accept any of these UTF-8 variants; only pure UTF-8 is allowed. const char utf8_modified[] = "\xa4 \xc0\x80 "; const char utf8_cesu8[] = "\xa8 \xED\xA0\x81\xED\xB0\x80 "; const char utf8_wobbly[] = "\xa5 \xED\xA0\x81 "; // utf8 str check TEST_SIMPLE_TREE_READ("\xa0", (mpack_node_check_utf8(node), true)); TEST_SIMPLE_TREE_READ("\xa0", (mpack_node_check_utf8(node), true)); TEST_SIMPLE_TREE_READ("\xa4test", (mpack_node_check_utf8(node), true)); TEST_SIMPLE_TREE_READ(utf8_null, (mpack_node_check_utf8(node), true)); TEST_SIMPLE_TREE_READ(utf8_valid, (mpack_node_check_utf8(node), true)); TEST_SIMPLE_TREE_READ(utf8_trimmed, (mpack_node_check_utf8(node), true)); TEST_SIMPLE_TREE_READ_ERROR(utf8_invalid, (mpack_node_check_utf8(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_invalid_trimmed, (mpack_node_check_utf8(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_truncated, (mpack_node_check_utf8(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_modified, (mpack_node_check_utf8(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_cesu8, (mpack_node_check_utf8(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_wobbly, (mpack_node_check_utf8(node), true), mpack_error_type); // utf8 cstr check TEST_SIMPLE_TREE_READ("\xa0", (mpack_node_check_utf8_cstr(node), true)); TEST_SIMPLE_TREE_READ("\xa4test", (mpack_node_check_utf8_cstr(node), true)); TEST_SIMPLE_TREE_READ_ERROR(utf8_null, (mpack_node_check_utf8_cstr(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ(utf8_valid, (mpack_node_check_utf8_cstr(node), true)); TEST_SIMPLE_TREE_READ(utf8_trimmed, (mpack_node_check_utf8_cstr(node), true)); TEST_SIMPLE_TREE_READ_ERROR(utf8_invalid, (mpack_node_check_utf8_cstr(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_invalid_trimmed, (mpack_node_check_utf8_cstr(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_truncated, (mpack_node_check_utf8_cstr(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_modified, (mpack_node_check_utf8_cstr(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_cesu8, (mpack_node_check_utf8_cstr(node), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_wobbly, (mpack_node_check_utf8_cstr(node), true), mpack_error_type); // utf8 str copy TEST_SIMPLE_TREE_READ("\xa0", 0 == mpack_node_copy_utf8(node, buf, 0)); TEST_SIMPLE_TREE_READ("\xa0", 0 == mpack_node_copy_utf8(node, buf, 4)); TEST_SIMPLE_TREE_READ("\xa4test", 4 == mpack_node_copy_utf8(node, buf, 4)); TEST_SIMPLE_TREE_READ_ERROR("\xa5hello", 0 == mpack_node_copy_utf8(node, buf, 4), mpack_error_too_big); TEST_SIMPLE_TREE_READ_ERROR("\xc0", 0 == mpack_node_copy_utf8(node, buf, 4), mpack_error_type); TEST_SIMPLE_TREE_READ(utf8_null, (mpack_node_copy_utf8(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ(utf8_valid, (mpack_node_copy_utf8(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ(utf8_trimmed, (mpack_node_copy_utf8(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ_ERROR(utf8_invalid, (mpack_node_copy_utf8(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_invalid_trimmed, (mpack_node_copy_utf8(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_truncated, (mpack_node_copy_utf8(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_modified, (mpack_node_copy_utf8(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_cesu8, (mpack_node_copy_utf8(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_wobbly, (mpack_node_copy_utf8(node, buf, sizeof(buf)), true), mpack_error_type); // cstr copy TEST_SIMPLE_TREE_READ_ASSERT("\xa0", mpack_node_copy_cstr(node, buf, 0)); TEST_SIMPLE_TREE_READ("\xa0", (mpack_node_copy_cstr(node, buf, 4), true)); TEST_TRUE(strlen(buf) == 0); TEST_SIMPLE_TREE_READ("\xa4test", (mpack_node_copy_cstr(node, buf, 5), true)); TEST_TRUE(strlen(buf) == 4); TEST_SIMPLE_TREE_READ_ERROR("\xa5hello", (mpack_node_copy_cstr(node, buf, 5), true), mpack_error_too_big); TEST_TRUE(strlen(buf) == 0); TEST_SIMPLE_TREE_READ_ERROR(utf8_null, (mpack_node_copy_cstr(node, buf, sizeof(buf)), true), mpack_error_type); TEST_TRUE(strlen(buf) == 0); TEST_SIMPLE_TREE_READ(utf8_valid, (mpack_node_copy_cstr(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ(utf8_invalid, (mpack_node_copy_cstr(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ(utf8_invalid_trimmed, (mpack_node_copy_cstr(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ(utf8_truncated, (mpack_node_copy_cstr(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ(utf8_modified, (mpack_node_copy_cstr(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ(utf8_cesu8, (mpack_node_copy_cstr(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ(utf8_wobbly, (mpack_node_copy_cstr(node, buf, sizeof(buf)), true)); // utf8 cstr copy TEST_SIMPLE_TREE_READ_ASSERT("\xa0", mpack_node_copy_utf8_cstr(node, buf, 0)); TEST_SIMPLE_TREE_READ("\xa0", (mpack_node_copy_utf8_cstr(node, buf, 4), true)); TEST_TRUE(strlen(buf) == 0); TEST_SIMPLE_TREE_READ("\xa4test", (mpack_node_copy_utf8_cstr(node, buf, 5), true)); TEST_TRUE(strlen(buf) == 4); TEST_SIMPLE_TREE_READ_ERROR("\xa5hello", (mpack_node_copy_utf8_cstr(node, buf, 5), true), mpack_error_too_big); TEST_TRUE(strlen(buf) == 0); TEST_SIMPLE_TREE_READ_ERROR(utf8_null, (mpack_node_copy_utf8_cstr(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ(utf8_valid, (mpack_node_copy_utf8_cstr(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ(utf8_trimmed, (mpack_node_copy_utf8_cstr(node, buf, sizeof(buf)), true)); TEST_SIMPLE_TREE_READ_ERROR(utf8_invalid, (mpack_node_copy_utf8_cstr(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_invalid_trimmed, (mpack_node_copy_utf8_cstr(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_truncated, (mpack_node_copy_utf8_cstr(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_modified, (mpack_node_copy_utf8_cstr(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_cesu8, (mpack_node_copy_utf8_cstr(node, buf, sizeof(buf)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_wobbly, (mpack_node_copy_utf8_cstr(node, buf, sizeof(buf)), true), mpack_error_type); #ifdef MPACK_MALLOC // cstr alloc TEST_SIMPLE_TREE_READ_ERROR(utf8_null, NULL == mpack_node_cstr_alloc(node, 256), mpack_error_type); // utf8 cstr alloc TEST_SIMPLE_TREE_READ_BREAK("\xa0", NULL == mpack_node_utf8_cstr_alloc(node, 0)); TEST_SIMPLE_TREE_READ("\xa0", NULL != (test = mpack_node_utf8_cstr_alloc(node, 4))); if (test) { TEST_TRUE(strlen(test) == 0); MPACK_FREE(test); } TEST_SIMPLE_TREE_READ_ERROR("\xa4test", NULL == mpack_node_utf8_cstr_alloc(node, 4), mpack_error_too_big); TEST_SIMPLE_TREE_READ("\xa4test", NULL != (test = mpack_node_utf8_cstr_alloc(node, 5))); if (test) { TEST_TRUE(strlen(test) == 4); TEST_TRUE(memcmp(test, "test", 4) == 0); MPACK_FREE(test); } TEST_SIMPLE_TREE_READ("\xa4test", NULL != (test = mpack_node_utf8_cstr_alloc(node, SIZE_MAX))); if (test) { TEST_TRUE(strlen(test) == 4); TEST_TRUE(memcmp(test, "test", 4) == 0); MPACK_FREE(test); } TEST_SIMPLE_TREE_READ_ERROR("\x01", NULL == mpack_node_utf8_cstr_alloc(node, 3), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_null, ((test = mpack_node_utf8_cstr_alloc(node, 256)), true), mpack_error_type); TEST_SIMPLE_TREE_READ(utf8_valid, ((test = mpack_node_utf8_cstr_alloc(node, 256)), true)); MPACK_FREE(test); TEST_SIMPLE_TREE_READ(utf8_trimmed, ((test = mpack_node_utf8_cstr_alloc(node, 256)), true)); MPACK_FREE(test); TEST_SIMPLE_TREE_READ_ERROR(utf8_invalid, ((test = mpack_node_utf8_cstr_alloc(node, 256)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_invalid_trimmed, ((test = mpack_node_utf8_cstr_alloc(node, 256)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_truncated, ((test = mpack_node_utf8_cstr_alloc(node, 256)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_modified, ((test = mpack_node_utf8_cstr_alloc(node, 256)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_cesu8, ((test = mpack_node_utf8_cstr_alloc(node, 256)), true), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR(utf8_wobbly, ((test = mpack_node_utf8_cstr_alloc(node, 256)), true), mpack_error_type); #endif } static void test_node_read_enum() { mpack_node_data_t pool[128]; typedef enum { APPLE , BANANA , ORANGE , COUNT} fruit_t; const char* fruits[] = {"apple", "banana", "orange"}; TEST_SIMPLE_TREE_READ("\xa5""apple", APPLE == (fruit_t)mpack_node_enum(node, fruits, COUNT)); TEST_SIMPLE_TREE_READ("\xa6""banana", BANANA == (fruit_t)mpack_node_enum(node, fruits, COUNT)); TEST_SIMPLE_TREE_READ("\xa6""orange", ORANGE == (fruit_t)mpack_node_enum(node, fruits, COUNT)); TEST_SIMPLE_TREE_READ_ERROR("\xa4""kiwi", COUNT == (fruit_t)mpack_node_enum(node, fruits, COUNT), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x01", COUNT == (fruit_t)mpack_node_enum(node, fruits, COUNT), mpack_error_type); TEST_SIMPLE_TREE_READ("\xa5""apple", APPLE == (fruit_t)mpack_node_enum_optional(node, fruits, COUNT)); TEST_SIMPLE_TREE_READ("\xa6""banana", BANANA == (fruit_t)mpack_node_enum_optional(node, fruits, COUNT)); TEST_SIMPLE_TREE_READ("\xa6""orange", ORANGE == (fruit_t)mpack_node_enum_optional(node, fruits, COUNT)); TEST_SIMPLE_TREE_READ("\xa4""kiwi", COUNT == (fruit_t)mpack_node_enum_optional(node, fruits, COUNT)); TEST_SIMPLE_TREE_READ("\x01", COUNT == (fruit_t)mpack_node_enum_optional(node, fruits, COUNT)); // test pre-existing error TEST_SIMPLE_TREE_READ_ERROR("\x01", (mpack_node_nil(node), COUNT == (fruit_t)mpack_node_enum(node, fruits, COUNT)), mpack_error_type); } static void test_node_read_array() { static const char test[] = "\x93\x90\x91\xc3\x92\xc3\xc3"; mpack_tree_t tree; TEST_TREE_INIT(&tree, test, sizeof(test) - 1); mpack_node_t root = mpack_tree_root(&tree); TEST_TRUE(mpack_type_array == mpack_node_type(root)); TEST_TRUE(3 == mpack_node_array_length(root)); TEST_TRUE(mpack_type_array == mpack_node_type(mpack_node_array_at(root, 0))); TEST_TRUE(0 == mpack_node_array_length(mpack_node_array_at(root, 0))); TEST_TRUE(mpack_type_array == mpack_node_type(mpack_node_array_at(root, 1))); TEST_TRUE(1 == mpack_node_array_length(mpack_node_array_at(root, 1))); TEST_TRUE(mpack_type_bool == mpack_node_type(mpack_node_array_at(mpack_node_array_at(root, 1), 0))); TEST_TRUE(true == mpack_node_bool(mpack_node_array_at(mpack_node_array_at(root, 1), 0))); TEST_TRUE(mpack_type_array == mpack_node_type(mpack_node_array_at(root, 2))); TEST_TRUE(2 == mpack_node_array_length(mpack_node_array_at(root, 2))); TEST_TRUE(mpack_type_bool == mpack_node_type(mpack_node_array_at(mpack_node_array_at(root, 2), 0))); TEST_TRUE(true == mpack_node_bool(mpack_node_array_at(mpack_node_array_at(root, 2), 0))); TEST_TRUE(mpack_type_bool == mpack_node_type(mpack_node_array_at(mpack_node_array_at(root, 2), 1))); TEST_TRUE(true == mpack_node_bool(mpack_node_array_at(mpack_node_array_at(root, 2), 1))); TEST_TRUE(mpack_ok == mpack_tree_error(&tree)); // test out of bounds TEST_TRUE(mpack_type_nil == mpack_node_type(mpack_node_array_at(root, 4))); TEST_TREE_DESTROY_ERROR(&tree, mpack_error_data); } static void test_node_read_map() { // test map using maps as keys and values static const char test[] = "\x82\x80\x81\x01\x02\x81\x03\x04\xc3"; mpack_tree_t tree; TEST_TREE_INIT(&tree, test, sizeof(test) - 1); mpack_node_t root = mpack_tree_root(&tree); TEST_TRUE(mpack_type_map == mpack_node_type(root)); TEST_TRUE(2 == mpack_node_map_count(root)); TEST_TRUE(mpack_type_map == mpack_node_type(mpack_node_map_key_at(root, 0))); TEST_TRUE(0 == mpack_node_map_count(mpack_node_map_key_at(root, 0))); TEST_TRUE(mpack_type_map == mpack_node_type(mpack_node_map_value_at(root, 0))); TEST_TRUE(1 == mpack_node_map_count(mpack_node_map_value_at(root, 0))); TEST_TRUE(1 == mpack_node_i32(mpack_node_map_key_at(mpack_node_map_value_at(root, 0), 0))); TEST_TRUE(2 == mpack_node_i32(mpack_node_map_value_at(mpack_node_map_value_at(root, 0), 0))); TEST_TRUE(mpack_type_map == mpack_node_type(mpack_node_map_key_at(root, 1))); TEST_TRUE(1 == mpack_node_map_count(mpack_node_map_key_at(root, 1))); TEST_TRUE(3 == mpack_node_i32(mpack_node_map_key_at(mpack_node_map_key_at(root, 1), 0))); TEST_TRUE(4 == mpack_node_i32(mpack_node_map_value_at(mpack_node_map_key_at(root, 1), 0))); TEST_TRUE(mpack_type_bool == mpack_node_type(mpack_node_map_value_at(root, 1))); TEST_TRUE(true == mpack_node_bool(mpack_node_map_value_at(root, 1))); TEST_TRUE(mpack_ok == mpack_tree_error(&tree)); // test out of bounds TEST_TRUE(mpack_type_nil == mpack_node_type(mpack_node_map_key_at(root, 2))); TEST_TREE_DESTROY_ERROR(&tree, mpack_error_data); } static void test_node_read_map_search() { static const char test[] = "\x89\x00\x01\xd0\x7f\x02\xfe\x03\xa5""alice\x04\xa3" "bob\x05\xa4""carl\x06\xa4""carl\x07\x10\x08\x10\x09"; mpack_node_data_t pool[128]; TEST_SIMPLE_TREE_READ(test, 1 == mpack_node_i32(mpack_node_map_uint(node, 0))); TEST_SIMPLE_TREE_READ(test, 1 == mpack_node_i32(mpack_node_map_int(node, 0))); TEST_SIMPLE_TREE_READ(test, 2 == mpack_node_i32(mpack_node_map_uint(node, 127))); // underlying tag type is int TEST_SIMPLE_TREE_READ(test, 3 == mpack_node_i32(mpack_node_map_int(node, -2))); TEST_SIMPLE_TREE_READ(test, 4 == mpack_node_i32(mpack_node_map_str(node, "alice", 5))); TEST_SIMPLE_TREE_READ(test, 5 == mpack_node_i32(mpack_node_map_cstr(node, "bob"))); TEST_SIMPLE_TREE_READ(test, mpack_node_map_contains_int(node, 0)); TEST_SIMPLE_TREE_READ(test, mpack_node_map_contains_uint(node, 0)); TEST_SIMPLE_TREE_READ(test, false == mpack_node_map_contains_int(node, 1)); TEST_SIMPLE_TREE_READ(test, false == mpack_node_map_contains_uint(node, 1)); TEST_SIMPLE_TREE_READ(test, mpack_node_map_contains_int(node, -2)); TEST_SIMPLE_TREE_READ(test, false == mpack_node_map_contains_int(node, -3)); TEST_SIMPLE_TREE_READ(test, true == mpack_node_map_contains_str(node, "alice", 5)); TEST_SIMPLE_TREE_READ(test, true == mpack_node_map_contains_cstr(node, "bob")); TEST_SIMPLE_TREE_READ(test, false == mpack_node_map_contains_str(node, "eve", 3)); TEST_SIMPLE_TREE_READ(test, false == mpack_node_map_contains_cstr(node, "eve")); TEST_SIMPLE_TREE_READ_ERROR(test, false == mpack_node_map_contains_int(node, 16), mpack_error_data); TEST_SIMPLE_TREE_READ_ERROR(test, false == mpack_node_map_contains_uint(node, 16), mpack_error_data); TEST_SIMPLE_TREE_READ_ERROR(test, false == mpack_node_map_contains_str(node, "carl", 4), mpack_error_data); TEST_SIMPLE_TREE_READ_ERROR(test, false == mpack_node_map_contains_cstr(node, "carl"), mpack_error_data); } static void test_node_read_compound_errors(void) { mpack_node_data_t pool[128]; TEST_SIMPLE_TREE_READ_ERROR("\x00", 0 == mpack_node_array_length(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", 0 == mpack_node_map_count(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", &tree.nil_node == mpack_node_array_at(node, 0).data, mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", &tree.nil_node == mpack_node_map_key_at(node, 0).data, mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", &tree.nil_node == mpack_node_map_value_at(node, 0).data, mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x80", &tree.nil_node == mpack_node_map_int(node, -1).data, mpack_error_data); TEST_SIMPLE_TREE_READ_ERROR("\x80", &tree.nil_node == mpack_node_map_uint(node, 1).data, mpack_error_data); TEST_SIMPLE_TREE_READ_ERROR("\x80", &tree.nil_node == mpack_node_map_str(node, "test", 4).data, mpack_error_data); TEST_SIMPLE_TREE_READ_ERROR("\x80", &tree.nil_node == mpack_node_map_cstr(node, "test").data, mpack_error_data); TEST_SIMPLE_TREE_READ_ERROR("\x00", &tree.nil_node == mpack_node_map_int(node, -1).data, mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", &tree.nil_node == mpack_node_map_uint(node, 1).data, mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", &tree.nil_node == mpack_node_map_str(node, "test", 4).data, mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", &tree.nil_node == mpack_node_map_cstr(node, "test").data, mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", false == mpack_node_map_contains_str(node, "test", 4), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", false == mpack_node_map_contains_cstr(node, "test"), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", 0 == mpack_node_exttype(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", 0 == mpack_node_data_len(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", 0 == mpack_node_strlen(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", NULL == mpack_node_data(node), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", 0 == mpack_node_copy_data(node, NULL, 0), mpack_error_type); char data[1] = {'a'}; TEST_SIMPLE_TREE_READ_ERROR("\x00", (mpack_node_copy_data(node, data, 1), true), mpack_error_type); TEST_TRUE(data[0] == 'a'); TEST_SIMPLE_TREE_READ_ERROR("\x00", (mpack_node_copy_cstr(node, data, 1), true), mpack_error_type); TEST_TRUE(data[0] == 0); #ifdef MPACK_MALLOC TEST_SIMPLE_TREE_READ_ERROR("\x00", NULL == mpack_node_data_alloc(node, 10), mpack_error_type); TEST_SIMPLE_TREE_READ_ERROR("\x00", NULL == mpack_node_cstr_alloc(node, 10), mpack_error_type); #endif data[0] = 'a'; TEST_SIMPLE_TREE_READ_ERROR("\xa3""bob", (mpack_node_copy_data(node, data, 2), true), mpack_error_too_big); TEST_TRUE(data[0] == 'a'); TEST_SIMPLE_TREE_READ_ERROR("\xa3""bob", (mpack_node_copy_cstr(node, data, 2), true), mpack_error_too_big); TEST_TRUE(data[0] == 0); #ifdef MPACK_MALLOC TEST_SIMPLE_TREE_READ_ERROR("\xa3""bob", NULL == mpack_node_cstr_alloc(node, 2), mpack_error_too_big); TEST_SIMPLE_TREE_READ_ERROR("\xa3""bob", NULL == mpack_node_data_alloc(node, 2), mpack_error_too_big); #endif } static void test_node_read_data(void) { static const char test[] = "\x93\xa5""alice\xc4\x03""bob\xd6\x07""carl"; mpack_tree_t tree; TEST_TREE_INIT(&tree, test, sizeof(test) - 1); mpack_node_t root = mpack_tree_root(&tree); mpack_node_t alice = mpack_node_array_at(root, 0); TEST_TRUE(5 == mpack_node_data_len(alice)); TEST_TRUE(5 == mpack_node_strlen(alice)); TEST_TRUE(NULL != mpack_node_data(alice)); TEST_TRUE(0 == memcmp("alice", mpack_node_data(alice), 5)); char alice_data[6] = {'s','s','s','s','s','s'}; mpack_node_copy_data(alice, alice_data, sizeof(alice_data)); TEST_TRUE(0 == memcmp("alices", alice_data, 6)); mpack_node_copy_cstr(alice, alice_data, sizeof(alice_data)); TEST_TRUE(0 == strcmp("alice", alice_data)); #ifdef MPACK_MALLOC char* alice_alloc = mpack_node_cstr_alloc(alice, 100); TEST_TRUE(0 == strcmp("alice", alice_alloc)); MPACK_FREE(alice_alloc); #endif mpack_node_t bob = mpack_node_array_at(root, 1); TEST_TRUE(3 == mpack_node_data_len(bob)); TEST_TRUE(0 == memcmp("bob", mpack_node_data(bob), 3)); #ifdef MPACK_MALLOC char* bob_alloc = mpack_node_data_alloc(bob, 100); TEST_TRUE(0 == memcmp("bob", bob_alloc, 3)); MPACK_FREE(bob_alloc); #endif mpack_node_t carl = mpack_node_array_at(root, 2); TEST_TRUE(7 == mpack_node_exttype(carl)); TEST_TRUE(4 == mpack_node_data_len(carl)); TEST_TRUE(0 == memcmp("carl", mpack_node_data(carl), 4)); TEST_TREE_DESTROY_NOERROR(&tree); } static void test_node_read_deep_stack(void) { static const int depth = 1200; char buf[4096]; uint8_t* p = (uint8_t*)buf; for (int i = 0; i < depth; ++i) { *p++ = 0x81; // one pair map *p++ = 0x04; // key four *p++ = 0x91; // value one element array } *p++ = 0x07; // final array value seven mpack_tree_t tree; TEST_TREE_INIT(&tree, buf, (size_t)(p - (uint8_t*)buf)); #ifdef MPACK_MALLOC mpack_node_t node = mpack_tree_root(&tree); for (int i = 0; i < depth; ++i) { TEST_TRUE(mpack_tree_error(&tree) == mpack_ok, "error at depth %i", i); TEST_TRUE(mpack_node_map_count(node) == 1, "error at depth %i", i); TEST_TRUE(mpack_node_u8(mpack_node_map_key_at(node, 0)) == 4, "error at depth %i", i); TEST_TRUE(mpack_node_array_length(mpack_node_map_value_at(node, 0)) == 1, "error at depth %i", i); node = mpack_node_array_at(mpack_node_map_value_at(node, 0), 0); } TEST_TRUE(mpack_node_u8(node) == 7, "error in final node"); TEST_TREE_DESTROY_NOERROR(&tree); #else TEST_TREE_DESTROY_ERROR(&tree, mpack_error_too_big); #endif } void test_node(void) { test_example_node(); // int/uint test_node_read_uint_fixnum(); test_node_read_uint_signed_fixnum(); test_node_read_negative_fixnum(); test_node_read_uint(); test_node_read_uint_signed(); test_node_read_int(); test_node_read_uint_bounds(); test_node_read_int_bounds(); test_node_read_ints_dynamic_int(); // other test_node_read_misc(); test_node_read_floats(); test_node_read_bad_type(); test_node_read_possible(); test_node_read_pre_error(); test_node_read_strings(); test_node_read_enum(); // compound types test_node_read_array(); test_node_read_map(); test_node_read_map_search(); test_node_read_compound_errors(); test_node_read_data(); test_node_read_deep_stack(); } #endif