diff --git a/axl_rle_test.c b/axl_rle_test.c new file mode 100644 index 0000000..70f7a0c --- /dev/null +++ b/axl_rle_test.c @@ -0,0 +1,233 @@ +#include "axl_memory.h" +#include "axl_rle.h" +#include "axl_koan.h" + +#define ASSERT_ARRAY_EQ(expected, actual, size) \ + do { \ + const u8* _e = (expected); \ + const u8* _a = (actual); \ + u32 _s = (size); \ + for (u32 _i = 0; _i < _s; _i++) { \ + if (_e[_i] != _a[_i]) { \ + char _r[256]; \ + snprintf(_r, sizeof(_r), "Mismatch at index %u: exp 0x%02X, got 0x%02X", \ + _i, _e[_i], _a[_i]); \ + KOAN_FAIL(_r); \ + } \ + } \ + } while (0) + +KOAN(encode_empty) +{ + u8 src[] = ""; + u8 dst[32]; + ASSERT_UINT_EQ(0, axl_rle_encode(src, 0, dst, sizeof(dst))); +} + +KOAN(encode_single) +{ + u8 src[] = {0xAA}; + u8 dst[32]; + u32 size = axl_rle_encode(src, 1, dst, sizeof(dst)); + ASSERT_UINT_EQ(2, size); + ASSERT_UINT_EQ(0x01, dst[0]); + ASSERT_UINT_EQ(0xAA, dst[1]); +} + +KOAN(encode_five_repeats) +{ + u8 src[] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA}; + u8 dst[32]; + u32 size = axl_rle_encode(src, 5, dst, sizeof(dst)); + ASSERT_UINT_EQ(2, size); + ASSERT_UINT_EQ(0x05, dst[0]); + ASSERT_UINT_EQ(0xAA, dst[1]); +} + +KOAN(encode_three_runs) +{ + u8 src[] = {0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xCC}; + u8 expected[] = {0x03, 0xAA, 0x02, 0xBB, 0x01, 0xCC}; + u8 dst[32]; + u32 size = axl_rle_encode(src, 6, dst, sizeof(dst)); + ASSERT_UINT_EQ(6, size); + ASSERT_ARRAY_EQ(expected, dst, 6); +} + +KOAN(encode_interleaved) +{ + u8 src[] = {0xAA, 0xAA, 0xBB, 0xBB, 0xAA, 0xAA}; + u8 expected[] = {0x02, 0xAA, 0x02, 0xBB, 0x02, 0xAA}; + u8 dst[32]; + u32 size = axl_rle_encode(src, 6, dst, sizeof(dst)); + ASSERT_UINT_EQ(6, size); + ASSERT_ARRAY_EQ(expected, dst, 6); +} + +KOAN(encode_all_different) +{ + u8 src[10]; + u8 dst[32]; + for (u32 i = 0; i < 10; i++) src[i] = (u8)i; + u32 size = axl_rle_encode(src, 10, dst, sizeof(dst)); + ASSERT_UINT_EQ(20, size); + for (u32 i = 0; i < 10; i++) { + ASSERT_UINT_EQ(0x01, dst[i*2]); + ASSERT_UINT_EQ((u8)i, dst[i*2+1]); + } +} + +KOAN(encode_null_ptr) +{ + u8 src[] = {0xAA}, dst[32]; + ASSERT_UINT_EQ(0, axl_rle_encode(NULL, 1, dst, sizeof(dst))); + ASSERT_UINT_EQ(0, axl_rle_encode(src, 1, NULL, 32)); +} + +KOAN(encode_zero_size) +{ + u8 src[] = {0xAA}; + u8 dst[32]; + ASSERT_UINT_EQ(0, axl_rle_encode(src, 0, dst, sizeof(dst))); + ASSERT_UINT_EQ(0, axl_rle_encode(src, 1, dst, 0)); +} + +KOAN(encode_buffer_too_small) +{ + u8 src[] = {0xAA, 0xAA, 0xAA, 0xBB}; + u8 dst[3]; + ASSERT_UINT_EQ(0, axl_rle_encode(src, 4, dst, sizeof(dst))); +} + +KOAN(encode_max_127) +{ + u8 src[127]; + u8 dst[32]; + for (u32 i = 0; i < 127; i++) src[i] = 0x77; + u32 size = axl_rle_encode(src, 127, dst, sizeof(dst)); + ASSERT_UINT_EQ(2, size); + ASSERT_UINT_EQ(0x7F, dst[0]); + ASSERT_UINT_EQ(0x77, dst[1]); +} + +KOAN(encode_decode_300) +{ + u8 src[300]; + u8 encoded[32]; + u8 decoded[400]; + for (u32 i = 0; i < 300; i++) src[i] = 0x55; + u32 encoded_size = axl_rle_encode(src, 300, encoded, sizeof(encoded)); + ASSERT_TRUE(encoded_size > 0 && encoded_size <= 6); + u32 decoded_size = axl_rle_decode(encoded, encoded_size, decoded, sizeof(decoded)); + ASSERT_UINT_EQ(300, decoded_size); + ASSERT_ARRAY_EQ(src, decoded, 300); +} + +KOAN(decode_empty) +{ + u8 src[] = ""; + u8 dst[32]; + ASSERT_UINT_EQ(0, axl_rle_decode(src, 0, dst, sizeof(dst))); +} + +KOAN(decode_single) +{ + u8 src[] = {0x01, 0xAA}; + u8 dst[32]; + u32 size = axl_rle_decode(src, 2, dst, sizeof(dst)); + ASSERT_UINT_EQ(1, size); + ASSERT_UINT_EQ(0xAA, dst[0]); +} + +KOAN(decode_five) +{ + u8 src[] = {0x05, 0xAA}; + u8 dst[32]; + u32 size = axl_rle_decode(src, 2, dst, sizeof(dst)); + ASSERT_UINT_EQ(5, size); + for (u32 i = 0; i < 5; i++) ASSERT_UINT_EQ(0xAA, dst[i]); +} + +KOAN(decode_three_runs) +{ + u8 src[] = {0x03, 0xAA, 0x02, 0xBB, 0x01, 0xCC}; + u8 expected[] = {0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xCC}; + u8 dst[32]; + u32 size = axl_rle_decode(src, 6, dst, sizeof(dst)); + ASSERT_UINT_EQ(6, size); + ASSERT_ARRAY_EQ(expected, dst, 6); +} + +KOAN(decode_null_ptr) +{ + u8 src[] = {0x01, 0xAA}, dst[32]; + ASSERT_UINT_EQ(0, axl_rle_decode(NULL, 2, dst, sizeof(dst))); + ASSERT_UINT_EQ(0, axl_rle_decode(src, 2, NULL, 32)); +} + +KOAN(decode_zero_size) +{ + u8 src[] = {0x01, 0xAA}; + u8 dst[32]; + ASSERT_UINT_EQ(0, axl_rle_decode(src, 0, dst, sizeof(dst))); + ASSERT_UINT_EQ(0, axl_rle_decode(src, 2, dst, 0)); +} + +KOAN(decode_buffer_too_small) +{ + u8 src[] = {0x05, 0xAA}; + u8 dst[3]; + ASSERT_UINT_EQ(0, axl_rle_decode(src, 2, dst, sizeof(dst))); +} + +KOAN(decode_incomplete_vlq) +{ + u8 src[] = {0x85}; + u8 dst[32]; + ASSERT_UINT_EQ(0, axl_rle_decode(src, 1, dst, sizeof(dst))); +} + +KOAN(decode_missing_value) +{ + u8 src[] = {0x05}; + u8 dst[32]; + ASSERT_UINT_EQ(0, axl_rle_decode(src, 1, dst, sizeof(dst))); +} + +KOAN(decode_zero_count) +{ + u8 src[] = {0x00, 0xAA}; + u8 dst[32]; + ASSERT_UINT_EQ(0, axl_rle_decode(src, 2, dst, sizeof(dst))); +} + +KOAN(roundtrip_simple) +{ + u8 original[] = {0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xCC, 0xCC, 0xCC}; + u8 encoded[32]; + u8 decoded[32]; + u32 encoded_size = axl_rle_encode(original, 9, encoded, sizeof(encoded)); + ASSERT_TRUE(encoded_size > 0); + u32 decoded_size = axl_rle_decode(encoded, encoded_size, decoded, sizeof(decoded)); + ASSERT_UINT_EQ(9, decoded_size); + ASSERT_ARRAY_EQ(original, decoded, 9); +} + +KOAN(roundtrip_all_different) +{ + u8 original[10]; + u8 encoded[32]; + u8 decoded[32]; + for (u32 i = 0; i < 10; i++) original[i] = (u8)i; + u32 encoded_size = axl_rle_encode(original, 10, encoded, sizeof(encoded)); + ASSERT_UINT_EQ(20, encoded_size); + u32 decoded_size = axl_rle_decode(encoded, encoded_size, decoded, sizeof(decoded)); + ASSERT_UINT_EQ(10, decoded_size); + ASSERT_ARRAY_EQ(original, decoded, 10); +} + +int main(void) +{ + axl_init(); + return koan_run_all(); +}