/* cmd/sbc_harness/tests/test_ihex.c - Tests for ihex.c * * Copyright (C) 2025 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later */ #include /* for putchar() */ #include #include #include "ihex.h" struct stdout { size_t len; }; LO_IMPLEMENTATION_STATIC(fmt_dest, struct stdout, stdout); static void stdout_putb(struct stdout *self, uint8_t b) { putchar(b); self->len++; } static size_t stdout_tell(struct stdout *self) { return self->len; } static lo_interface fmt_dest fmt_stdout = lo_box_stdout_as_fmt_dest(&((struct stdout){})); #define test_assert(expr) do { \ if (!(expr)) \ fmt_print( \ fmt_stdout, \ "test failure: ", __FILE__, ":", __LINE__, ":", __func__, \ ": " #expr "\n"); \ } while (0) static char *input = /* ,-byte count * | ,-address * | | ,-record type * | | | ,- checksum *[][--][][..............................][]\r\n */ ":020000041000EA\r\n" /* base_addr = linear(0x1000) = 0x1000<<16 */ ":1000000000B5324B212058609868022188439860DF\r\n" /* memcpy(chip[base_addr+0x0000], "\x00\xB5\x32\x4B\x21\x20\x58\x60\x98\x68\x02\x21\x88\x43\x98\x60", 16) */ ":10001000D860186158612E4B002199600221596106\r\n" /* memcpy(chip[base_addr+0x0010], "\xD8\x60\x18\x61\x58\x61\x2E\x4B\x00\x21\x99\x60\x02\x21\x59\x61", 16) */ ":10BE9C000000000000000000000000000000000096\r\n" /* memcpy(chip[base_addr+0xBE9C], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) */ ":04BEAC00CC4A00205C\r\n" /* memcpy(chip[base_addr+0xBEAC], "\x00\xCC\x4A\x00\x20", 5) */ ":04000005100001E9FD\r\n" /* start_exec_at = linear(0x100001E9) */ ":00000001FF\r\n"; /* EOF */ static int cnt = 0; static error handle_data(void *, uint32_t off, uint8_t count, uint8_t *dat) { switch (cnt) { case 0: test_assert(off == UINT32_C(0x10000000)); test_assert(count == 16); test_assert(memcmp(dat, "\x00\xB5\x32\x4B\x21\x20\x58\x60\x98\x68\x02\x21\x88\x43\x98\x60", 16) == 0); break; case 1: test_assert(off == UINT32_C(0x10000010)); test_assert(count == 16); test_assert(memcmp(dat, "\xD8\x60\x18\x61\x58\x61\x2E\x4B\x00\x21\x99\x60\x02\x21\x59\x61", 16) == 0); break; case 2: test_assert(off == UINT32_C(0x1000BE9C)); test_assert(count == 16); test_assert(memcmp(dat, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0); break; case 4: test_assert(off == UINT32_C(0x1000BE9C)); test_assert(count == 5); test_assert(memcmp(dat, "\x00\xCC\x4A\x00\x20", 5) == 0); break; default: test_assert(false); } cnt++; return ERROR_NULL; } static error handle_set_exec_start_seg(void *, uint16_t LM_UNUSED(cs), uint16_t LM_UNUSED(ip)) { switch (cnt) { default: test_assert(false); } cnt++; return ERROR_NULL; } static error handle_set_exec_start_lin(void *, uint32_t eip) { switch (cnt) { case 5: test_assert(eip == UINT32_C(0x100001E9)); break; default: test_assert(false); } cnt++; return ERROR_NULL; } static error handle_eof(void *) { switch (cnt) { case 6: break; default: test_assert(false); } cnt++; return ERROR_NULL; } int main() { struct ihex_decoder dec = { .handle_data = handle_data, .handle_set_exec_start_seg = handle_set_exec_start_seg, .handle_set_exec_start_lin = handle_set_exec_start_lin, .handle_eof = handle_eof, }; size_t_and_error ret = ihex_decoder_writev(&dec, &((struct iovec){ .iov_base = input, .iov_len = strlen(input), }), 1); fmt_print(fmt_stdout, "ret = (", ret.size_t, ", ", (error, ret.err), ")\n", "cnt = ", cnt, "\n"); test_assert(ret.size_t == strlen(input)); test_assert(ERROR_IS_NULL(ret.err)); test_assert(cnt == 6); return 0; }