1047 lines
47 KiB
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
|
|
|