]> git.proxmox.com Git - mirror_frr.git/blame - tests/lib/test_printfrr.c
*: auto-convert to SPDX License IDs
[mirror_frr.git] / tests / lib / test_printfrr.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
b9911c2e
DL
2/*
3 * printfrr() unit test
4 * Copyright (C) 2019 David Lamparter
b9911c2e
DL
5 */
6
7#include "zebra.h"
8
9#include <math.h>
10
11#include "lib/printfrr.h"
12#include "lib/memory.h"
13#include "lib/prefix.h"
016cfe70 14#include "lib/nexthop.h"
b9911c2e
DL
15
16static int errors;
17
afb35622 18static void printcmp(const char *fmt, ...) PRINTFRR(1, 2);
b9911c2e
DL
19static void printcmp(const char *fmt, ...)
20{
21 va_list ap;
22 char buf[256], bufrr[256], *p;
23 int cmp;
24 memset(bufrr, 0xcc, sizeof(bufrr));
25
26 va_start(ap, fmt);
27 vsnprintf(buf, sizeof(buf), fmt, ap);
28 va_end(ap);
29
30 va_start(ap, fmt);
31 vsnprintfrr(bufrr, sizeof(bufrr), fmt, ap);
32 va_end(ap);
33
34 cmp = strcmp(buf, bufrr);
35
36 /* OS dependent "+nan" vs. "nan" */
37 if (cmp && (p = strstr(bufrr, "+nan"))) {
38 p[0] = ' ';
39 if (!strcmp(buf, bufrr))
40 cmp = 0;
41 p[0] = '+';
42 }
43 printf("fmt: \"%s\"\nsys: \"%s\"\nfrr: \"%s\"\n%s\n\n",
44 fmt, buf, bufrr, cmp ? "ERROR" : "ok");
45
46 if (cmp)
47 errors++;
48}
49
cb4928ce
DL
50static int printchk(const char *ref, const char *fmt, ...) PRINTFRR(2, 3);
51static int printchk(const char *ref, const char *fmt, ...)
b9911c2e
DL
52{
53 va_list ap;
54 char bufrr[256];
212e04e5
DL
55 bool truncfail = false;
56 size_t i;
57 size_t expectlen;
58
b9911c2e
DL
59 memset(bufrr, 0xcc, sizeof(bufrr));
60
212e04e5
DL
61 va_start(ap, fmt);
62 expectlen = vsnprintfrr(NULL, 0, fmt, ap);
63 va_end(ap);
64
65 va_start(ap, fmt);
66 vsnprintfrr(bufrr, 7, fmt, ap);
67 va_end(ap);
68
69 if (strnlen(bufrr, 7) == 7)
70 truncfail = true;
71 if (strnlen(bufrr, 7) < 7 && strncmp(ref, bufrr, 6) != 0)
72 truncfail = true;
73 for (i = 7; i < sizeof(bufrr); i++)
74 if (bufrr[i] != (char)0xcc) {
75 truncfail = true;
76 break;
77 }
78
79 if (truncfail) {
80 printf("truncation test FAILED:\n"
81 "fmt: \"%s\"\nref: \"%s\"\nfrr[:7]: \"%s\"\n%s\n\n",
82 fmt, ref, bufrr, strcmp(ref, bufrr) ? "ERROR" : "ok");
83 errors++;
84 }
85
487eefcf
DL
86 struct fmt_outpos outpos[16];
87 struct fbuf fb = {
88 .buf = bufrr,
89 .pos = bufrr,
90 .len = sizeof(bufrr) - 1,
91 .outpos = outpos,
92 .outpos_n = array_size(outpos),
93 };
94
b9911c2e 95 va_start(ap, fmt);
487eefcf
DL
96 vbprintfrr(&fb, fmt, ap);
97 fb.pos[0] = '\0';
b9911c2e
DL
98 va_end(ap);
99
487eefcf 100 printf("fmt: \"%s\"\nref: \"%s\"\nfrr: \"%s\"\n%s\n",
b9911c2e
DL
101 fmt, ref, bufrr, strcmp(ref, bufrr) ? "ERROR" : "ok");
102 if (strcmp(ref, bufrr))
103 errors++;
212e04e5
DL
104 if (strlen(bufrr) != expectlen) {
105 printf("return value <> length mismatch\n");
106 errors++;
107 }
487eefcf
DL
108
109 for (size_t i = 0; i < fb.outpos_i; i++)
110 printf("\t[%zu: %u..%u] = \"%.*s\"\n", i,
111 outpos[i].off_start,
112 outpos[i].off_end,
113 (int)(outpos[i].off_end - outpos[i].off_start),
114 bufrr + outpos[i].off_start);
115 printf("\n");
cb4928ce 116 return 0;
b9911c2e
DL
117}
118
9c4380da
DL
119static void test_va(const char *ref, const char *fmt, ...) PRINTFRR(2, 3);
120static void test_va(const char *ref, const char *fmt, ...)
121{
122 struct va_format vaf;
123 va_list ap;
124
125 va_start(ap, fmt);
126 vaf.fmt = fmt;
127 vaf.va = &ap;
128
129 printchk(ref, "VA [%pVA] %s", &vaf, "--");
130
131 va_end(ap);
132}
133
b9911c2e
DL
134int main(int argc, char **argv)
135{
136 size_t i;
137 float flts[] = {
138 123.456789,
139 23.456789e-30,
140 3.456789e+30,
141 INFINITY,
142 NAN,
143 };
144 uint64_t ui64 = 0xfeed1278cafef00d;
145 struct in_addr ip;
146 char *p;
147 char buf[256];
148
149 printcmp("%d %u %d %u", 123, 123, -456, -456);
150 printcmp("%lld %llu %lld %llu", 123LL, 123LL, -456LL, -456LL);
151
152 printcmp("%-20s,%20s,%.20s", "test", "test", "test");
153 printcmp("%-3s,%3s,%.3s", "test", "test", "test");
154 printcmp("%-6.3s,%6.3s,%6.3s", "test", "test", "test");
155 printcmp("%*s,%*s,%.*s", -3, "test", 3, "test", 3, "test");
156
157 for (i = 0; i < array_size(flts); i++) {
158 printcmp("%-6.3e,%6.3e,%+06.3e", flts[i], flts[i], flts[i]);
159 printcmp("%-6.3f,%6.3f,%+06.3f", flts[i], flts[i], flts[i]);
160 printcmp("%-6.3g,%6.3g,%+06.3g", flts[i], flts[i], flts[i]);
161 printcmp("%-6.3a,%6.3a,%+06.3a", flts[i], flts[i], flts[i]);
162 }
163
164 printchk("-77385308584349683 18369358765125201933 feed1278cafef00d",
165 "%Ld %Lu %Lx", ui64, ui64, ui64);
166
167 inet_aton("192.168.1.2", &ip);
168 printchk("192.168.1.2", "%pI4", &ip);
169 printchk(" 192.168.1.2", "%20pI4", &ip);
212e04e5 170 printchk("192.168.1.2 ", "%-20pI4", &ip);
b9911c2e
DL
171
172 printcmp("%p", &ip);
173
9c4380da
DL
174 test_va("VA [192.168.1.2 1234] --", "%pI4 %u", &ip, 1234);
175
2c5b4d80
DL
176 inet_aton("0.0.0.0", &ip);
177 printchk("0.0.0.0", "%pI4", &ip);
178 printchk("*", "%pI4s", &ip);
179
b9911c2e
DL
180 snprintfrr(buf, sizeof(buf), "test%s", "#1");
181 csnprintfrr(buf, sizeof(buf), "test%s", "#2");
182 assert(strcmp(buf, "test#1test#2") == 0);
183
184 p = asnprintfrr(MTYPE_TMP, buf, sizeof(buf), "test%s", "#3");
185 assert(p == buf);
186 assert(strcmp(buf, "test#3") == 0);
187
188 p = asnprintfrr(MTYPE_TMP, buf, 4, "test%s", "#4");
189 assert(p != buf);
190 assert(strcmp(p, "test#4") == 0);
191 XFREE(MTYPE_TMP, p);
192
193 p = asprintfrr(MTYPE_TMP, "test%s", "#5");
194 assert(strcmp(p, "test#5") == 0);
195 XFREE(MTYPE_TMP, p);
196
543a2684
DL
197 struct prefix pfx;
198
199 str2prefix("192.168.1.23/24", &pfx);
200 printchk("192.168.1.23/24", "%pFX", &pfx);
201 printchk("192.168.1.23", "%pFXh", &pfx);
202
203 str2prefix("2001:db8::1234/64", &pfx);
204 printchk("2001:db8::1234/64", "%pFX", &pfx);
205 printchk("2001:db8::1234", "%pFXh", &pfx);
206
207 pfx.family = AF_UNIX;
208 printchk("UNK prefix", "%pFX", &pfx);
209 printchk("{prefix.af=AF_UNIX}", "%pFXh", &pfx);
210
211 str2prefix_eth("02:ca:fe:f0:0d:1e/48", (struct prefix_eth *)&pfx);
212 printchk("02:ca:fe:f0:0d:1e/48", "%pFX", &pfx);
213 printchk("02:ca:fe:f0:0d:1e", "%pFXh", &pfx);
214
b9911c2e
DL
215 struct prefix_sg sg;
216 sg.src.s_addr = INADDR_ANY;
217 sg.grp.s_addr = INADDR_ANY;
d51f8b0f 218 printchk("(*,*)", "%pPSG4", &sg);
b9911c2e
DL
219
220 inet_aton("192.168.1.2", &sg.src);
d51f8b0f 221 printchk("(192.168.1.2,*)", "%pPSG4", &sg);
b9911c2e
DL
222
223 inet_aton("224.1.2.3", &sg.grp);
d51f8b0f 224 printchk("(192.168.1.2,224.1.2.3)", "%pPSG4", &sg);
b9911c2e
DL
225
226 sg.src.s_addr = INADDR_ANY;
d51f8b0f 227 printchk("(*,224.1.2.3)", "%pPSG4", &sg);
b9911c2e 228
a4cb97a6
DL
229 uint8_t randhex[] = { 0x12, 0x34, 0x00, 0xca, 0xfe, 0x00, 0xaa, 0x55 };
230
7798203f
DL
231 FMT_NSTD(printchk("12 34 00 ca fe 00 aa 55", "%.8pHX", randhex));
232 FMT_NSTD(printchk("12 34 00 ca fe 00 aa 55", "%.*pHX",
233 (int)sizeof(randhex), randhex));
234 FMT_NSTD(printchk("12 34 00 ca", "%.4pHX", randhex));
235
236 printchk("12 34 00 ca fe 00 aa 55", "%8pHX", randhex);
237 printchk("12 34 00 ca fe 00 aa 55", "%*pHX",
a4cb97a6 238 (int)sizeof(randhex), randhex);
7798203f
DL
239 printchk("12 34 00 ca", "%4pHX", randhex);
240
241 printchk("", "%pHX", randhex);
242
243 printchk("12:34:00:ca:fe:00:aa:55", "%8pHXc", randhex);
244 printchk("123400cafe00aa55", "%8pHXn", randhex);
245
246 printchk("/test/pa\\ th/\\~spe\\ncial\\x01/file.name", "%pSE",
247 "/test/pa th/~spe\ncial\x01/file.name");
248 printchk("/test/pa\\ th/\\~spe\\n", "%17pSE",
249 "/test/pa th/~spe\ncial\x01/file.name");
250
251 char nulltest[] = { 'n', 'u', 0, 'l', 'l' };
252
253 printchk("nu\\x00ll", "%5pSE", nulltest);
254 printchk("nu\\x00ll", "%*pSE", 5, nulltest);
a4cb97a6 255
7798203f
DL
256 printchk("bl\\\"ah\\x01te[st\\nab]c", "%pSQ",
257 "bl\"ah\x01te[st\nab]c");
258 printchk("\"bl\\\"ah\\x01te[st\\nab]c\"", "%pSQq",
259 "bl\"ah\x01te[st\nab]c");
260 printchk("\"bl\\\"ah\\x01te[st\\x0aab\\]c\"", "%pSQqs",
261 "bl\"ah\x01te[st\nab]c");
262 printchk("\"\"", "%pSQqn", "");
263 printchk("\"\"", "%pSQqn", (char *)NULL);
264 printchk("(null)", "%pSQq", (char *)NULL);
a4cb97a6 265
016cfe70
PZ
266 /*
267 * %pNH<foo> tests
268 *
269 * gateway addresses only for now: interfaces require more setup
270 */
fec9fb29
DL
271 printchk("(null)", "%pNHcg", (struct nexthop *)NULL);
272 printchk("(null)", "%pNHci", (struct nexthop *)NULL);
016cfe70
PZ
273
274 struct nexthop nh;
275
276 memset(&nh, 0, sizeof(nh));
277
278 nh.type = NEXTHOP_TYPE_IPV4;
279 inet_aton("3.2.1.0", &nh.gate.ipv4);
280 printchk("3.2.1.0", "%pNHcg", &nh);
281
282 nh.type = NEXTHOP_TYPE_IPV6;
283 inet_pton(AF_INET6, "fe2c::34", &nh.gate.ipv6);
284 printchk("fe2c::34", "%pNHcg", &nh);
285
2c76ba43
DL
286 /* time printing */
287
288 /* need a non-UTC timezone for testing */
289 setenv("TZ", "TEST-01:00", 1);
290 tzset();
291
292 struct timespec ts;
293 struct timeval tv;
294 time_t tt;
295
296 ts.tv_sec = tv.tv_sec = tt = 1642015880;
297 ts.tv_nsec = 123456789;
298 tv.tv_usec = 234567;
299
300 printchk("Wed Jan 12 20:31:20 2022", "%pTSR", &ts);
301 printchk("Wed Jan 12 20:31:20 2022", "%pTVR", &tv);
302 printchk("Wed Jan 12 20:31:20 2022", "%pTTR", &tt);
303
304 FMT_NSTD(printchk("Wed Jan 12 20:31:20 2022", "%.3pTSR", &ts));
305
306 printchk("2022-01-12T20:31:20.123", "%pTSRi", &ts);
307 printchk("2022-01-12 20:31:20.123", "%pTSRip", &ts);
308 printchk("2022-01-12 20:31:20.123", "%pTSRpi", &ts);
309 FMT_NSTD(printchk("2022-01-12T20:31:20", "%.0pTSRi", &ts));
310 FMT_NSTD(printchk("2022-01-12T20:31:20.123456789", "%.9pTSRi", &ts));
311 FMT_NSTD(printchk("2022-01-12T20:31:20", "%.3pTTRi", &tt));
312
313 ts.tv_sec = tv.tv_sec = tt = 9 * 86400 + 12345;
314
315 printchk("1w 2d 03:25:45.123", "%pTSIp", &ts);
316 printchk("1w2d03:25:45.123", "%pTSI", &ts);
317 printchk("1w2d03:25:45.234", "%pTVI", &tv);
318 printchk("1w2d03:25:45", "%pTTI", &tt);
319
320 printchk("1w 2d 03h", "%pTVItp", &tv);
321 printchk("1w2d03h", "%pTSIt", &ts);
322
323 printchk("219:25:45", "%pTVIh", &tv);
324 printchk("13165:45", "%pTVIm", &tv);
325
326 ts.tv_sec = tv.tv_sec = tt = 1 * 86400 + 12345;
327
328 printchk("1d 03:25:45.123", "%pTSIp", &ts);
329 printchk("1d03:25:45.234", "%pTVI", &tv);
330
331 printchk("1d 03h 25m", "%pTVItp", &tv);
332 printchk("1d03h25m", "%pTSIt", &ts);
333
334 printchk("98745.234", "%pTVId", &tv);
335
336 printchk("27:25:45", "%pTVIh", &tv);
337 printchk("1645:45", "%pTVIm", &tv);
338
339 ts.tv_sec = tv.tv_sec = tt = 12345;
340
341 printchk("03:25:45.123", "%pTSIp", &ts);
342 printchk("03:25:45.123", "%pTSI", &ts);
343 printchk("03:25:45.234", "%pTVI", &tv);
344 printchk("03:25:45", "%pTTI", &tt);
345
346 printchk("03:25:45", "%pTSItp", &ts);
347 printchk("03:25:45", "%pTVIt", &tv);
348
349 printchk("12345.234", "%pTVId", &tv);
350
351 printchk("03:25:45", "%pTVIh", &tv);
352 printchk("205:45", "%pTVIm", &tv);
353
354 ts.tv_sec = tv.tv_sec = tt = 0;
355
356 printchk("00:00:00.123", "%pTSIp", &ts);
357 printchk("00:00:00.123", "%pTSI", &ts);
358 printchk("00:00:00.234", "%pTVI", &tv);
359 printchk("00:00:00", "%pTTI", &tt);
360
361 printchk("00:00:00", "%pTVItp", &tv);
362 printchk("00:00:00", "%pTSIt", &ts);
363
364 printchk("0.234", "%pTVId", &tv);
365 printchk("0.234", "%pTVIdx", &tv);
366 printchk("-", "%pTTIdx", &tt);
367
368 printchk("00:00:00", "%pTVIhx", &tv);
369 printchk("--:--:--", "%pTTIhx", &tt);
370 printchk("00:00", "%pTVImx", &tv);
371 printchk("--:--", "%pTTImx", &tt);
372
373 ts.tv_sec = tv.tv_sec = tt = -10;
374
375 printchk("-00:00:09.876", "%pTSIp", &ts);
376 printchk("-00:00:09.876", "%pTSI", &ts);
377 printchk("-00:00:09.765", "%pTVI", &tv);
378 printchk("-00:00:10", "%pTTI", &tt);
379
380 printchk("-00:00:09", "%pTSItp", &ts);
381 printchk("-00:00:09", "%pTSIt", &ts);
382 printchk("-00:00:09", "%pTVIt", &tv);
383 printchk("-00:00:10", "%pTTIt", &tt);
384
385 printchk("-9.765", "%pTVId", &tv);
386 printchk("-", "%pTVIdx", &tv);
387
388 printchk("-00:00:09", "%pTSIh", &ts);
389 printchk("--:--:--", "%pTVIhx", &tv);
390 printchk("--:--:--", "%pTTIhx", &tt);
391
392 printchk("-00:09", "%pTSIm", &ts);
393 printchk("--:--", "%pTVImx", &tv);
394 printchk("--:--", "%pTTImx", &tt);
395
b9911c2e
DL
396 return !!errors;
397}