1 /* Test for wchar_t/multi-byte conversion and precision in vfprintf.
2 Copyright (C) 2017-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
24 #include <support/check.h>
25 #include <support/test-driver.h>
28 #define DYNARRAY_STRUCT str
29 #define DYNARRAY_ELEMENT char
30 #define DYNARRAY_PREFIX str_
31 #include <malloc/dynarray-skeleton.c>
33 #define DYNARRAY_STRUCT wstr
34 #define DYNARRAY_ELEMENT wchar_t
35 #define DYNARRAY_PREFIX wstr_
36 #include <malloc/dynarray-skeleton.c>
38 #define DYNARRAY_STRUCT len
39 #define DYNARRAY_ELEMENT size_t
40 #define DYNARRAY_PREFIX len_
41 #include <malloc/dynarray-skeleton.c>
43 /* This should be larger than the internal buffer in vfprintf. The
44 constant needs to be kept in sync with the format strings in
45 test_mbs_long and test_wide_long. */
46 enum { WIDE_STRING_LENGTH
= 1000 };
48 /* Creates two large, random strings used for truncation testing.
49 After the call, *MBS will be encoded in UTF-8, and *WIDE will
50 contain the same string in the internal UCS-32 encoding. Both
51 strings are null-terminated. The array *LENGTH counts the number
52 of multi-byte characters for each prefix string of *WIDE: The first
53 N wide characters of *WIDE correspond the first (*LENGTH)[N] bytes
54 of *MBS. The caller should deallocate all three arrays using
57 make_random_string (char **mbs
, wchar_t **wide
, size_t **length
)
66 for (int i
= 0; i
< WIDE_STRING_LENGTH
; ++i
)
68 len_add (&len
, str_size (&str
));
69 /* Cover some multi-byte UTF-8 sequences. Avoid the null
71 uint32_t ch
= 1 + (rand () % 521);
74 /* Limited UTF-8 conversion. */
79 /* We only implement two-byte sequences. */
80 uint32_t first
= ch
>> 6;
81 TEST_VERIFY (first
< 32);
82 str_add (&str
, 0xC0 | first
);
83 str_add (&str
, 0x80 | (ch
& 0x3f));
86 len_add (&len
, str_size (&str
));
87 wstr_add (&wstr
, L
'\0');
90 *mbs
= str_finalize (&str
, NULL
);
91 TEST_VERIFY_EXIT (*mbs
!= NULL
);
92 *wide
= wstr_finalize (&wstr
, NULL
);
93 TEST_VERIFY_EXIT (*wide
!= NULL
);
94 *length
= len_finalize (&len
, NULL
);
95 TEST_VERIFY_EXIT (*length
!= NULL
);
98 /* snprintf tests (multi-byte result). */
100 test_mbs_result (void)
104 /* ASCII wide string. */
105 memset (buf
, '@', sizeof (buf
));
106 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%ls", L
"xyz") == 3);
107 TEST_VERIFY (strcmp (buf
, "xyz") == 0);
109 /* Unicode wide string. */
110 memset (buf
, '@', sizeof (buf
));
111 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%ls", L
"x\u00DFz") == 4);
112 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
114 /* Varying precisions. */
115 memset (buf
, '@', sizeof (buf
));
116 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%.1ls", L
"x\u00DFz") == 1);
117 TEST_VERIFY (strcmp (buf
, "x") == 0);
118 memset (buf
, '@', sizeof (buf
));
119 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%.2ls", L
"x\u00DFz") == 1);
120 TEST_VERIFY (strcmp (buf
, "x") == 0);
121 memset (buf
, '@', sizeof (buf
));
122 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%.3ls", L
"x\u00DFz") == 3);
123 TEST_VERIFY (strcmp (buf
, "x\xC3\x9F") == 0);
124 memset (buf
, '@', sizeof (buf
));
125 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%.4ls", L
"x\u00DFz") == 4);
126 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
127 memset (buf
, '@', sizeof (buf
));
128 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%.5ls", L
"x\u00DFz") == 4);
129 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
131 /* Varying precisions with width 2, right-justified. */
132 memset (buf
, '@', sizeof (buf
));
133 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%2.1ls", L
"x\u00DFz") == 2);
134 TEST_VERIFY (strcmp (buf
, " x") == 0);
135 memset (buf
, '@', sizeof (buf
));
136 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%2.2ls", L
"x\u00DFz") == 2);
137 TEST_VERIFY (strcmp (buf
, " x") == 0);
138 memset (buf
, '@', sizeof (buf
));
139 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%2.3ls", L
"x\u00DFz") == 3);
140 TEST_VERIFY (strcmp (buf
, "x\xC3\x9F") == 0);
141 memset (buf
, '@', sizeof (buf
));
142 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%2.4ls", L
"x\u00DFz") == 4);
143 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
144 memset (buf
, '@', sizeof (buf
));
145 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%2.5ls", L
"x\u00DFz") == 4);
146 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
148 /* Varying precisions with width 2, left-justified. */
149 memset (buf
, '@', sizeof (buf
));
150 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-2.1ls", L
"x\u00DFz") == 2);
151 TEST_VERIFY (strcmp (buf
, "x ") == 0);
152 memset (buf
, '@', sizeof (buf
));
153 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-2.2ls", L
"x\u00DFz") == 2);
154 TEST_VERIFY (strcmp (buf
, "x ") == 0);
155 memset (buf
, '@', sizeof (buf
));
156 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-2.3ls", L
"x\u00DFz") == 3);
157 TEST_VERIFY (strcmp (buf
, "x\xC3\x9F") == 0);
158 memset (buf
, '@', sizeof (buf
));
159 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-2.4ls", L
"x\u00DFz") == 4);
160 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
161 memset (buf
, '@', sizeof (buf
));
162 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-2.5ls", L
"x\u00DFz") == 4);
163 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
165 /* Varying precisions with width 3, right-justified. */
166 memset (buf
, '@', sizeof (buf
));
167 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%3.1ls", L
"x\u00DFz") == 3);
168 TEST_VERIFY (strcmp (buf
, " x") == 0);
169 memset (buf
, '@', sizeof (buf
));
170 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%3.2ls", L
"x\u00DFz") == 3);
171 TEST_VERIFY (strcmp (buf
, " x") == 0);
172 memset (buf
, '@', sizeof (buf
));
173 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%3.3ls", L
"x\u00DFz") == 3);
174 TEST_VERIFY (strcmp (buf
, "x\xC3\x9F") == 0);
175 memset (buf
, '@', sizeof (buf
));
176 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%3.4ls", L
"x\u00DFz") == 4);
177 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
178 memset (buf
, '@', sizeof (buf
));
179 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%3.5ls", L
"x\u00DFz") == 4);
180 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
182 /* Varying precisions with width 3, left-justified. */
183 memset (buf
, '@', sizeof (buf
));
184 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-3.1ls", L
"x\u00DFz") == 3);
185 TEST_VERIFY (strcmp (buf
, "x ") == 0);
186 memset (buf
, '@', sizeof (buf
));
187 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-3.2ls", L
"x\u00DFz") == 3);
188 TEST_VERIFY (strcmp (buf
, "x ") == 0);
189 memset (buf
, '@', sizeof (buf
));
190 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-3.3ls", L
"x\u00DFz") == 3);
191 TEST_VERIFY (strcmp (buf
, "x\xC3\x9F") == 0);
192 memset (buf
, '@', sizeof (buf
));
193 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-3.4ls", L
"x\u00DFz") == 4);
194 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
195 memset (buf
, '@', sizeof (buf
));
196 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-3.5ls", L
"x\u00DFz") == 4);
197 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
199 /* Varying precisions with width 4, right-justified. */
200 memset (buf
, '@', sizeof (buf
));
201 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%4.1ls", L
"x\u00DFz") == 4);
202 TEST_VERIFY (strcmp (buf
, " x") == 0);
203 memset (buf
, '@', sizeof (buf
));
204 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%4.2ls", L
"x\u00DFz") == 4);
205 TEST_VERIFY (strcmp (buf
, " x") == 0);
206 memset (buf
, '@', sizeof (buf
));
207 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%4.3ls", L
"x\u00DFz") == 4);
208 TEST_VERIFY (strcmp (buf
, " x\xC3\x9F") == 0);
209 memset (buf
, '@', sizeof (buf
));
210 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%4.4ls", L
"x\u00DFz") == 4);
211 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
212 memset (buf
, '@', sizeof (buf
));
213 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%4.5ls", L
"x\u00DFz") == 4);
214 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
216 /* Varying precisions with width 4, left-justified. */
217 memset (buf
, '@', sizeof (buf
));
218 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-4.1ls", L
"x\u00DFz") == 4);
219 TEST_VERIFY (strcmp (buf
, "x ") == 0);
220 memset (buf
, '@', sizeof (buf
));
221 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-4.2ls", L
"x\u00DFz") == 4);
222 TEST_VERIFY (strcmp (buf
, "x ") == 0);
223 memset (buf
, '@', sizeof (buf
));
224 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-4.3ls", L
"x\u00DFz") == 4);
225 TEST_VERIFY (strcmp (buf
, "x\xC3\x9F ") == 0);
226 memset (buf
, '@', sizeof (buf
));
227 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-4.4ls", L
"x\u00DFz") == 4);
228 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
229 memset (buf
, '@', sizeof (buf
));
230 TEST_VERIFY (snprintf (buf
, sizeof (buf
), "%-4.5ls", L
"x\u00DFz") == 4);
231 TEST_VERIFY (strcmp (buf
, "x\xC3\x9Fz") == 0);
234 /* swprintf tests (wide string result). */
236 test_wide_result (void)
241 /* ASCII wide string. */
242 wmemset (buf
, '@', size
);
243 TEST_VERIFY (swprintf (buf
, size
, L
"%s", "xyz") == 3);
244 TEST_VERIFY (wcscmp (buf
, L
"xyz") == 0);
246 /* Unicode wide string. */
247 wmemset (buf
, '@', size
);
248 TEST_VERIFY (swprintf (buf
, size
, L
"%s", "x\xC3\x9Fz") == 3);
249 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
251 /* Varying precisions. */
252 wmemset (buf
, '@', size
);
253 TEST_VERIFY (swprintf (buf
, size
, L
"%.1s", "x\xC3\x9Fz") == 1);
254 TEST_VERIFY (wcscmp (buf
, L
"x") == 0);
255 wmemset (buf
, '@', size
);
256 TEST_VERIFY (swprintf (buf
, size
, L
"%.2s", "x\xC3\x9Fz") == 2);
257 TEST_VERIFY (wcscmp (buf
, L
"x\u00DF") == 0);
258 wmemset (buf
, '@', size
);
259 TEST_VERIFY (swprintf (buf
, size
, L
"%.3s", "x\xC3\x9Fz") == 3);
260 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
261 wmemset (buf
, '@', size
);
262 TEST_VERIFY (swprintf (buf
, size
, L
"%.4s", "x\xC3\x9Fz") == 3);
263 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
265 /* Varying precisions with width 2, right-justified. */
266 wmemset (buf
, '@', size
);
267 TEST_VERIFY (swprintf (buf
, size
, L
"%2.1s", "x\xC3\x9Fz") == 2);
268 TEST_VERIFY (wcscmp (buf
, L
" x") == 0);
269 wmemset (buf
, '@', size
);
270 TEST_VERIFY (swprintf (buf
, size
, L
"%2.2s", "x\xC3\x9Fz") == 2);
271 TEST_VERIFY (wcscmp (buf
, L
"x\u00DF") == 0);
272 wmemset (buf
, '@', size
);
273 TEST_VERIFY (swprintf (buf
, size
, L
"%2.3s", "x\xC3\x9Fz") == 3);
274 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
275 wmemset (buf
, '@', size
);
276 TEST_VERIFY (swprintf (buf
, size
, L
"%2.4s", "x\xC3\x9Fz") == 3);
277 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
279 /* Varying precisions with width 2, left-justified. */
280 wmemset (buf
, '@', size
);
281 TEST_VERIFY (swprintf (buf
, size
, L
"%-2.1s", "x\xC3\x9Fz") == 2);
282 TEST_VERIFY (wcscmp (buf
, L
"x ") == 0);
283 wmemset (buf
, '@', size
);
284 TEST_VERIFY (swprintf (buf
, size
, L
"%-2.2s", "x\xC3\x9Fz") == 2);
285 TEST_VERIFY (wcscmp (buf
, L
"x\u00DF") == 0);
286 wmemset (buf
, '@', size
);
287 TEST_VERIFY (swprintf (buf
, size
, L
"%-2.3s", "x\xC3\x9Fz") == 3);
288 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
289 wmemset (buf
, '@', size
);
290 TEST_VERIFY (swprintf (buf
, size
, L
"%-2.4s", "x\xC3\x9Fz") == 3);
291 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
293 /* Varying precisions with width 3, right-justified. */
294 wmemset (buf
, '@', size
);
295 TEST_VERIFY (swprintf (buf
, size
, L
"%3.1s", "x\xC3\x9Fz") == 3);
296 TEST_VERIFY (wcscmp (buf
, L
" x") == 0);
297 wmemset (buf
, '@', size
);
298 TEST_VERIFY (swprintf (buf
, size
, L
"%3.2s", "x\xC3\x9Fz") == 3);
299 TEST_VERIFY (wcscmp (buf
, L
" x\u00DF") == 0);
300 wmemset (buf
, '@', size
);
301 TEST_VERIFY (swprintf (buf
, size
, L
"%3.3s", "x\xC3\x9Fz") == 3);
302 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
303 wmemset (buf
, '@', size
);
304 TEST_VERIFY (swprintf (buf
, size
, L
"%3.4s", "x\xC3\x9Fz") == 3);
305 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
307 /* Varying precisions with width 3, left-justified. */
308 wmemset (buf
, '@', size
);
309 TEST_VERIFY (swprintf (buf
, size
, L
"%-3.1s", "x\xC3\x9Fz") == 3);
310 TEST_VERIFY (wcscmp (buf
, L
"x ") == 0);
311 wmemset (buf
, '@', size
);
312 TEST_VERIFY (swprintf (buf
, size
, L
"%-3.2s", "x\xC3\x9Fz") == 3);
313 TEST_VERIFY (wcscmp (buf
, L
"x\u00DF ") == 0);
314 wmemset (buf
, '@', size
);
315 TEST_VERIFY (swprintf (buf
, size
, L
"%-3.3s", "x\xC3\x9Fz") == 3);
316 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
317 wmemset (buf
, '@', size
);
318 TEST_VERIFY (swprintf (buf
, size
, L
"%-3.4s", "x\xC3\x9Fz") == 3);
319 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz") == 0);
321 /* Varying precisions with width 4, right-justified. */
322 wmemset (buf
, '@', size
);
323 TEST_VERIFY (swprintf (buf
, size
, L
"%4.1s", "x\xC3\x9Fz") == 4);
324 TEST_VERIFY (wcscmp (buf
, L
" x") == 0);
325 wmemset (buf
, '@', size
);
326 TEST_VERIFY (swprintf (buf
, size
, L
"%4.2s", "x\xC3\x9Fz") == 4);
327 TEST_VERIFY (wcscmp (buf
, L
" x\u00DF") == 0);
328 wmemset (buf
, '@', size
);
329 TEST_VERIFY (swprintf (buf
, size
, L
"%4.3s", "x\xC3\x9Fz") == 4);
330 TEST_VERIFY (wcscmp (buf
, L
" x\u00DFz") == 0);
331 wmemset (buf
, '@', size
);
332 TEST_VERIFY (swprintf (buf
, size
, L
"%4.4s", "x\xC3\x9Fz") == 4);
333 TEST_VERIFY (wcscmp (buf
, L
" x\u00DFz") == 0);
334 wmemset (buf
, '@', size
);
335 TEST_VERIFY (swprintf (buf
, size
, L
"%4.5s", "x\xC3\x9Fz") == 4);
336 TEST_VERIFY (wcscmp (buf
, L
" x\u00DFz") == 0);
338 /* Varying precisions with width 4, left-justified. */
339 wmemset (buf
, '@', size
);
340 TEST_VERIFY (swprintf (buf
, size
, L
"%-4.1s", "x\xC3\x9Fz") == 4);
341 TEST_VERIFY (wcscmp (buf
, L
"x ") == 0);
342 wmemset (buf
, '@', size
);
343 TEST_VERIFY (swprintf (buf
, size
, L
"%-4.2s", "x\xC3\x9Fz") == 4);
344 TEST_VERIFY (wcscmp (buf
, L
"x\u00DF ") == 0);
345 wmemset (buf
, '@', size
);
346 TEST_VERIFY (swprintf (buf
, size
, L
"%-4.3s", "x\xC3\x9Fz") == 4);
347 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz ") == 0);
348 wmemset (buf
, '@', size
);
349 TEST_VERIFY (swprintf (buf
, size
, L
"%-4.4s", "x\xC3\x9Fz") == 4);
350 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz ") == 0);
351 wmemset (buf
, '@', size
);
352 TEST_VERIFY (swprintf (buf
, size
, L
"%-4.5s", "x\xC3\x9Fz") == 4);
353 TEST_VERIFY (wcscmp (buf
, L
"x\u00DFz ") == 0);
356 /* Test with long strings and multi-byte result. */
358 test_mbs_long (const char *mbs
, const wchar_t *wide
, const size_t *length
)
361 _Static_assert (sizeof (buf
) > 3 * WIDE_STRING_LENGTH
,
362 "buffer size consistent with string length");
363 const char *suffix
= "||TERM";
364 TEST_VERIFY_EXIT (sizeof (buf
)
365 > length
[WIDE_STRING_LENGTH
] + strlen (suffix
));
367 /* Test formatting of the entire string. */
369 int ret
= snprintf (buf
, sizeof (buf
), "%ls%s", wide
, suffix
);
370 TEST_VERIFY (ret
== length
[WIDE_STRING_LENGTH
] + strlen (suffix
));
371 TEST_VERIFY (memcmp (buf
, mbs
, length
[WIDE_STRING_LENGTH
]) == 0);
372 TEST_VERIFY (strcmp (buf
+ length
[WIDE_STRING_LENGTH
], suffix
) == 0);
374 /* Left-justified string, printed in full. */
375 ret
= snprintf (buf
, sizeof (buf
), "%-3500ls%s", wide
, suffix
);
376 TEST_VERIFY (ret
== 3500 + strlen (suffix
));
377 TEST_VERIFY (memcmp (buf
, mbs
, length
[WIDE_STRING_LENGTH
]) == 0);
378 for (size_t i
= length
[WIDE_STRING_LENGTH
]; i
< 3500; ++i
)
379 TEST_VERIFY (buf
[i
] == ' ');
380 TEST_VERIFY (strcmp (buf
+ 3500, suffix
) == 0);
382 /* Right-justified string, printed in full. */
383 ret
= snprintf (buf
, sizeof (buf
), "%3500ls%s", wide
, suffix
);
384 TEST_VERIFY (ret
== 3500 + strlen (suffix
));
385 size_t padding
= 3500 - length
[WIDE_STRING_LENGTH
];
386 for (size_t i
= 0; i
< padding
; ++i
)
387 TEST_VERIFY (buf
[i
] == ' ');
388 TEST_VERIFY (memcmp (buf
+ padding
, mbs
, length
[WIDE_STRING_LENGTH
]) == 0);
389 TEST_VERIFY (strcmp (buf
+ 3500, suffix
) == 0);
392 size_t wide_characters_converted
= 0;
393 for (int mbs_len
= 0; mbs_len
<= length
[WIDE_STRING_LENGTH
] + 1;
396 if (wide_characters_converted
< WIDE_STRING_LENGTH
397 && mbs_len
>= length
[wide_characters_converted
+ 1])
398 /* The requested prefix length contains room for another wide
400 ++wide_characters_converted
;
401 if (test_verbose
> 0)
402 printf ("info: %s: mbs_len=%d wide_chars_converted=%zu length=%zu\n",
403 __func__
, mbs_len
, wide_characters_converted
,
404 length
[wide_characters_converted
]);
405 TEST_VERIFY (length
[wide_characters_converted
] <= mbs_len
);
406 TEST_VERIFY (wide_characters_converted
== 0
407 || length
[wide_characters_converted
- 1] < mbs_len
);
409 int ret
= snprintf (buf
, sizeof (buf
), "%.*ls%s", mbs_len
, wide
, suffix
);
410 TEST_VERIFY (ret
== length
[wide_characters_converted
] + strlen (suffix
));
411 TEST_VERIFY (memcmp (buf
, mbs
, length
[wide_characters_converted
]) == 0);
412 TEST_VERIFY (strcmp (buf
+ length
[wide_characters_converted
],
415 /* Left-justified string, printed in full. */
417 printf ("info: %s: left-justified\n", __func__
);
418 ret
= snprintf (buf
, sizeof (buf
), "%-3500.*ls%s",
419 mbs_len
, wide
, suffix
);
420 TEST_VERIFY (ret
== 3500 + strlen (suffix
));
421 TEST_VERIFY (memcmp (buf
, mbs
, length
[wide_characters_converted
]) == 0);
422 for (size_t i
= length
[wide_characters_converted
]; i
< 3500; ++i
)
423 TEST_VERIFY (buf
[i
] == ' ');
424 TEST_VERIFY (strcmp (buf
+ 3500, suffix
) == 0);
426 /* Right-justified string, printed in full. */
428 printf ("info: %s: right-justified\n", __func__
);
429 ret
= snprintf (buf
, sizeof (buf
), "%3500.*ls%s", mbs_len
, wide
, suffix
);
430 TEST_VERIFY (ret
== 3500 + strlen (suffix
));
431 size_t padding
= 3500 - length
[wide_characters_converted
];
432 for (size_t i
= 0; i
< padding
; ++i
)
433 TEST_VERIFY (buf
[i
] == ' ');
434 TEST_VERIFY (memcmp (buf
+ padding
, mbs
,
435 length
[wide_characters_converted
]) == 0);
436 TEST_VERIFY (strcmp (buf
+ 3500, suffix
) == 0);
440 /* Test with long strings and wide string result. */
442 test_wide_long (const char *mbs
, const wchar_t *wide
, const size_t *length
)
445 _Static_assert (sizeof (buf
) > sizeof (wchar_t) * WIDE_STRING_LENGTH
,
446 "buffer size consistent with string length");
447 const wchar_t *suffix
= L
"||TERM";
448 TEST_VERIFY_EXIT (sizeof (buf
)
449 > length
[WIDE_STRING_LENGTH
] + wcslen (suffix
));
451 /* Test formatting of the entire string. */
453 int ret
= swprintf (buf
, sizeof (buf
), L
"%s%ls", mbs
, suffix
);
454 TEST_VERIFY (ret
== WIDE_STRING_LENGTH
+ wcslen (suffix
));
455 TEST_VERIFY (wmemcmp (buf
, wide
, WIDE_STRING_LENGTH
) == 0);
456 TEST_VERIFY (wcscmp (buf
+ WIDE_STRING_LENGTH
, suffix
) == 0);
458 /* Left-justified string, printed in full. */
459 ret
= swprintf (buf
, sizeof (buf
), L
"%-1500s%ls", mbs
, suffix
);
460 TEST_VERIFY (ret
== 1500 + wcslen (suffix
));
461 TEST_VERIFY (wmemcmp (buf
, wide
, WIDE_STRING_LENGTH
) == 0);
462 for (size_t i
= WIDE_STRING_LENGTH
; i
< 1500; ++i
)
463 TEST_VERIFY (buf
[i
] == L
' ');
464 TEST_VERIFY (wcscmp (buf
+ 1500, suffix
) == 0);
466 /* Right-justified string, printed in full. */
467 ret
= swprintf (buf
, sizeof (buf
), L
"%1500s%ls", mbs
, suffix
);
468 TEST_VERIFY (ret
== 1500 + wcslen (suffix
));
469 size_t padding
= 1500 - WIDE_STRING_LENGTH
;
470 for (size_t i
= 0; i
< padding
; ++i
)
471 TEST_VERIFY (buf
[i
] == ' ');
472 TEST_VERIFY (wmemcmp (buf
+ padding
, wide
, WIDE_STRING_LENGTH
) == 0);
473 TEST_VERIFY (wcscmp (buf
+ 1500, suffix
) == 0);
476 for (int wide_len
= 0; wide_len
<= WIDE_STRING_LENGTH
+ 1; ++wide_len
)
478 size_t actual_wide_len
;
479 if (wide_len
< WIDE_STRING_LENGTH
)
480 actual_wide_len
= wide_len
;
482 actual_wide_len
= WIDE_STRING_LENGTH
;
483 if (test_verbose
> 0)
484 printf ("info: %s: wide_len=%d actual_wide_len=%zu\n",
485 __func__
, wide_len
, actual_wide_len
);
487 int ret
= swprintf (buf
, sizeof (buf
), L
"%.*s%ls",
488 wide_len
, mbs
, suffix
);
489 TEST_VERIFY (ret
== actual_wide_len
+ wcslen (suffix
));
490 TEST_VERIFY (wmemcmp (buf
, wide
, actual_wide_len
) == 0);
491 TEST_VERIFY (wcscmp (buf
+ actual_wide_len
, suffix
) == 0);
493 /* Left-justified string, printed in full. */
494 ret
= swprintf (buf
, sizeof (buf
), L
"%-1500.*s%ls",
495 wide_len
, mbs
, suffix
);
496 TEST_VERIFY (ret
== 1500 + wcslen (suffix
));
497 TEST_VERIFY (wmemcmp (buf
, wide
, actual_wide_len
) == 0);
498 for (size_t i
= actual_wide_len
; i
< 1500; ++i
)
499 TEST_VERIFY (buf
[i
] == L
' ');
500 TEST_VERIFY (wcscmp (buf
+ 1500, suffix
) == 0);
502 /* Right-justified string, printed in full. */
503 ret
= swprintf (buf
, sizeof (buf
), L
"%1500.*s%ls",
504 wide_len
, mbs
, suffix
);
505 TEST_VERIFY (ret
== 1500 + wcslen (suffix
));
506 size_t padding
= 1500 - actual_wide_len
;
507 for (size_t i
= 0; i
< padding
; ++i
)
508 TEST_VERIFY (buf
[i
] == L
' ');
509 TEST_VERIFY (wmemcmp (buf
+ padding
, wide
, actual_wide_len
) == 0);
510 TEST_VERIFY (wcscmp (buf
+ 1500, suffix
) == 0);
517 /* This test only covers UTF-8 as a multi-byte character set. A
518 locale with a multi-byte character set with shift state would be
519 a relevant test target as well, but glibc currently does not ship
521 TEST_VERIFY (setlocale (LC_CTYPE
, "de_DE.UTF-8") != NULL
);
529 make_random_string (&mbs
, &wide
, &length
);
530 TEST_VERIFY (strlen (mbs
) == length
[WIDE_STRING_LENGTH
]);
531 if (test_verbose
> 0)
532 printf ("info: long multi-byte string contains %zu characters\n",
533 length
[WIDE_STRING_LENGTH
]);
534 test_mbs_long (mbs
, wide
, length
);
535 test_wide_long (mbs
, wide
, length
);
543 #include <support/test-driver.c>