4 * The canonical version of this file is maintained in the rra-c-util package,
5 * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
7 * Written by Russ Allbery <eagle@eyrie.org>
8 * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006
9 * Russ Allbery <eagle@eyrie.org>
10 * Copyright 2009, 2010
11 * The Board of Trustees of the Leland Stanford Junior University
12 * Copyright 1995 Patrick Powell
13 * Copyright 2001 Hrvoje Niksic
15 * This code is based on code written by Patrick Powell (papowell@astart.com)
16 * It may be used for any purpose as long as this notice remains intact
17 * on all source code distributions
21 #include <portable/system.h>
23 #include <tests/tap/basic.h>
26 * Disable the requirement that format strings be literals. We need variable
27 * formats for easy testing.
29 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2) || defined(__clang__)
30 # pragma GCC diagnostic ignored "-Wformat-nonliteral"
34 * Intentionally don't add the printf attribute here since we pass a
35 * zero-length printf format during testing and don't want warnings.
37 int test_snprintf(char *str, size_t count, const char *fmt, ...);
38 int test_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
40 static const char string[] = "abcdefghijklmnopqrstuvwxyz0123456789";
42 static const char *const fp_formats[] = {
43 "%-1.5f", "%1.5f", "%31.9f", "%10.5f", "% 10.5f", "%+22.9f",
44 "%+4.9f", "%01.3f", "%3.1f", "%3.2f", "%.0f", "%.1f",
47 /* %e and %g formats aren't really implemented yet. */
49 "%-1.5e", "%1.5e", "%31.9e", "%10.5e", "% 10.5e", "%+22.9e",
50 "%+4.9e", "%01.3e", "%3.1e", "%3.2e", "%.0e", "%.1e",
52 "%-1.5g", "%1.5g", "%31.9g", "%10.5g", "% 10.5g", "%+22.9g",
53 "%+4.9g", "%01.3g", "%3.1g", "%3.2g", "%.0g", "%.1g",
58 static const char *const int_formats[] = {
59 "%-1.5d", "%1.5d", "%31.9d", "%5.5d", "%10.5d", "% 10.5d",
60 "%+22.30d", "%01.3d", "%4d", "%d", "%ld", NULL
62 static const char *const uint_formats[] = {
63 "%-1.5lu", "%1.5lu", "%31.9lu", "%5.5lu", "%10.5lu", "% 10.5lu",
64 "%+6.30lu", "%01.3lu", "%4lu", "%lu", "%4lx", "%4lX",
65 "%01.3lx", "%1lo", NULL
67 static const char *const llong_formats[] = {
68 "%lld", "%-1.5lld", "%1.5lld", "%123.9lld", "%5.5lld",
69 "%10.5lld", "% 10.5lld", "%+22.33lld", "%01.3lld", "%4lld",
72 static const char *const ullong_formats[] = {
73 "%llu", "%-1.5llu", "%1.5llu", "%123.9llu", "%5.5llu",
74 "%10.5llu", "% 10.5llu", "%+22.33llu", "%01.3llu", "%4llu",
78 static const double fp_nums[] = {
79 -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, 0.9996, 1.996,
80 4.136, 0.1, 0.01, 0.001, 10.1, 0
82 static long int_nums[] = {
83 -1, 134, 91340, 341, 0203, 0
85 static unsigned long uint_nums[] = {
86 (unsigned long) -1, 134, 91340, 341, 0203, 0
88 static long long llong_nums[] = {
89 ~(long long) 0, /* All-1 bit pattern. */
90 (~(unsigned long long) 0) >> 1, /* Largest signed long long. */
91 -150, 134, 91340, 341,
94 static unsigned long long ullong_nums[] = {
95 ~(unsigned long long) 0, /* All-1 bit pattern. */
96 (~(unsigned long long) 0) >> 1, /* Largest signed long long. */
103 test_format(bool trunc, const char *expected, int count,
104 const char *format, ...)
110 va_start(args, format);
111 result = test_vsnprintf(buf, trunc ? 32 : sizeof(buf), format, args);
113 is_string(expected, buf, "format %s, wanted %s", format, expected);
114 is_int(count, result, "...and output length correct");
127 (18 + (ARRAY_SIZE(fp_formats) - 1) * ARRAY_SIZE(fp_nums)
128 + (ARRAY_SIZE(int_formats) - 1) * ARRAY_SIZE(int_nums)
129 + (ARRAY_SIZE(uint_formats) - 1) * ARRAY_SIZE(uint_nums)
130 + (ARRAY_SIZE(llong_formats) - 1) * ARRAY_SIZE(llong_nums)
131 + (ARRAY_SIZE(ullong_formats) - 1) * ARRAY_SIZE(ullong_nums)) * 2);
133 is_int(4, test_snprintf(NULL, 0, "%s", "abcd"), "simple string length");
134 is_int(2, test_snprintf(NULL, 0, "%d", 20), "number length");
135 is_int(7, test_snprintf(NULL, 0, "Test %.2s", "abcd"), "limited string");
136 is_int(1, test_snprintf(NULL, 0, "%c", 'a'), "character length");
137 is_int(0, test_snprintf(NULL, 0, ""), "empty format length");
139 test_format(true, "abcd", 4, "%s", "abcd");
140 test_format(true, "20", 2, "%d", 20);
141 test_format(true, "Test ab", 7, "Test %.2s", "abcd");
142 test_format(true, "a", 1, "%c", 'a');
143 test_format(true, "", 0, "");
144 test_format(true, "abcdefghijklmnopqrstuvwxyz01234", 36, "%s", string);
145 test_format(true, "abcdefghij", 10, "%.10s", string);
146 test_format(true, " abcdefghij", 12, "%12.10s", string);
147 test_format(true, " abcdefghijklmnopqrstuvwxyz0", 40, "%40s", string);
148 test_format(true, "abcdefghij ", 14, "%-14.10s", string);
149 test_format(true, " abcdefghijklmnopq", 50, "%50s", string);
150 test_format(true, "%abcd%", 6, "%%%0s%%", "abcd");
151 test_format(true, "", 0, "%.0s", string);
152 test_format(true, "abcdefghijklmnopqrstuvwxyz 444", 32, "%.26s %d",
154 test_format(true, "abcdefghijklmnopqrstuvwxyz -2.", 32, "%.26s %.1f",
156 test_format(true, "abcdefghij4444", 14, "%.10s%n%d", string, &count, 4444);
157 is_int(10, count, "correct output from %%n");
158 test_format(true, "abcdefghijklmnopqrstuvwxyz01234", 36, "%n%s%ln",
159 &count, string, &lcount);
160 is_int(0, count, "correct output from two %%n");
161 is_int(31, lcount, "correct output from long %%ln");
162 test_format(true, "(null)", 6, "%s", NULL);
164 for (i = 0; fp_formats[i] != NULL; i++)
165 for (j = 0; j < ARRAY_SIZE(fp_nums); j++) {
166 count = sprintf(lgbuf, fp_formats[i], fp_nums[j]);
167 test_format(false, lgbuf, count, fp_formats[i], fp_nums[j]);
169 for (i = 0; int_formats[i] != NULL; i++)
170 for (j = 0; j < ARRAY_SIZE(int_nums); j++) {
171 count = sprintf(lgbuf, int_formats[i], int_nums[j]);
172 test_format(false, lgbuf, count, int_formats[i], int_nums[j]);
174 for (i = 0; uint_formats[i] != NULL; i++)
175 for (j = 0; j < ARRAY_SIZE(uint_nums); j++) {
176 count = sprintf(lgbuf, uint_formats[i], uint_nums[j]);
177 test_format(false, lgbuf, count, uint_formats[i], uint_nums[j]);
179 for (i = 0; llong_formats[i] != NULL; i++)
180 for (j = 0; j < ARRAY_SIZE(llong_nums); j++) {
181 count = sprintf(lgbuf, llong_formats[i], llong_nums[j]);
182 test_format(false, lgbuf, count, llong_formats[i], llong_nums[j]);
184 for (i = 0; ullong_formats[i] != NULL; i++)
185 for (j = 0; j < ARRAY_SIZE(ullong_nums); j++) {
186 count = sprintf(lgbuf, ullong_formats[i], ullong_nums[j]);
187 test_format(false, lgbuf, count, ullong_formats[i],