openat: Fix theoretically possible issue on GNU/Hurd.
[gnulib.git] / tests / test-nstrftime.c
blobcb9e2d6adcbb2440dc61d617237ff9e584e39fde
1 /* Test that nstrftime works as required.
2 Copyright (C) 2011-2020 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Jim Meyering. */
19 #include <config.h>
21 #include "strftime.h"
23 #include <errno.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <time.h>
27 #include <unistd.h>
29 #include "macros.h"
30 #define STREQ(a, b) (strcmp (a, b) == 0)
32 /* Support for settings like TZ='<+00>0' was added in IEEE Std 1003.1-2001. */
33 #define TZ_ANGLE_BRACKETS_SHOULD_WORK (200112 <= _POSIX_VERSION)
35 struct posixtm_test
37 time_t in;
38 int in_ns;
39 char const *fmt;
40 char const *exp;
43 static struct posixtm_test const T[] =
45 { 1300000000, 0, "%F", "2011-03-13" },
46 { 0, 10, "%T.%N", "00:00:00.000000010" },
47 { 56, 123456789, "%T.%12N", "00:00:56.123456789000" },
48 { 0, 0, NULL, NULL }
51 static int
52 posixtm_test (void)
54 int fail = 0;
55 unsigned int i;
57 for (i = 0; T[i].fmt; i++)
59 char buf[1000];
60 time_t t = T[i].in;
61 struct tm *tm = gmtime (&t);
62 size_t n;
64 ASSERT (tm);
66 n = nstrftime (buf, sizeof buf, T[i].fmt, tm, 0, T[i].in_ns);
67 if (n == 0)
69 fail = 1;
70 printf ("nstrftime failed with format %s\n", T[i].fmt);
73 if (! STREQ (buf, T[i].exp))
75 fail = 1;
76 printf ("%s: result mismatch: got %s, expected %s\n",
77 T[i].fmt, buf, T[i].exp);
81 return fail;
84 struct tzalloc_test
86 timezone_t tz;
87 char const *setting;
90 static struct tzalloc_test TZ[] =
92 #define Pacific 0
93 { 0, "PST8PDT,M3.2.0,M11.1.0" },
94 #define Arizona 1
95 { 0, "MST7" },
96 #define UTC 2
97 { 0, 0 },
98 #define CentEur 3
99 { 0, "CET-1CEST,M3.5.0,M10.5.0/3" },
100 #define Japan 4
101 { 0, "JST-9" },
102 #define NZ 5
103 { 0, "NZST-12NZDT,M9.5.0,M4.1.0/3" },
104 #define Unknown 6
105 { 0, "<-00>0" },
106 { 0 }
109 struct localtime_rz_test
111 /* Input parameters. */
112 struct tzalloc_test *tza;
113 time_t t;
115 /* Expected result. */
116 char const *exp;
118 /* Determines if an incorrectly unset tm_isdst
119 results in failure or just a warning. */
120 int ahistorical;
123 static struct localtime_rz_test LT[] =
125 { TZ+Pacific, 0, "1969-12-31 16:00:00 -0800 (PST)", 0 },
126 { TZ+Arizona, 0, "1969-12-31 17:00:00 -0700 (MST)", 0 },
127 { TZ+UTC , 0, "1970-01-01 00:00:00 +0000 (UTC)", 0 },
128 { TZ+CentEur, 0, "1970-01-01 01:00:00 +0100 (CET)", 0 },
129 { TZ+Japan , 0, "1970-01-01 09:00:00 +0900 (JST)", 0 },
130 { TZ+NZ , 0, "1970-01-01 13:00:00 +1300 (NZDT)", 1 },
131 { TZ+Pacific, 500000001, "1985-11-04 16:53:21 -0800 (PST)", 0 },
132 { TZ+Arizona, 500000001, "1985-11-04 17:53:21 -0700 (MST)", 0 },
133 { TZ+UTC , 500000001, "1985-11-05 00:53:21 +0000 (UTC)", 0 },
134 { TZ+CentEur, 500000001, "1985-11-05 01:53:21 +0100 (CET)", 1 },
135 { TZ+Japan , 500000001, "1985-11-05 09:53:21 +0900 (JST)", 0 },
136 { TZ+NZ , 500000001, "1985-11-05 13:53:21 +1300 (NZDT)", 0 },
137 { TZ+Pacific, 1000000002, "2001-09-08 18:46:42 -0700 (PDT)", 0 },
138 { TZ+Arizona, 1000000002, "2001-09-08 18:46:42 -0700 (MST)", 0 },
139 { TZ+UTC , 1000000002, "2001-09-09 01:46:42 +0000 (UTC)", 0 },
140 { TZ+CentEur, 1000000002, "2001-09-09 03:46:42 +0200 (CEST)", 0 },
141 { TZ+Japan , 1000000002, "2001-09-09 10:46:42 +0900 (JST)", 0 },
142 { TZ+NZ , 1000000002, "2001-09-09 13:46:42 +1200 (NZST)", 0 },
143 #if TZ_ANGLE_BRACKETS_SHOULD_WORK
144 { TZ+Unknown, 0, "1970-01-01 00:00:00 -0000 (-00)", 0 },
145 { TZ+Unknown, 500000001, "1985-11-05 00:53:21 -0000 (-00)", 0 },
146 { TZ+Unknown, 1000000002, "2001-09-09 01:46:42 -0000 (-00)", 0 },
147 #endif
148 { 0 }
151 static int
152 tzalloc_test (void)
154 int fail = 0;
155 int i;
157 for (i = 0; LT[i].tza; i++)
159 struct tzalloc_test *tza = LT[i].tza;
160 long lt = LT[i].t;
161 timezone_t tz = tza->tz;
162 char const *setting;
163 static char const format[] = "%Y-%m-%d %H:%M:%S %z (%Z)";
164 char buf[1000];
165 struct tm tm;
166 size_t n;
168 if (!tz && tza->setting)
170 tz = tzalloc (tza->setting);
171 if (!tz)
173 fail = 1;
174 printf ("%s: tzalloc: %s\n", TZ[i].setting, strerror (errno));
175 continue;
177 tza->tz = tz;
180 setting = tza->setting ? tza->setting : "UTC0";
182 if (!localtime_rz (tz, &LT[i].t, &tm))
184 fail = 1;
185 printf ("%s: %ld: localtime_rz: %s\n", setting, lt,
186 strerror (errno));
187 continue;
190 n = nstrftime (buf, sizeof buf, format, &tm, tz, 0);
191 if (n == 0)
193 fail = 1;
194 printf ("%s: %ld: nstrftime failed\n", setting, lt);
195 continue;
198 if (! (STREQ (buf, LT[i].exp)
199 || (!tz && n == strlen (LT[i].exp)
200 && memcmp (buf, LT[i].exp, n - sizeof "(GMT)" + 1) == 0
201 && STREQ (buf + n - sizeof "(GMT)" + 1, "(GMT)"))))
203 /* Don't fail for unhandled dst in ahistorical entries,
204 as gnulib doesn't currently fix that issue, seen on Darwin 14. */
205 if (!LT[i].ahistorical || tm.tm_isdst)
206 fail = 1;
207 printf ("%s: expected \"%s\", got \"%s\"\n",
208 setting, LT[i].exp, buf);
212 return fail;
216 static int
217 quarter_test (void)
219 int result = 0;
220 size_t mon;
222 /* Check %q. */
223 for (mon = 1; mon <= 12; mon++)
225 char out[2];
226 char exp[2] = {0,};
227 struct tm qtm = { .tm_mon = mon - 1 };
228 char fmt[3] = {'%','q','\0'};
230 size_t r = nstrftime (out, sizeof (out), fmt, &qtm, 0, 0);
231 if (r == 0)
233 puts ("nstrftime(\"%q\") failed");
234 result = 1;
235 break;
238 exp[0] = mon < 4 ? '1' : mon < 7 ? '2' : mon < 10 ? '3' : '4';
239 if (strcmp (out, exp) != 0)
241 printf ("nstrftime %%q: expected \"%s\", got \"%s\"\n", exp, out);
242 result = 1;
243 break;
247 return result;
251 main (void)
253 int fail = 0;
254 fail |= posixtm_test ();
255 fail |= tzalloc_test ();
256 fail |= quarter_test ();
257 return fail;
261 Local Variables:
262 indent-tabs-mode: nil
263 End: