]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-calendarspec.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / test / test-calendarspec.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
36697dc0
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2012 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
21#include <string.h>
22
b5efdb8a 23#include "alloc-util.h"
36697dc0 24#include "calendarspec.h"
07630cea 25#include "string-util.h"
36697dc0
LP
26#include "util.h"
27
28static void test_one(const char *input, const char *output) {
29 CalendarSpec *c;
aaa87092 30 _cleanup_free_ char *p = NULL, *q = NULL;
36697dc0
LP
31 usec_t u;
32 char buf[FORMAT_TIMESTAMP_MAX];
33 int r;
34
35 assert_se(calendar_spec_from_string(input, &c) >= 0);
36
37 assert_se(calendar_spec_to_string(c, &p) >= 0);
38 printf("\"%s\" → \"%s\"\n", input, p);
39
40 assert_se(streq(p, output));
36697dc0
LP
41
42 u = now(CLOCK_REALTIME);
43 r = calendar_spec_next_usec(c, u, &u);
44 printf("Next: %s\n", r < 0 ? strerror(-r) : format_timestamp(buf, sizeof(buf), u));
aaa87092 45 calendar_spec_free(c);
36697dc0 46
aaa87092
LP
47 assert_se(calendar_spec_from_string(p, &c) >= 0);
48 assert_se(calendar_spec_to_string(c, &q) >= 0);
36697dc0 49 calendar_spec_free(c);
aaa87092
LP
50
51 assert_se(streq(q, p));
36697dc0
LP
52}
53
9d5bd70d
HV
54static void test_next(const char *input, const char *new_tz, usec_t after, usec_t expect) {
55 CalendarSpec *c;
56 usec_t u;
57 char *old_tz;
58 char buf[FORMAT_TIMESTAMP_MAX];
59 int r;
60
61 old_tz = getenv("TZ");
62 if (old_tz)
63 old_tz = strdupa(old_tz);
64
65 if (new_tz)
66 assert_se(setenv("TZ", new_tz, 1) >= 0);
67 else
68 assert_se(unsetenv("TZ") >= 0);
69 tzset();
70
71 assert_se(calendar_spec_from_string(input, &c) >= 0);
72
73 printf("\"%s\"\n", input);
74
75 u = after;
76 r = calendar_spec_next_usec(c, after, &u);
250517d2 77 printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u));
9d5bd70d
HV
78 if (expect != (usec_t)-1)
79 assert_se(r >= 0 && u == expect);
80 else
81 assert(r == -ENOENT);
82
83 calendar_spec_free(c);
84
85 if (old_tz)
86 assert_se(setenv("TZ", old_tz, 1) >= 0);
87 else
88 assert_se(unsetenv("TZ") >= 0);
89 tzset();
90}
91
21b3a0fc
LP
92static void test_timestamp(void) {
93 char buf[FORMAT_TIMESTAMP_MAX];
94 _cleanup_free_ char *t = NULL;
95 CalendarSpec *c;
96 usec_t x, y;
97
98 /* Ensure that a timestamp is also a valid calendar specification. Convert forth and back */
99
100 x = now(CLOCK_REALTIME);
101
102 assert_se(format_timestamp_us(buf, sizeof(buf), x));
103 printf("%s\n", buf);
104 assert_se(calendar_spec_from_string(buf, &c) >= 0);
105 assert_se(calendar_spec_to_string(c, &t) >= 0);
106 calendar_spec_free(c);
107 printf("%s\n", t);
108
109 assert_se(parse_timestamp(t, &y) >= 0);
110 assert_se(y == x);
111}
112
250517d2
ZJS
113static void test_hourly_bug_4031(void) {
114 CalendarSpec *c;
115 usec_t n, u, w;
116 char buf[FORMAT_TIMESTAMP_MAX], zaf[FORMAT_TIMESTAMP_MAX];
117 int r;
118
119 assert_se(calendar_spec_from_string("hourly", &c) >= 0);
120 n = now(CLOCK_REALTIME);
121 assert_se((r = calendar_spec_next_usec(c, n, &u)) >= 0);
122
123 printf("Now: %s (%"PRIu64")\n", format_timestamp_us(buf, sizeof buf, n), n);
124 printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u), u);
125
126 assert_se((r = calendar_spec_next_usec(c, u, &w)) >= 0);
127 printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(zaf, sizeof zaf, w), w);
128
129 assert_se(n < u);
130 assert_se(u <= n + USEC_PER_HOUR);
131 assert_se(u < w);
132 assert_se(w <= u + USEC_PER_HOUR);
a5d5c0d2
EV
133
134 calendar_spec_free(c);
250517d2
ZJS
135}
136
36697dc0
LP
137int main(int argc, char* argv[]) {
138 CalendarSpec *c;
139
e638d050
DC
140 test_one("Sat,Thu,Mon-Wed,Sat-Sun", "Mon..Thu,Sat,Sun *-*-* 00:00:00");
141 test_one("Sat,Thu,Mon..Wed,Sat..Sun", "Mon..Thu,Sat,Sun *-*-* 00:00:00");
36697dc0
LP
142 test_one("Mon,Sun 12-*-* 2,1:23", "Mon,Sun 2012-*-* 01,02:23:00");
143 test_one("Wed *-1", "Wed *-*-01 00:00:00");
144 test_one("Wed-Wed,Wed *-1", "Wed *-*-01 00:00:00");
e638d050 145 test_one("Wed..Wed,Wed *-1", "Wed *-*-01 00:00:00");
36697dc0 146 test_one("Wed, 17:48", "Wed *-*-* 17:48:00");
6bae2fd4 147 test_one("Wednesday,", "Wed *-*-* 00:00:00");
e638d050
DC
148 test_one("Wed-Sat,Tue 12-10-15 1:2:3", "Tue..Sat 2012-10-15 01:02:03");
149 test_one("Wed..Sat,Tue 12-10-15 1:2:3", "Tue..Sat 2012-10-15 01:02:03");
36697dc0
LP
150 test_one("*-*-7 0:0:0", "*-*-07 00:00:00");
151 test_one("10-15", "*-10-15 00:00:00");
152 test_one("monday *-12-* 17:00", "Mon *-12-* 17:00:00");
a2eb5ea7
DC
153 test_one("Mon,Fri *-*-3,1,2 *:30:45", "Mon,Fri *-*-01,02,03 *:30:45");
154 test_one("12,14,13,12:20,10,30", "*-*-* 12,13,14:10,20,30:00");
36697dc0
LP
155 test_one("mon,fri *-1/2-1,3 *:30:45", "Mon,Fri *-01/2-01,03 *:30:45");
156 test_one("03-05 08:05:40", "*-03-05 08:05:40");
157 test_one("08:05:40", "*-*-* 08:05:40");
158 test_one("05:40", "*-*-* 05:40:00");
159 test_one("Sat,Sun 12-05 08:05:40", "Sat,Sun *-12-05 08:05:40");
160 test_one("Sat,Sun 08:05:40", "Sat,Sun *-*-* 08:05:40");
161 test_one("2003-03-05 05:40", "2003-03-05 05:40:00");
162 test_one("2003-03-05", "2003-03-05 00:00:00");
163 test_one("03-05", "*-03-05 00:00:00");
164 test_one("hourly", "*-*-* *:00:00");
165 test_one("daily", "*-*-* 00:00:00");
166 test_one("monthly", "*-*-01 00:00:00");
167 test_one("weekly", "Mon *-*-* 00:00:00");
dbfd41e2
LP
168 test_one("minutely", "*-*-* *:*:00");
169 test_one("quarterly", "*-01,04,07,10-01 00:00:00");
170 test_one("semi-annually", "*-01,07-01 00:00:00");
171 test_one("annually", "*-01-01 00:00:00");
36697dc0 172 test_one("*:2/3", "*-*-* *:02/3:00");
9d5bd70d 173 test_one("2015-10-25 01:00:00 uTc", "2015-10-25 01:00:00 UTC");
48d26c01
IK
174 test_one("2015-10-25 01:00:00 Asia/Vladivostok", "2015-10-25 01:00:00 Asia/Vladivostok");
175 test_one("weekly Pacific/Auckland", "Mon *-*-* 00:00:00 Pacific/Auckland");
f22554a0
HV
176 test_one("2016-03-27 03:17:00.4200005", "2016-03-27 03:17:00.420001");
177 test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000");
9904dc00
DC
178 test_one("9..11,13:00,30", "*-*-* 09..11,13:00,30:00");
179 test_one("1..3-1..3 1..3:1..3", "*-01..03-01..03 01..03:01..03:00");
a2eb5ea7 180 test_one("00:00:1.125..2.125", "*-*-* 00:00:01.125000..02.125000");
9904dc00
DC
181 test_one("00:00:1.0..3.8", "*-*-* 00:00:01..03");
182 test_one("00:00:01..03", "*-*-* 00:00:01..03");
a2eb5ea7 183 test_one("00:00:01/2,02..03", "*-*-* 00:00:01/2,02..03");
8ea80351
DC
184 test_one("*-*~1 Utc", "*-*~01 00:00:00 UTC");
185 test_one("*-*~05,3 ", "*-*~03,05 00:00:00");
186 test_one("*-*~* 00:00:00", "*-*-* 00:00:00");
408a51e1
DC
187 test_one("Monday", "Mon *-*-* 00:00:00");
188 test_one("Monday *-*-*", "Mon *-*-* 00:00:00");
189 test_one("*-*-*", "*-*-* 00:00:00");
3215e35c 190 test_one("*:*:*", "*-*-* *:*:*");
c0df71fa
DC
191 test_one("*:*", "*-*-* *:*:00");
192 test_one("12:*", "*-*-* 12:*:00");
193 test_one("*:30", "*-*-* *:30:00");
a2eb5ea7
DC
194 test_one("93..00-*-*", "1993..2000-*-* 00:00:00");
195 test_one("00..07-*-*", "2000..2007-*-* 00:00:00");
196 test_one("*:20..39/5", "*-*-* *:20..35/5:00");
197 test_one("00:00:20..40/1", "*-*-* 00:00:20..40");
963e3d83 198 test_one("*~03/1,03..05", "*-*~03/1,03..05 00:00:00");
d80e5b74
ZJS
199 /* UNIX timestamps are always UTC */
200 test_one("@1493187147", "2017-04-26 06:12:27 UTC");
201 test_one("@1493187147 UTC", "2017-04-26 06:12:27 UTC");
202 test_one("@0", "1970-01-01 00:00:00 UTC");
203 test_one("@0 UTC", "1970-01-01 00:00:00 UTC");
9d5bd70d
HV
204
205 test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000);
206 test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000);
207 test_next("2016-03-27 03:17:00", "EET", 12345, -1);
208 test_next("2016-03-27 03:17:00 UTC", NULL, 12345, 1459048620000000);
209 test_next("2016-03-27 03:17:00 UTC", "", 12345, 1459048620000000);
210 test_next("2016-03-27 03:17:00 UTC", "CET", 12345, 1459048620000000);
211 test_next("2016-03-27 03:17:00 UTC", "EET", 12345, 1459048620000000);
f22554a0
HV
212 test_next("2016-03-27 03:17:00.420000001 UTC", "EET", 12345, 1459048620420000);
213 test_next("2016-03-27 03:17:00.4200005 UTC", "EET", 12345, 1459048620420001);
214 test_next("2015-11-13 09:11:23.42", "EET", 12345, 1447398683420000);
215 test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683420000, 1447398685190000);
216 test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683419999, 1447398683420000);
a022d76e 217 test_next("Sun 16:00:00", "CET", 1456041600123456, 1456066800000000);
f6e7d66b 218 test_next("*-04-31", "", 12345, -1);
8ea80351
DC
219 test_next("2016-02~01 UTC", "", 12345, 1456704000000000);
220 test_next("Mon 2017-05~01..07 UTC", "", 12345, 1496016000000000);
221 test_next("Mon 2017-05~07/1 UTC", "", 12345, 1496016000000000);
a2eb5ea7
DC
222 test_next("2017-08-06 9,11,13,15,17:00 UTC", "", 1502029800000000, 1502031600000000);
223 test_next("2017-08-06 9..17/2:00 UTC", "", 1502029800000000, 1502031600000000);
224 test_next("2016-12-* 3..21/6:00 UTC", "", 1482613200000001, 1482634800000000);
48d26c01
IK
225 test_next("2017-09-24 03:30:00 Pacific/Auckland", "", 12345, 1506177000000000);
226 // Due to daylight saving time - 2017-09-24 02:30:00 does not exist
227 test_next("2017-09-24 02:30:00 Pacific/Auckland", "", 12345, -1);
228 test_next("2017-04-02 02:30:00 Pacific/Auckland", "", 12345, 1491053400000000);
229 // Confirm that even though it's a time change here (backward) 02:30 happens only once
230 test_next("2017-04-02 02:30:00 Pacific/Auckland", "", 1491053400000000, -1);
231 test_next("2017-04-02 03:30:00 Pacific/Auckland", "", 12345, 1491060600000000);
232 // Confirm that timezones in the Spec work regardless of current timezone
233 test_next("2017-09-09 20:42:00 Pacific/Auckland", "", 12345, 1504946520000000);
234 test_next("2017-09-09 20:42:00 Pacific/Auckland", "EET", 12345, 1504946520000000);
36697dc0
LP
235
236 assert_se(calendar_spec_from_string("test", &c) < 0);
04773cb5 237 assert_se(calendar_spec_from_string(" utc", &c) < 0);
408a51e1 238 assert_se(calendar_spec_from_string(" ", &c) < 0);
36697dc0
LP
239 assert_se(calendar_spec_from_string("", &c) < 0);
240 assert_se(calendar_spec_from_string("7", &c) < 0);
241 assert_se(calendar_spec_from_string("121212:1:2", &c) < 0);
f22554a0
HV
242 assert_se(calendar_spec_from_string("2000-03-05.23 00:00:00", &c) < 0);
243 assert_se(calendar_spec_from_string("2000-03-05 00:00.1:00", &c) < 0);
244 assert_se(calendar_spec_from_string("00:00:00/0.00000001", &c) < 0);
32b52369 245 assert_se(calendar_spec_from_string("00:00:00.0..00.9", &c) < 0);
8ea80351
DC
246 assert_se(calendar_spec_from_string("2016~11-22", &c) < 0);
247 assert_se(calendar_spec_from_string("*-*~5/5", &c) < 0);
6bae2fd4
DC
248 assert_se(calendar_spec_from_string("Monday.. 12:00", &c) < 0);
249 assert_se(calendar_spec_from_string("Monday..", &c) < 0);
9dfa81a0
DC
250 assert_se(calendar_spec_from_string("-00:+00/-5", &c) < 0);
251 assert_se(calendar_spec_from_string("00:+00/-5", &c) < 0);
252 assert_se(calendar_spec_from_string("2016- 11- 24 12: 30: 00", &c) < 0);
a2eb5ea7
DC
253 assert_se(calendar_spec_from_string("*~29", &c) < 0);
254 assert_se(calendar_spec_from_string("*~16..31", &c) < 0);
255 assert_se(calendar_spec_from_string("12..1/2-*", &c) < 0);
256 assert_se(calendar_spec_from_string("*:05..05", &c) < 0);
257 assert_se(calendar_spec_from_string("*:05..10/6", &c) < 0);
258 assert_se(calendar_spec_from_string("20/4:00", &c) < 0);
259 assert_se(calendar_spec_from_string("00:00/60", &c) < 0);
c0aebb4b
DC
260 assert_se(calendar_spec_from_string("00:00:2300", &c) < 0);
261 assert_se(calendar_spec_from_string("00:00:18446744073709551615", &c) < 0);
36697dc0 262
21b3a0fc 263 test_timestamp();
250517d2 264 test_hourly_bug_4031();
21b3a0fc 265
36697dc0
LP
266 return 0;
267}