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 |
365 | print_string_hex (const char *, 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 (format: "%s : " , header); |
373 | |
374 | if (str == NULL) |
375 | { |
376 | printf (format: "<NULL>\n" ); |
377 | return; |
378 | } |
379 | |
380 | while (*s) |
381 | { |
382 | /* isgraph equivalent, but independent of current locale. */ |
383 | if (' ' <= *s && *s <= '~') |
384 | putchar (c: *s); |
385 | else |
386 | { |
387 | if (tictoc) |
388 | printf (format: "\033[36m" ); |
389 | else |
390 | printf (format: "\033[31m" ); |
391 | tictoc = ! tictoc; |
392 | |
393 | printf (format: "\\x%02x\033[0m" , (unsigned char) *s); |
394 | } |
395 | |
396 | ++ s; |
397 | } |
398 | printf (format: " - %s\n" , str); |
399 | |
400 | s = str; |
401 | wlen = mbsrtowcs (dst: w, src: &s, len: strlen (s), NULL); |
402 | printf (format: "%*s" , (int) strlen (header) + 3, " " ); |
403 | for (i = 0; i < wlen && i < strlen (str); i ++) |
404 | { |
405 | if (' ' <= w[i] && w[i] <= '~') |
406 | putchar (c: w[i]); |
407 | else |
408 | printf (format: "<U%04X>" , (int) w[i]); |
409 | } |
410 | printf (format: "\n" ); |
411 | } |
412 | |
413 | static void |
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 (format: "%s:%d: error: strftime output incorrect\n" , filename, lineno); |
421 | print_string_hex (header: "Got" , str: got); |
422 | print_string_hex (header: "Exp" , str: 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 |
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 (s: buffer, TMBUFLEN, format: "%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 |
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 (format: "%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 (format: "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: &tm, buffer: expected_time); |
515 | tm_to_printed (tm: &tm2, buffer: got_time); |
516 | TEST_COMPARE_STRING (got_time, expected_time); |
517 | } |
518 | |
519 | return 0; |
520 | } |
521 | |
522 | #include <support/test-driver.c> |
523 | |