1 /* Data-driven tests for strftime/strptime.
2    Copyright (C) 2019-2022 Free Software Foundation, Inc.  This file is
3    part of the GNU C Library.
4 
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.
9 
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.
14 
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/>.  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <time.h>
23 #include <locale.h>
24 #include <wchar.h>
25 
26 #include <support/check.h>
27 #include <array_length.h>
28 #include <libc-diag.h>
29 
30 /* These exist for the convenience of writing the test data, because
31    zero-based vs one-based.  */
32 typedef enum
33   {
34     Sun, Mon, Tue, Wed, Thu, Fri, Sat
35   } WeekDay;
36 
37 typedef enum
38   {
39     Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
40   } Month;
41 
42 typedef struct
43 {
44   /* A descriptive name of the test.  */
45   const char *name;
46 
47   /* The specific date and time to be tested.  */
48   int y, m, d;
49   WeekDay w;
50   int hh, mm, ss;
51 
52   /* The locale under which the conversion is done.  */
53   const char *locale;
54 
55   /* Format passed to strftime.  */
56   const char *format;
57 
58   /* Expected data, NUL terminated.  */
59   const char *printed;
60 
61 } Data;
62 
63 /* Notes:
64 
65    Years are full 4-digit years, the code compensates.  Likewise,
66    use month and weekday enums (above) which are zero-based.
67 
68    The encoded strings are multibyte strings in the C locale which
69    reflect the same binary data as the expected strings.  When you run
70    the test, the strings are printed as-is to stdout, so if your
71    terminal is set for the correct encoding, they'll be printed
72    "correctly".  Put the Unicode codes and UTF-8 samples in the
73    comments.
74 
75    For convenience, mis-matched strings are printed in
76    paste-compatible format, raw text format, and Unicode format.  Use
77    "" between a hex escape sequence (like \xe8) and a following hex
78    digit which should be considered as a printable character.
79 
80    To verify text, save the correct text in a file, and use "od -tx1
81    -tc file" to see the raw hex values.  */
82 
83 const Data data[] = {
84 
85   { "Baseline test",
86     2019, Mar, 27, Wed, 14,  3, 22, "en_US.ISO-8859-1", "%Y-%m-%d %T",
87     "2019-03-27 14:03:22" },
88 
89 
90   { "Japanese era change, BCE/CE, before transition",
91     0, Dec, 31, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
92     /* <U7D00><U5143><U524D>01<U5E74> 紀元前01年 */
93     "\xe7\xb4\x80\xe5\x85\x83\xe5\x89\x8d""01\xe5\xb9\xb4" },
94   { "Japanese era change, BCE/CE, after transition",
95     1, Jan,  1, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
96     /* <U897F><U66A6>01<U5E74> 西暦01年 */
97     "\xe8\xa5\xbf\xe6\x9a\xa6""01\xe5\xb9\xb4" },
98 
99   { "Japanese era change, BCE/CE, before transition",
100     0, Dec, 31, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
101     /* <U7D00><U5143><U524D>01<U5E74> 紀元前01年 */
102     "\xb5\xaa\xb8\xb5\xc1\xb0""01\xc7\xaf" },
103   { "Japanese era change, BCE/CE, after transition",
104     1, Jan,  1, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
105     /* <U897F><U66A6>01<U5E74> 西暦01年 */
106     "\xc0\xbe\xce\xf1""01\xc7\xaf" },
107 
108 
109   { "Japanese era change, 1873, before transition",
110     1872, Dec, 31, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
111     /* <U897F><U66A6>1872<U5E74> 西暦1872年 */
112     "\xe8\xa5\xbf\xe6\x9a\xa6""1872\xe5\xb9\xb4" },
113   { "Japanese era change, 1873, after transition",
114     1873, Jan,  1, Wed, 12, 00, 00, "ja_JP.UTF-8", "%EY",
115     /* <U660E><U6CBB>06<U5E74> 明治06年 */
116     "\xe6\x98\x8e\xe6\xb2\xbb""06\xe5\xb9\xb4" },
117 
118 
119   { "Japanese era change, 1873, before transition",
120     1872, Dec, 31, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
121     /* <U897F><U66A6>1872<U5E74> 西暦1872年 */
122     "\xc0\xbe\xce\xf1""1872\xc7\xaf" },
123   { "Japanese era change, 1873, after transition",
124     1873, Jan,  1, Wed, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
125     /* <U660E><U6CBB>06<U5E74> 明治06年 */
126     "\xcc\xc0\xbc\xa3""06\xc7\xaf" },
127 
128 
129   { "Japanese era change, 1912, before transition year",
130     1911, Dec, 31, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
131     /* <U660E><U6CBB>44<U5E74> 明治44年 */
132     "\xe6\x98\x8e\xe6\xb2\xbb""44\xe5\xb9\xb4" },
133   { "Japanese era change, 1912, start of transition year",
134     1912, Jan,  1, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
135     /* <U660E><U6CBB>45<U5E74> 明治45年 */
136     "\xe6\x98\x8e\xe6\xb2\xbb""45\xe5\xb9\xb4" },
137 
138   { "Japanese era change, 1912, before transition",
139     1912, Jul, 29, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
140     /* <U660E><U6CBB>45<U5E74> 明治45年 */
141     "\xe6\x98\x8e\xe6\xb2\xbb""45\xe5\xb9\xb4" },
142   { "Japanese era change, 1912, after transition",
143     1912, Jul, 30, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
144     /* <U5927><U6B63><U5143><U5E74> 大正元年 */
145     "\xe5\xa4\xa7\xe6\xad\xa3\xe5\x85\x83\xe5\xb9\xb4" },
146 
147   { "Japanese era change, 1912, before end of transition year",
148     1912, Dec, 31, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
149     /* <U5927><U6B63><U5143><U5E74> 大正元年 */
150     "\xe5\xa4\xa7\xe6\xad\xa3\xe5\x85\x83\xe5\xb9\xb4" },
151   { "Japanese era change, 1912, after transition year",
152     1913, Jan,  1, Wed, 12, 00, 00, "ja_JP.UTF-8", "%EY",
153     /* <U5927><U6B63>02<U5E74> 大正02年 */
154     "\xe5\xa4\xa7\xe6\xad\xa3""02\xe5\xb9\xb4" },
155 
156 
157   { "Japanese era change, 1912, before transition year",
158     1911, Dec, 31, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
159     /* <U660E><U6CBB>44<U5E74> 明治44年 */
160     "\xcc\xc0\xbc\xa3""44\xc7\xaf" },
161   { "Japanese era change, 1912, start of transition year",
162     1912, Jan,  1, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
163     /* <U660E><U6CBB>45<U5E74> 明治45年 */
164     "\xcc\xc0\xbc\xa3""45\xc7\xaf" },
165 
166   { "Japanese era change, 1912, before transition",
167     1912, Jul, 29, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
168     /* <U660E><U6CBB>45<U5E74> 明治45年 */
169     "\xcc\xc0\xbc\xa3""45\xc7\xaf" },
170   { "Japanese era change, 1912, after transition",
171     1912, Jul, 30, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
172     /* <U5927><U6B63><U5143><U5E74> 大正元年 */
173     "\xc2\xe7\xc0\xb5\xb8\xb5\xc7\xaf" },
174 
175   { "Japanese era change, 1912, before end of transition year",
176     1912, Dec, 31, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
177     /* <U5927><U6B63><U5143><U5E74> 大正元年 */
178     "\xc2\xe7\xc0\xb5\xb8\xb5\xc7\xaf" },
179   { "Japanese era change, 1912, after transition year",
180     1913, Jan,  1, Wed, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
181     /* <U5927><U6B63>02<U5E74> 大正02年 */
182     "\xc2\xe7\xc0\xb5""02\xc7\xaf" },
183 
184 
185   { "Japanese era change, 1926, before transition year",
186     1925, Dec, 31, Thu, 12, 00, 00, "ja_JP.UTF-8", "%EY",
187     /* <U5927><U6B63>14<U5E74> 大正14年 */
188     "\xe5\xa4\xa7\xe6\xad\xa3""14\xe5\xb9\xb4" },
189   { "Japanese era change, 1926, start of transition year",
190     1926, Jan,  1, Fri, 12, 00, 00, "ja_JP.UTF-8", "%EY",
191     /* <U5927><U6B63>15<U5E74> 大正15年 */
192     "\xe5\xa4\xa7\xe6\xad\xa3""15\xe5\xb9\xb4" },
193 
194   { "Japanese era change, 1926, before transition",
195     1926, Dec, 24, Fri, 12, 00, 00, "ja_JP.UTF-8", "%EY",
196     /* <U5927><U6B63>15<U5E74> 大正15年 */
197     "\xe5\xa4\xa7\xe6\xad\xa3""15\xe5\xb9\xb4" },
198   { "Japanese era change, 1926, after transition",
199     1926, Dec, 25, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
200     /* <U662D><U548C><U5143><U5E74> 昭和元年 */
201     "\xe6\x98\xad\xe5\x92\x8c\xe5\x85\x83\xe5\xb9\xb4" },
202 
203   { "Japanese era change, 1926, before end of transition year",
204     1926, Dec, 31, Fri, 12, 00, 00, "ja_JP.UTF-8", "%EY",
205     /* <U662D><U548C><U5143><U5E74> 昭和元年 */
206     "\xe6\x98\xad\xe5\x92\x8c\xe5\x85\x83\xe5\xb9\xb4" },
207   { "Japanese era change, 1926, after transition year",
208     1927, Jan,  1, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
209     /*  <U662D><U548C>02<U5E74> 昭和02年 */
210     "\xe6\x98\xad\xe5\x92\x8c""02\xe5\xb9\xb4" },
211 
212 
213   { "Japanese era change, 1926, before transition year",
214     1925, Dec, 31, Thu, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
215     /* <U5927><U6B63>14<U5E74> 大正14年 */
216     "\xc2\xe7\xc0\xb5""14\xc7\xaf" },
217   { "Japanese era change, 1926, start of transition year",
218     1926, Jan,  1, Fri, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
219     /* <U5927><U6B63>15<U5E74> 大正15年 */
220     "\xc2\xe7\xc0\xb5""15\xc7\xaf" },
221 
222   { "Japanese era change, 1926, before transition",
223     1926, Dec, 24, Fri, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
224     /* <U5927><U6B63>15<U5E74> 大正15年 */
225     "\xc2\xe7\xc0\xb5""15\xc7\xaf" },
226   { "Japanese era change, 1926, after transition",
227     1926, Dec, 25, Sat, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
228     /* <U662D><U548C><U5143><U5E74> 昭和元年 */
229     "\xbe\xbc\xcf\xc2\xb8\xb5\xc7\xaf" },
230 
231   { "Japanese era change, 1926, before end of transition year",
232     1926, Dec, 31, Fri, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
233     /* <U662D><U548C><U5143><U5E74> 昭和元年 */
234     "\xbe\xbc\xcf\xc2\xb8\xb5\xc7\xaf" },
235   { "Japanese era change, 1926, after transition year",
236     1927, Jan,  1, Sat, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
237     /*  <U662D><U548C>02<U5E74> 昭和02年 */
238     "\xbe\xbc\xcf\xc2""02\xc7\xaf" },
239 
240 
241   { "Japanese era change, 1989, before transition year",
242     1988, Dec, 31, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
243     /* <U662D><U548C>63<U5E74> 昭和63年 */
244     "\xe6\x98\xad\xe5\x92\x8c""63\xe5\xb9\xb4" },
245   { "Japanese era change, 1989, start of transition year",
246     1989, Jan,  1, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
247     /* <U662D><U548C>64<U5E74> 昭和64年 */
248     "\xe6\x98\xad\xe5\x92\x8c""64\xe5\xb9\xb4" },
249 
250   { "Japanese era change, 1989, before transition",
251     1989, Jan,  7, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
252     /* <U662D><U548C>64<U5E74> 昭和64年 */
253     "\xe6\x98\xad\xe5\x92\x8c""64\xe5\xb9\xb4" },
254   { "Japanese era change, 1989, after transition",
255     1989, Jan,  8, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
256     /* <U5E73><U6210><U5143><U5E74> 平成元年 */
257     "\xe5\xb9\xb3\xe6\x88\x90\xe5\x85\x83\xe5\xb9\xb4" },
258 
259   { "Japanese era change, 1989, end of transition year",
260     1989, Dec, 31, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
261     /* <U5E73><U6210><U5143><U5E74> 平成元年 */
262     "\xe5\xb9\xb3\xe6\x88\x90\xe5\x85\x83\xe5\xb9\xb4" },
263   { "Japanese era change, 1989, after transition year",
264     1990, Jan,  1, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
265     /* <U5E73><U6210>02<U5E74> 平成02年 */
266     "\xe5\xb9\xb3\xe6\x88\x90""02\xe5\xb9\xb4" },
267 
268 
269   { "Japanese era change, 1989, before transition year",
270     1988, Dec, 31, Sat, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
271     /* <U662D><U548C>63<U5E74> 昭和63年 */
272     "\xbe\xbc\xcf\xc2""63\xc7\xaf" },
273   { "Japanese era change, 1989, start of transition year",
274     1989, Jan,  1, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
275     /* <U662D><U548C>64<U5E74> 昭和64年 */
276     "\xbe\xbc\xcf\xc2""64\xc7\xaf" },
277 
278   { "Japanese era change, 1989, before transition",
279     1989, Jan,  7, Sat, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
280     /* <U662D><U548C>64<U5E74> 昭和64年 */
281     "\xbe\xbc\xcf\xc2""64\xc7\xaf" },
282   { "Japanese era change, 1989, after transition",
283     1989, Jan,  8, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
284     /* <U5E73><U6210><U5143><U5E74> 平成元年 */
285     "\xca\xbf\xc0\xae\xb8\xb5\xc7\xaf" },
286 
287   { "Japanese era change, 1989, end of transition year",
288     1989, Dec, 31, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
289     /* <U5E73><U6210><U5143><U5E74> 平成元年 */
290     "\xca\xbf\xc0\xae\xb8\xb5\xc7\xaf" },
291   { "Japanese era change, 1989, after transition year",
292     1990, Jan,  1, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
293     /* <U5E73><U6210>02<U5E74> 平成02年 */
294     "\xca\xbf\xc0\xae""02\xc7\xaf" },
295 
296 
297   { "Japanese era change, 2019, before transition year",
298     2018, Dec, 31, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
299     /* <U5E73><U6210>30<U5E74> 昭和30年 */
300     "\xe5\xb9\xb3\xe6\x88\x90""30\xe5\xb9\xb4" },
301   { "Japanese era change, 2019, start of transition year",
302     2019, Jan,  1, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
303     /* <U5E73><U6210>30<U5E74> 昭和31年 */
304     "\xe5\xb9\xb3\xe6\x88\x90""31\xe5\xb9\xb4" },
305 
306   { "Japanese era change, 2019, before transition",
307     2019, Apr, 30, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
308     /* <U5E73><U6210>30<U5E74> 昭和31年 */
309     "\xe5\xb9\xb3\xe6\x88\x90""31\xe5\xb9\xb4" },
310   { "Japanese era change, 2019, after transition",
311     2019, May,  1, Wed, 12, 00, 00, "ja_JP.UTF-8", "%EY",
312     /* <U4EE4><U548C><U5143><U5E74> 令和元年 */
313     "\xe4\xbb\xa4\xe5\x92\x8c\xe5\x85\x83\xe5\xb9\xb4" },
314 
315   { "Japanese era change, 2019, end of transition year",
316     2019, Dec, 31, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
317     /* <U4EE4><U548C><U5143><U5E74> 令和元年 */
318     "\xe4\xbb\xa4\xe5\x92\x8c\xe5\x85\x83\xe5\xb9\xb4" },
319   { "Japanese era change, 2019, after transition year",
320     2020, Jan,  1, Wed, 12, 00, 00, "ja_JP.UTF-8", "%EY",
321     /* <U4EE4><U548C>02<U5E74> 令和02年 */
322     "\xe4\xbb\xa4\xe5\x92\x8c""02\xe5\xb9\xb4" },
323 
324 
325   { "Japanese era change, 2019, before transition year",
326     2018, Dec, 31, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
327     /* <U5E73><U6210>30<U5E74> 昭和30年 */
328     "\xca\xbf\xc0\xae""30\xc7\xaf" },
329   { "Japanese era change, 2019, start of transition year",
330     2019, Jan,  1, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
331     /* <U5E73><U6210>30<U5E74> 昭和31年 */
332     "\xca\xbf\xc0\xae""31\xc7\xaf" },
333 
334   { "Japanese era change, 2019, before transition",
335     2019, Apr, 30, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
336     /* <U5E73><U6210>30<U5E74> 昭和31年 */
337     "\xca\xbf\xc0\xae""31\xc7\xaf" },
338   { "Japanese era change, 2019, after transition",
339     2019, May,  1, Wed, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
340     /* <U4EE4><U548C><U5143><U5E74> 令和元年 */
341     "\xce\xe1\xcf\xc2\xb8\xb5\xc7\xaf" },
342 
343   { "Japanese era change, 2019, end of transition year",
344     2019, Dec, 31, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
345     /* <U4EE4><U548C><U5143><U5E74> 令和元年 */
346     "\xce\xe1\xcf\xc2\xb8\xb5\xc7\xaf" },
347   { "Japanese era change, 2019, after transition year",
348     2020, Jan,  1, Wed, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
349     /* <U4EE4><U548C>02<U5E74> 令和02年 */
350     "\xce\xe1\xcf\xc2""02\xc7\xaf" },
351 };
352 
353 #define NDATA array_length(data)
354 
355 /* Size of buffer passed to strftime.  */
356 #define STRBUFLEN 1000
357 /* Size of buffer passed to tm_to_printed.  */
358 #define TMBUFLEN 50
359 
360 /* Helper function to compare strings and print out mismatches in a
361    format suitable for maintaining this test.  TEST_COMPARE_STRINGS
362    prints out a less suitable format.  */
363 
364 static void
print_string_hex(const char * header,const char * str)365 print_string_hex (const char *header, const char *str)
366 {
367   int tictoc = 0;
368   const char *s = str;
369   wchar_t w[STRBUFLEN];
370   size_t i, wlen;
371 
372   printf ("%s : ", header);
373 
374   if (str == NULL)
375     {
376       printf ("<NULL>\n");
377       return;
378     }
379 
380   while (*s)
381     {
382       /* isgraph equivalent, but independent of current locale.  */
383       if (' ' <= *s && *s <= '~')
384 	putchar (*s);
385       else
386 	{
387 	  if (tictoc)
388 	    printf ("\033[36m");
389 	  else
390 	    printf ("\033[31m");
391 	  tictoc = ! tictoc;
392 
393 	  printf ("\\x%02x\033[0m", (unsigned char) *s);
394 	}
395 
396       ++ s;
397     }
398   printf (" - %s\n", str);
399 
400   s = str;
401   wlen = mbsrtowcs (w, &s, strlen (s), NULL);
402   printf ("%*s", (int) strlen (header) + 3, " ");
403   for (i = 0; i < wlen && i < strlen (str); i ++)
404     {
405       if (' ' <= w[i] && w[i] <= '~')
406 	putchar (w[i]);
407       else
408 	printf ("<U%04X>", (int) w[i]);
409     }
410   printf ("\n");
411 }
412 
413 static void
compare_strings(const char * got,const char * expected,const char * filename,int lineno)414 compare_strings (const char *got, const char *expected,
415 		 const char *filename, int lineno)
416 {
417   if (got && expected && strcmp (got, expected) == 0)
418     return;
419   support_record_failure ();
420   printf ("%s:%d: error: strftime output incorrect\n", filename, lineno);
421   print_string_hex ("Got", got);
422   print_string_hex ("Exp", expected);
423 }
424 #define COMPARE_STRINGS(g,e) compare_strings (g, e, __FILE__, __LINE__)
425 
426 const char *weekday_name[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
427 			       "Sat" };
428 
429 /* Helper function to create a printable version of struct tm.  */
430 static void
tm_to_printed(struct tm * tm,char * buffer)431 tm_to_printed (struct tm *tm, char *buffer)
432 {
433   const char *wn;
434   char temp[50];
435 
436   if (0 <= tm->tm_wday && tm->tm_wday <= 6)
437     wn = weekday_name[tm->tm_wday];
438   else
439     {
440       wn = temp;
441       sprintf (temp, "%d", tm->tm_wday);
442     }
443 
444   DIAG_PUSH_NEEDS_COMMENT;
445 #if __GNUC_PREREQ (9, 0)
446   /* GCC 9 warns that strncmp may truncate its output, but that's why
447      we're using it.  When it needs to truncate, it got corrupted
448      data, and we only care that the string is different than valid
449      data, which won't truncate.  */
450   DIAG_IGNORE_NEEDS_COMMENT (9, "-Wformat-truncation=");
451 #endif
452   snprintf (buffer, TMBUFLEN, "%04d/%02d/%02d %02d:%02d:%02d %s",
453 	    tm->tm_year + 1900,
454 	    tm->tm_mon + 1,
455 	    tm->tm_mday,
456 	    tm->tm_hour,
457 	    tm->tm_min,
458 	    tm->tm_sec,
459 	    wn);
460   DIAG_POP_NEEDS_COMMENT;
461 }
462 
463 static int
do_test(void)464 do_test (void)
465 {
466   int i;
467   char buffer[STRBUFLEN];
468   char expected_time[TMBUFLEN];
469   char got_time[TMBUFLEN];
470 
471   for (i = 0; i < NDATA; i ++)
472     {
473       const Data *d = &(data[i]);
474       struct tm tm;
475       struct tm tm2;
476       size_t rv;
477       char *rvp;
478 
479       /* Print this just to help debug failures.  */
480       printf ("%s:\n\t%s %s %s\n", d->name, d->locale, d->format, d->printed);
481 
482       tm.tm_year = d->y - 1900;
483       tm.tm_mon = d->m;
484       tm.tm_mday = d->d;
485       tm.tm_wday = d->w;
486       tm.tm_hour = d->hh;
487       tm.tm_min = d->mm;
488       tm.tm_sec = d->ss;
489       tm.tm_isdst = -1;
490 
491       /* LC_ALL may interfere with the snprintf in tm_to_printed.  */
492       if (setlocale (LC_TIME, d->locale) == NULL)
493 	{
494 	  /* See the LOCALES list in the Makefile.  */
495 	  printf ("locale %s does not exist!\n", d->locale);
496 	  exit (EXIT_FAILURE);
497 	}
498       /* This is just for printing wide characters if there's an error.  */
499       setlocale (LC_CTYPE, d->locale);
500 
501       rv = strftime (buffer, sizeof (buffer), d->format, &tm);
502 
503       TEST_COMPARE (rv, strlen (d->printed));
504       COMPARE_STRINGS (buffer, d->printed);
505 
506       /* Copy the original time, so that any fields not affected by
507 	 the call to strptime will match.  */
508       tm2 = tm;
509 
510       rvp = strptime (d->printed, d->format, &tm2);
511 
512       TEST_COMPARE_STRING (rvp, "");
513 
514       tm_to_printed (&tm, expected_time);
515       tm_to_printed (&tm2, got_time);
516       TEST_COMPARE_STRING (got_time, expected_time);
517     }
518 
519   return 0;
520 }
521 
522 #include <support/test-driver.c>
523