src.dualinventive.com/fw/libdi_fw-tests/libdi/3rdparty/mpack/test/test-common.c

429 lines
22 KiB
C

/*
* 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.
*/
// we need internal to access the utf-8 check functions
#define MPACK_INTERNAL 1
#include "test-common.h"
#include <math.h>
#include "test.h"
static void test_tags_special(void) {
// ensure there is only one inline definition (the global
// address is in test.c)
TEST_TRUE(fn_mpack_tag_nil == &mpack_tag_nil);
// test comparison with invalid tags
// (invalid enum values cause undefined behavior in C++)
#if MPACK_DEBUG && !defined(__cplusplus)
mpack_tag_t invalid = mpack_tag_nil();
invalid.type = (mpack_type_t)-1;
TEST_ASSERT(mpack_tag_cmp(invalid, invalid));
#endif
}
static void test_tags_simple(void) {
// ensure tag types are correct
TEST_TRUE(mpack_tag_nil().type == mpack_type_nil);
TEST_TRUE(mpack_tag_bool(false).type == mpack_type_bool);
TEST_TRUE(mpack_tag_int(0).type == mpack_type_int);
TEST_TRUE(mpack_tag_uint(0).type == mpack_type_uint);
// uints
TEST_TRUE(mpack_tag_uint(0).v.u == 0);
TEST_TRUE(mpack_tag_uint(1).v.u == 1);
TEST_TRUE(mpack_tag_uint(INT32_MAX).v.u == INT32_MAX);
TEST_TRUE(mpack_tag_uint(INT64_MAX).v.u == INT64_MAX);
// ints
TEST_TRUE(mpack_tag_int(0).v.i == 0);
TEST_TRUE(mpack_tag_int(1).v.i == 1);
// when using INT32_C() and compiling the test suite as c++, gcc complains:
// error: this decimal constant is unsigned only in ISO C90 [-Werror]
TEST_TRUE(mpack_tag_int(INT64_C(-2147483648)).v.i == INT64_C(-2147483648));
TEST_TRUE(mpack_tag_int(INT64_MIN).v.i == INT64_MIN);
// bools
TEST_TRUE(mpack_tag_bool(true).v.b == true);
TEST_TRUE(mpack_tag_bool(false).v.b == false);
TEST_TRUE(mpack_tag_bool(1).v.b == true);
TEST_TRUE(mpack_tag_bool(0).v.b == false);
// comparisons of simple types
TEST_TRUE(true == mpack_tag_equal(mpack_tag_nil(), mpack_tag_nil()));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_nil(), mpack_tag_bool(false)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_nil(), mpack_tag_uint(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_bool(false), mpack_tag_int(0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_bool(false), mpack_tag_bool(false)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_bool(true), mpack_tag_bool(true)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_bool(false), mpack_tag_bool(true)));
// uint/int comparisons
TEST_TRUE(true == mpack_tag_equal(mpack_tag_uint(0), mpack_tag_uint(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_uint(0), mpack_tag_uint(1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_uint(0), mpack_tag_uint(1)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_uint(1), mpack_tag_uint(1)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_int(0), mpack_tag_int(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_int(0), mpack_tag_int(-1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_int(0), mpack_tag_int(-1)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_int(-1), mpack_tag_int(-1)));
// int to uint comparisons
TEST_TRUE(true == mpack_tag_equal(mpack_tag_uint(0), mpack_tag_int(0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_uint(1), mpack_tag_int(1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_uint(0), mpack_tag_int(1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_uint(0), mpack_tag_int(1)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_int(0), mpack_tag_uint(0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_int(1), mpack_tag_uint(1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_int(0), mpack_tag_uint(1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_int(0), mpack_tag_uint(1)));
// ordering
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_uint(0), mpack_tag_uint(1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_uint(1), mpack_tag_uint(0)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_int(-2), mpack_tag_int(-1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_int(-1), mpack_tag_int(-2)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_str(0), mpack_tag_str(1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_str(1), mpack_tag_str(0)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_bin(0), mpack_tag_bin(1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_bin(1), mpack_tag_bin(0)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_array(0), mpack_tag_array(1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_array(1), mpack_tag_array(0)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_map(0), mpack_tag_map(1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_map(1), mpack_tag_map(0)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_ext(1, 1), mpack_tag_ext(2, 0)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_ext(1, 1), mpack_tag_ext(1, 2)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_ext(2, 0), mpack_tag_ext(1, 1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_ext(1, 2), mpack_tag_ext(1, 1)));
}
static void test_tags_reals(void) {
// types
TEST_TRUE(mpack_tag_float(0.0f).type == mpack_type_float);
TEST_TRUE(mpack_tag_double(0.0).type == mpack_type_double);
TEST_TRUE(mpack_tag_float((float)NAN).type == mpack_type_float);
TEST_TRUE(mpack_tag_double((double)NAN).type == mpack_type_double);
// float comparisons
TEST_TRUE(true == mpack_tag_equal(mpack_tag_float(0), mpack_tag_float(0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_float(1), mpack_tag_float(1)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_float(MPACK_INFINITY), mpack_tag_float(MPACK_INFINITY)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_float(-MPACK_INFINITY), mpack_tag_float(-MPACK_INFINITY)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_float(0), mpack_tag_float(1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_float(1), mpack_tag_float(MPACK_INFINITY)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_float(MPACK_INFINITY), mpack_tag_float(-MPACK_INFINITY)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_float(0), mpack_tag_float(NAN)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_float(MPACK_INFINITY), mpack_tag_float(NAN)));
// double comparisons
TEST_TRUE(true == mpack_tag_equal(mpack_tag_double(0), mpack_tag_double(0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_double(1), mpack_tag_double(1)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_double(MPACK_INFINITY), mpack_tag_double(MPACK_INFINITY)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_double(-MPACK_INFINITY), mpack_tag_double(-MPACK_INFINITY)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_double(0), mpack_tag_double(1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_double(1), mpack_tag_double(MPACK_INFINITY)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_double(MPACK_INFINITY), mpack_tag_double(-MPACK_INFINITY)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_double(0), mpack_tag_double(NAN)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_double(MPACK_INFINITY), mpack_tag_double(NAN)));
// float/double comparisons
TEST_TRUE(false == mpack_tag_equal(mpack_tag_double(0), mpack_tag_float(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_double(1), mpack_tag_float(1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_double(MPACK_INFINITY), mpack_tag_float(MPACK_INFINITY)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_double(-MPACK_INFINITY), mpack_tag_float(-MPACK_INFINITY)));
// here we're comparing NaNs and we expect true. this is because we compare
// floats bit-for-bit, not using operator==
TEST_TRUE(true == mpack_tag_equal(mpack_tag_float(NAN), mpack_tag_float(NAN)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_double(NAN), mpack_tag_double(NAN)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_float(NAN), mpack_tag_double(NAN)));
}
static void test_tags_compound() {
TEST_TRUE(mpack_tag_array(0).type == mpack_type_array);
TEST_TRUE(mpack_tag_map(0).type == mpack_type_map);
TEST_TRUE(mpack_tag_str(0).type == mpack_type_str);
TEST_TRUE(mpack_tag_bin(0).type == mpack_type_bin);
TEST_TRUE(mpack_tag_ext(0, 0).type == mpack_type_ext);
TEST_TRUE(true == mpack_tag_equal(mpack_tag_array(0), mpack_tag_array(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_array(0), mpack_tag_array(1)));
TEST_TRUE(0 == mpack_tag_cmp(mpack_tag_array(0), mpack_tag_array(0)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_array(0), mpack_tag_array(1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_array(1), mpack_tag_array(0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_map(0), mpack_tag_map(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_map(0), mpack_tag_map(1)));
TEST_TRUE(0 == mpack_tag_cmp(mpack_tag_map(0), mpack_tag_map(0)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_map(0), mpack_tag_map(1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_map(1), mpack_tag_map(0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_str(0), mpack_tag_str(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_str(0), mpack_tag_str(1)));
TEST_TRUE(0 == mpack_tag_cmp(mpack_tag_str(0), mpack_tag_str(0)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_str(0), mpack_tag_str(1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_str(1), mpack_tag_str(0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_bin(0), mpack_tag_bin(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_bin(0), mpack_tag_bin(1)));
TEST_TRUE(0 == mpack_tag_cmp(mpack_tag_bin(0), mpack_tag_bin(0)));
TEST_TRUE(-1 == mpack_tag_cmp(mpack_tag_bin(0), mpack_tag_bin(1)));
TEST_TRUE(1 == mpack_tag_cmp(mpack_tag_bin(1), mpack_tag_bin(0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_ext(0, 0), mpack_tag_ext(0, 0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_ext(0, 1), mpack_tag_ext(0, 1)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_ext(127, 0), mpack_tag_ext(127, 0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_ext(127, 1), mpack_tag_ext(127, 1)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_ext(-128, 0), mpack_tag_ext(-128, 0)));
TEST_TRUE(true == mpack_tag_equal(mpack_tag_ext(-128, 1), mpack_tag_ext(-128, 1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_ext(0, 0), mpack_tag_ext(127, 0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_ext(0, 0), mpack_tag_ext(-128, 0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_ext(0, 0), mpack_tag_ext(0, 1)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_array(0), mpack_tag_map(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_array(0), mpack_tag_str(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_array(0), mpack_tag_bin(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_array(0), mpack_tag_ext(0, 0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_map(0), mpack_tag_array(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_map(0), mpack_tag_str(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_map(0), mpack_tag_bin(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_map(0), mpack_tag_ext(0, 0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_str(0), mpack_tag_array(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_str(0), mpack_tag_map(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_str(0), mpack_tag_bin(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_str(0), mpack_tag_ext(0, 0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_bin(0), mpack_tag_array(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_bin(0), mpack_tag_map(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_bin(0), mpack_tag_str(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_bin(0), mpack_tag_ext(0, 0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_ext(0, 0), mpack_tag_array(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_ext(0, 0), mpack_tag_map(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_ext(0, 0), mpack_tag_str(0)));
TEST_TRUE(false == mpack_tag_equal(mpack_tag_ext(0, 0), mpack_tag_bin(0)));
}
static void test_string(const char* str, const char* content) {
#if MPACK_STRINGS
// with strings enabled, the string should contain the expected content
TEST_TRUE(strstr(str, content) != NULL, "string \"%s\" does not contain \"%s\"", str, content);
#else
// strings should be blank when disabled
MPACK_UNUSED(content);
TEST_TRUE(strcmp(str, "") == 0, "string is not empty: %s", str);
#endif
}
static void test_strings() {
test_string(mpack_error_to_string(mpack_ok), "ok");
#define TEST_ERROR_STRING(error) test_string(mpack_error_to_string(mpack_error_##error), #error)
TEST_ERROR_STRING(io);
TEST_ERROR_STRING(invalid);
TEST_ERROR_STRING(type);
TEST_ERROR_STRING(too_big);
TEST_ERROR_STRING(memory);
TEST_ERROR_STRING(bug);
TEST_ERROR_STRING(data);
#undef TEST_ERROR_STRING
#define TEST_ERROR_TYPE(type) test_string(mpack_type_to_string(mpack_type_##type), #type)
TEST_ERROR_TYPE(nil);
TEST_ERROR_TYPE(bool);
TEST_ERROR_TYPE(float);
TEST_ERROR_TYPE(double);
TEST_ERROR_TYPE(int);
TEST_ERROR_TYPE(uint);
TEST_ERROR_TYPE(str);
TEST_ERROR_TYPE(bin);
TEST_ERROR_TYPE(ext);
TEST_ERROR_TYPE(array);
TEST_ERROR_TYPE(map);
#undef TEST_ERROR_TYPE
// test strings for invalid enum values
// (invalid enum values cause undefined behavior in C++)
#if MPACK_DEBUG && !defined(__cplusplus)
TEST_ASSERT(mpack_error_to_string((mpack_error_t)-1));
TEST_ASSERT(mpack_type_to_string((mpack_type_t)-1));
#endif
}
static void test_utf8_check(void) {
#define EXPAND_STR_ARGS(str) str, sizeof(str) - 1
// ascii
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\x00")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\x7F")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\x00""\x7F")));
// nul
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\x00")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test\x00""test")));
TEST_TRUE(false == mpack_utf8_check_no_null(EXPAND_STR_ARGS("\x00")));
TEST_TRUE(false == mpack_utf8_check_no_null(EXPAND_STR_ARGS("test\x00""test")));
// 2-byte sequences
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xC2\x80")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xDF\xBF")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test\xC2\x80""test")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test\xDF\xBF""test")));
// truncated 2-byte sequences
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xC2")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xDF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xC2")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xDF")));
// 2-byte overlong sequences
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xC0\xBF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xC1\xBF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xC0\xBF""test")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xC1\xBF""test")));
// not continuation bytes
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xC2\x02")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xC2\xC0")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xC2\xE0")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xC2\x02""test")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xC2\xC0""test")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xC2\xE0""test")));
// miscellaneous 2-byte sequences
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xC2\x80\xDF\xBF")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test\xC2\x80""test\xDF\xBF""test")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xC2\x70\xDF\xBF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xC2\x80\xDF\xEF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xC2\x00""test\xDF\xBF""test")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xC2\x80""test\xDF\xEF""test")));
// 3-byte sequences
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xE0\xA0\x80")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xE7\xA0\xBF")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xEF\xBF\xBF")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test\xE0\xA0\x80""test")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test\xE7\xA0\xBF""test")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test\xEF\xBF\xBF""test")));
// truncated 3-byte sequences
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xE0")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xEF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xE7\x80")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xEA\xBF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xE0")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xEA\xBF")));
// 3-byte overlong sequences
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xE0\x80\x80")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xE0\x9F\xFF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xE0\x80\x80""test")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xE0\x9F\xFF""test")));
// not continuation bytes
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xE0\x00\x80")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xE0\xF0\x80")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xE0\x80\x00")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xE0\x80\xF0")));
// surrogates
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xED\x9F\xBF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xED\xA0\x80")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xED\xBF\xBF")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xEE\x80\x80")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xED\x9F\xBF\xEE\x80\x80")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xED\x9F\xBF\xED\xBF\xBF\xEE\x80\x80")));
// miscellaneous 3-byte sequences
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xE0\xA0\x80\xE7\xA0\xBF\xEF\xBF\xBF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xE0\xA0\x80\xE7\x00\xBF\xEF\xBF\xBF")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xE0\xA0\x80\xE7\xA0\xBF\xEF\xBF\x7F")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test\xE0\xA0\x80""test\xE7\xA0\xBF""test\xEF\xBF\xBF""test")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xE0\xA0\x80""test\xE7\xD0\xBF""test\xEF\xBF\xBF""test")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xE0\xA0\x80""test\xE7\xA0\xBF""test\xEF\x1F\xBF""test")));
// 4-byte sequences
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xF0\x90\x80\x80"))); // U+10000
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xF4\x8F\xBF\xBF"))); // limit
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("\xF0\x90\x80\x80\xF4\x8F\xBF\xBF")));
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test\xF0\x90\x80\x80""test"))); // U+10000
TEST_TRUE(true == mpack_utf8_check(EXPAND_STR_ARGS("test\xF4\x8F\xBF\xBF""test"))); // limit
// truncated 4-byte sequences
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xF0\x90")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xF1\x90\xB0")));
// 4-byte overlong sequences
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xF0\x80\x80\x80"))); // NUL
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xF0\x8F\xBF\xBF"))); // U+9999 (overlong)
// not continuation bytes
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xF0\x60\x80\x80")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xF1\x90\xD0\x80")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xF2\x90\x80\xF0")));
// unicode limit
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xF4\x90\x80\x80"))); // U+110000 (out of bounds)
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xF6\x80\x80\x80")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("\xF7\x80\x80\x80")));
// 5- and 6-byte sequences
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xF8\x80\x80\x80\x80""test")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xFB\x80\x80\x80\x80""test")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xFD\x80\x80\x80\x80\x80""test")));
// other invalid bytes
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xC0""testtesttest")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xC1""testtesttest")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xF5""testtesttest")));
TEST_TRUE(false == mpack_utf8_check(EXPAND_STR_ARGS("test\xFF""testtesttest")));
}
void test_common() {
test_tags_special();
test_tags_simple();
test_tags_reals();
test_tags_compound();
test_strings();
test_utf8_check();
}