Branch data Line data Source code
1 : : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 : : *
3 : : * Copyright © 2018 Endless Mobile, Inc.
4 : : *
5 : : * This library is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU Lesser General Public
7 : : * License as published by the Free Software Foundation; either
8 : : * version 2.1 of the License, or (at your option) any later version.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Lesser General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public
16 : : * License along with this library; if not, write to the Free Software
17 : : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 : : *
19 : : * Authors:
20 : : * - Philip Withnall <withnall@endlessm.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : :
25 : : #include <glib.h>
26 : : #include <gio/gio.h>
27 : : #include <libmogwai-tariff/period.h>
28 : : #include <locale.h>
29 : :
30 : :
31 : : static void
32 : 6 : assert_period_validate (GDateTime *start,
33 : : GDateTime *end,
34 : : MwtPeriodRepeatType repeat_type,
35 : : guint repeat_period)
36 : : {
37 : 6 : g_autoptr(GError) error = NULL;
38 : :
39 : 6 : gboolean retval = mwt_period_validate (start, end, repeat_type, repeat_period, &error);
40 [ + - + - : 6 : g_assert_error (error, MWT_PERIOD_ERROR, MWT_PERIOD_ERROR_INVALID);
- + ]
41 [ - + ]: 6 : g_assert_false (retval);
42 : 6 : }
43 : :
44 : : static GTimeZone *
45 : 572 : time_zone_new (const gchar *tz_str)
46 : : {
47 : : #if GLIB_CHECK_VERSION(2, 68, 0)
48 : 1144 : g_autoptr(GTimeZone) tz = g_time_zone_new_identifier (tz_str);
49 [ - + ]: 572 : g_assert_nonnull (tz);
50 : 572 : return g_steal_pointer (&tz);
51 : : #else
52 : : return g_time_zone_new (tz_str);
53 : : #endif
54 : : }
55 : :
56 : : /* Test constructing a #MwtPeriod object with invalid arguments. */
57 : : static void
58 : 1 : test_period_validation (void)
59 : : {
60 : 2 : g_autoptr(GDateTime) start = g_date_time_new_utc (2000, 01, 01, 01, 01, 01);
61 : 2 : g_autoptr(GDateTime) end = g_date_time_new_utc (2000, 02, 01, 01, 01, 01);
62 : :
63 : 1 : assert_period_validate (NULL, end, MWT_PERIOD_REPEAT_HOUR, 1);
64 : 1 : assert_period_validate (start, NULL, MWT_PERIOD_REPEAT_HOUR, 1);
65 : 1 : assert_period_validate (end, start, MWT_PERIOD_REPEAT_HOUR, 1);
66 : 1 : assert_period_validate (start, end, MWT_PERIOD_REPEAT_NONE, 1);
67 : 1 : assert_period_validate (start, end, MWT_PERIOD_REPEAT_HOUR, 0);
68 : 1 : assert_period_validate (start, end, 500, 1);
69 : 1 : }
70 : :
71 : : /* Test the GObject properties on a period. */
72 : : static void
73 : 1 : test_period_properties (void)
74 : : {
75 : 2 : g_autoptr(GDateTime) start = g_date_time_new_utc (2000, 01, 01, 01, 01, 01);
76 : 2 : g_autoptr(GDateTime) end = g_date_time_new_utc (2000, 02, 01, 01, 01, 01);
77 : :
78 : 1 : g_autoptr(MwtPeriod) period = NULL;
79 : 1 : period = mwt_period_new (start, end, MWT_PERIOD_REPEAT_HOUR, 1,
80 : : "capacity-limit", (guint64) 5671,
81 : : NULL);
82 [ - + ]: 1 : g_assert_true (MWT_IS_PERIOD (period));
83 : :
84 [ - + ]: 1 : g_assert_true (g_date_time_equal (mwt_period_get_start (period), start));
85 [ - + ]: 1 : g_assert_true (g_date_time_equal (mwt_period_get_end (period), end));
86 [ - + ]: 1 : g_assert_cmpint (mwt_period_get_repeat_type (period), ==, MWT_PERIOD_REPEAT_HOUR);
87 [ - + ]: 1 : g_assert_cmpuint (mwt_period_get_repeat_period (period), ==, 1);
88 [ - + ]: 1 : g_assert_cmpuint (mwt_period_get_capacity_limit (period), ==, 5671);
89 : :
90 : 1 : g_autoptr(GDateTime) actual_start = NULL;
91 : 1 : g_autoptr(GDateTime) actual_end = NULL;
92 : : MwtPeriodRepeatType repeat_type;
93 : : guint repeat_period;
94 : : guint64 capacity_limit;
95 : :
96 : 1 : g_object_get (G_OBJECT (period),
97 : : "start", &actual_start,
98 : : "end", &actual_end,
99 : : "repeat-type", &repeat_type,
100 : : "repeat-period", &repeat_period,
101 : : "capacity-limit", &capacity_limit,
102 : : NULL);
103 : :
104 [ - + ]: 1 : g_assert_true (g_date_time_equal (actual_start, start));
105 [ - + ]: 1 : g_assert_true (g_date_time_equal (actual_end, end));
106 [ - + ]: 1 : g_assert_cmpint (repeat_type, ==, MWT_PERIOD_REPEAT_HOUR);
107 [ - + ]: 1 : g_assert_cmpuint (repeat_period, ==, 1);
108 [ - + ]: 1 : g_assert_cmpuint (capacity_limit, ==, 5671);
109 : 1 : }
110 : :
111 : : /* Test that the default values of all the limit properties for a period are
112 : : * sensible. */
113 : : static void
114 : 1 : test_period_properties_defaults (void)
115 : : {
116 : 2 : g_autoptr(GDateTime) start = g_date_time_new_utc (2000, 01, 01, 01, 01, 01);
117 : 2 : g_autoptr(GDateTime) end = g_date_time_new_utc (2000, 02, 01, 01, 01, 01);
118 : :
119 : 1 : g_autoptr(MwtPeriod) period = NULL;
120 : 1 : period = mwt_period_new (start, end, MWT_PERIOD_REPEAT_NONE, 0,
121 : : /* leave everything as default */
122 : : NULL);
123 [ - + ]: 1 : g_assert_true (MWT_IS_PERIOD (period));
124 : :
125 : : /* Test default property values. */
126 [ - + ]: 1 : g_assert_cmpuint (mwt_period_get_capacity_limit (period), ==, G_MAXUINT64);
127 : 1 : }
128 : :
129 : : /* Test mwt_period_contains_time() returns correct results for a variety of
130 : : * situations. This tests mwt_period_get_next_recurrence() at the same time,
131 : : * since their results are quite tightly linked. */
132 : : static void
133 : 1 : test_period_contains_time (void)
134 : : {
135 : : const struct
136 : : {
137 : : gint start_year;
138 : : gint start_month;
139 : : gint start_day;
140 : : gint start_hour;
141 : : gint start_minute;
142 : : gdouble start_seconds;
143 : : const gchar *start_tz;
144 : :
145 : : gint end_year;
146 : : gint end_month;
147 : : gint end_day;
148 : : gint end_hour;
149 : : gint end_minute;
150 : : gdouble end_seconds;
151 : : const gchar *end_tz;
152 : :
153 : : MwtPeriodRepeatType repeat_type;
154 : : guint repeat_period;
155 : :
156 : : gint when_year;
157 : : gint when_month;
158 : : gint when_day;
159 : : gint when_hour;
160 : : gint when_minute;
161 : : gdouble when_seconds;
162 : : const gchar *when_tz;
163 : :
164 : : gboolean expected_contains;
165 : :
166 : : gint expected_contains_start_year;
167 : : gint expected_contains_start_month;
168 : : gint expected_contains_start_day;
169 : : gint expected_contains_start_hour;
170 : : gint expected_contains_start_minute;
171 : : gdouble expected_contains_start_seconds;
172 : : const gchar *expected_contains_start_tz;
173 : :
174 : : gint expected_contains_end_year;
175 : : gint expected_contains_end_month;
176 : : gint expected_contains_end_day;
177 : : gint expected_contains_end_hour;
178 : : gint expected_contains_end_minute;
179 : : gdouble expected_contains_end_seconds;
180 : : const gchar *expected_contains_end_tz;
181 : :
182 : : gboolean expected_next;
183 : :
184 : : gint expected_next_start_year;
185 : : gint expected_next_start_month;
186 : : gint expected_next_start_day;
187 : : gint expected_next_start_hour;
188 : : gint expected_next_start_minute;
189 : : gdouble expected_next_start_seconds;
190 : : const gchar *expected_next_start_tz;
191 : :
192 : : gint expected_next_end_year;
193 : : gint expected_next_end_month;
194 : : gint expected_next_end_day;
195 : : gint expected_next_end_hour;
196 : : gint expected_next_end_minute;
197 : : gdouble expected_next_end_seconds;
198 : : const gchar *expected_next_end_tz;
199 : : }
200 : 1 : vectors[] =
201 : : {
202 : : /* Test boundaries on a simple period-1 weekly repeat. */
203 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
204 : : MWT_PERIOD_REPEAT_WEEK, 1,
205 : : 2017, 12, 31, 23, 59, 59.99, "Z",
206 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
207 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z" },
208 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
209 : : MWT_PERIOD_REPEAT_WEEK, 1,
210 : : 2018, 1, 1, 0, 0, 0.0, "Z",
211 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
212 : : TRUE, 2018, 1, 8, 0, 0, 0.0, "Z", 2018, 1, 8, 4, 0, 0.0, "Z" },
213 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
214 : : MWT_PERIOD_REPEAT_WEEK, 1,
215 : : 2018, 1, 1, 2, 0, 0.0, "Z",
216 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
217 : : TRUE, 2018, 1, 8, 0, 0, 0.0, "Z", 2018, 1, 8, 4, 0, 0.0, "Z" },
218 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
219 : : MWT_PERIOD_REPEAT_WEEK, 1,
220 : : 2018, 1, 1, 3, 59, 59.99, "Z",
221 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
222 : : TRUE, 2018, 1, 8, 0, 0, 0.0, "Z", 2018, 1, 8, 4, 0, 0.0, "Z" },
223 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
224 : : MWT_PERIOD_REPEAT_WEEK, 1,
225 : : 2018, 1, 1, 4, 0, 0.0, "Z",
226 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
227 : : TRUE, 2018, 1, 8, 0, 0, 0.0, "Z", 2018, 1, 8, 4, 0, 0.0, "Z" },
228 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
229 : : MWT_PERIOD_REPEAT_WEEK, 1,
230 : : 2018, 1, 7, 23, 59, 59.99, "Z",
231 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
232 : : TRUE, 2018, 1, 8, 0, 0, 0.0, "Z", 2018, 1, 8, 4, 0, 0.0, "Z" },
233 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
234 : : MWT_PERIOD_REPEAT_WEEK, 1,
235 : : 2018, 1, 8, 0, 0, 0.0, "Z",
236 : : TRUE, 2018, 1, 8, 0, 0, 0.0, "Z", 2018, 1, 8, 4, 0, 0.0, "Z",
237 : : TRUE, 2018, 1, 15, 0, 0, 0.0, "Z", 2018, 1, 15, 4, 0, 0.0, "Z" },
238 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
239 : : MWT_PERIOD_REPEAT_WEEK, 1,
240 : : 2018, 1, 8, 2, 0, 0.0, "Z",
241 : : TRUE, 2018, 1, 8, 0, 0, 0.0, "Z", 2018, 1, 8, 4, 0, 0.0, "Z",
242 : : TRUE, 2018, 1, 15, 0, 0, 0.0, "Z", 2018, 1, 15, 4, 0, 0.0, "Z" },
243 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
244 : : MWT_PERIOD_REPEAT_WEEK, 1,
245 : : 2018, 1, 8, 3, 59, 59.99, "Z",
246 : : TRUE, 2018, 1, 8, 0, 0, 0.0, "Z", 2018, 1, 8, 4, 0, 0.0, "Z",
247 : : TRUE, 2018, 1, 15, 0, 0, 0.0, "Z", 2018, 1, 15, 4, 0, 0.0, "Z" },
248 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
249 : : MWT_PERIOD_REPEAT_WEEK, 1,
250 : : 2018, 1, 8, 4, 0, 0.0, "Z",
251 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
252 : : TRUE, 2018, 1, 15, 0, 0, 0.0, "Z", 2018, 1, 15, 4, 0, 0.0, "Z" },
253 : : /* The same, but with a period-3 repeat. */
254 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
255 : : MWT_PERIOD_REPEAT_WEEK, 3,
256 : : 2018, 1, 1, 2, 0, 0.0, "Z",
257 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
258 : : TRUE, 2018, 1, 22, 0, 0, 0.0, "Z", 2018, 1, 22, 4, 0, 0.0, "Z" },
259 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
260 : : MWT_PERIOD_REPEAT_WEEK, 3,
261 : : 2018, 1, 8, 2, 0, 0.0, "Z",
262 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
263 : : TRUE, 2018, 1, 22, 0, 0, 0.0, "Z", 2018, 1, 22, 4, 0, 0.0, "Z" },
264 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
265 : : MWT_PERIOD_REPEAT_WEEK, 3,
266 : : 2018, 1, 15, 2, 0, 0.0, "Z",
267 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
268 : : TRUE, 2018, 1, 22, 0, 0, 0.0, "Z", 2018, 1, 22, 4, 0, 0.0, "Z" },
269 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
270 : : MWT_PERIOD_REPEAT_WEEK, 3,
271 : : 2018, 1, 22, 2, 0, 0.0, "Z",
272 : : TRUE, 2018, 1, 22, 0, 0, 0.0, "Z", 2018, 1, 22, 4, 0, 0.0, "Z",
273 : : TRUE, 2018, 2, 12, 0, 0, 0.0, "Z", 2018, 2, 12, 4, 0, 0.0, "Z" },
274 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
275 : : MWT_PERIOD_REPEAT_WEEK, 3,
276 : : 2018, 1, 29, 2, 0, 0.0, "Z",
277 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
278 : : TRUE, 2018, 2, 12, 0, 0, 0.0, "Z", 2018, 2, 12, 4, 0, 0.0, "Z" },
279 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
280 : : MWT_PERIOD_REPEAT_WEEK, 3,
281 : : 2018, 2, 5, 2, 0, 0.0, "Z",
282 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
283 : : TRUE, 2018, 2, 12, 0, 0, 0.0, "Z", 2018, 2, 12, 4, 0, 0.0, "Z" },
284 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
285 : : MWT_PERIOD_REPEAT_WEEK, 3,
286 : : 2018, 2, 12, 2, 0, 0.0, "Z",
287 : : TRUE, 2018, 2, 12, 0, 0, 0.0, "Z", 2018, 2, 12, 4, 0, 0.0, "Z",
288 : : TRUE, 2018, 3, 5, 0, 0, 0.0, "Z", 2018, 3, 5, 4, 0, 0.0, "Z" },
289 : : /* Test hourly repeats. */
290 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 0, 30, 0.0, "Z",
291 : : MWT_PERIOD_REPEAT_HOUR, 1,
292 : : 2017, 12, 31, 23, 59, 59.99, "Z",
293 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
294 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 0, 30, 0.0, "Z" },
295 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 0, 30, 0.0, "Z",
296 : : MWT_PERIOD_REPEAT_HOUR, 1,
297 : : 2018, 1, 1, 0, 0, 0.0, "Z",
298 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 0, 30, 0.0, "Z",
299 : : TRUE, 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 1, 30, 0.0, "Z" },
300 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 0, 30, 0.0, "Z",
301 : : MWT_PERIOD_REPEAT_HOUR, 1,
302 : : 2018, 1, 1, 0, 29, 59.99, "Z",
303 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 0, 30, 0.0, "Z",
304 : : TRUE, 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 1, 30, 0.0, "Z" },
305 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 0, 30, 0.0, "Z",
306 : : MWT_PERIOD_REPEAT_HOUR, 1,
307 : : 2018, 1, 1, 0, 30, 0.0, "Z",
308 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
309 : : TRUE, 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 1, 30, 0.0, "Z" },
310 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 0, 30, 0.0, "Z",
311 : : MWT_PERIOD_REPEAT_HOUR, 1,
312 : : 2018, 1, 1, 1, 0, 0.0, "Z",
313 : : TRUE, 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 1, 30, 0.0, "Z",
314 : : TRUE, 2018, 1, 1, 2, 0, 0.0, "Z", 2018, 1, 1, 2, 30, 0.0, "Z" },
315 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 0, 30, 0.0, "Z",
316 : : MWT_PERIOD_REPEAT_HOUR, 1,
317 : : 2018, 1, 1, 2, 5, 0.0, "Z",
318 : : TRUE, 2018, 1, 1, 2, 0, 0.0, "Z", 2018, 1, 1, 2, 30, 0.0, "Z",
319 : : TRUE, 2018, 1, 1, 3, 0, 0.0, "Z", 2018, 1, 1, 3, 30, 0.0, "Z" },
320 : : /* Test daily repeats. */
321 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
322 : : MWT_PERIOD_REPEAT_DAY, 2,
323 : : 2017, 12, 31, 23, 59, 59.99, "Z",
324 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
325 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z" },
326 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
327 : : MWT_PERIOD_REPEAT_DAY, 2,
328 : : 2018, 1, 1, 0, 0, 0.0, "Z",
329 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
330 : : TRUE, 2018, 1, 3, 0, 0, 0.0, "Z", 2018, 1, 3, 4, 0, 0.0, "Z" },
331 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
332 : : MWT_PERIOD_REPEAT_DAY, 2,
333 : : 2018, 1, 1, 3, 0, 0.0, "Z",
334 : : TRUE, 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
335 : : TRUE, 2018, 1, 3, 0, 0, 0.0, "Z", 2018, 1, 3, 4, 0, 0.0, "Z" },
336 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
337 : : MWT_PERIOD_REPEAT_DAY, 2,
338 : : 2018, 1, 1, 4, 0, 0.0, "Z",
339 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
340 : : TRUE, 2018, 1, 3, 0, 0, 0.0, "Z", 2018, 1, 3, 4, 0, 0.0, "Z" },
341 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
342 : : MWT_PERIOD_REPEAT_DAY, 2,
343 : : 2018, 1, 2, 0, 0, 0.0, "Z",
344 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
345 : : TRUE, 2018, 1, 3, 0, 0, 0.0, "Z", 2018, 1, 3, 4, 0, 0.0, "Z" },
346 : : { 2018, 1, 1, 0, 0, 0.0, "Z", 2018, 1, 1, 4, 0, 0.0, "Z",
347 : : MWT_PERIOD_REPEAT_DAY, 2,
348 : : 2018, 1, 3, 0, 0, 0.0, "Z",
349 : : TRUE, 2018, 1, 3, 0, 0, 0.0, "Z", 2018, 1, 3, 4, 0, 0.0, "Z",
350 : : TRUE, 2018, 1, 5, 0, 0, 0.0, "Z", 2018, 1, 5, 4, 0, 0.0, "Z" },
351 : : /* Test monthly repeats (at period-2). */
352 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
353 : : MWT_PERIOD_REPEAT_MONTH, 2,
354 : : 2018, 1, 1, 0, 0, 0.0, "Z",
355 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
356 : : TRUE, 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z" },
357 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
358 : : MWT_PERIOD_REPEAT_MONTH, 2,
359 : : 2018, 1, 1, 1, 0, 0.0, "Z",
360 : : TRUE, 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
361 : : TRUE, 2018, 3, 1, 1, 0, 0.0, "Z", 2018, 3, 1, 5, 0, 0.0, "Z" },
362 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
363 : : MWT_PERIOD_REPEAT_MONTH, 2,
364 : : 2018, 1, 1, 4, 0, 0.0, "Z",
365 : : TRUE, 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
366 : : TRUE, 2018, 3, 1, 1, 0, 0.0, "Z", 2018, 3, 1, 5, 0, 0.0, "Z" },
367 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
368 : : MWT_PERIOD_REPEAT_MONTH, 2,
369 : : 2018, 1, 1, 5, 0, 0.0, "Z",
370 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
371 : : TRUE, 2018, 3, 1, 1, 0, 0.0, "Z", 2018, 3, 1, 5, 0, 0.0, "Z" },
372 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
373 : : MWT_PERIOD_REPEAT_MONTH, 2,
374 : : 2018, 1, 8, 4, 0, 0.0, "Z",
375 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
376 : : TRUE, 2018, 3, 1, 1, 0, 0.0, "Z", 2018, 3, 1, 5, 0, 0.0, "Z" },
377 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
378 : : MWT_PERIOD_REPEAT_MONTH, 2,
379 : : 2018, 1, 31, 4, 0, 0.0, "Z",
380 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
381 : : TRUE, 2018, 3, 1, 1, 0, 0.0, "Z", 2018, 3, 1, 5, 0, 0.0, "Z" },
382 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
383 : : MWT_PERIOD_REPEAT_MONTH, 2,
384 : : 2018, 2, 1, 4, 0, 0.0, "Z",
385 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
386 : : TRUE, 2018, 3, 1, 1, 0, 0.0, "Z", 2018, 3, 1, 5, 0, 0.0, "Z" },
387 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
388 : : MWT_PERIOD_REPEAT_MONTH, 2,
389 : : 2018, 3, 1, 4, 0, 0.0, "Z",
390 : : TRUE, 2018, 3, 1, 1, 0, 0.0, "Z", 2018, 3, 1, 5, 0, 0.0, "Z",
391 : : TRUE, 2018, 5, 1, 1, 0, 0.0, "Z", 2018, 5, 1, 5, 0, 0.0, "Z" },
392 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
393 : : MWT_PERIOD_REPEAT_MONTH, 2,
394 : : 2018, 4, 1, 4, 0, 0.0, "Z",
395 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
396 : : TRUE, 2018, 5, 1, 1, 0, 0.0, "Z", 2018, 5, 1, 5, 0, 0.0, "Z" },
397 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
398 : : MWT_PERIOD_REPEAT_MONTH, 2,
399 : : 2018, 5, 1, 4, 0, 0.0, "Z",
400 : : TRUE, 2018, 5, 1, 1, 0, 0.0, "Z", 2018, 5, 1, 5, 0, 0.0, "Z",
401 : : TRUE, 2018, 7, 1, 1, 0, 0.0, "Z", 2018, 7, 1, 5, 0, 0.0, "Z" },
402 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
403 : : MWT_PERIOD_REPEAT_MONTH, 2,
404 : : 2018, 11, 1, 4, 0, 0.0, "Z",
405 : : TRUE, 2018, 11, 1, 1, 0, 0.0, "Z", 2018, 11, 1, 5, 0, 0.0, "Z",
406 : : TRUE, 2019, 1, 1, 1, 0, 0.0, "Z", 2019, 1, 1, 5, 0, 0.0, "Z" },
407 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
408 : : MWT_PERIOD_REPEAT_MONTH, 2,
409 : : 2118, 1, 1, 4, 0, 0.0, "Z",
410 : : TRUE, 2118, 1, 1, 1, 0, 0.0, "Z", 2118, 1, 1, 5, 0, 0.0, "Z",
411 : : TRUE, 2118, 3, 1, 1, 0, 0.0, "Z", 2118, 3, 1, 5, 0, 0.0, "Z" },
412 : : /* Test yearly repeats. */
413 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
414 : : MWT_PERIOD_REPEAT_YEAR, 1,
415 : : 2018, 1, 1, 0, 0, 0.0, "Z",
416 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
417 : : TRUE, 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z" },
418 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
419 : : MWT_PERIOD_REPEAT_YEAR, 1,
420 : : 2018, 1, 1, 1, 0, 0.0, "Z",
421 : : TRUE, 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
422 : : TRUE, 2019, 1, 1, 1, 0, 0.0, "Z", 2019, 1, 1, 5, 0, 0.0, "Z" },
423 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
424 : : MWT_PERIOD_REPEAT_YEAR, 1,
425 : : 2019, 1, 1, 4, 0, 0.0, "Z",
426 : : TRUE, 2019, 1, 1, 1, 0, 0.0, "Z", 2019, 1, 1, 5, 0, 0.0, "Z",
427 : : TRUE, 2020, 1, 1, 1, 0, 0.0, "Z", 2020, 1, 1, 5, 0, 0.0, "Z" },
428 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
429 : : MWT_PERIOD_REPEAT_YEAR, 1,
430 : : 2020, 1, 1, 4, 0, 0.0, "Z",
431 : : TRUE, 2020, 1, 1, 1, 0, 0.0, "Z", 2020, 1, 1, 5, 0, 0.0, "Z",
432 : : TRUE, 2021, 1, 1, 1, 0, 0.0, "Z", 2021, 1, 1, 5, 0, 0.0, "Z" },
433 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
434 : : MWT_PERIOD_REPEAT_YEAR, 1,
435 : : 3000, 1, 1, 0, 59, 59.99, "Z",
436 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
437 : : TRUE, 3000, 1, 1, 1, 0, 0.0, "Z", 3000, 1, 1, 5, 0, 0.0, "Z" },
438 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
439 : : MWT_PERIOD_REPEAT_YEAR, 1,
440 : : 3000, 1, 1, 1, 0, 0.0, "Z",
441 : : TRUE, 3000, 1, 1, 1, 0, 0.0, "Z", 3000, 1, 1, 5, 0, 0.0, "Z",
442 : : TRUE, 3001, 1, 1, 1, 0, 0.0, "Z", 3001, 1, 1, 5, 0, 0.0, "Z" },
443 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
444 : : MWT_PERIOD_REPEAT_YEAR, 1,
445 : : 3000, 1, 1, 4, 0, 0.0, "Z",
446 : : TRUE, 3000, 1, 1, 1, 0, 0.0, "Z", 3000, 1, 1, 5, 0, 0.0, "Z",
447 : : TRUE, 3001, 1, 1, 1, 0, 0.0, "Z", 3001, 1, 1, 5, 0, 0.0, "Z" },
448 : : { 2018, 1, 1, 1, 0, 0.0, "Z", 2018, 1, 1, 5, 0, 0.0, "Z",
449 : : MWT_PERIOD_REPEAT_YEAR, 1,
450 : : 3000, 1, 1, 5, 0, 0.0, "Z",
451 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
452 : : TRUE, 3001, 1, 1, 1, 0, 0.0, "Z", 3001, 1, 1, 5, 0, 0.0, "Z" },
453 : : /* Leap year handling. 2020 is a leap year. A period on the 30th of January
454 : : * which repeats monthly should repeat on the last day of February. */
455 : : { 2018, 1, 30, 1, 0, 0.0, "Z", 2018, 1, 30, 5, 0, 0.0, "Z",
456 : : MWT_PERIOD_REPEAT_MONTH, 1,
457 : : 2018, 1, 30, 4, 0, 0.0, "Z",
458 : : TRUE, 2018, 1, 30, 1, 0, 0.0, "Z", 2018, 1, 30, 5, 0, 0.0, "Z",
459 : : TRUE, 2018, 2, 28, 1, 0, 0.0, "Z", 2018, 2, 28, 5, 0, 0.0, "Z" },
460 : : { 2018, 1, 30, 1, 0, 0.0, "Z", 2018, 1, 30, 5, 0, 0.0, "Z",
461 : : MWT_PERIOD_REPEAT_MONTH, 1,
462 : : 2018, 2, 28, 4, 0, 0.0, "Z",
463 : : TRUE, 2018, 2, 28, 1, 0, 0.0, "Z", 2018, 2, 28, 5, 0, 0.0, "Z",
464 : : TRUE, 2018, 3, 30, 1, 0, 0.0, "Z", 2018, 3, 30, 5, 0, 0.0, "Z" },
465 : : { 2018, 1, 30, 1, 0, 0.0, "Z", 2018, 1, 30, 5, 0, 0.0, "Z",
466 : : MWT_PERIOD_REPEAT_MONTH, 1,
467 : : 2020, 1, 28, 4, 0, 0.0, "Z",
468 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
469 : : TRUE, 2020, 1, 30, 1, 0, 0.0, "Z", 2020, 1, 30, 5, 0, 0.0, "Z" },
470 : : { 2018, 1, 30, 1, 0, 0.0, "Z", 2018, 1, 30, 5, 0, 0.0, "Z",
471 : : MWT_PERIOD_REPEAT_MONTH, 1,
472 : : 2020, 2, 29, 4, 0, 0.0, "Z",
473 : : TRUE, 2020, 2, 29, 1, 0, 0.0, "Z", 2020, 2, 29, 5, 0, 0.0, "Z",
474 : : TRUE, 2020, 3, 30, 1, 0, 0.0, "Z", 2020, 3, 30, 5, 0, 0.0, "Z" },
475 : : /* Check DST handling. There’s a DST switch on 2018-03-25 in Europe/London,
476 : : * where the clocks go forward 1h at 01:00, so the period 01:00–01:59 does
477 : : * not exist: so we expect no recurrences on 2018-03-25 at all, but expect
478 : : * recurrences during the normal time period (01:30–01:45) in subsequent
479 : : * weeks. */
480 : : { 2018, 3, 18, 1, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 45, 0.0, "Europe/London",
481 : : MWT_PERIOD_REPEAT_WEEK, 1,
482 : : 2018, 3, 18, 1, 35, 0.0, "Europe/London",
483 : : TRUE, 2018, 3, 18, 1, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 45, 0.0, "Europe/London",
484 : : TRUE, 2018, 4, 1, 1, 30, 0.0, "Europe/London", 2018, 4, 1, 1, 45, 0.0, "Europe/London" },
485 : : { 2018, 3, 18, 1, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 45, 0.0, "Europe/London",
486 : : MWT_PERIOD_REPEAT_WEEK, 1,
487 : : 2018, 3, 25, 1, 0, 0.0, "Europe/London",
488 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Europe/London", 0, 0, 0, 0, 0, 0.0, "Europe/London",
489 : : TRUE, 2018, 4, 1, 1, 30, 0.0, "Europe/London", 2018, 4, 1, 1, 45, 0.0, "Europe/London" },
490 : : { 2018, 3, 18, 1, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 45, 0.0, "Europe/London",
491 : : MWT_PERIOD_REPEAT_WEEK, 1,
492 : : 2018, 3, 25, 0, 59, 59.99, "Europe/London",
493 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Europe/London", 0, 0, 0, 0, 0, 0.0, "Europe/London",
494 : : TRUE, 2018, 4, 1, 1, 30, 0.0, "Europe/London", 2018, 4, 1, 1, 45, 0.0, "Europe/London" },
495 : : { 2018, 3, 18, 1, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 45, 0.0, "Europe/London",
496 : : MWT_PERIOD_REPEAT_WEEK, 1,
497 : : 2018, 3, 25, 1, 35, 0.0, "Europe/London",
498 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Europe/London", 0, 0, 0, 0, 0, 0.0, "Europe/London",
499 : : TRUE, 2018, 4, 1, 1, 30, 0.0, "Europe/London", 2018, 4, 1, 1, 45, 0.0, "Europe/London" },
500 : : { 2018, 3, 18, 1, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 45, 0.0, "Europe/London",
501 : : MWT_PERIOD_REPEAT_WEEK, 1,
502 : : 2018, 3, 25, 2, 0, 0.0, "Europe/London",
503 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Europe/London", 0, 0, 0, 0, 0, 0.0, "Europe/London",
504 : : TRUE, 2018, 4, 1, 1, 30, 0.0, "Europe/London", 2018, 4, 1, 1, 45, 0.0, "Europe/London" },
505 : : { 2018, 3, 18, 1, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 45, 0.0, "Europe/London",
506 : : MWT_PERIOD_REPEAT_WEEK, 1,
507 : : 2018, 4, 1, 1, 29, 59.99, "Europe/London",
508 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Europe/London", 0, 0, 0, 0, 0, 0.0, "Europe/London",
509 : : TRUE, 2018, 4, 1, 1, 30, 0.0, "Europe/London", 2018, 4, 1, 1, 45, 0.0, "Europe/London" },
510 : : { 2018, 3, 18, 1, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 45, 0.0, "Europe/London",
511 : : MWT_PERIOD_REPEAT_WEEK, 1,
512 : : 2018, 4, 1, 1, 35, 0.0, "Europe/London",
513 : : TRUE, 2018, 4, 1, 1, 30, 0.0, "Europe/London", 2018, 4, 1, 1, 45, 0.0, "Europe/London",
514 : : TRUE, 2018, 4, 8, 1, 30, 0.0, "Europe/London", 2018, 4, 8, 1, 45, 0.0, "Europe/London" },
515 : : { 2018, 3, 18, 1, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 45, 0.0, "Europe/London",
516 : : MWT_PERIOD_REPEAT_WEEK, 1,
517 : : 2018, 4, 1, 1, 45, 0.0, "Europe/London",
518 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Europe/London", 0, 0, 0, 0, 0, 0.0, "Europe/London",
519 : : TRUE, 2018, 4, 8, 1, 30, 0.0, "Europe/London", 2018, 4, 8, 1, 45, 0.0, "Europe/London" },
520 : : { 2018, 3, 18, 1, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 45, 0.0, "Europe/London",
521 : : MWT_PERIOD_REPEAT_WEEK, 1,
522 : : 2018, 4, 8, 1, 35, 0.0, "Europe/London",
523 : : TRUE, 2018, 4, 8, 1, 30, 0.0, "Europe/London", 2018, 4, 8, 1, 45, 0.0, "Europe/London",
524 : : TRUE, 2018, 4, 15, 1, 30, 0.0, "Europe/London", 2018, 4, 15, 1, 45, 0.0, "Europe/London" },
525 : : /* A DST check for a period which contains a DST hole and some time on
526 : : * either side. This is the same DST switch as above; the period
527 : : * 01:00–01:59 does not exist. However, since our recurrence contains time
528 : : * either side, we expect the recurrence to exist every week, including
529 : : * the week of the DST switch. The length of the recurrence (not tested
530 : : * here) will be 60 minutes shorter on that week, though. */
531 : : { 2018, 3, 18, 0, 30, 0.0, "Europe/London", 2018, 3, 18, 2, 30, 0.0, "Europe/London",
532 : : MWT_PERIOD_REPEAT_WEEK, 1,
533 : : 2018, 3, 18, 1, 35, 0.0, "Europe/London",
534 : : TRUE, 2018, 3, 18, 0, 30, 0.0, "Europe/London", 2018, 3, 18, 2, 30, 0.0, "Europe/London",
535 : : TRUE, 2018, 3, 25, 0, 30, 0.0, "Europe/London", 2018, 3, 25, 2, 30, 0.0, "Europe/London" },
536 : : { 2018, 3, 18, 0, 30, 0.0, "Europe/London", 2018, 3, 18, 2, 30, 0.0, "Europe/London",
537 : : MWT_PERIOD_REPEAT_WEEK, 1,
538 : : 2018, 3, 25, 0, 30, 0.0, "Europe/London",
539 : : TRUE, 2018, 3, 25, 0, 30, 0.0, "Europe/London", 2018, 3, 25, 2, 30, 0.0, "Europe/London",
540 : : TRUE, 2018, 4, 1, 0, 30, 0.0, "Europe/London", 2018, 4, 1, 2, 30, 0.0, "Europe/London" },
541 : : { 2018, 3, 18, 0, 30, 0.0, "Europe/London", 2018, 3, 18, 2, 30, 0.0, "Europe/London",
542 : : MWT_PERIOD_REPEAT_WEEK, 1,
543 : : 2018, 3, 25, 1, 0, 0.0, "Europe/London",
544 : : TRUE, 2018, 3, 25, 0, 30, 0.0, "Europe/London", 2018, 3, 25, 2, 30, 0.0, "Europe/London",
545 : : TRUE, 2018, 4, 1, 0, 30, 0.0, "Europe/London", 2018, 4, 1, 2, 30, 0.0, "Europe/London" },
546 : : { 2018, 3, 18, 0, 30, 0.0, "Europe/London", 2018, 3, 18, 2, 30, 0.0, "Europe/London",
547 : : MWT_PERIOD_REPEAT_WEEK, 1,
548 : : 2018, 3, 25, 2, 0, 0.0, "Europe/London",
549 : : TRUE, 2018, 3, 25, 0, 30, 0.0, "Europe/London", 2018, 3, 25, 2, 30, 0.0, "Europe/London",
550 : : TRUE, 2018, 4, 1, 0, 30, 0.0, "Europe/London", 2018, 4, 1, 2, 30, 0.0, "Europe/London" },
551 : : /* Partial overlap with a DST hole, using all the same setup as
552 : : * immediately above. */
553 : : { 2018, 3, 18, 0, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 30, 0.0, "Europe/London",
554 : : MWT_PERIOD_REPEAT_WEEK, 1,
555 : : 2018, 3, 18, 0, 35, 0.0, "Europe/London",
556 : : TRUE, 2018, 3, 18, 0, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 30, 0.0, "Europe/London",
557 : : TRUE, 2018, 3, 25, 0, 30, 0.0, "Europe/London", 2018, 3, 25, 2, 0, 0.0, "Europe/London" },
558 : : { 2018, 3, 18, 0, 30, 0.0, "Europe/London", 2018, 3, 18, 1, 30, 0.0, "Europe/London",
559 : : MWT_PERIOD_REPEAT_WEEK, 1,
560 : : 2018, 3, 25, 0, 35, 0.0, "Europe/London",
561 : : TRUE, 2018, 3, 25, 0, 30, 0.0, "Europe/London", 2018, 3, 25, 2, 0, 0.0, "Europe/London",
562 : : TRUE, 2018, 4, 1, 0, 30, 0.0, "Europe/London", 2018, 4, 1, 1, 30, 0.0, "Europe/London" },
563 : : /* Test what gnome-control-center does, which is to have two periods: one
564 : : * covers all time (no need to test that, as it doesn’t recur), and the
565 : : * other covers 22:00–06:00 at the start of the Unix time period in 1970,
566 : : * and recurs every day. Test that works, and doesn’t perform badly. (This
567 : : * is an implicit performance test, in that the test shouldn’t take
568 : : * forever to run, rather than an explicit one counting loop cycles. We’re
569 : : * not *that* concerned about performance. */
570 : : { 1970, 1, 1, 22, 0, 0.0, "Z", 1970, 1, 2, 6, 0, 0.0, "Z",
571 : : MWT_PERIOD_REPEAT_DAY, 1,
572 : : 2018, 2, 1, 21, 59, 59.99, "Z",
573 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
574 : : TRUE, 2018, 2, 1, 22, 0, 0.0, "Z", 2018, 2, 2, 6, 0, 0.0, "Z" },
575 : : { 1970, 1, 1, 22, 0, 0.0, "Z", 1970, 1, 2, 6, 0, 0.0, "Z",
576 : : MWT_PERIOD_REPEAT_DAY, 1,
577 : : 2018, 2, 1, 22, 0, 0.0, "Z",
578 : : TRUE, 2018, 2, 1, 22, 0, 0.0, "Z", 2018, 2, 2, 6, 0, 0.0, "Z",
579 : : TRUE, 2018, 2, 2, 22, 0, 0.0, "Z", 2018, 2, 3, 6, 0, 0.0, "Z" },
580 : : { 1970, 1, 1, 22, 0, 0.0, "Z", 1970, 1, 2, 6, 0, 0.0, "Z",
581 : : MWT_PERIOD_REPEAT_DAY, 1,
582 : : 2018, 2, 2, 1, 0, 0.0, "Z",
583 : : TRUE, 2018, 2, 1, 22, 0, 0.0, "Z", 2018, 2, 2, 6, 0, 0.0, "Z",
584 : : TRUE, 2018, 2, 2, 22, 0, 0.0, "Z", 2018, 2, 3, 6, 0, 0.0, "Z" },
585 : : { 1970, 1, 1, 22, 0, 0.0, "Z", 1970, 1, 2, 6, 0, 0.0, "Z",
586 : : MWT_PERIOD_REPEAT_DAY, 1,
587 : : 2018, 2, 2, 6, 0, 0.0, "Z",
588 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
589 : : TRUE, 2018, 2, 2, 22, 0, 0.0, "Z", 2018, 2, 3, 6, 0, 0.0, "Z" },
590 : : /* Test situations where there is no next recurrence (THE END OF TIME),
591 : : * where either the next recurring start time, or end time, or both, would
592 : : * overflow #GDateTime. */
593 : : { 1970, 1, 1, 22, 0, 0.0, "Z", 1970, 1, 2, 6, 0, 0.0, "Z",
594 : : MWT_PERIOD_REPEAT_DAY, 1,
595 : : 9999, 12, 29, 22, 0, 0.0, "Z",
596 : : TRUE, 9999, 12, 29, 22, 0, 0.0, "Z", 9999, 12, 30, 6, 0, 0.0, "Z",
597 : : TRUE, 9999, 12, 30, 22, 0, 0.0, "Z", 9999, 12, 31, 6, 0, 0.0, "Z" },
598 : : { 1970, 1, 1, 22, 0, 0.0, "Z", 1970, 1, 2, 6, 0, 0.0, "Z",
599 : : MWT_PERIOD_REPEAT_DAY, 1,
600 : : 9999, 12, 30, 22, 0, 0.0, "Z",
601 : : TRUE, 9999, 12, 30, 22, 0, 0.0, "Z", 9999, 12, 31, 6, 0, 0.0, "Z",
602 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z" },
603 : : { 1970, 1, 1, 22, 0, 0.0, "Z", 1970, 1, 2, 6, 0, 0.0, "Z",
604 : : MWT_PERIOD_REPEAT_DAY, 1,
605 : : 9999, 12, 31, 22, 0, 0.0, "Z",
606 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
607 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z" },
608 : : { 2018, 1, 1, 22, 0, 0.0, "Z", 2018, 1, 1, 23, 0, 0.0, "Z",
609 : : MWT_PERIOD_REPEAT_DAY, 1,
610 : : 9999, 12, 29, 22, 0, 0.0, "Z",
611 : : TRUE, 9999, 12, 29, 22, 0, 0.0, "Z", 9999, 12, 29, 23, 0, 0.0, "Z",
612 : : TRUE, 9999, 12, 30, 22, 0, 0.0, "Z", 9999, 12, 30, 23, 0, 0.0, "Z" },
613 : : { 2018, 1, 1, 22, 0, 0.0, "Z", 2018, 1, 1, 23, 0, 0.0, "Z",
614 : : MWT_PERIOD_REPEAT_DAY, 1,
615 : : 9999, 12, 30, 22, 0, 0.0, "Z",
616 : : TRUE, 9999, 12, 30, 22, 0, 0.0, "Z", 9999, 12, 30, 23, 0, 0.0, "Z",
617 : : TRUE, 9999, 12, 31, 22, 0, 0.0, "Z", 9999, 12, 31, 23, 0, 0.0, "Z" },
618 : : { 2018, 1, 1, 22, 0, 0.0, "Z", 2018, 1, 1, 23, 0, 0.0, "Z",
619 : : MWT_PERIOD_REPEAT_DAY, 1,
620 : : 9999, 12, 31, 22, 0, 0.0, "Z",
621 : : TRUE, 9999, 12, 31, 22, 0, 0.0, "Z", 9999, 12, 31, 23, 0, 0.0, "Z",
622 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z" },
623 : : { 2018, 1, 1, 22, 0, 0.0, "Z", 2018, 1, 1, 23, 0, 0.0, "Z",
624 : : MWT_PERIOD_REPEAT_DAY, 1,
625 : : 9999, 12, 31, 23, 0, 0.0, "Z",
626 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
627 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z" },
628 : : /* More DST checks. There’s a DST switch on 2018-10-28 in Europe/London,
629 : : * where the clocks go backward 1h at 02:00, so the period 01:00–01:59
630 : : * happens twice (once in the daylight savings timezone, once outside it).
631 : : * We expect a recurrence to fall on the first occurrence of those hours,
632 : : * but not the second (since that’s not a week later).
633 : : * In this test, we sometimes express the timezone as ±hh to make it clear
634 : : * which side of the DST switch a time is on: the times
635 : : * 2018-10-28T01:30:00+01 and 2018-10-28T01:30:00+00 both happen in
636 : : * Europe/London (in that order). */
637 : : { 2018, 10, 21, 1, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 45, 0.0, "Europe/London",
638 : : MWT_PERIOD_REPEAT_WEEK, 1,
639 : : 2018, 10, 21, 1, 35, 0.0, "Europe/London",
640 : : TRUE, 2018, 10, 21, 1, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 45, 0.0, "Europe/London",
641 : : TRUE, 2018, 10, 28, 1, 30, 0.0, "+01", 2018, 10, 28, 1, 45, 0.0, "+01" },
642 : : { 2018, 10, 21, 1, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 45, 0.0, "Europe/London",
643 : : MWT_PERIOD_REPEAT_WEEK, 1,
644 : : 2018, 10, 28, 1, 35, 0.0, "+01",
645 : : TRUE, 2018, 10, 28, 1, 30, 0.0, "+01", 2018, 10, 28, 1, 45, 0.0, "+01",
646 : : TRUE, 2018, 11, 04, 1, 30, 0.0, "Europe/London", 2018, 11, 04, 1, 45, 0.0, "Europe/London" },
647 : : { 2018, 10, 21, 1, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 45, 0.0, "Europe/London",
648 : : MWT_PERIOD_REPEAT_WEEK, 1,
649 : : 2018, 10, 28, 2, 0, 0.0, "+01",
650 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
651 : : TRUE, 2018, 11, 04, 1, 30, 0.0, "Europe/London", 2018, 11, 04, 1, 45, 0.0, "Europe/London" },
652 : : { 2018, 10, 21, 1, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 45, 0.0, "Europe/London",
653 : : MWT_PERIOD_REPEAT_WEEK, 1,
654 : : 2018, 10, 28, 1, 0, 0.0, "+00",
655 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
656 : : TRUE, 2018, 11, 04, 1, 30, 0.0, "Europe/London", 2018, 11, 04, 1, 45, 0.0, "Europe/London" },
657 : : { 2018, 10, 21, 1, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 45, 0.0, "Europe/London",
658 : : MWT_PERIOD_REPEAT_WEEK, 1,
659 : : 2018, 10, 28, 1, 35, 0.0, "+00",
660 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
661 : : TRUE, 2018, 11, 04, 1, 30, 0.0, "Europe/London", 2018, 11, 04, 1, 45, 0.0, "Europe/London" },
662 : : { 2018, 10, 21, 1, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 45, 0.0, "Europe/London",
663 : : MWT_PERIOD_REPEAT_WEEK, 1,
664 : : 2018, 11, 04, 1, 35, 0.0, "+00",
665 : : TRUE, 2018, 11, 04, 1, 30, 0.0, "Europe/London", 2018, 11, 04, 1, 45, 0.0, "Europe/London",
666 : : TRUE, 2018, 11, 11, 1, 30, 0.0, "Europe/London", 2018, 11, 11, 1, 45, 0.0, "Europe/London" },
667 : : /* Another DST check with looping time as above, where the period contains
668 : : * the looping time period, plus some extra normal time before and after.
669 : : * We expect that the recurrence will contain both the first and second
670 : : * occurrence of the looped hours. */
671 : : { 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 2, 30, 0.0, "Europe/London",
672 : : MWT_PERIOD_REPEAT_WEEK, 1,
673 : : 2018, 10, 21, 1, 35, 0.0, "Europe/London",
674 : : TRUE, 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 2, 30, 0.0, "Europe/London",
675 : : TRUE, 2018, 10, 28, 0, 30, 0.0, "+01", 2018, 10, 28, 2, 30, 0.0, "+00" },
676 : : { 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 2, 30, 0.0, "Europe/London",
677 : : MWT_PERIOD_REPEAT_WEEK, 1,
678 : : 2018, 10, 28, 1, 35, 0.0, "+01",
679 : : TRUE, 2018, 10, 28, 0, 30, 0.0, "+01", 2018, 10, 28, 2, 30, 0.0, "+00",
680 : : TRUE, 2018, 11, 04, 0, 30, 0.0, "Europe/London", 2018, 11, 04, 2, 30, 0.0, "Europe/London" },
681 : : { 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 2, 30, 0.0, "Europe/London",
682 : : MWT_PERIOD_REPEAT_WEEK, 1,
683 : : 2018, 10, 28, 1, 35, 0.0, "+00",
684 : : TRUE, 2018, 10, 28, 0, 30, 0.0, "+01", 2018, 10, 28, 2, 30, 0.0, "+00",
685 : : TRUE, 2018, 11, 04, 0, 30, 0.0, "Europe/London", 2018, 11, 04, 2, 30, 0.0, "Europe/London" },
686 : : { 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 2, 30, 0.0, "Europe/London",
687 : : MWT_PERIOD_REPEAT_WEEK, 1,
688 : : 2018, 10, 28, 2, 30, 0.0, "+00",
689 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
690 : : TRUE, 2018, 11, 04, 0, 30, 0.0, "Europe/London", 2018, 11, 04, 2, 30, 0.0, "Europe/London" },
691 : : /* Another DST check with looping time as above, where the period
692 : : * partially overlaps the looping time period, plus some extra normal time
693 : : * before it (but not after it). We expect that the recurrence will
694 : : * contain part of the first occurrence of the looped hours, but none of
695 : : * the second. */
696 : : { 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 30, 0.0, "Europe/London",
697 : : MWT_PERIOD_REPEAT_WEEK, 1,
698 : : 2018, 10, 21, 0, 35, 0.0, "Europe/London",
699 : : TRUE, 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 30, 0.0, "Europe/London",
700 : : TRUE, 2018, 10, 28, 0, 30, 0.0, "+01", 2018, 10, 28, 1, 30, 0.0, "+01" },
701 : : { 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 30, 0.0, "Europe/London",
702 : : MWT_PERIOD_REPEAT_WEEK, 1,
703 : : 2018, 10, 28, 0, 35, 0.0, "+01",
704 : : TRUE, 2018, 10, 28, 0, 30, 0.0, "+01", 2018, 10, 28, 1, 30, 0.0, "+01",
705 : : TRUE, 2018, 11, 4, 0, 30, 0.0, "Europe/London", 2018, 11, 4, 1, 30, 0.0, "Europe/London" },
706 : : { 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 30, 0.0, "Europe/London",
707 : : MWT_PERIOD_REPEAT_WEEK, 1,
708 : : 2018, 10, 28, 1, 29, 0.0, "+01",
709 : : TRUE, 2018, 10, 28, 0, 30, 0.0, "+01", 2018, 10, 28, 1, 30, 0.0, "+01",
710 : : TRUE, 2018, 11, 4, 0, 30, 0.0, "Europe/London", 2018, 11, 4, 1, 30, 0.0, "Europe/London" },
711 : : { 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 30, 0.0, "Europe/London",
712 : : MWT_PERIOD_REPEAT_WEEK, 1,
713 : : 2018, 10, 28, 1, 30, 0.0, "+01",
714 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
715 : : TRUE, 2018, 11, 4, 0, 30, 0.0, "Europe/London", 2018, 11, 4, 1, 30, 0.0, "Europe/London" },
716 : : { 2018, 10, 21, 0, 30, 0.0, "Europe/London", 2018, 10, 21, 1, 30, 0.0, "Europe/London",
717 : : MWT_PERIOD_REPEAT_WEEK, 1,
718 : : 2018, 10, 28, 1, 30, 0.0, "+00",
719 : : FALSE, 0, 0, 0, 0, 0, 0.0, "Z", 0, 0, 0, 0, 0, 0.0, "Z",
720 : : TRUE, 2018, 11, 4, 0, 30, 0.0, "Europe/London", 2018, 11, 4, 1, 30, 0.0, "Europe/London" },
721 : : };
722 : :
723 [ + + ]: 95 : for (gsize i = 0; i < G_N_ELEMENTS (vectors); i++)
724 : : {
725 : 188 : g_autoptr(GTimeZone) start_tz = time_zone_new (vectors[i].start_tz);
726 : 94 : g_autoptr(GDateTime) start =
727 : 94 : g_date_time_new (start_tz, vectors[i].start_year, vectors[i].start_month,
728 : 94 : vectors[i].start_day, vectors[i].start_hour,
729 : 94 : vectors[i].start_minute, vectors[i].start_seconds);
730 : 188 : g_autoptr(GTimeZone) end_tz = time_zone_new (vectors[i].end_tz);
731 : 94 : g_autoptr(GDateTime) end =
732 : 94 : g_date_time_new (end_tz, vectors[i].end_year, vectors[i].end_month,
733 : 94 : vectors[i].end_day, vectors[i].end_hour,
734 : 94 : vectors[i].end_minute, vectors[i].end_seconds);
735 : 188 : g_autoptr(GTimeZone) when_tz = time_zone_new (vectors[i].when_tz);
736 : 94 : g_autoptr(GDateTime) when =
737 : 94 : g_date_time_new (when_tz, vectors[i].when_year, vectors[i].when_month,
738 : 94 : vectors[i].when_day, vectors[i].when_hour,
739 : 94 : vectors[i].when_minute, vectors[i].when_seconds);
740 : :
741 : 94 : g_autoptr(GDateTime) expected_contains_start = NULL;
742 : 94 : g_autoptr(GDateTime) expected_contains_end = NULL;
743 : :
744 [ + + ]: 94 : if (vectors[i].expected_contains)
745 : : {
746 : 110 : g_autoptr(GTimeZone) expected_contains_start_tz = time_zone_new (vectors[i].expected_contains_start_tz);
747 : 55 : expected_contains_start =
748 : 55 : g_date_time_new (expected_contains_start_tz, vectors[i].expected_contains_start_year, vectors[i].expected_contains_start_month,
749 : 55 : vectors[i].expected_contains_start_day, vectors[i].expected_contains_start_hour,
750 : 55 : vectors[i].expected_contains_start_minute, vectors[i].expected_contains_start_seconds);
751 : 55 : g_autoptr(GTimeZone) expected_contains_end_tz = time_zone_new (vectors[i].expected_contains_end_tz);
752 : 55 : expected_contains_end =
753 : 55 : g_date_time_new (expected_contains_end_tz, vectors[i].expected_contains_end_year, vectors[i].expected_contains_end_month,
754 : 55 : vectors[i].expected_contains_end_day, vectors[i].expected_contains_end_hour,
755 : 55 : vectors[i].expected_contains_end_minute, vectors[i].expected_contains_end_seconds);
756 : : }
757 : :
758 : 94 : g_autoptr(GDateTime) expected_next_start = NULL;
759 : 94 : g_autoptr(GDateTime) expected_next_end = NULL;
760 : :
761 [ + + ]: 94 : if (vectors[i].expected_next)
762 : : {
763 : 180 : g_autoptr(GTimeZone) expected_next_start_tz = time_zone_new (vectors[i].expected_next_start_tz);
764 : 90 : expected_next_start =
765 : 90 : g_date_time_new (expected_next_start_tz, vectors[i].expected_next_start_year, vectors[i].expected_next_start_month,
766 : 90 : vectors[i].expected_next_start_day, vectors[i].expected_next_start_hour,
767 : 90 : vectors[i].expected_next_start_minute, vectors[i].expected_next_start_seconds);
768 : 90 : g_autoptr(GTimeZone) expected_next_end_tz = time_zone_new (vectors[i].expected_next_end_tz);
769 : 90 : expected_next_end =
770 : 90 : g_date_time_new (expected_next_end_tz, vectors[i].expected_next_end_year, vectors[i].expected_next_end_month,
771 : 90 : vectors[i].expected_next_end_day, vectors[i].expected_next_end_hour,
772 : 90 : vectors[i].expected_next_end_minute, vectors[i].expected_next_end_seconds);
773 : : }
774 : :
775 : 188 : g_autofree gchar *start_str = g_date_time_format (start, "%FT%T%:::z");
776 : 188 : g_autofree gchar *end_str = g_date_time_format (end, "%FT%T%:::z");
777 : 188 : g_autofree gchar *when_str = g_date_time_format (when, "%FT%T%:::z");
778 : :
779 : 94 : g_test_message ("Vector %" G_GSIZE_FORMAT ": start %s, end %s, when %s",
780 : : i, start_str, end_str, when_str);
781 : :
782 : 94 : g_autoptr(MwtPeriod) period =
783 : 94 : mwt_period_new (start, end, vectors[i].repeat_type,
784 : 94 : vectors[i].repeat_period,
785 : : /* leave everything as default */
786 : : NULL);
787 : :
788 : 94 : g_autoptr(GDateTime) out_contains_start = NULL;
789 : 94 : g_autoptr(GDateTime) out_contains_end = NULL;
790 : 94 : g_autoptr(GDateTime) out_next_start = NULL;
791 : 94 : g_autoptr(GDateTime) out_next_end = NULL;
792 : :
793 : : gboolean actual_contains =
794 : 94 : mwt_period_contains_time (period, when, &out_contains_start, &out_contains_end);
795 : : gboolean actual_next =
796 : 94 : mwt_period_get_next_recurrence (period, when, &out_next_start, &out_next_end);
797 : :
798 [ + + ]: 94 : if (vectors[i].expected_contains)
799 : : {
800 [ - + ]: 55 : g_assert_true (actual_contains);
801 [ - + ]: 55 : g_assert_nonnull (out_contains_start);
802 [ - + ]: 55 : g_assert_nonnull (out_contains_end);
803 [ - + ]: 55 : g_assert_true (g_date_time_equal (out_contains_start, expected_contains_start));
804 [ - + ]: 55 : g_assert_true (g_date_time_equal (out_contains_end, expected_contains_end));
805 : : }
806 : : else
807 : : {
808 [ - + ]: 39 : g_assert_false (actual_contains);
809 [ - + ]: 39 : g_assert_null (out_contains_start);
810 [ - + ]: 39 : g_assert_null (out_contains_end);
811 : : }
812 : :
813 [ + + ]: 94 : if (vectors[i].expected_next)
814 : : {
815 [ - + ]: 90 : g_assert_true (actual_next);
816 [ - + ]: 90 : g_assert_nonnull (out_next_start);
817 [ - + ]: 90 : g_assert_nonnull (out_next_end);
818 [ - + ]: 90 : g_assert_true (g_date_time_equal (out_next_start, expected_next_start));
819 [ - + ]: 90 : g_assert_true (g_date_time_equal (out_next_end, expected_next_end));
820 : : }
821 : : else
822 : : {
823 [ - + ]: 4 : g_assert_false (actual_next);
824 [ - + ]: 4 : g_assert_null (out_next_start);
825 [ - + ]: 4 : g_assert_null (out_next_end);
826 : : }
827 : : }
828 : 1 : }
829 : :
830 : : /* Test overflow handling in mwt_period_contains_time(). */
831 : : static void
832 : 1 : test_period_contains_time_overflow (void)
833 : : {
834 : : /* This tries to trigger an overflow in the overflow check at the top of
835 : : * date_time_add_repeat_period(). */
836 : 2 : g_autoptr(GDateTime) start1 = g_date_time_new_utc (2018, 2, 1, 1, 0, 0.0);
837 : 2 : g_autoptr(GDateTime) end1 = g_date_time_new_utc (2018, 2, 1, 5, 0, 0.0);
838 : 2 : g_autoptr(GDateTime) when1 = g_date_time_new_utc (9999, 1, 1, 2, 0, 0.0);
839 : :
840 : 1 : g_autoptr(MwtPeriod) period1 =
841 : 1 : mwt_period_new (start1, end1, MWT_PERIOD_REPEAT_YEAR, G_MAXUINT,
842 : : /* leave everything as default */
843 : : NULL);
844 : 1 : g_autoptr(GDateTime) out_start1 = NULL;
845 : 1 : g_autoptr(GDateTime) out_end1 = NULL;
846 [ - + ]: 1 : g_assert_false (mwt_period_contains_time (period1, when1, &out_start1, &out_end1));
847 [ - + ]: 1 : g_assert_null (out_start1);
848 [ - + ]: 1 : g_assert_null (out_end1);
849 : :
850 : : /* This tries to trigger an overflow in the g_date_time_add_days() call in
851 : : * date_time_add_repeat_period(). However, I think min_n_periods is always
852 : : * calculated such that an overflow is not possible. Keep the test case just
853 : : * in case. */
854 : 2 : g_autoptr(GDateTime) start2 = g_date_time_new_utc (9999, 12, 31, 1, 0, 0.0);
855 : 2 : g_autoptr(GDateTime) end2 = g_date_time_new_utc (9999, 12, 31, 5, 0, 0.0);
856 : 2 : g_autoptr(GDateTime) when2 = g_date_time_new_utc (9999, 12, 31, 6, 0, 0.0);
857 : :
858 : 1 : g_autoptr(MwtPeriod) period2 =
859 : 1 : mwt_period_new (start2, end2, MWT_PERIOD_REPEAT_DAY, 1,
860 : : /* leave everything as default */
861 : : NULL);
862 : 1 : g_autoptr(GDateTime) out_start2 = NULL;
863 : 1 : g_autoptr(GDateTime) out_end2 = NULL;
864 [ - + ]: 1 : g_assert_false (mwt_period_contains_time (period2, when2, &out_start2, &out_end2));
865 [ - + ]: 1 : g_assert_null (out_start2);
866 [ - + ]: 1 : g_assert_null (out_end2);
867 : 1 : }
868 : :
869 : : /* Test that calling mwt_period_next_recurrence() with a %NULL #GDateTime gives
870 : : * the base time for the #MwtPeriod, regardless of whether the period has any
871 : : * recurrences. */
872 : : static void
873 : 1 : test_period_next_recurrence_first (void)
874 : : {
875 : 2 : g_autoptr(GDateTime) start = g_date_time_new_utc (2018, 2, 1, 1, 0, 0.0);
876 : 2 : g_autoptr(GDateTime) end = g_date_time_new_utc (2018, 2, 1, 5, 0, 0.0);
877 : :
878 : 1 : g_autoptr(MwtPeriod) period1 =
879 : 1 : mwt_period_new (start, end, MWT_PERIOD_REPEAT_NONE, 0,
880 : : /* leave everything as default */
881 : : NULL);
882 : 1 : g_autoptr(GDateTime) out_start1 = NULL;
883 : 1 : g_autoptr(GDateTime) out_end1 = NULL;
884 [ - + ]: 1 : g_assert_true (mwt_period_get_next_recurrence (period1, NULL, &out_start1, &out_end1));
885 [ - + ]: 1 : g_assert_true (g_date_time_equal (start, out_start1));
886 [ - + ]: 1 : g_assert_true (g_date_time_equal (end, out_end1));
887 : :
888 : 1 : g_autoptr(MwtPeriod) period2 =
889 : 1 : mwt_period_new (start, end, MWT_PERIOD_REPEAT_DAY, 1,
890 : : /* leave everything as default */
891 : : NULL);
892 : 1 : g_autoptr(GDateTime) out_start2 = NULL;
893 : 1 : g_autoptr(GDateTime) out_end2 = NULL;
894 [ - + ]: 1 : g_assert_true (mwt_period_get_next_recurrence (period2, NULL, &out_start2, &out_end2));
895 [ - + ]: 1 : g_assert_true (g_date_time_equal (start, out_start2));
896 [ - + ]: 1 : g_assert_true (g_date_time_equal (end, out_end2));
897 : 1 : }
898 : :
899 : : int
900 : 1 : main (int argc,
901 : : char **argv)
902 : : {
903 : 1 : setlocale (LC_ALL, "");
904 : 1 : g_test_init (&argc, &argv, NULL);
905 : :
906 : 1 : g_test_add_func ("/period/validation", test_period_validation);
907 : 1 : g_test_add_func ("/period/properties", test_period_properties);
908 : 1 : g_test_add_func ("/period/properties/defaults", test_period_properties_defaults);
909 : 1 : g_test_add_func ("/period/contains-time", test_period_contains_time);
910 : 1 : g_test_add_func ("/period/contains-time/overflow", test_period_contains_time_overflow);
911 : 1 : g_test_add_func ("/period/next-recurrence/first", test_period_next_recurrence_first);
912 : :
913 : 1 : return g_test_run ();
914 : : }
|