Commit | Line | Data |
---|---|---|
eff136f6 MW |
1 | #include "config.h" |
2 | ||
3 | #include <assert.h> | |
4 | #include <float.h> | |
5 | #include <stdarg.h> | |
6 | #include <stdio.h> | |
7 | #include <stdlib.h> | |
8 | #include <string.h> | |
9 | ||
10 | #include "dstr.h" | |
36188114 | 11 | #include "macros.h" |
3efcfd2d MW |
12 | #include "report.h" |
13 | #include "tvec.h" | |
eff136f6 | 14 | |
3efcfd2d | 15 | static struct tvec_state tvstate; |
eff136f6 | 16 | static dstr d = DSTR_INIT; |
3efcfd2d | 17 | static char strbuf[1024]; |
eff136f6 | 18 | |
3efcfd2d | 19 | #define TESTGROUP(name) TVEC_TESTGROUP_TAG(grp, &tvstate, name) |
eff136f6 MW |
20 | |
21 | static void PRINTF_LIKE(1, 2) format(const char *fmt, ...) | |
22 | { | |
23 | va_list ap; | |
24 | va_start(ap, fmt); | |
25 | dstr_reset(&d); | |
26 | dstr_vputf(&d, fmt, &ap); | |
27 | va_end(ap); | |
28 | } | |
29 | ||
30 | static void PRINTF_LIKE(1, 2) prepare(const char *fmt, ...) | |
31 | { | |
32 | va_list ap; | |
33 | int n; | |
34 | ||
35 | va_start(ap, fmt); | |
36 | #ifdef HAVE_SNPRINTF | |
3efcfd2d | 37 | n = vsnprintf(strbuf, sizeof(strbuf), fmt, ap); |
eff136f6 | 38 | #else |
3efcfd2d | 39 | n = vsprintf(strbuf, fmt, ap); |
eff136f6 | 40 | #endif |
3efcfd2d | 41 | assert(0 <= n && n < sizeof(strbuf)); |
eff136f6 MW |
42 | } |
43 | ||
3efcfd2d | 44 | #define TEST_KNOWN(fmtargs, want) do { \ |
eff136f6 | 45 | format fmtargs; \ |
3efcfd2d MW |
46 | tvec_claimeq_string(&tvstate, d.buf, d.len, want, strlen(want), \ |
47 | __FILE__, __LINE__, "format " #fmtargs); \ | |
eff136f6 MW |
48 | } while (0) |
49 | ||
3efcfd2d | 50 | #define TEST_REF(fmtargs) do { \ |
eff136f6 | 51 | format fmtargs; \ |
3efcfd2d MW |
52 | prepare fmtargs; \ |
53 | tvec_claimeq_string(&tvstate, d.buf, d.len, strbuf, strlen(strbuf), \ | |
54 | __FILE__, __LINE__, "format " #fmtargs); \ | |
eff136f6 MW |
55 | } while (0) |
56 | ||
57 | #define LENGTHY \ | |
58 | "This is a rather longer string than the code is expecting: will it fit?" | |
59 | ||
3efcfd2d | 60 | int main(int argc, char *argv[]) |
eff136f6 | 61 | { |
3efcfd2d MW |
62 | struct tvec_test test; |
63 | int argpos; | |
64 | ||
65 | tvec_parseargs(argc, argv, &tvstate, &argpos, &tvec_adhocconfig); | |
66 | if (argpos < argc) die(2, "no input files expected"); | |
67 | tvec_adhoc(&tvstate, &test); | |
68 | ||
69 | TESTGROUP("basics") { | |
70 | TEST_KNOWN(("Hello, world!"), "Hello, world!"); | |
71 | TEST_KNOWN(("just a ->%%<- sign"), "just a ->%<- sign"); | |
72 | } | |
73 | ||
74 | TESTGROUP("integers") { | |
75 | TEST_KNOWN(("Testing, testing, %d, %d, %d.", 1, 2, 3), | |
76 | "Testing, testing, 1, 2, 3."); | |
77 | TEST_KNOWN(("->%5d<-", 138), "-> 138<-"); | |
78 | TEST_KNOWN(("->%*d<-", 5, 138), "-> 138<-"); | |
79 | TEST_KNOWN(("->%-*d<-", 5, 138), "->138 <-"); | |
80 | TEST_KNOWN(("->%*d<-", -5, 138), "->138 <-"); | |
81 | TEST_KNOWN(("->%-*d<-", -5, 138), "->138 <-"); | |
82 | } | |
83 | ||
84 | TESTGROUP("strings") { | |
85 | TEST_KNOWN(("->%.*s<-", 5, "truncate me"), "->trunc<-"); | |
86 | TEST_KNOWN(("->%.*s<-", -5, "don't truncate me"), | |
87 | "->don't truncate me<-"); | |
88 | TEST_KNOWN(("Truncation indirect: ->%.*s<-", 10, | |
89 | "a long string to be chopped"), | |
90 | "Truncation indirect: ->a long str<-"); | |
91 | } | |
92 | ||
93 | TESTGROUP("combinations") { | |
94 | TEST_KNOWN(("%08lx:%s", 0x65604204ul, "tripe-ec"), "65604204:tripe-ec"); | |
95 | TEST_REF(("big float: ->%f<- and integer %d\n", DBL_MAX, 42)); | |
96 | } | |
97 | ||
98 | TESTGROUP("argument-order") { | |
99 | TEST_KNOWN(("Testing, testing, %3$d, %2$d, %1$d.", 3, 2, 1), | |
100 | "Testing, testing, 1, 2, 3."); | |
101 | TEST_KNOWN(("Truncation indirect: ->%1$.*2$s<-", | |
102 | "a long string to be chopped", 10), | |
103 | "Truncation indirect: ->a long str<-"); | |
104 | } | |
105 | ||
106 | TESTGROUP("misc") | |
107 | TEST_KNOWN(("%s", LENGTHY), LENGTHY); | |
108 | ||
109 | return (tvec_end(&tvstate)); | |
eff136f6 | 110 | } |