/* 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(); }