posixtm-tests: make T const-correct; add a test case
[gnulib.git] / tests / test-posixtm.c
1 /* Test that openat_safer leave standard fds alone.
2    Copyright (C) 2009 Free Software Foundation, Inc.
3
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.
8
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.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Jim Meyering.  */
18
19 #include <config.h>
20
21 #include "posixtm.h"
22 #include "intprops.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <time.h>
27
28 #define STREQ(a, b) (strcmp (a, b) == 0)
29
30 #define ASSERT(expr) \
31   do                                                                         \
32     {                                                                        \
33       if (!(expr))                                                           \
34         {                                                                    \
35           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
36           fflush (stderr);                                                   \
37           abort ();                                                          \
38         }                                                                    \
39     }                                                                        \
40   while (0)
41
42 struct posixtm_test
43 {
44   char const *in;
45   unsigned int syntax_bits;
46   char const *expected;
47 };
48
49 /* Test mainly with syntax_bits == 13
50    (aka: (PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS))  */
51
52 static struct posixtm_test const T[] =
53   {
54     { "000001010000.00", 13, "-62167219200 Sat Jan  1 00:00:00 0" },
55     { "190112132045.51", 13, " -2147483649 Fri Dec 13 20:45:51 1901" },
56     { "190112132045.52", 13, " -2147483648 Fri Dec 13 20:45:52 1901" },
57     { "190112132045.53", 13, " -2147483647 Fri Dec 13 20:45:53 1901" },
58     { "190112132046.52", 13, " -2147483588 Fri Dec 13 20:46:52 1901" },
59     { "190112132145.52", 13, " -2147480048 Fri Dec 13 21:45:52 1901" },
60     { "190112142045.52", 13, " -2147397248 Sat Dec 14 20:45:52 1901" },
61     { "190201132045.52", 13, " -2144805248 Mon Jan 13 20:45:52 1902" },
62     { "196912312359.59", 13, "          -1 Wed Dec 31 23:59:59 1969" },
63     { "197001010000.00", 13, "           0 Thu Jan  1 00:00:00 1970" },
64     { "197001010000.01", 13, "           1 Thu Jan  1 00:00:01 1970" },
65     { "197001010001.00", 13, "          60 Thu Jan  1 00:01:00 1970" },
66     { "197001010000.60", 13, "          60 Thu Jan  1 00:01:00 1970" },
67     { "197001010100.00", 13, "        3600 Thu Jan  1 01:00:00 1970" },
68     { "197001020000.00", 13, "       86400 Fri Jan  2 00:00:00 1970" },
69     { "197002010000.00", 13, "     2678400 Sun Feb  1 00:00:00 1970" },
70     { "197101010000.00", 13, "    31536000 Fri Jan  1 00:00:00 1971" },
71     { "197001000000.00", 13, "           * *" },
72     { "197000010000.00", 13, "           * *" },
73     { "197001010060.00", 13, "           * *" },
74     { "197001012400.00", 13, "           * *" },
75     { "197001320000.00", 13, "           * *" },
76     { "197013010000.00", 13, "           * *" },
77     { "203801190314.06", 13, "  2147483646 Tue Jan 19 03:14:06 2038" },
78     { "203801190314.07", 13, "  2147483647 Tue Jan 19 03:14:07 2038" },
79     { "203801190314.08", 13, "  2147483648 Tue Jan 19 03:14:08 2038" },
80     { "999912312359.59", 13, "253402300799 Fri Dec 31 23:59:59 9999" },
81     { "1112131415",      13, "  1323785700 Tue Dec 13 14:15:00 2011" },
82     { "1112131415.16",   13, "  1323785716 Tue Dec 13 14:15:16 2011" },
83     { "201112131415.16", 13, "  1323785716 Tue Dec 13 14:15:16 2011" },
84     { "191112131415.16", 13, " -1831974284 Wed Dec 13 14:15:16 1911" },
85     { "203712131415.16", 13, "  2144326516 Sun Dec 13 14:15:16 2037" },
86     { "3712131415.16",   13, "  2144326516 Sun Dec 13 14:15:16 2037" },
87     { "6812131415.16",   13, "  3122633716 Thu Dec 13 14:15:16 2068" },
88     { "6912131415.16",   13, "    -1590284 Sat Dec 13 14:15:16 1969" },
89     { "7012131415.16",   13, "    29945716 Sun Dec 13 14:15:16 1970" },
90     { "1213141599",       2, "   945094500 Mon Dec 13 14:15:00 1999" },
91     { "1213141500",       2, "   976716900 Wed Dec 13 14:15:00 2000" },
92     { NULL,               0, NULL }
93   };
94
95 int
96 main (void)
97 {
98   unsigned int i;
99   int fail = 0;
100   char curr_year_str[30];
101   struct tm *tm;
102   time_t t_now;
103   int err;
104   size_t n_bytes;
105
106   /* The above test data requires Universal Time, e.g., TZ="UTC0".  */
107   err = setenv ("TZ", "UTC0", 1);
108   ASSERT (err == 0);
109
110   t_now = time (NULL);
111   ASSERT (t_now != (time_t) -1);
112   tm = localtime (&t_now);
113   ASSERT (tm);
114   n_bytes = strftime (curr_year_str, sizeof curr_year_str, "%Y", tm);
115   ASSERT (0 < n_bytes);
116
117   /* This test data also assumes that time_t is signed and is at least
118      39 bits wide, so that it can represent all years from 0000 through
119      9999.  A host with 32-bit signed time_t can represent only time
120      stamps in the range 1901-12-13 20:45:52 through 2038-01-18
121      03:14:07 UTC, assuming POSIX time_t with no leap seconds, so test
122      cases outside this range will not work on such a host.  */
123   if ( ! TYPE_SIGNED (time_t))
124     {
125       fprintf (stderr, "%s: this test requires signed time_t\n");
126       return 77;
127     }
128
129   if (sizeof (time_t) * CHAR_BIT < 39)
130     {
131       fprintf (stderr, "%s: this test requires time_t at least 39 bits wide\n");
132       return 77;
133     }
134
135
136   for (i = 0; T[i].in; i++)
137     {
138       char out_buf[100];
139       time_t t;
140
141       /* The first two tests assume that the current year is 2002.
142          If an input string does not specify the year number, and
143          the expected output year is not the same as the current year,
144          then skip the test.  For example:
145          { "12131415.16", "  1039788916 Fri Dec 13 14:15:16 2002" }, */
146       if (8 <= strlen (T[i].in)
147           && (T[i].in[8] == '.' || T[i].in[8] == '\0')
148           && 4 < strlen (T[i].expected)
149           && ! STREQ (T[i].expected + (strlen (T[i].expected) - 4),
150                       curr_year_str))
151         continue;
152
153       if (posixtime (&t, T[i].in, T[i].syntax_bits))
154         sprintf (out_buf, "%12ld %s", (long int) t, ctime (&t));
155       else
156         sprintf (out_buf, "%12s %s", "*", "*\n");
157
158       out_buf[strlen (out_buf) - 1] = '\0';
159       if (!STREQ (out_buf, T[i].expected))
160         {
161           printf ("mismatch (-: actual; +:expected)\n-%s\n+%s\n",
162                   out_buf, T[i].expected);
163           fail = 1;
164         }
165     }
166
167   return fail;
168 }
169
170 /*
171 Local Variables:
172 indent-tabs-mode: nil
173 End:
174 */