1 /*
2  * tests for mktime(), mkgmtime(), timespec_to_iso8601() and
3  * iso8601_to_timespec().
4  * mktime() is a libc function, why test it?
5  *
6  * This file is Copyright (c) 2010-2019 by the GPSD project
7  * SPDX-License-Identifier: BSD-2-clause
8  */
9 #include <limits.h>
10 #include <math.h>       /* for fabs() */
11 #include <stdbool.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <time.h>
16 
17 #include "../gps.h"
18 #include "../compiler.h"
19 #include "../timespec.h"
20 
21 static struct
22 {
23     struct tm t;
24     time_t result;
25 } tests[] = {
26     /* *INDENT-OFF* */
27     /* sec, min,  h, md, mon, year, wd,  yd, isdst, gmtoff, zone,
28      * time_t what */
29 
30     /* lower limit */
31     {{   0,   0,  0,  1,   0,   70,  0,   0,     0,      0,    0}, 0},
32     /* upper limit */
33     {{   7,  14,  3, 19,   0,  138,  0,   0,     0,      0,    0}, 0x7fffffff},
34     /* leap year */
35     {{   0,   0, 12,  1,   0,   99,  0,   0,     0,      0,    0}, 915192000},
36     /* leap year */
37     {{   0,   0, 12,  1,   1,   99,  0,   0,     0,      0,    0}, 917870400},
38     /* leap year */
39     {{   0,   0, 12,  1,   2,   99,  0,   0,     0,      0,    0}, 920289600},
40     /* leap year */
41     {{   0,   0, 12,  1,   8,   99,  0,   0,     0,      0,    0}, 936187200},
42     /* leap year */
43     {{   0,   0, 12,  1,   0,  100,  0,   0,     0,      0,    0}, 946728000},
44     /* leap year */
45     {{   0,   0, 12,  1,   1,  100,  0,   0,     0,      0,    0}, 949406400},
46     /* leap year */
47     {{   0,   0, 12,  1,   2,  100,  0,   0,     0,      0,    0}, 951912000},
48     /* leap year */
49     {{   0,   0, 12,  1,   8,  100,  0,   0,     0,      0,    0}, 967809600},
50     /* leap year */
51     {{   0,   0, 12,  1,   0,  101,  0,   0,     0,      0,    0}, 978350400},
52     /* leap year */
53     {{   0,   0, 12,  1,   1,  101,  0,   0,     0,      0,    0}, 981028800},
54     /* leap year */
55     {{   0,   0, 12,  1,   2,  101,  0,   0,     0,      0,    0}, 983448000},
56     /* leap year */
57     {{   0,   0, 12,  1,   8,  101,  0,   0,     0,      0,    0}, 999345600},
58     /* leap year */
59     {{   0,   0, 12,  1,   0,  102,  0,   0,     0,      0,    0}, 1009886400},
60     /* leap year */
61     {{   0,   0, 12,  1,   1,  102,  0,   0,     0,      0,    0}, 1012564800},
62     /* leap year */
63     {{   0,   0, 12,  1,   2,  102,  0,   0,     0,      0,    0}, 1014984000},
64     /* leap year */
65     {{   0,   0, 12,  1,   8,  102,  0,   0,     0,      0,    0}, 1030881600},
66     /* leap year */
67     {{   0,   0, 12,  1,   0,  103,  0,   0,     0,      0,    0}, 1041422400},
68     /* leap year */
69     {{   0,   0, 12,  1,   1,  103,  0,   0,     0,      0,    0}, 1044100800},
70     /* leap year */
71     {{   0,   0, 12,  1,   2,  103,  0,   0,     0,      0,    0}, 1046520000},
72     /* leap year */
73     {{   0,   0, 12,  1,   8,  103,  0,   0,     0,      0,    0}, 1062417600},
74     /* leap year */
75     {{   0,   0, 12,  1,   0,  104,  0,   0,     0,      0,    0}, 1072958400},
76     /* leap year */
77     {{   0,   0, 12,  1,   1,  104,  0,   0,     0,      0,    0}, 1075636800},
78     /* leap year */
79     {{   0,   0, 12,  1,   2,  104,  0,   0,     0,      0,    0}, 1078142400},
80     {{   0,   0, 12,  1,   2,  104,  0,   0,     0,      0,    0}, 1078142400},
81     /* leap year */
82     {{   0,   0, 12,  1,   8,  104,  0,   0,     0,      0,    0}, 1094040000},
83     /* leap year */
84     {{   0,   0, 12,  1,   0,  108,  0,   0,     0,      0,    0}, 1199188800},
85     /* leap year */
86     {{   0,   0, 12,  1,   1,  108,  0,   0,     0,      0,    0}, 1201867200},
87     /* leap year */
88     {{   0,   0, 12,  1,   2,  108,  0,   0,     0,      0,    0}, 1204372800},
89     /* leap year */
90     {{   0,   0, 12,  1,   8,  108,  0,   0,     0,      0,    0}, 1220270400},
91     /* year wrap */
92     {{  59,  59, 23, 31,  12,  110,  0,   0,     0,      0,    0}, 1296518399},
93     /* year wrap */
94     {{   0,   0,  0,  1,   0,  111,  0,   0,     0,      0,    0}, 1293840000},
95     /* year wrap */
96     {{  59,  59, 23, 31,  12,  111,  0,   0,     0,      0,    0}, 1328054399},
97     /* year wrap */
98     {{   0,   0,  0,  1,   0,  112,  0,   0,     0,      0,    0}, 1325376000},
99     /* year wrap */
100     {{  59,  59, 23, 31,  12,  112,  0,   0,     0,      0,    0}, 1359676799},
101     /* year wrap */
102     {{   0,   0,  0,  1,   0,  113,  0,   0,     0,      0,    0}, 1356998400},
103     /* month wrap */
104     {{  59,  59, 23, 31,   0,  115,  0,   0,     0,      0,    0}, 1422748799},
105     /* month wrap */
106     {{   0,   0,  0,  1,   1,  115,  0,   0,     0,      0,    0}, 1422748800},
107     /* month wrap */
108     {{  59,  59, 23, 28,   1,  115,  0,   0,     0,      0,    0}, 1425167999},
109     /* month wrap */
110     {{   0,   0,  0,  1,   2,  115,  0,   0,     0,      0,    0}, 1425168000},
111     /* month wrap */
112     {{  59,  59, 23, 31,   2,  115,  0,   0,     0,      0,    0}, 1427846399},
113     /* month wrap */
114     {{   0,   0,  0,  1,   3,  115,  0,   0,     0,      0,    0}, 1427846400},
115     /* month wrap */
116     {{  59,  59, 23, 30,   3,  115,  0,   0,     0,      0,    0}, 1430438399},
117     /* month wrap */
118     {{   0,   0,  0,  1,   4,  115,  0,   0,     0,      0,    0}, 1430438400},
119     /* month wrap */
120     {{  59,  59, 23, 31,   4,  115,  0,   0,     0,      0,    0}, 1433116799},
121     /* month wrap */
122     {{   0,   0,  0,  1,   5,  115,  0,   0,     0,      0,    0}, 1433116800},
123     /* month wrap */
124     {{  59,  59, 23, 30,   5,  115,  0,   0,     0,      0,    0}, 1435708799},
125     /* month wrap */
126     {{   0,   0,  0,  1,   6,  115,  0,   0,     0,      0,    0}, 1435708800},
127     /* month wrap */
128     {{  59,  59, 23, 31,   6,  115,  0,   0,     0,      0,    0}, 1438387199},
129     /* month wrap */
130     {{   0,   0,  0,  1,   7,  115,  0,   0,     0,      0,    0}, 1438387200},
131     /* month wrap */
132     {{  59,  59, 23, 31,   7,  115,  0,   0,     0,      0,    0}, 1441065599},
133     /* month wrap */
134     {{   0,   0,  0,  1,   8,  115,  0,   0,     0,      0,    0}, 1441065600},
135     /* month wrap */
136     {{  59,  59, 23, 30,   8,  115,  0,   0,     0,      0,    0}, 1443657599},
137     /* month wrap */
138     {{   0,   0,  0,  1,   9,  115,  0,   0,     0,      0,    0}, 1443657600},
139     /* month wrap */
140     {{  59,  59, 23, 31,   9,  115,  0,   0,     0,      0,    0}, 1446335999},
141     /* month wrap */
142     {{   0,   0,  0,  1,  10,  115,  0,   0,     0,      0,    0}, 1446336000},
143     /* month wrap */
144     {{  59,  59, 23, 30,  10,  115,  0,   0,     0,      0,    0}, 1448927999},
145     /* month wrap */
146     {{   0,   0,  0,  1,  11,  115,  0,   0,     0,      0,    0}, 1448928000},
147     /* month wrap */
148     {{  59,  59, 23, 31,  11,  115,  0,   0,     0,      0,    0}, 1451606399},
149     /* month wrap */
150     {{   0,   0,  0,  1,   0,  116,  0,   0,     0,      0,    0}, 1451606400},
151     /* *INDENT-ON* */
152 };
153 
154 
155 /* tests for timespec_to_iso8601() */
156 static struct
157 {
158     timespec_t ts_time;
159     char *iso8601;        /* iso8601 result */
160 } tests1[] = {
161     /* time zero */
162     {{0, 0}, "1970-01-01T00:00:00.000Z"},
163 
164     /* before/after leap second end of 2008, notice no :60! */
165     {{1230767999L, 1000000L}, "2008-12-31T23:59:59.001Z"},
166     {{1230767999L, 10000000L}, "2008-12-31T23:59:59.010Z"},
167     {{1230767999L, 100000000L}, "2008-12-31T23:59:59.100Z"},
168     {{1230768000L, 20000000L}, "2009-01-01T00:00:00.020Z"},
169 
170     /* test for rounding at %.3f */
171     {{1541766896L, 999412000L}, "2018-11-09T12:34:56.999Z"},
172     {{1541766896L, 999499000L}, "2018-11-09T12:34:56.999Z"},
173     {{1541766896L, 999500000L}, "2018-11-09T12:34:57.000Z"},
174     {{1541766896L, 999501000L}, "2018-11-09T12:34:57.000Z"},
175 
176     /* the end of time: 2038 */
177     {{2147483647L, 123456000L}, "2038-01-19T03:14:07.123Z"},
178 
179 #if 4 < SIZEOF_TIME_T
180     /* this next line generates compiler warning if 4 < sizeof(time_t)
181      * if so, the test will fail, and your system will break in 2038 */
182     {{2147483648L, 123456000L}, "2038-01-19T03:14:08.123Z"},
183 #endif
184 
185 };
186 
main(int argc UNUSED,char * argv[]UNUSED)187 int main(int argc UNUSED, char *argv[] UNUSED)
188 {
189     int i;
190     char tbuf[128];
191     bool failed = false;
192     timespec_t ts_time;
193     char ts_buf[TIMESPEC_LEN];
194 
195     (void)setenv("TZ", "GMT", 1);
196 
197     /* test mktime() */
198     for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
199         time_t ts = mktime(&tests[i].t);
200         if (ts != tests[i].result) {
201             failed = true;
202             (void)strftime(tbuf, sizeof(tbuf), "%F %T", &tests[i].t);
203             (void)printf("test_mktime: mktime() test %2d failed.\n"
204                          "  Time returned from: %s should be %lu "
205                          " (but was: %lu)\n",
206                          i, tbuf, (unsigned long)tests[i].result,
207                          (unsigned long)ts);
208         }
209     }
210 
211     /* test mkgmtime() */
212     for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
213         time_t ts = mkgmtime(&tests[i].t);
214         if (ts != tests[i].result) {
215             failed = true;
216             (void)strftime(tbuf, sizeof(tbuf), "%F %T", &tests[i].t);
217             (void)printf("test_mktime: mkgmtime() test %2d failed.\n"
218                          "  Time returned from: %s should be %lu "
219                          " (but was: %lu)\n",
220                          i, tbuf, (unsigned long)tests[i].result,
221                          (unsigned long)ts);
222         }
223     }
224 
225     /* test timespec_to_iso8601() */
226     if ( 4 >= sizeof(time_t)) {
227         (void)printf("WARNING: time_t too small.  This gpsd binary "
228                      "will fail at the 2038 roll over\n");
229     }
230 
231     for (i = 0; i < (int)(sizeof(tests1) / sizeof(tests1[0])); i++) {
232         timespec_to_iso8601(tests1[i].ts_time, tbuf, sizeof(tbuf));
233         if (0 != strcmp(tests1[i].iso8601, tbuf)) {
234             failed = true;
235             (void)printf("test_mktime: timespec_to_iso8601() test %s failed.\n"
236                          "  Got %s, s/b %s\n",
237                          timespec_str(&tests1[i].ts_time, ts_buf,
238                                       sizeof(ts_buf)),
239                          tbuf, tests1[i].iso8601);
240         }
241     }
242 
243     /* test iso8601_to_timespec() */
244     for (i = 0; i < (int)(sizeof(tests1) / sizeof(tests1[0])); i++) {
245         timespec_t ts_tmp;
246         ts_time = iso8601_to_timespec(tests1[i].iso8601);
247         TS_SUB(&ts_tmp, &ts_time, &tests1[i].ts_time);
248         if (0.001 <= fabs(TSTONS(&ts_tmp))) {
249             failed = true;
250             (void)printf("test_mktime: iso8601_to_timespec() test %s failed.\n"
251                          "  Got %.3f, s/b %.3f\n",
252                          tests1[i].iso8601, TSTONS(&ts_time),
253                          TSTONS(&tests1[i].ts_time));
254         }
255     }
256 
257     return (int)failed;
258 }
259 
260 /* end */
261 
262