1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
/* This software was written by Dirk Engling <erdgeist@erdgeist.org>
It is considered beerware. Prost. Skol. Cheers or whatever.
$id$ */
/* System */
#include <string.h>
/* 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();
}
|