common: Improve a function's documentation and comments.
[gnupg.git] / common / t-timestuff.c
1 /* t-timestuff.c - Regression tests for time functions
2  * Copyright (C) 2007 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify it
7  * under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * GnuPG is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * General Public License for more details.
25  *
26  * You should have received a copies of the GNU General Public License
27  * and the GNU Lesser General Public License along with this program;
28  * if not, see <http://www.gnu.org/licenses/>.
29  */
30
31 #include <config.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <time.h>
37
38 #include "mischelp.h"
39
40 #include "t-support.h"
41
42
43 static int
44 cmp_time_s (struct tm *a, struct tm *b)
45 {
46   if (a->tm_year != b->tm_year
47       || a->tm_mon  != b->tm_mon
48       || a->tm_mday != b->tm_mday
49       || a->tm_hour != b->tm_hour
50       || a->tm_min  != b->tm_min
51       || a->tm_sec  != b->tm_sec
52       || a->tm_wday != b->tm_wday
53       || a->tm_yday != b->tm_yday
54       || !a->tm_isdst != !b->tm_isdst)
55     return -1;
56   return 0;
57 }
58
59
60
61 static void
62 test_timegm (void)
63 {
64   static struct {
65     int year, mon, mday, hour, min, sec;
66   } tvalues[] = {
67     { -1 },
68     { -2,  1 },
69     { -2,  2 },
70     { -2,  86399 },
71     { -2,  86400 },
72     { -2,  0x7ffffffe },
73     { -2,  0x7fffffff },
74     /* Note: Because we use mktime below we can only start with the
75        day after Epoch.  */
76     { 1970, 0, 2, 0, 0 , 1},
77     { 1970, 0, 2, 0, 0 , 2},
78     { 1970, 0, 2, 12, 0 , 0},
79     { 1970, 0, 2, 23, 59 , 59},
80     { 1999, 11, 31, 23, 59 , 59},
81     { 2000, 0, 1, 0, 0, 0},
82     { 2000, 0, 1, 0, 0, 1},
83     { 2010, 11, 31, 23, 59 , 59},
84     { 2010, 0, 1, 0, 0, 0},
85     { 2010, 0, 1, 0, 0, 1},
86     /* On GNU based 32 bit systems the end of all ticks will be on
87        20380119T031408 (unless Uli takes compassion on us and changes
88        time_t to a u64).  We check that the previous day is okay.  */
89     { 2038, 0, 18, 23, 59, 59}
90
91   };
92   int tidx;
93   time_t now, atime;
94   struct tm tbuf, tbuf2, *tp;
95
96   for (tidx=0; tidx < DIM (tvalues); tidx++)
97     {
98       if (tvalues[tidx].year == -1)
99         {
100           now = time (NULL);
101         }
102       else if (tvalues[tidx].year == -2)
103         {
104           now = tvalues[tidx].mon;
105         }
106       else
107         {
108           memset (&tbuf, 0, sizeof tbuf);
109           tbuf.tm_year = tvalues[tidx].year - 1900;
110           tbuf.tm_mon  = tvalues[tidx].mon;
111           tbuf.tm_mday = tvalues[tidx].mday;
112           tbuf.tm_hour = tvalues[tidx].hour;
113           tbuf.tm_min  = tvalues[tidx].min;
114           tbuf.tm_sec  = tvalues[tidx].sec;
115 #ifdef HAVE_TIMEGM
116           now = timegm (&tbuf);
117 #else
118           now = mktime (&tbuf);
119 #endif
120         }
121       if (now == (time_t)(-1))
122         fail (tidx);
123
124       tp = gmtime (&now);
125       if (!tp)
126         fail (tidx);
127       else
128         {
129           tbuf = *tp;
130           tbuf2 = tbuf;
131 #ifdef HAVE_TIMEGM
132           atime = timegm (&tbuf);
133 #else
134           atime = mktime (&tbuf);
135 #endif
136           if (atime == (time_t)(-1))
137             fail (tidx);
138           else if (atime != now)
139             fail (tidx);
140
141           tp = gmtime (&atime);
142           if (!tp)
143             fail (tidx);
144           else if (cmp_time_s (tp, &tbuf))
145             fail (tidx);
146           else if (cmp_time_s (tp, &tbuf2))
147             fail (tidx);
148         }
149     }
150 }
151
152
153
154 int
155 main (int argc, char **argv)
156 {
157   (void)argc;
158   (void)argv;
159
160   /* If we do not have timegm, we use mktime.  However, we need to use
161      UTC in this case so that the 20380118T235959 test does not fail
162      for other timezones.  */
163 #ifndef HAVE_TIMEGM
164 # ifdef HAVE_SETENV
165   setenv ("TZ", "UTC", 1);
166 #else
167   putenv (xstrdup ("TZ=UTC"));
168 #endif
169   tzset ();
170 #endif
171
172   test_timegm ();
173
174   return 0;
175 }