src.dualinventive.com/dinet/libdi-php/libdi/3rdparty/mpack/test/test-write.c

1047 lines
47 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.
*/
#include "test-write.h"
#include "test.h"
#if MPACK_WRITER
mpack_error_t test_write_error = mpack_ok;
void test_write_error_handler(mpack_writer_t* writer, mpack_error_t error) {
TEST_TRUE(test_write_error == mpack_ok, "error handler was called multiple times");
TEST_TRUE(error != mpack_ok, "error handler was called with mpack_ok");
TEST_TRUE(mpack_writer_error(writer) == error, "writer error does not match given error");
test_write_error = error;
}
// writes ints using the auto int()/uint() functions
static void test_write_simple_auto_int() {
char buf[4096];
// positive fixnums
TEST_SIMPLE_WRITE("\x00", mpack_write_uint(&writer, 0));
TEST_SIMPLE_WRITE("\x01", mpack_write_uint(&writer, 1));
TEST_SIMPLE_WRITE("\x02", mpack_write_uint(&writer, 2));
TEST_SIMPLE_WRITE("\x0f", mpack_write_uint(&writer, 0x0f));
TEST_SIMPLE_WRITE("\x10", mpack_write_uint(&writer, 0x10));
TEST_SIMPLE_WRITE("\x7e", mpack_write_uint(&writer, 0x7e));
TEST_SIMPLE_WRITE("\x7f", mpack_write_uint(&writer, 0x7f));
// positive fixnums with signed int functions
TEST_SIMPLE_WRITE("\x00", mpack_write_int(&writer, 0));
TEST_SIMPLE_WRITE("\x01", mpack_write_int(&writer, 1));
TEST_SIMPLE_WRITE("\x02", mpack_write_int(&writer, 2));
TEST_SIMPLE_WRITE("\x0f", mpack_write_int(&writer, 0x0f));
TEST_SIMPLE_WRITE("\x10", mpack_write_int(&writer, 0x10));
TEST_SIMPLE_WRITE("\x7e", mpack_write_int(&writer, 0x7e));
TEST_SIMPLE_WRITE("\x7f", mpack_write_int(&writer, 0x7f));
// negative fixnums
TEST_SIMPLE_WRITE("\xff", mpack_write_int(&writer, -1));
TEST_SIMPLE_WRITE("\xfe", mpack_write_int(&writer, -2));
TEST_SIMPLE_WRITE("\xf0", mpack_write_int(&writer, -16));
TEST_SIMPLE_WRITE("\xe1", mpack_write_int(&writer, -31));
TEST_SIMPLE_WRITE("\xe0", mpack_write_int(&writer, -32));
// uints
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_uint(&writer, 0x80));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_uint(&writer, 0xff));
TEST_SIMPLE_WRITE("\xcd\x01\x00", mpack_write_uint(&writer, 0x100));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write_uint(&writer, 0xffff));
TEST_SIMPLE_WRITE("\xce\x00\x01\x00\x00", mpack_write_uint(&writer, 0x10000));
TEST_SIMPLE_WRITE("\xce\xff\xff\xff\xff", mpack_write_uint(&writer, 0xffffffff));
TEST_SIMPLE_WRITE("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", mpack_write_uint(&writer, UINT64_C(0x100000000)));
TEST_SIMPLE_WRITE("\xcf\xff\xff\xff\xff\xff\xff\xff\xff", mpack_write_uint(&writer, UINT64_C(0xffffffffffffffff)));
// positive ints with signed value
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_int(&writer, 0x80));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_int(&writer, 0xff));
TEST_SIMPLE_WRITE("\xcd\x01\x00", mpack_write_int(&writer, 0x100));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write_int(&writer, 0xffff));
TEST_SIMPLE_WRITE("\xce\x00\x01\x00\x00", mpack_write_int(&writer, 0x10000));
TEST_SIMPLE_WRITE("\xce\xff\xff\xff\xff", mpack_write_int(&writer, INT64_C(0xffffffff)));
TEST_SIMPLE_WRITE("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", mpack_write_int(&writer, INT64_C(0x100000000)));
TEST_SIMPLE_WRITE("\xcf\x7f\xff\xff\xff\xff\xff\xff\xff", mpack_write_int(&writer, INT64_C(0x7fffffffffffffff)));
// ints
TEST_SIMPLE_WRITE("\xd0\xdf", mpack_write_int(&writer, -33));
TEST_SIMPLE_WRITE("\xd0\x80", mpack_write_int(&writer, -128));
TEST_SIMPLE_WRITE("\xd1\xff\x7f", mpack_write_int(&writer, -129));
TEST_SIMPLE_WRITE("\xd1\x80\x00", mpack_write_int(&writer, -32768));
TEST_SIMPLE_WRITE("\xd2\xff\xff\x7f\xff", mpack_write_int(&writer, -32769));
// 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_SIMPLE_WRITE("\xd2\x80\x00\x00\x00", mpack_write_int(&writer, INT64_C(-2147483648)));
TEST_SIMPLE_WRITE("\xd3\xff\xff\xff\xff\x7f\xff\xff\xff", mpack_write_int(&writer, INT64_C(-2147483649)));
TEST_SIMPLE_WRITE("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", mpack_write_int(&writer, INT64_MIN));
}
// writes ints using the sized iXX()/uXX() functions
static void test_write_simple_size_int_fixnums() {
char buf[4096];
// positive fixnums
TEST_SIMPLE_WRITE("\x00", mpack_write_u8(&writer, 0));
TEST_SIMPLE_WRITE("\x01", mpack_write_u8(&writer, 1));
TEST_SIMPLE_WRITE("\x02", mpack_write_u8(&writer, 2));
TEST_SIMPLE_WRITE("\x0f", mpack_write_u8(&writer, 0x0f));
TEST_SIMPLE_WRITE("\x10", mpack_write_u8(&writer, 0x10));
TEST_SIMPLE_WRITE("\x7f", mpack_write_u8(&writer, 0x7f));
TEST_SIMPLE_WRITE("\x00", mpack_write_u16(&writer, 0));
TEST_SIMPLE_WRITE("\x01", mpack_write_u16(&writer, 1));
TEST_SIMPLE_WRITE("\x02", mpack_write_u16(&writer, 2));
TEST_SIMPLE_WRITE("\x0f", mpack_write_u16(&writer, 0x0f));
TEST_SIMPLE_WRITE("\x10", mpack_write_u16(&writer, 0x10));
TEST_SIMPLE_WRITE("\x7f", mpack_write_u16(&writer, 0x7f));
TEST_SIMPLE_WRITE("\x00", mpack_write_u32(&writer, 0));
TEST_SIMPLE_WRITE("\x01", mpack_write_u32(&writer, 1));
TEST_SIMPLE_WRITE("\x02", mpack_write_u32(&writer, 2));
TEST_SIMPLE_WRITE("\x0f", mpack_write_u32(&writer, 0x0f));
TEST_SIMPLE_WRITE("\x10", mpack_write_u32(&writer, 0x10));
TEST_SIMPLE_WRITE("\x7f", mpack_write_u32(&writer, 0x7f));
TEST_SIMPLE_WRITE("\x00", mpack_write_u64(&writer, 0));
TEST_SIMPLE_WRITE("\x01", mpack_write_u64(&writer, 1));
TEST_SIMPLE_WRITE("\x02", mpack_write_u64(&writer, 2));
TEST_SIMPLE_WRITE("\x0f", mpack_write_u64(&writer, 0x0f));
TEST_SIMPLE_WRITE("\x10", mpack_write_u64(&writer, 0x10));
TEST_SIMPLE_WRITE("\x7f", mpack_write_u64(&writer, 0x7f));
// positive fixnums with signed int functions
TEST_SIMPLE_WRITE("\x00", mpack_write_i8(&writer, 0));
TEST_SIMPLE_WRITE("\x01", mpack_write_i8(&writer, 1));
TEST_SIMPLE_WRITE("\x02", mpack_write_i8(&writer, 2));
TEST_SIMPLE_WRITE("\x0f", mpack_write_i8(&writer, 0x0f));
TEST_SIMPLE_WRITE("\x10", mpack_write_i8(&writer, 0x10));
TEST_SIMPLE_WRITE("\x7f", mpack_write_i8(&writer, 0x7f));
TEST_SIMPLE_WRITE("\x00", mpack_write_i16(&writer, 0));
TEST_SIMPLE_WRITE("\x01", mpack_write_i16(&writer, 1));
TEST_SIMPLE_WRITE("\x02", mpack_write_i16(&writer, 2));
TEST_SIMPLE_WRITE("\x0f", mpack_write_i16(&writer, 0x0f));
TEST_SIMPLE_WRITE("\x10", mpack_write_i16(&writer, 0x10));
TEST_SIMPLE_WRITE("\x7f", mpack_write_i16(&writer, 0x7f));
TEST_SIMPLE_WRITE("\x00", mpack_write_i32(&writer, 0));
TEST_SIMPLE_WRITE("\x01", mpack_write_i32(&writer, 1));
TEST_SIMPLE_WRITE("\x02", mpack_write_i32(&writer, 2));
TEST_SIMPLE_WRITE("\x0f", mpack_write_i32(&writer, 0x0f));
TEST_SIMPLE_WRITE("\x10", mpack_write_i32(&writer, 0x10));
TEST_SIMPLE_WRITE("\x7f", mpack_write_i32(&writer, 0x7f));
TEST_SIMPLE_WRITE("\x00", mpack_write_i64(&writer, 0));
TEST_SIMPLE_WRITE("\x01", mpack_write_i64(&writer, 1));
TEST_SIMPLE_WRITE("\x02", mpack_write_i64(&writer, 2));
TEST_SIMPLE_WRITE("\x0f", mpack_write_i64(&writer, 0x0f));
TEST_SIMPLE_WRITE("\x10", mpack_write_i64(&writer, 0x10));
TEST_SIMPLE_WRITE("\x7f", mpack_write_i64(&writer, 0x7f));
// negative fixnums
TEST_SIMPLE_WRITE("\xff", mpack_write_i8(&writer, -1));
TEST_SIMPLE_WRITE("\xfe", mpack_write_i8(&writer, -2));
TEST_SIMPLE_WRITE("\xf0", mpack_write_i8(&writer, -16));
TEST_SIMPLE_WRITE("\xe0", mpack_write_i8(&writer, -32));
TEST_SIMPLE_WRITE("\xff", mpack_write_i16(&writer, -1));
TEST_SIMPLE_WRITE("\xfe", mpack_write_i16(&writer, -2));
TEST_SIMPLE_WRITE("\xf0", mpack_write_i16(&writer, -16));
TEST_SIMPLE_WRITE("\xe0", mpack_write_i16(&writer, -32));
TEST_SIMPLE_WRITE("\xff", mpack_write_i32(&writer, -1));
TEST_SIMPLE_WRITE("\xfe", mpack_write_i32(&writer, -2));
TEST_SIMPLE_WRITE("\xf0", mpack_write_i32(&writer, -16));
TEST_SIMPLE_WRITE("\xe0", mpack_write_i32(&writer, -32));
TEST_SIMPLE_WRITE("\xff", mpack_write_i64(&writer, -1));
TEST_SIMPLE_WRITE("\xfe", mpack_write_i64(&writer, -2));
TEST_SIMPLE_WRITE("\xf0", mpack_write_i64(&writer, -16));
TEST_SIMPLE_WRITE("\xe0", mpack_write_i64(&writer, -32));
}
static void test_write_simple_size_int() {
char buf[4096];
// uints
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_u8(&writer, 0x80));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_u8(&writer, 0xff));
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_u16(&writer, 0x80));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_u16(&writer, 0xff));
TEST_SIMPLE_WRITE("\xcd\x01\x00", mpack_write_u16(&writer, 0x100));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write_u16(&writer, 0xffff));
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_u32(&writer, 0x80));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_u32(&writer, 0xff));
TEST_SIMPLE_WRITE("\xcd\x01\x00", mpack_write_u32(&writer, 0x100));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write_u32(&writer, 0xffff));
TEST_SIMPLE_WRITE("\xce\x00\x01\x00\x00", mpack_write_u32(&writer, 0x10000));
TEST_SIMPLE_WRITE("\xce\xff\xff\xff\xff", mpack_write_u32(&writer, 0xffffffff));
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_u64(&writer, 0x80));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_u64(&writer, 0xff));
TEST_SIMPLE_WRITE("\xcd\x01\x00", mpack_write_u64(&writer, 0x100));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write_u64(&writer, 0xffff));
TEST_SIMPLE_WRITE("\xce\x00\x01\x00\x00", mpack_write_u64(&writer, 0x10000));
TEST_SIMPLE_WRITE("\xce\xff\xff\xff\xff", mpack_write_u64(&writer, 0xffffffff));
TEST_SIMPLE_WRITE("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", mpack_write_u64(&writer, UINT64_C(0x100000000)));
TEST_SIMPLE_WRITE("\xcf\xff\xff\xff\xff\xff\xff\xff\xff", mpack_write_u64(&writer, UINT64_C(0xffffffffffffffff)));
// positive ints with signed value
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_i16(&writer, 0x80));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_i16(&writer, 0xff));
TEST_SIMPLE_WRITE("\xcd\x01\x00", mpack_write_i16(&writer, 0x100));
TEST_SIMPLE_WRITE("\xcd\x7f\xff", mpack_write_i16(&writer, 0x7fff));
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_i32(&writer, 0x80));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_i32(&writer, 0xff));
TEST_SIMPLE_WRITE("\xcd\x01\x00", mpack_write_i32(&writer, 0x100));
TEST_SIMPLE_WRITE("\xcd\x7f\xff", mpack_write_i32(&writer, 0x7fff));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write_i32(&writer, 0xffff));
TEST_SIMPLE_WRITE("\xce\x00\x01\x00\x00", mpack_write_i32(&writer, 0x10000));
TEST_SIMPLE_WRITE("\xce\x7f\xff\xff\xff", mpack_write_i32(&writer, 0x7fffffff));
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_i64(&writer, 0x80));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_i64(&writer, 0xff));
TEST_SIMPLE_WRITE("\xcd\x01\x00", mpack_write_i64(&writer, 0x100));
TEST_SIMPLE_WRITE("\xcd\x7f\xff", mpack_write_i64(&writer, 0x7fff));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write_i64(&writer, 0xffff));
TEST_SIMPLE_WRITE("\xce\x00\x01\x00\x00", mpack_write_i64(&writer, 0x10000));
TEST_SIMPLE_WRITE("\xce\x7f\xff\xff\xff", mpack_write_i64(&writer, 0x7fffffff));
TEST_SIMPLE_WRITE("\xce\xff\xff\xff\xff", mpack_write_i64(&writer, INT64_C(0xffffffff)));
TEST_SIMPLE_WRITE("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", mpack_write_i64(&writer, UINT64_C(0x100000000)));
TEST_SIMPLE_WRITE("\xcf\x7f\xff\xff\xff\xff\xff\xff\xff", mpack_write_i64(&writer, UINT64_C(0x7fffffffffffffff)));
// negative ints
TEST_SIMPLE_WRITE("\xd0\xdf", mpack_write_i8(&writer, -33));
TEST_SIMPLE_WRITE("\xd0\x80", mpack_write_i8(&writer, -128));
TEST_SIMPLE_WRITE("\xd0\xdf", mpack_write_i16(&writer, -33));
TEST_SIMPLE_WRITE("\xd0\x80", mpack_write_i16(&writer, -128));
TEST_SIMPLE_WRITE("\xd1\xff\x7f", mpack_write_i16(&writer, -129));
TEST_SIMPLE_WRITE("\xd1\x80\x00", mpack_write_i16(&writer, -32768));
TEST_SIMPLE_WRITE("\xd0\xdf", mpack_write_i32(&writer, -33));
TEST_SIMPLE_WRITE("\xd0\x80", mpack_write_i32(&writer, -128));
TEST_SIMPLE_WRITE("\xd1\xff\x7f", mpack_write_i32(&writer, -129));
TEST_SIMPLE_WRITE("\xd1\x80\x00", mpack_write_i32(&writer, -32768));
TEST_SIMPLE_WRITE("\xd2\xff\xff\x7f\xff", mpack_write_i32(&writer, -32769));
// 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_SIMPLE_WRITE("\xd2\x80\x00\x00\x00", mpack_write_i32(&writer, INT64_C(-2147483648)));
TEST_SIMPLE_WRITE("\xd2\x80\x00\x00\x00", mpack_write_i64(&writer, INT64_C(-2147483648)));
TEST_SIMPLE_WRITE("\xd0\xdf", mpack_write_i64(&writer, -33));
TEST_SIMPLE_WRITE("\xd0\x80", mpack_write_i64(&writer, -128));
TEST_SIMPLE_WRITE("\xd1\xff\x7f", mpack_write_i64(&writer, -129));
TEST_SIMPLE_WRITE("\xd1\x80\x00", mpack_write_i64(&writer, -32768));
TEST_SIMPLE_WRITE("\xd2\xff\xff\x7f\xff", mpack_write_i64(&writer, -32769));
TEST_SIMPLE_WRITE("\xd3\xff\xff\xff\xff\x7f\xff\xff\xff", mpack_write_i64(&writer, INT64_C(-2147483649)));
TEST_SIMPLE_WRITE("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", mpack_write_i64(&writer, INT64_MIN));
}
// writes ints using the dynamic tag writer function
static void test_write_simple_tag_int() {
char buf[4096];
// positive fixnums
TEST_SIMPLE_WRITE("\x00", mpack_write_tag(&writer, mpack_tag_uint(0)));
TEST_SIMPLE_WRITE("\x01", mpack_write_tag(&writer, mpack_tag_uint(1)));
TEST_SIMPLE_WRITE("\x02", mpack_write_tag(&writer, mpack_tag_uint(2)));
TEST_SIMPLE_WRITE("\x0f", mpack_write_tag(&writer, mpack_tag_uint(0x0f)));
TEST_SIMPLE_WRITE("\x10", mpack_write_tag(&writer, mpack_tag_uint(0x10)));
TEST_SIMPLE_WRITE("\x7f", mpack_write_tag(&writer, mpack_tag_uint(0x7f)));
// positive fixnums with signed value
TEST_SIMPLE_WRITE("\x00", mpack_write_tag(&writer, mpack_tag_int(0)));
TEST_SIMPLE_WRITE("\x01", mpack_write_tag(&writer, mpack_tag_int(1)));
TEST_SIMPLE_WRITE("\x02", mpack_write_tag(&writer, mpack_tag_int(2)));
TEST_SIMPLE_WRITE("\x0f", mpack_write_tag(&writer, mpack_tag_int(0x0f)));
TEST_SIMPLE_WRITE("\x10", mpack_write_tag(&writer, mpack_tag_int(0x10)));
TEST_SIMPLE_WRITE("\x7f", mpack_write_tag(&writer, mpack_tag_int(0x7f)));
// negative fixnums
TEST_SIMPLE_WRITE("\xff", mpack_write_tag(&writer, mpack_tag_int(-1)));
TEST_SIMPLE_WRITE("\xfe", mpack_write_tag(&writer, mpack_tag_int(-2)));
TEST_SIMPLE_WRITE("\xf0", mpack_write_tag(&writer, mpack_tag_int(-16)));
TEST_SIMPLE_WRITE("\xe0", mpack_write_tag(&writer, mpack_tag_int(-32)));
// uints
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_tag(&writer, mpack_tag_uint(0x80)));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_tag(&writer, mpack_tag_uint(0xff)));
TEST_SIMPLE_WRITE("\xcd\x01\x00", mpack_write_tag(&writer, mpack_tag_uint(0x100)));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write_tag(&writer, mpack_tag_uint(0xffff)));
TEST_SIMPLE_WRITE("\xce\x00\x01\x00\x00", mpack_write_tag(&writer, mpack_tag_uint(0x10000)));
TEST_SIMPLE_WRITE("\xce\xff\xff\xff\xff", mpack_write_tag(&writer, mpack_tag_uint(0xffffffff)));
TEST_SIMPLE_WRITE("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", mpack_write_tag(&writer, mpack_tag_uint(UINT64_C(0x100000000))));
TEST_SIMPLE_WRITE("\xcf\xff\xff\xff\xff\xff\xff\xff\xff", mpack_write_tag(&writer, mpack_tag_uint(UINT64_C(0xffffffffffffffff))));
// positive ints with signed value
TEST_SIMPLE_WRITE("\xcc\x80", mpack_write_tag(&writer, mpack_tag_int(0x80)));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write_tag(&writer, mpack_tag_int(0xff)));
TEST_SIMPLE_WRITE("\xcd\x01\x00", mpack_write_tag(&writer, mpack_tag_int(0x100)));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write_tag(&writer, mpack_tag_int(0xffff)));
TEST_SIMPLE_WRITE("\xce\x00\x01\x00\x00", mpack_write_tag(&writer, mpack_tag_int(0x10000)));
TEST_SIMPLE_WRITE("\xce\xff\xff\xff\xff", mpack_write_tag(&writer, mpack_tag_int(INT64_C(0xffffffff))));
TEST_SIMPLE_WRITE("\xcf\x00\x00\x00\x01\x00\x00\x00\x00", mpack_write_tag(&writer, mpack_tag_int(INT64_C(0x100000000))));
TEST_SIMPLE_WRITE("\xcf\x7f\xff\xff\xff\xff\xff\xff\xff", mpack_write_tag(&writer, mpack_tag_int(INT64_C(0x7fffffffffffffff))));
// ints
TEST_SIMPLE_WRITE("\xd0\xdf", mpack_write_tag(&writer, mpack_tag_int(-33)));
TEST_SIMPLE_WRITE("\xd0\x80", mpack_write_tag(&writer, mpack_tag_int(-128)));
TEST_SIMPLE_WRITE("\xd1\xff\x7f", mpack_write_tag(&writer, mpack_tag_int(-129)));
TEST_SIMPLE_WRITE("\xd1\x80\x00", mpack_write_tag(&writer, mpack_tag_int(-32768)));
TEST_SIMPLE_WRITE("\xd2\xff\xff\x7f\xff", mpack_write_tag(&writer, mpack_tag_int(-32769)));
// 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_SIMPLE_WRITE("\xd2\x80\x00\x00\x00", mpack_write_tag(&writer, mpack_tag_int(INT64_C(-2147483648))));
TEST_SIMPLE_WRITE("\xd3\xff\xff\xff\xff\x7f\xff\xff\xff", mpack_write_tag(&writer, mpack_tag_int(INT64_C(-2147483649))));
TEST_SIMPLE_WRITE("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", mpack_write_tag(&writer, mpack_tag_int(INT64_MIN)));
}
static void test_write_simple_misc() {
char buf[4096];
TEST_SIMPLE_WRITE("\xc0", mpack_write_nil(&writer));
TEST_SIMPLE_WRITE("\xc2", mpack_write_bool(&writer, false));
TEST_SIMPLE_WRITE("\xc3", mpack_write_bool(&writer, true));
TEST_SIMPLE_WRITE("\xc2", mpack_write_false(&writer));
TEST_SIMPLE_WRITE("\xc3", mpack_write_true(&writer));
// we just test a few floats for now. this could certainly be extended to
// test more values like subnormal floats, infinities, etc.
TEST_SIMPLE_WRITE("\xca\x00\x00\x00\x00", mpack_write_float(&writer, 0.0f));
TEST_SIMPLE_WRITE("\xca\x40\x2d\xf3\xb6", mpack_write_float(&writer, 2.718f));
TEST_SIMPLE_WRITE("\xca\xc0\x2d\xf3\xb6", mpack_write_float(&writer, -2.718f));
TEST_SIMPLE_WRITE("\xcb\x00\x00\x00\x00\x00\x00\x00\x00", mpack_write_double(&writer, 0.0));
TEST_SIMPLE_WRITE("\xcb\x40\x09\x21\xfb\x53\xc8\xd4\xf1", mpack_write_double(&writer, 3.14159265));
TEST_SIMPLE_WRITE("\xcb\xc0\x09\x21\xfb\x53\xc8\xd4\xf1", mpack_write_double(&writer, -3.14159265));
TEST_SIMPLE_WRITE("\xde\xad\xbe\xef", mpack_write_object_bytes(&writer, "\xde\xad\xbe\xef", 4));
}
#ifdef MPACK_MALLOC
static void test_write_tag_tracking() {
char* buf;
size_t size;
mpack_writer_t writer;
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_array(&writer, 8);
mpack_write_tag(&writer, mpack_tag_nil());
mpack_write_tag(&writer, mpack_tag_bool(true));
mpack_write_tag(&writer, mpack_tag_bool(false));
mpack_write_tag(&writer, mpack_tag_uint(4));
mpack_write_tag(&writer, mpack_tag_int(-3));
mpack_write_tag(&writer, mpack_tag_str(0));
mpack_finish_str(&writer);
mpack_write_tag(&writer, mpack_tag_bin(0));
mpack_finish_bin(&writer);
mpack_write_tag(&writer, mpack_tag_array(1));
mpack_write_tag(&writer, mpack_tag_nil());
mpack_finish_array(&writer);
mpack_finish_array(&writer);
TEST_DESTROY_MATCH("\x98\xC0\xC3\xC2\x04\xFD\xA0\xC4\x00\x91\xC0");
}
static void test_write_basic_structures() {
char* buf;
size_t size;
mpack_writer_t writer;
// we use a mix of int writers below to test their tracking.
// []
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_array(&writer, 0);
mpack_finish_array(&writer);
TEST_DESTROY_MATCH("\x90");
// [nil]
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_array(&writer, 1);
mpack_write_nil(&writer);
mpack_finish_array(&writer);
TEST_DESTROY_MATCH("\x91\xc0");
// range(15)
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_array(&writer, 15);
for (int i = 0; i < 15; ++i)
mpack_write_i32(&writer, i);
mpack_finish_array(&writer);
TEST_DESTROY_MATCH(
"\x9f\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
);
// range(16) (larger than infix)
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_array(&writer, 16);
for (int i = 0; i < 16; ++i)
mpack_write_u32(&writer, (uint32_t)i);
mpack_finish_array(&writer);
TEST_DESTROY_MATCH(
"\xdc\x00\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c"
"\x0d\x0e\x0f"
);
// UINT16_MAX nils
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_array(&writer, UINT16_MAX);
for (int i = 0; i < UINT16_MAX; ++i)
mpack_write_nil(&writer);
mpack_finish_array(&writer);
{
const char prefix[] = "\xdc\xff\xff";
TEST_WRITER_DESTROY_NOERROR(&writer);
TEST_TRUE(memcmp(prefix, buf, sizeof(prefix)-1) == 0, "array prefix is incorrect");
TEST_TRUE(size == UINT16_MAX + sizeof(prefix)-1);
}
if (buf)
MPACK_FREE(buf);
// UINT16_MAX+1 nils (largest category)
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_array(&writer, UINT16_MAX+1);
for (int i = 0; i < UINT16_MAX+1; ++i)
mpack_write_nil(&writer);
mpack_finish_array(&writer);
{
const char prefix[] = "\xdd\x00\x01\x00\x00";
TEST_WRITER_DESTROY_NOERROR(&writer);
TEST_TRUE(memcmp(prefix, buf, sizeof(prefix)-1) == 0, "array prefix is incorrect");
TEST_TRUE(size == UINT16_MAX+1 + sizeof(prefix)-1);
}
if (buf)
MPACK_FREE(buf);
// {}
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_map(&writer, 0);
mpack_finish_map(&writer);
TEST_DESTROY_MATCH("\x80");
// {nil:nil}
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_map(&writer, 1);
mpack_write_nil(&writer);
mpack_write_nil(&writer);
mpack_finish_map(&writer);
TEST_DESTROY_MATCH("\x81\xc0\xc0");
// {0:0,1:1}
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_map(&writer, 2);
mpack_write_i8(&writer, 0);
mpack_write_i16(&writer, 0);
mpack_write_u8(&writer, 1);
mpack_write_u16(&writer, 1);
mpack_finish_map(&writer);
TEST_DESTROY_MATCH("\x82\x00\x00\x01\x01");
// {0:1, 2:3, ..., 28:29}
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_map(&writer, 15);
for (int i = 0; i < 30; ++i)
mpack_write_i8(&writer, (int8_t)i);
mpack_finish_map(&writer);
TEST_DESTROY_MATCH(
"\x8f\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
"\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"
);
// {0:1, 2:3, ..., 28:29, 30:31} (larger than infix)
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_map(&writer, 16);
for (int i = 0; i < 32; ++i)
mpack_write_int(&writer, i);
mpack_finish_map(&writer);
TEST_DESTROY_MATCH(
"\xde\x00\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c"
"\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c"
"\x1d\x1e\x1f"
);
// UINT16_MAX nil:nils
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_map(&writer, UINT16_MAX);
for (int i = 0; i < UINT16_MAX*2; ++i)
mpack_write_nil(&writer);
mpack_finish_map(&writer);
{
const char prefix[] = "\xde\xff\xff";
TEST_WRITER_DESTROY_NOERROR(&writer);
TEST_TRUE(memcmp(prefix, buf, sizeof(prefix)-1) == 0, "map prefix is incorrect");
TEST_TRUE(size == UINT16_MAX*2 + sizeof(prefix)-1);
}
if (buf)
MPACK_FREE(buf);
// UINT16_MAX+1 nil:nils (largest category)
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_map(&writer, UINT16_MAX+1);
for (int i = 0; i < (UINT16_MAX+1)*2; ++i)
mpack_write_nil(&writer);
mpack_finish_map(&writer);
{
const char prefix[] = "\xdf\x00\x01\x00\x00";
TEST_WRITER_DESTROY_NOERROR(&writer);
TEST_TRUE(memcmp(prefix, buf, sizeof(prefix)-1) == 0, "map prefix is incorrect");
TEST_TRUE(size == (UINT16_MAX+1)*2 + sizeof(prefix)-1);
}
if (buf)
MPACK_FREE(buf);
}
static void test_write_small_structure_trees() {
char* buf;
size_t size;
mpack_writer_t writer;
// [[]]
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_array(&writer, 1);
mpack_start_array(&writer, 0);
mpack_finish_array(&writer);
mpack_finish_array(&writer);
TEST_DESTROY_MATCH("\x91\x90");
// [[], [0], [1, 2]]
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_array(&writer, 3);
mpack_start_array(&writer, 0);
mpack_finish_array(&writer);
mpack_start_array(&writer, 1);
mpack_write_int(&writer, 0);
mpack_finish_array(&writer);
mpack_start_array(&writer, 2);
mpack_write_int(&writer, 1);
mpack_write_int(&writer, 2);
mpack_finish_array(&writer);
mpack_finish_array(&writer);
TEST_DESTROY_MATCH("\x93\x90\x91\x00\x92\x01\x02");
// miscellaneous tree of arrays of various small sizes
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_array(&writer, 5);
mpack_start_array(&writer, 0);
mpack_finish_array(&writer);
mpack_start_array(&writer, 1);
mpack_write_nil(&writer);
mpack_finish_array(&writer);
mpack_start_array(&writer, 2);
mpack_start_array(&writer, 0);
mpack_finish_array(&writer);
mpack_start_array(&writer, 1);
mpack_write_nil(&writer);
mpack_finish_array(&writer);
mpack_finish_array(&writer);
mpack_start_array(&writer, 15);
for (int i = 0; i < 15; ++i)
mpack_write_int(&writer, i);
mpack_finish_array(&writer);
mpack_start_array(&writer, 16);
for (int i = 0; i < 16; ++i)
mpack_write_int(&writer, i);
mpack_finish_array(&writer);
mpack_finish_array(&writer);
TEST_DESTROY_MATCH(
"\x95\x90\x91\xc0\x92\x90\x91\xc0\x9f\x00\x01\x02\x03\x04\x05\x06"
"\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\xdc\x00\x10\x00\x01\x02\x03\x04"
"\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
);
// miscellaneous tree of maps of various small sizes
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_map(&writer, 5);
mpack_write_int(&writer, 0);
mpack_start_map(&writer, 0);
mpack_finish_map(&writer);
mpack_write_int(&writer, 1);
mpack_start_map(&writer, 1);
mpack_write_int(&writer, 0);
mpack_write_nil(&writer);
mpack_finish_map(&writer);
mpack_write_int(&writer, 2);
mpack_start_map(&writer, 2);
mpack_write_int(&writer, 0);
mpack_start_map(&writer, 0);
mpack_finish_map(&writer);
mpack_write_int(&writer, 1);
mpack_start_map(&writer, 1);
mpack_write_nil(&writer);
mpack_write_nil(&writer);
mpack_finish_map(&writer);
mpack_finish_map(&writer);
mpack_write_int(&writer, 3);
mpack_start_map(&writer, 15);
for (int i = 0; i < 15; ++i) {
mpack_write_int(&writer, i);
mpack_write_int(&writer, i);
}
mpack_finish_map(&writer);
mpack_write_int(&writer, 4);
mpack_start_map(&writer, 16);
for (int i = 0; i < 16; ++i) {
mpack_write_int(&writer, i);
mpack_write_int(&writer, i);
}
mpack_finish_map(&writer);
mpack_finish_map(&writer);
TEST_DESTROY_MATCH(
"\x85\x00\x80\x01\x81\x00\xc0\x02\x82\x00\x80\x01\x81\xc0\xc0\x03"
"\x8f\x00\x00\x01\x01\x02\x02\x03\x03\x04\x04\x05\x05\x06\x06\x07"
"\x07\x08\x08\x09\x09\x0a\x0a\x0b\x0b\x0c\x0c\x0d\x0d\x0e\x0e\x04"
"\xde\x00\x10\x00\x00\x01\x01\x02\x02\x03\x03\x04\x04\x05\x05\x06"
"\x06\x07\x07\x08\x08\x09\x09\x0a\x0a\x0b\x0b\x0c\x0c\x0d\x0d\x0e"
"\x0e\x0f\x0f"
);
// miscellaneous mix of maps and arrays of various small sizes
mpack_writer_init_growable(&writer, &buf, &size);
mpack_start_map(&writer, 5);
mpack_write_int(&writer, -47);
mpack_start_array(&writer, 1);
mpack_write_nil(&writer);
mpack_finish_array(&writer);
mpack_start_array(&writer, 0);
mpack_finish_array(&writer);
mpack_start_map(&writer, 1);
mpack_write_nil(&writer);
mpack_write_int(&writer, 0);
mpack_finish_map(&writer);
mpack_write_nil(&writer);
mpack_start_map(&writer, 2);
mpack_write_nil(&writer);
mpack_start_array(&writer, 0);
mpack_finish_array(&writer);
mpack_write_int(&writer, 4);
mpack_write_int(&writer, 5);
mpack_finish_map(&writer);
mpack_write_cstr(&writer, "hello");
mpack_start_array(&writer, 3);
mpack_write_cstr_or_nil(&writer, "bonjour");
mpack_write_cstr_or_nil(&writer, NULL);
mpack_write_int(&writer, -1);
mpack_finish_array(&writer);
mpack_start_array(&writer, 1);
mpack_write_int(&writer, 92);
mpack_finish_array(&writer);
mpack_write_int(&writer, 350);
mpack_finish_map(&writer);
TEST_DESTROY_MATCH(
"\x85\xd0\xd1\x91\xc0\x90\x81\xc0\x00\xc0\x82\xc0\x90\x04\x05\xa5"
"\x68\x65\x6c\x6c\x6f\x93\xa7\x62\x6f\x6e\x6a\x6f\x75\x72\xc0\xff"
"\x91\x5c\xcd\x01\x5e"
);
}
static bool test_write_deep_growth(void) {
// test a growable writer with a very deep stack and lots
// of data to see if both the growable buffer and the tracking
// stack grow properly. we allow mpack_error_memory as an
// error (since it will be simulated by the failure system.)
char* buf;
size_t size;
mpack_writer_t writer;
#define TEST_POSSIBLE_FAILURE() do { \
if (mpack_writer_error(&writer) == mpack_error_memory) { \
TEST_TRUE(test_write_error == mpack_error_memory, "writer error handler was not called?"); \
test_write_error = mpack_ok; \
mpack_writer_destroy(&writer); \
TEST_TRUE(buf == NULL); \
return false; \
} \
} while (0)
mpack_writer_init_growable(&writer, &buf, &size);
if (mpack_writer_error(&writer) == mpack_error_memory) {
mpack_writer_destroy(&writer);
TEST_TRUE(buf == NULL);
return false;
}
TEST_TRUE(test_write_error == mpack_ok);
mpack_writer_set_error_handler(&writer, test_write_error_handler);
const int depth = 40;
const int nums = 1000;
for (int i = 0; i < depth; ++i) {
mpack_start_array(&writer, 1);
TEST_POSSIBLE_FAILURE();
}
mpack_start_array(&writer, (uint32_t)nums);
TEST_POSSIBLE_FAILURE();
for (int i = 0; i < nums; ++i) {
mpack_write_u64(&writer, UINT64_MAX);
TEST_POSSIBLE_FAILURE();
}
mpack_finish_array(&writer);
TEST_POSSIBLE_FAILURE();
for (int i = 0; i < depth; ++i) {
mpack_finish_array(&writer);
TEST_POSSIBLE_FAILURE();
}
#undef TEST_POSSIBLE_FAILURE
mpack_error_t error = mpack_writer_destroy(&writer);
if (error == mpack_ok) {
MPACK_FREE(buf);
return true;
}
if (error == mpack_error_memory) {
TEST_TRUE(buf == NULL);
return false;
}
TEST_TRUE(false, "unexpected error state %i (%s)", (int)error, mpack_error_to_string(error));
return true;
}
#endif
#if MPACK_WRITE_TRACKING
static void test_write_tracking() {
char buf[4096];
mpack_writer_t writer;
// cancel
mpack_writer_init(&writer, buf, sizeof(buf));
mpack_start_map(&writer, 5);
mpack_start_array(&writer, 5);
mpack_writer_flag_error(&writer, mpack_error_data);
TEST_WRITER_DESTROY_ERROR(&writer, mpack_error_data);
// finishing type when nothing was open
mpack_writer_init(&writer, buf, sizeof(buf));
TEST_BREAK((mpack_finish_map(&writer), true));
TEST_WRITER_DESTROY_ERROR(&writer, mpack_error_bug);
// closing unfinished type
mpack_writer_init(&writer, buf, sizeof(buf));
mpack_start_array(&writer, 1);
TEST_BREAK((mpack_finish_array(&writer), true));
TEST_WRITER_DESTROY_ERROR(&writer, mpack_error_bug);
// writing elements in a string
mpack_writer_init(&writer, buf, sizeof(buf));
mpack_start_str(&writer, 50);
TEST_BREAK((mpack_write_nil(&writer), true));
TEST_WRITER_DESTROY_ERROR(&writer, mpack_error_bug);
// writing too many elements
mpack_writer_init(&writer, buf, sizeof(buf));
mpack_start_array(&writer, 0);
TEST_BREAK((mpack_write_nil(&writer), true));
TEST_WRITER_DESTROY_ERROR(&writer, mpack_error_bug);
// writing bytes with nothing open
mpack_writer_init(&writer, buf, sizeof(buf));
TEST_BREAK((mpack_write_bytes(&writer, "test", 4), true));
TEST_WRITER_DESTROY_ERROR(&writer, mpack_error_bug);
// writing bytes in an array
mpack_writer_init(&writer, buf, sizeof(buf));
mpack_start_array(&writer, 50);
TEST_BREAK((mpack_write_bytes(&writer, "test", 4), true));
TEST_WRITER_DESTROY_ERROR(&writer, mpack_error_bug);
// writing too many bytes
mpack_writer_init(&writer, buf, sizeof(buf));
mpack_start_str(&writer, 2);
TEST_BREAK((mpack_write_bytes(&writer, "test", 4), true));
TEST_WRITER_DESTROY_ERROR(&writer, mpack_error_bug);
}
#endif
#if MPACK_HAS_GENERIC
static void test_write_generic(void) {
char buf[4096];
// int8
TEST_SIMPLE_WRITE("\x7f", mpack_write(&writer, (int8_t)INT8_MAX));
TEST_SIMPLE_WRITE("\x01", mpack_write(&writer, (int8_t)1));
TEST_SIMPLE_WRITE("\x00", mpack_write(&writer, (int8_t)0));
TEST_SIMPLE_WRITE("\xd0\x80", mpack_write(&writer, (int8_t)INT8_MIN));
// int16
TEST_SIMPLE_WRITE("\xcd\x7f\xff", mpack_write(&writer, (int16_t)INT16_MAX));
TEST_SIMPLE_WRITE("\x7f", mpack_write(&writer, (int16_t)INT8_MAX));
TEST_SIMPLE_WRITE("\x00", mpack_write(&writer, (int16_t)0));
TEST_SIMPLE_WRITE("\xd0\x80", mpack_write(&writer, (int16_t)INT8_MIN));
TEST_SIMPLE_WRITE("\xd1\x80\x00", mpack_write(&writer, (int16_t)INT16_MIN));
// int32
TEST_SIMPLE_WRITE("\xce\x7f\xff\xff\xff", mpack_write(&writer, (int32_t)INT32_MAX));
TEST_SIMPLE_WRITE("\xcd\x7f\xff", mpack_write(&writer, (int32_t)INT16_MAX));
TEST_SIMPLE_WRITE("\x7f", mpack_write(&writer, (int32_t)INT8_MAX));
TEST_SIMPLE_WRITE("\x00", mpack_write(&writer, (int32_t)0));
TEST_SIMPLE_WRITE("\xd0\x80", mpack_write(&writer, (int32_t)INT8_MIN));
TEST_SIMPLE_WRITE("\xd1\x80\x00", mpack_write(&writer, (int32_t)INT16_MIN));
TEST_SIMPLE_WRITE("\xd2\x80\x00\x00\x00", mpack_write(&writer, (int32_t)INT32_MIN));
// int64
TEST_SIMPLE_WRITE("\xcf\x7f\xff\xff\xff\xff\xff\xff\xff", mpack_write(&writer, (int64_t)INT64_MAX));
TEST_SIMPLE_WRITE("\xce\x7f\xff\xff\xff", mpack_write(&writer, (int64_t)INT32_MAX));
TEST_SIMPLE_WRITE("\xcd\x7f\xff", mpack_write(&writer, (int64_t)INT16_MAX));
TEST_SIMPLE_WRITE("\x7f", mpack_write(&writer, (int64_t)INT8_MAX));
TEST_SIMPLE_WRITE("\x00", mpack_write(&writer, (int64_t)0));
TEST_SIMPLE_WRITE("\xd0\x80", mpack_write(&writer, (int64_t)INT8_MIN));
TEST_SIMPLE_WRITE("\xd1\x80\x00", mpack_write(&writer, (int64_t)INT16_MIN));
TEST_SIMPLE_WRITE("\xd2\x80\x00\x00\x00", mpack_write(&writer, (int64_t)INT32_MIN));
TEST_SIMPLE_WRITE("\xd3\x80\x00\x00\x00\x00\x00\x00\x00", mpack_write(&writer, (int64_t)INT64_MIN));
// uint8
TEST_SIMPLE_WRITE("\x00", mpack_write(&writer, (uint8_t)0));
TEST_SIMPLE_WRITE("\x7f", mpack_write(&writer, (uint8_t)127));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write(&writer, (uint8_t)UINT8_MAX));
// uint16
TEST_SIMPLE_WRITE("\x00", mpack_write(&writer, (uint16_t)0));
TEST_SIMPLE_WRITE("\x7f", mpack_write(&writer, (uint16_t)127));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write(&writer, (uint16_t)UINT8_MAX));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write(&writer, (uint16_t)UINT16_MAX));
// uint32
TEST_SIMPLE_WRITE("\x00", mpack_write(&writer, (uint32_t)0));
TEST_SIMPLE_WRITE("\x7f", mpack_write(&writer, (uint32_t)127));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write(&writer, (uint32_t)UINT8_MAX));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write(&writer, (uint32_t)UINT16_MAX));
TEST_SIMPLE_WRITE("\xce\xff\xff\xff\xff", mpack_write(&writer, (uint32_t)UINT32_MAX));
// uint64
TEST_SIMPLE_WRITE("\x00", mpack_write(&writer, (uint64_t)0));
TEST_SIMPLE_WRITE("\x7f", mpack_write(&writer, (uint64_t)127));
TEST_SIMPLE_WRITE("\xcc\xff", mpack_write(&writer, (uint64_t)UINT8_MAX));
TEST_SIMPLE_WRITE("\xcd\xff\xff", mpack_write(&writer, (uint64_t)UINT16_MAX));
TEST_SIMPLE_WRITE("\xce\xff\xff\xff\xff", mpack_write(&writer, (uint64_t)UINT32_MAX));
TEST_SIMPLE_WRITE("\xcf\xff\xff\xff\xff\xff\xff\xff\xff", mpack_write(&writer, (uint64_t)UINT64_MAX));
// float and double
// TODO: we just test a few floats for now. this could certainly be extended to
// test more values like subnormal floats, infinities, etc.
TEST_SIMPLE_WRITE("\xca\x00\x00\x00\x00", mpack_write(&writer, (float)0.0f));
TEST_SIMPLE_WRITE("\xca\x40\x2d\xf3\xb6", mpack_write(&writer, (float)2.718f));
TEST_SIMPLE_WRITE("\xca\xc0\x2d\xf3\xb6", mpack_write(&writer, (float)-2.718f));
TEST_SIMPLE_WRITE("\xcb\x00\x00\x00\x00\x00\x00\x00\x00", mpack_write(&writer, (double)0.0));
TEST_SIMPLE_WRITE("\xcb\x40\x09\x21\xfb\x53\xc8\xd4\xf1", mpack_write(&writer, (double)3.14159265));
TEST_SIMPLE_WRITE("\xcb\xc0\x09\x21\xfb\x53\xc8\xd4\xf1", mpack_write(&writer, (double)-3.14159265));
// bool
// TODO: when we pass direct true or false into the _Generic it seems not to emit the correct stream
bool b = false;
TEST_SIMPLE_WRITE("\xc2", mpack_write(&writer, b));
b = true;
TEST_SIMPLE_WRITE("\xc3", mpack_write(&writer, b));
// char *
TEST_SIMPLE_WRITE("\xc0", mpack_write(&writer, (char *)NULL));
TEST_SIMPLE_WRITE("\xa4""1337", mpack_write(&writer, (char *)"1337"));
// const char *
TEST_SIMPLE_WRITE("\xc0", mpack_write(&writer, (const char *)NULL));
TEST_SIMPLE_WRITE("\xa4""1337", mpack_write(&writer, (const char *)"1337"));
// string literals
TEST_SIMPLE_WRITE("\xa0", mpack_write(&writer, ""));
TEST_SIMPLE_WRITE("\xa4""1337", mpack_write(&writer, "1337"));
}
static void test_write_generic_kv(void) {
char key[] = "foo";
char value[] = "bar";
char buf[4096];
// int8, int16, int32, int64
TEST_SIMPLE_WRITE("\xa3""foo""\x7f", mpack_write_kv(&writer, key, (int8_t)INT8_MAX));
TEST_SIMPLE_WRITE("\xa3""foo""\xcd\x7f\xff", mpack_write_kv(&writer, key, (int16_t)INT16_MAX));
TEST_SIMPLE_WRITE("\xa3""foo""\xce\x7f\xff\xff\xff", mpack_write_kv(&writer, key, (int32_t)INT32_MAX));
TEST_SIMPLE_WRITE("\xa3""foo""\xcf\x7f\xff\xff\xff\xff\xff\xff\xff", mpack_write_kv(&writer, key, (int64_t)INT64_MAX));
// uint8, uint16, uint32, uint64
TEST_SIMPLE_WRITE("\xa3""foo""\xcc\xff", mpack_write_kv(&writer, key, (uint8_t)UINT8_MAX));
TEST_SIMPLE_WRITE("\xa3""foo""\xcd\xff\xff", mpack_write_kv(&writer, key, (uint16_t)UINT16_MAX));
TEST_SIMPLE_WRITE("\xa3""foo""\xce\xff\xff\xff\xff", mpack_write_kv(&writer, key, (uint64_t)UINT32_MAX));
TEST_SIMPLE_WRITE("\xa3""foo""\xcf\xff\xff\xff\xff\xff\xff\xff\xff", mpack_write_kv(&writer, key, (uint64_t)UINT64_MAX));
// float, double and bool
TEST_SIMPLE_WRITE("\xa3""foo""\xca\xc0\x2d\xf3\xb6", mpack_write_kv(&writer, key, (float)-2.718f));
TEST_SIMPLE_WRITE("\xa3""foo""\xcb\xc0\x09\x21\xfb\x53\xc8\xd4\xf1", mpack_write_kv(&writer, key, (double)-3.14159265));
TEST_SIMPLE_WRITE("\xa3""foo""\xc2", mpack_write_kv(&writer, key, (bool)false));
// char *, const char *, literal
TEST_SIMPLE_WRITE("\xa3""foo""\xa3""bar", mpack_write_kv(&writer, key, (char *)value));
TEST_SIMPLE_WRITE("\xa3""foo""\xa3""bar", mpack_write_kv(&writer, key, (const char *)value));
TEST_SIMPLE_WRITE("\xa3""foo""\xa3""bar", mpack_write_kv(&writer, key, value));
TEST_SIMPLE_WRITE("\xa3""foo""\xa3""bar", mpack_write_kv(&writer, key, "bar"));
}
#endif
static void test_write_utf8(void) {
char buf[4096];
// these test strings are mostly duplicated from test-expect.c, but
// without the MessagePack header
const char utf8_null[] = "hello\x00world";
const char utf8_valid[] = " \xCF\x80 \xe4\xb8\xad \xf0\xa0\x80\xb6";
const char utf8_trimmed[] = "\xf0\xa0\x80\xb6";
const char utf8_invalid[] = " \x80 ";
const char utf8_invalid_trimmed[] = "\xa0";
const char utf8_truncated[] = "\xf0\xa0";
// we don't accept any of these UTF-8 variants; only pure UTF-8 is allowed.
const char utf8_modified[] = " \xc0\x80 ";
const char utf8_cesu8[] = " \xED\xA0\x81\xED\xB0\x80 ";
const char utf8_wobbly[] = " \xED\xA0\x81 ";
// all non-UTF-8 writers should write these strings without error
TEST_SIMPLE_WRITE_NOERROR(mpack_write_str(&writer, utf8_null, sizeof(utf8_null)-1));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_str(&writer, utf8_valid, sizeof(utf8_valid)-1));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_str(&writer, utf8_trimmed, sizeof(utf8_trimmed)-1));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_str(&writer, utf8_invalid, sizeof(utf8_invalid)-1));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_str(&writer, utf8_invalid_trimmed, sizeof(utf8_invalid_trimmed)-1));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_str(&writer, utf8_truncated, sizeof(utf8_truncated)-1));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_str(&writer, utf8_modified, sizeof(utf8_modified)-1));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_str(&writer, utf8_cesu8, sizeof(utf8_cesu8)-1));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_str(&writer, utf8_wobbly, sizeof(utf8_wobbly)-1));
// as should the non-UTF-8 cstr writers
// (the utf8_null test here is writing up to the null-terminator which
// is not what is expected, but there is no way to test for that error.
// null-terminated strings are bad!)
TEST_SIMPLE_WRITE_NOERROR(mpack_write_cstr(&writer, utf8_null));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_cstr(&writer, utf8_valid));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_cstr(&writer, utf8_trimmed));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_cstr(&writer, utf8_invalid));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_cstr(&writer, utf8_invalid_trimmed));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_cstr(&writer, utf8_truncated));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_cstr(&writer, utf8_modified));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_cstr(&writer, utf8_cesu8));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_cstr(&writer, utf8_wobbly));
// test UTF-8 cstr writers
// NUL is valid in UTF-8, so we allow it by the non-cstr API. (If you're
// using it to write, you should also using some non-cstr API to
// read, so the NUL will be safely handled.)
TEST_SIMPLE_WRITE_NOERROR(mpack_write_utf8(&writer, utf8_null, sizeof(utf8_null)-1));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_utf8(&writer, utf8_valid, sizeof(utf8_valid)-1));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_utf8(&writer, utf8_trimmed, sizeof(utf8_trimmed)-1));
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8(&writer, utf8_invalid, sizeof(utf8_invalid)-1), mpack_error_invalid);
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8(&writer, utf8_invalid_trimmed, sizeof(utf8_invalid_trimmed)-1), mpack_error_invalid);
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8(&writer, utf8_truncated, sizeof(utf8_truncated)-1), mpack_error_invalid);
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8(&writer, utf8_modified, sizeof(utf8_modified)-1), mpack_error_invalid);
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8(&writer, utf8_cesu8, sizeof(utf8_cesu8)-1), mpack_error_invalid);
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8(&writer, utf8_wobbly, sizeof(utf8_wobbly)-1), mpack_error_invalid);
// test UTF-8 cstr writers
TEST_SIMPLE_WRITE_NOERROR(mpack_write_utf8_cstr(&writer, utf8_null)); // again, up to null-terminator, which is valid...
TEST_SIMPLE_WRITE_NOERROR(mpack_write_utf8_cstr(&writer, utf8_valid));
TEST_SIMPLE_WRITE_NOERROR(mpack_write_utf8_cstr(&writer, utf8_trimmed));
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8_cstr(&writer, utf8_invalid), mpack_error_invalid);
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8_cstr(&writer, utf8_invalid_trimmed), mpack_error_invalid);
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8_cstr(&writer, utf8_truncated), mpack_error_invalid);
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8_cstr(&writer, utf8_modified), mpack_error_invalid);
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8_cstr(&writer, utf8_cesu8), mpack_error_invalid);
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8_cstr(&writer, utf8_wobbly), mpack_error_invalid);
// some basic tests for utf8_cstr_or_nil
TEST_SIMPLE_WRITE("\xa5hello", mpack_write_utf8_cstr_or_nil(&writer, "hello"));
TEST_SIMPLE_WRITE("\xc0", mpack_write_utf8_cstr_or_nil(&writer, NULL));
TEST_SIMPLE_WRITE_ERROR(mpack_write_utf8_cstr_or_nil(&writer, utf8_invalid), mpack_error_invalid);
}
static void test_misc(void) {
// writing too much data without a flush callback
// should result in mpack_error_too_big
char shortbuf[10];
mpack_writer_t writer;
mpack_writer_init(&writer, shortbuf, sizeof(shortbuf));
mpack_write_cstr(&writer, "The quick brown fox jumps over the lazy dog.");
TEST_WRITER_DESTROY_ERROR(&writer, mpack_error_too_big);
}
void test_writes() {
/*
const char c[] =
"\x85\xd0\xd1\x91\xc0\x90\x81\xc0\x00\xc0\x82\xc0\x90\x04\x05\xa5"
"\x68\x65\x6c\x6c\x6f\x93\xa7\x62\x6f\x6e\x6a\x6f\x75\x72\xc0\xff"
"\x91\x5c\xcd\x01\x5e"
;
mpack_debug_print(c, sizeof(c)-1);
*/
test_write_simple_auto_int();
test_write_simple_size_int_fixnums();
test_write_simple_size_int();
test_write_simple_tag_int();
#if MPACK_HAS_GENERIC
test_write_generic();
test_write_generic_kv();
#endif
test_write_simple_misc();
test_write_utf8();
#ifdef MPACK_MALLOC
test_write_tag_tracking();
test_write_basic_structures();
test_write_small_structure_trees();
test_system_fail_until_ok(&test_write_deep_growth);
#endif
#if MPACK_WRITE_TRACKING
test_write_tracking();
#endif
test_misc();
}
#endif