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

365 lines
15 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-buffer.h"
#include "test-expect.h"
#include "test-write.h"
static const char test_numbers[] =
"\x02" // 2
"\x11" // 17
"\x1d" // 29
"\x2b" // 43
"\x3b" // 59
"\x47" // 71
"\x59" // 89
"\x65" // 101
"\xcc\x83" // 131
"\xcc\x95" // 149
"\xcc\x9d" // 157
"\xcc\xad" // 173
"\xcc\xbf" // 191
"\xcc\xc7" // 199
"\xcc\xdf" // 223
"\xcc\xe3" // 227
"\xcd\x01\x01" // 257
"\xcd\x1d\x5d" // 7517
"\xcd\x39\xaf" // 14767
"\xcd\x56\x0b" // 22027
"\xcd\x72\x55" // 29269
"\xcd\x8e\xab" // 36523
"\xcd\xab\x01" // 43777
"\xcd\xc7\x57" // 51031
"\xce\x00\x01\x00\x01" // 65537
"\xce\x1c\x72\xaa\xb3" // 477276851
"\xce\x38\xe4\x55\x59" // 954488153
"\xce\x55\x56\x00\x19" // 1431699481
"\xce\x71\xc7\xaa\xab" // 1908910763
"\xce\x8e\x39\x55\x77" // 2386122103
"\xce\xaa\xab\x00\x17" // 2863333399
"\xce\xc7\x1c\xaa\xa9" // 3340544681
"\xcf\x00\x00\x00\x01\x00\x00\x00\x0f" // 4294967311
"\xcf\x1a\xf2\x86\xbd\x86\xbc\xa2\x67" // 1941762537917555303
"\xcf\x35\xe5\x0d\x7a\x0d\x79\x44\x0f" // 3883525071540143119
"\xcf\x50\xd7\x94\x36\x94\x35\xe4\x51" // 5825287605162730577
"\xcf\x6b\xca\x1a\xf3\x1a\xf2\x88\x31" // 7767050138785318961
"\xcf\x86\xbc\xa1\xaf\xa1\xaf\x28\x3f" // 9708812672407906367
"\xcf\xa1\xaf\x28\x6c\x28\x6b\xc8\x11" // 11650575206030493713
"\xcf\xbc\xa1\xaf\x28\xaf\x28\x68\x03" // 13592337739653081091
;
static const char test_strings[] =
"\x9F"
"\xA0"
"\xA1""a"
"\xA2""ab"
"\xA3""abc"
"\xA4""abcd"
"\xA5""abcde"
"\xA6""abcdef"
"\xA7""abcdefg"
"\xA8""abcdefgh"
"\xA9""abcdefghi"
"\xAA""abcdefghij"
"\xAB""abcdefghijk"
"\xAC""abcdefghijkl"
"\xAD""abcdefghijklm"
"\xAE""abcdefghijklmn";
// a semi-random list of buffer sizes we will test with. each buffer
// test is run with each of these buffer sizes to test the fill and
// flush functions.
static const size_t test_buffer_sizes[] = {
32, 33, 34, 35, 36, 37, 39, 43, 48, 51,
52, 53, 57, 59, 64, 67, 89, 127, 128,
129, 131, 160, 163, 191, 192, 193,
251, 256, 257, 509, 512, 521,
1021, 1024, 1031, 2039, 2048, 2053,
4093, 4096, 4099, 7919, 8192,
16384, 32768
};
#if MPACK_READER
typedef struct test_fill_state_t {
const char* data;
size_t remaining;
} test_fill_state_t;
static size_t test_buffer_fill(mpack_reader_t* reader, char* buffer, size_t count) {
test_fill_state_t* state = (test_fill_state_t*)reader->context;
if (state->remaining < count)
count = state->remaining;
memcpy(buffer, state->data, count);
state->data += count;
state->remaining -= count;
return count;
}
#endif
#if MPACK_WRITER
typedef struct test_flush_state_t {
char* data;
size_t remaining;
} test_flush_state_t;
static void test_buffer_flush(mpack_writer_t* writer, const char* buffer, size_t count) {
test_flush_state_t* state = (test_flush_state_t*)writer->context;
if (state->remaining < count) {
mpack_writer_flag_error(writer, mpack_error_too_big);
return;
}
memcpy(state->data, buffer, count);
state->data += count;
state->remaining -= count;
}
#endif
#if MPACK_EXPECT
static void test_expect_buffer_values(mpack_reader_t* reader) {
TEST_READ_NOERROR(reader, 2 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 17 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 29 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 43 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 59 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 71 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 89 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 101 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 131 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 149 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 157 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 173 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 191 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 199 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 223 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 227 == mpack_expect_u8(reader));
TEST_READ_NOERROR(reader, 257 == mpack_expect_u16(reader));
TEST_READ_NOERROR(reader, 7517 == mpack_expect_u16(reader));
TEST_READ_NOERROR(reader, 14767 == mpack_expect_u16(reader));
TEST_READ_NOERROR(reader, 22027 == mpack_expect_u16(reader));
TEST_READ_NOERROR(reader, 29269 == mpack_expect_u16(reader));
TEST_READ_NOERROR(reader, 36523 == mpack_expect_u16(reader));
TEST_READ_NOERROR(reader, 43777 == mpack_expect_u16(reader));
TEST_READ_NOERROR(reader, 51031 == mpack_expect_u16(reader));
TEST_READ_NOERROR(reader, 65537 == mpack_expect_u32(reader));
TEST_READ_NOERROR(reader, 477276851 == mpack_expect_u32(reader));
TEST_READ_NOERROR(reader, 954488153 == mpack_expect_u32(reader));
TEST_READ_NOERROR(reader, 1431699481 == mpack_expect_u32(reader));
TEST_READ_NOERROR(reader, 1908910763 == mpack_expect_u32(reader));
// when using UINT32_C() and compiling the test suite as c++, gcc complains:
// error: this decimal constant is unsigned only in ISO C90 [-Werror]
TEST_READ_NOERROR(reader, UINT64_C(2386122103) == mpack_expect_u32(reader));
TEST_READ_NOERROR(reader, UINT64_C(2863333399) == mpack_expect_u32(reader));
TEST_READ_NOERROR(reader, UINT64_C(3340544681) == mpack_expect_u32(reader));
TEST_READ_NOERROR(reader, UINT64_C(4294967311) == mpack_expect_u64(reader));
TEST_READ_NOERROR(reader, UINT64_C(1941762537917555303) == mpack_expect_u64(reader));
TEST_READ_NOERROR(reader, UINT64_C(3883525071540143119) == mpack_expect_u64(reader));
TEST_READ_NOERROR(reader, UINT64_C(5825287605162730577) == mpack_expect_u64(reader));
TEST_READ_NOERROR(reader, UINT64_C(7767050138785318961) == mpack_expect_u64(reader));
TEST_READ_NOERROR(reader, UINT64_C(9708812672407906367) == mpack_expect_u64(reader));
TEST_READ_NOERROR(reader, UINT64_C(11650575206030493713) == mpack_expect_u64(reader));
TEST_READ_NOERROR(reader, UINT64_C(13592337739653081091) == mpack_expect_u64(reader));
}
#endif
#if MPACK_WRITER
static void test_write_buffer_values(mpack_writer_t* writer) {
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 2));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 17));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 29));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 43));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 59));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 71));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 89));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 101));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 131));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 149));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 157));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 173));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 191));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 199));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 223));
TEST_WRITE_NOERROR(writer, mpack_write_u8(writer, 227));
TEST_WRITE_NOERROR(writer, mpack_write_u16(writer, 257));
TEST_WRITE_NOERROR(writer, mpack_write_u16(writer, 7517));
TEST_WRITE_NOERROR(writer, mpack_write_u16(writer, 14767));
TEST_WRITE_NOERROR(writer, mpack_write_u16(writer, 22027));
TEST_WRITE_NOERROR(writer, mpack_write_u16(writer, 29269));
TEST_WRITE_NOERROR(writer, mpack_write_u16(writer, 36523));
TEST_WRITE_NOERROR(writer, mpack_write_u16(writer, 43777));
TEST_WRITE_NOERROR(writer, mpack_write_u16(writer, 51031));
TEST_WRITE_NOERROR(writer, mpack_write_u32(writer, 65537));
TEST_WRITE_NOERROR(writer, mpack_write_u32(writer, 477276851));
TEST_WRITE_NOERROR(writer, mpack_write_u32(writer, 954488153));
TEST_WRITE_NOERROR(writer, mpack_write_u32(writer, 1431699481));
TEST_WRITE_NOERROR(writer, mpack_write_u32(writer, 1908910763));
// when using UINT32_C() and compiling the test suite as c++, gcc complains:
// error: this decimal constant is unsigned only in ISO C90 [-Werror]
TEST_WRITE_NOERROR(writer, mpack_write_u32(writer, UINT64_C(2386122103)));
TEST_WRITE_NOERROR(writer, mpack_write_u32(writer, UINT64_C(2863333399)));
TEST_WRITE_NOERROR(writer, mpack_write_u32(writer, UINT64_C(3340544681)));
TEST_WRITE_NOERROR(writer, mpack_write_u64(writer, UINT64_C(4294967311)));
TEST_WRITE_NOERROR(writer, mpack_write_u64(writer, UINT64_C(1941762537917555303)));
TEST_WRITE_NOERROR(writer, mpack_write_u64(writer, UINT64_C(3883525071540143119)));
TEST_WRITE_NOERROR(writer, mpack_write_u64(writer, UINT64_C(5825287605162730577)));
TEST_WRITE_NOERROR(writer, mpack_write_u64(writer, UINT64_C(7767050138785318961)));
TEST_WRITE_NOERROR(writer, mpack_write_u64(writer, UINT64_C(9708812672407906367)));
TEST_WRITE_NOERROR(writer, mpack_write_u64(writer, UINT64_C(11650575206030493713)));
TEST_WRITE_NOERROR(writer, mpack_write_u64(writer, UINT64_C(13592337739653081091)));
}
#endif
#if MPACK_EXPECT
static void test_expect_buffer(void) {
for (size_t i = 0; i < sizeof(test_buffer_sizes) / sizeof(test_buffer_sizes[0]); ++i) {
// initialize the reader with our buffer reader function
mpack_reader_t reader;
size_t size = test_buffer_sizes[i];
char* buffer = (char*)malloc(size);
test_fill_state_t state = {test_numbers, sizeof(test_numbers) - 1};
mpack_reader_init(&reader, buffer, size, 0);
mpack_reader_set_fill(&reader, test_buffer_fill);
mpack_reader_set_context(&reader, &state);
// read and destroy, ensuring no errors
test_expect_buffer_values(&reader);
TEST_READER_DESTROY_NOERROR(&reader);
free(buffer);
}
}
#endif
#if MPACK_WRITER
static void test_write_buffer(void) {
for (size_t i = 0; i < sizeof(test_buffer_sizes) / sizeof(test_buffer_sizes[0]); ++i) {
size_t size = test_buffer_sizes[i];
size_t output_size = 0xffff;
char* output = (char*)malloc(output_size);
// initialize the writer with our buffer writer function
mpack_writer_t writer;
char* buffer = (char*)malloc(size);
char* pos = output;
test_flush_state_t state = {output, output_size};
mpack_writer_init(&writer, buffer, size);
mpack_writer_set_flush(&writer, test_buffer_flush);
mpack_writer_set_context(&writer, &state);
// read and destroy, ensuring no errors
test_write_buffer_values(&writer);
TEST_WRITER_DESTROY_NOERROR(&writer);
free(buffer);
// check output
TEST_TRUE(output_size - state.remaining == sizeof(test_numbers) - 1,
"output contains %i bytes but %i were expected",
(int)(pos - output), (int)sizeof(test_numbers) - 1);
TEST_TRUE(memcmp(output, test_numbers, sizeof(test_numbers) - 1) == 0,
"output does not match test buffer");
free(output);
}
}
#endif
#if MPACK_READER
static void test_inplace_buffer(void) {
for (size_t i = 0; i < sizeof(test_buffer_sizes) / sizeof(test_buffer_sizes[0]); ++i) {
// initialize the reader with our buffer reader function
mpack_reader_t reader;
size_t size = test_buffer_sizes[i];
char* buffer = (char*)malloc(size);
test_fill_state_t state = {test_strings, sizeof(test_strings) - 1};
mpack_reader_init(&reader, buffer, size, 0);
mpack_reader_set_fill(&reader, test_buffer_fill);
mpack_reader_set_context(&reader, &state);
// read the array
mpack_tag_t tag = mpack_read_tag(&reader);
TEST_TRUE(tag.type == mpack_type_array, "wrong type: %i %s", (int)tag.type, mpack_type_to_string(tag.type));
TEST_TRUE(tag.v.n == 15, "wrong array count: %i", tag.v.n);
// check each string, using inplace if it's less than or equal to the
// length of the buffer size
static const char* ref = "abcdefghijklmn";
const char* val;
char r[15];
for (size_t j = 0; j < 15; ++j) {
mpack_tag_t peek = mpack_peek_tag(&reader);
tag = mpack_read_tag(&reader);
TEST_TRUE(mpack_tag_equal(peek, tag), "peeked tag does not match read tag");
TEST_TRUE(tag.type == mpack_type_str, "wrong type: %i %s", (int)tag.type, mpack_type_to_string(tag.type));
TEST_TRUE(tag.v.l == j, "string is the wrong length: %i bytes", (int)tag.v.l);
if (tag.v.l <= reader.size) {
val = mpack_read_bytes_inplace(&reader, tag.v.l);
} else {
mpack_read_bytes(&reader, r, tag.v.l);
val = r;
}
TEST_TRUE(memcmp(val, ref, tag.v.l) == 0, "strings do not match!");
mpack_done_str(&reader);
}
// destroy, ensuring no errors
mpack_done_array(&reader);
TEST_READER_DESTROY_NOERROR(&reader);
free(buffer);
}
}
#endif
void test_buffers(void) {
MPACK_UNUSED(test_numbers);
MPACK_UNUSED(test_strings);
MPACK_UNUSED(test_buffer_sizes);
#if MPACK_EXPECT
test_expect_buffer();
#endif
#if MPACK_WRITER
test_write_buffer();
#endif
#if MPACK_READER
test_inplace_buffer();
#endif
}