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