From 1f9494979268b62ed4b4588fb7d9e790c0e12100 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Mon, 26 Oct 2026 22:32:52 +0100 Subject: replace all calls to sprintf with a format helper that advances a cursor. Also convert the meta-formatter (i.e. results printer) to this scheme --- tests/t_fmt.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 tests/t_fmt.c (limited to 'tests/t_fmt.c') diff --git a/tests/t_fmt.c b/tests/t_fmt.c new file mode 100644 index 0000000..bc23ed5 --- /dev/null +++ b/tests/t_fmt.c @@ -0,0 +1,108 @@ +/* This software was written by Dirk Engling + It is considered beerware. Prost. Skol. Cheers or whatever. + + $id$ */ + +/* System */ +#include + +/* Opentracker */ +#include "ot_fmt.h" +#include "test.h" + +static void case_appends_in_sequence(void) { + char buffer[64]; + char *r = buffer, *re = buffer + sizeof(buffer); + + test_case("appends follow each other and advance the cursor"); + fmt_append(&r, re, "d8:completei%zde", (size_t)7); + fmt_append(&r, re, "ee"); + *r = 0; + CHECK_STR(buffer, "d8:completei7eee"); + CHECK_INT(r - buffer, 16); +} + +static void case_truncation_stops_at_the_end(void) { + char buffer[16]; + char *r = buffer, *re = buffer + 8; /* pretend the buffer ends early */ + + memset(buffer, '#', sizeof(buffer)); + test_case("a value too long for the room left stops at the end"); + fmt_append(&r, re, "%s", "0123456789"); + CHECK_PTR(r, re); + + test_case("and writes nothing past it"); + CHECK_INT(buffer[8], '#'); + CHECK_INT(buffer[15], '#'); +} + +static void case_a_full_buffer_takes_nothing_more(void) { + char buffer[16]; + char *r = buffer + 8, *re = buffer + 8; + + memset(buffer, '#', sizeof(buffer)); + test_case("appending to a cursor already at the end changes nothing"); + fmt_append(&r, re, "more"); + CHECK_PTR(r, re); + CHECK_INT(buffer[8], '#'); +} + +static void case_an_append_that_just_fits(void) { + char buffer[8]; + char *r = buffer, *re = buffer + 3; + + memset(buffer, '#', sizeof(buffer)); + test_case("three characters into three bytes of room still truncate"); + fmt_append(&r, re, "abc"); + CHECK_PTR(r, re); + CHECK_INT(buffer[0], 'a'); + CHECK_INT(buffer[1], 'b'); + + test_case("because snprintf spends the last byte on its terminator"); + CHECK_INT(buffer[2], 0); + CHECK_INT(buffer[3], '#'); +} + +static void case_bytes_are_all_or_nothing(void) { + char buffer[16]; + char *r = buffer, *re = buffer + 8; + + memset(buffer, '#', sizeof(buffer)); + test_case("a run of bytes is written when it fits"); + fmt_bytes(&r, re, "\0\1\2\3", 4); + CHECK_PTR(r, buffer + 4); + CHECK_MEM(buffer, "\0\1\2\3", 4); + + test_case("a run that would not fit is refused whole"); + fmt_bytes(&r, re, "abcde", 5); + CHECK_PTR(r, re); + CHECK_INT(buffer[4], '#'); + + test_case("a run of exactly the room left is written"); + r = buffer + 4; + fmt_bytes(&r, re, "wxyz", 4); + CHECK_PTR(r, re); + CHECK_MEM(buffer + 4, "wxyz", 4); + CHECK_INT(buffer[8], '#'); +} + +static void case_bytes_do_not_terminate(void) { + char buffer[8]; + char *r = buffer, *re = buffer + 4; + + memset(buffer, '#', sizeof(buffer)); + test_case("unlike an append, a run of bytes may fill the room exactly"); + fmt_bytes(&r, re, "abcd", 4); + CHECK_PTR(r, re); + CHECK_MEM(buffer, "abcd", 4); + CHECK_INT(buffer[4], '#'); +} + +void test_fmt(void) { + case_appends_in_sequence(); + case_truncation_stops_at_the_end(); + case_a_full_buffer_takes_nothing_more(); + case_an_append_that_just_fits(); + case_bytes_are_all_or_nothing(); + case_bytes_do_not_terminate(); +} -- cgit v1.3