apfl/src/encode_test.c

201 lines
5.7 KiB
C
Raw Normal View History

2023-03-05 16:02:42 +00:00
#include <inttypes.h>
#include <math.h>
#include "test.h"
#include "apfl.h"
#include "encode.h"
#define HEXDUMP_FMT "%02X%02X%02X%02X%02X%02X%02X%02X"
#define HEXDUMP_ARGS(b) \
(unsigned int)((b)[0]), \
(unsigned int)((b)[1]), \
(unsigned int)((b)[2]), \
(unsigned int)((b)[3]), \
(unsigned int)((b)[4]), \
(unsigned int)((b)[5]), \
(unsigned int)((b)[6]), \
(unsigned int)((b)[7])
static void
test_u64(testctx t, void (*fn)(testctx, uint_least64_t, unsigned char[8]))
{
fn(t, 0, (unsigned char[8]) {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00});
fn(t, 1, (unsigned char[8]) {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00});
fn(t, 42, (unsigned char[8]) {0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00});
fn(t, 666, (unsigned char[8]) {0x9A,0x02,0x00,0x00,0x00,0x00,0x00,0x00});
fn(t, 0x1122334455667788, (unsigned char[8]) {0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11});
fn(t, 0xFFFFFFFFFFFFFFFF, (unsigned char[8]) {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF});
}
static void u64_encode_callback(testctx t, uint_least64_t n, unsigned char bytes[8])
{
struct apfl_allocator allocator = test_allocator(t);
struct apfl_string_builder sb = apfl_string_builder_init(allocator);
struct apfl_io_writer w = apfl_io_string_writer(&sb);
if (!apfl_encode_u64(w, n)) {
test_failf(t, "Could not encode u64 0x%" PRIxLEAST64, n);
return;
}
struct apfl_string have = apfl_string_builder_move_string(&sb);
if (have.len != 8) {
test_failf(t, "Encoded length is incorrect. Got %d", (int)have.len);
return;
}
struct apfl_string_view want = { .bytes = bytes, .len = 8, };
if (!apfl_string_eq(want, have)) {
test_failf(
t,
"Encoding for 0x%" PRIxLEAST64 " is wrong. have " HEXDUMP_FMT ", want " HEXDUMP_FMT,
n,
HEXDUMP_ARGS(have.bytes),
HEXDUMP_ARGS(bytes)
);
return;
}
apfl_string_deinit(allocator, &have);
}
static void u64_decode_callback(testctx t, uint_least64_t want, unsigned char bytes[8])
{
struct apfl_string_view input = { .bytes = bytes, .len = 8, };
struct apfl_io_string_reader_data reader_data = apfl_io_string_reader_create(input);
struct apfl_io_reader r = apfl_io_string_reader(&reader_data);
uint_least64_t have;
if (!apfl_decode_u64(r, &have)) {
test_failf(t, "Could not decode u64 0x%" PRIxLEAST64, want);
return;
}
if (want != have) {
test_failf(
t,
"Decoding failed, have 0x%" PRIxLEAST64 ", want 0x%" PRIxLEAST64 ".",
have,
want
);
return;
}
}
TEST(encode_u64, t) {
test_u64(t, u64_encode_callback);
}
TEST(decode_u64, t) {
test_u64(t, u64_decode_callback);
}
static void
test_double(testctx t, void (*fn)(testctx, double, unsigned char[8]))
{
fn(t, 0, (unsigned char[8]) {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00});
fn(t, 1, (unsigned char[8]) {0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x3F});
fn(t, 42, (unsigned char[8]) {0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x40});
fn(t, -2.75, (unsigned char[8]) {0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xC0});
fn(t, 1337.42, (unsigned char[8]) {0x48,0xE1,0x7A,0x14,0xAE,0xE5,0x94,0x40});
fn(t, 1E+50, (unsigned char[8]) {0x9A,0x64,0x7E,0xC5,0x0E,0x1B,0x51,0x4A});
fn(t, 1E-12, (unsigned char[8]) {0x11,0xEA,0x2D,0x81,0x99,0x97,0x71,0x3D});
fn(t, NAN, (unsigned char[8]) {0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x7F});
fn(t, -NAN, (unsigned char[8]) {0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF});
fn(t, INFINITY, (unsigned char[8]) {0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x7F});
fn(t, -INFINITY, (unsigned char[8]) {0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF});
}
static void
double_encode_callback(testctx t, double d, unsigned char bytes[8])
{
struct apfl_allocator allocator = test_allocator(t);
struct apfl_string_builder sb = apfl_string_builder_init(allocator);
struct apfl_io_writer w = apfl_io_string_writer(&sb);
if (!apfl_encode_double(w, d)) {
test_failf(t, "Could not encode double %a", d);
return;
}
struct apfl_string have = apfl_string_builder_move_string(&sb);
if (have.len != 8) {
test_failf(t, "Encoded length is incorrect. Got %d", (int)have.len);
return;
}
struct apfl_string_view want = { .bytes = bytes, .len = 8, };
if (!apfl_string_eq(want, have)) {
test_failf(
t,
"Encoding for %a is wrong. have " HEXDUMP_FMT ", want " HEXDUMP_FMT,
d,
HEXDUMP_ARGS(have.bytes),
HEXDUMP_ARGS(bytes)
);
return;
}
apfl_string_deinit(allocator, &have);
}
static bool
cmpdouble(double a, double b)
{
if (isnan(a)) {
return isnan(b) && signbit(a) == signbit(b);
} else {
return a == b;
}
}
static void
double_decode_callback(testctx t, double want, unsigned char bytes[8])
{
struct apfl_string_view input = { .bytes = bytes, .len = 8, };
struct apfl_io_string_reader_data reader_data = apfl_io_string_reader_create(input);
struct apfl_io_reader r = apfl_io_string_reader(&reader_data);
double have;
if (!apfl_decode_double(r, &have)) {
test_failf(t, "Could not decode double %a", want);
return;
}
if (!cmpdouble(want, have)) {
test_failf(
t,
"Decoding failed, have %a, want %a.",
have,
want
);
return;
}
}
TEST(encode_double, t) {
test_double(t, double_encode_callback);
}
TEST(decode_double, t) {
test_double(t, double_decode_callback);
}
TESTS_BEGIN
ADDTEST(encode_u64),
ADDTEST(decode_u64),
ADDTEST(encode_double),
ADDTEST(decode_double),
TESTS_END