]>
Commit | Line | Data |
---|---|---|
3ebebd19 DM |
1 | #!/usr/bin/perl |
2 | ||
3 | use lib '../src'; | |
4 | use strict; | |
5 | use warnings; | |
f236e576 | 6 | use POSIX (); |
3ebebd19 DM |
7 | use Data::Dumper; |
8 | use Time::Local; | |
9 | use Test::More; | |
10 | ||
11 | use PVE::CalendarEvent; | |
12 | ||
f236e576 WB |
13 | # Time tests should run in a controlled setting |
14 | $ENV{TZ} = 'UTC'; | |
15 | POSIX::tzset(); | |
16 | ||
3ebebd19 DM |
17 | my $alldays = [0,1,2,3,4,5,6]; |
18 | my $tests = [ | |
19 | [ | |
20 | '*', | |
21 | { h => '*', m => '*', dow => $alldays }, | |
22 | [ | |
23 | [0, 60], | |
24 | [30, 60], | |
25 | [59, 60], | |
26 | [60, 120], | |
27 | ] | |
28 | ], | |
29 | [ | |
30 | '*/10', | |
31 | { h => '*', m => [0, 10, 20, 30, 40, 50], dow => $alldays }, | |
32 | [ | |
33 | [0, 600], | |
34 | [599, 600], | |
35 | [600, 1200], | |
36 | [50*60, 60*60] | |
37 | ] | |
38 | ], | |
39 | [ | |
40 | '*/12:0' , | |
41 | { h => [0, 12], m => [0], dow => $alldays }, | |
42 | [ | |
43 | [ 10, 43200], | |
44 | [ 13*3600, 24*3600], | |
45 | ] | |
46 | ], | |
47 | [ | |
48 | '1/12:0/15' , | |
49 | { h => [1, 13], m => [0, 15, 30, 45], dow => $alldays }, | |
50 | [ | |
51 | [0, 3600], | |
52 | [3600, 3600+15*60], | |
53 | [3600+16*60, 3600+30*60 ], | |
54 | [3600+30*60, 3600+45*60 ], | |
55 | [3600+45*60, 3600+12*3600], | |
56 | [13*3600 + 1, 13*3600+15*60], | |
57 | [13*3600 + 15*60, 13*3600+30*60], | |
58 | [13*3600 + 30*60, 13*3600+45*60], | |
59 | [13*3600 + 45*60, 25*3600], | |
60 | ], | |
61 | ], | |
62 | [ | |
63 | '1,4,6', | |
64 | { h => '*', m => [1, 4, 6], dow => $alldays}, | |
65 | [ | |
66 | [0, 60], | |
67 | [60, 4*60], | |
68 | [4*60+60, 6*60], | |
69 | [6*60, 3600+60], | |
70 | ] | |
71 | ], | |
72 | [ | |
73 | '0..3', | |
74 | { h => '*', m => [ 0, 1, 2, 3 ], dow => $alldays }, | |
75 | ], | |
76 | [ | |
77 | '23..23:0..3', | |
78 | { h => [ 23 ], m => [ 0, 1, 2, 3 ], dow => $alldays }, | |
79 | ], | |
80 | [ | |
81 | 'Mon', | |
82 | { h => [0], m => [0], dow => [1] }, | |
83 | [ | |
84 | [0, 4*86400], # Note: Epoch 0 is Thursday, 1. January 1970 | |
85 | [4*86400, 11*86400], | |
86 | [11*86400, 18*86400], | |
87 | ], | |
88 | ], | |
89 | [ | |
90 | 'sat..sun', | |
91 | { h => [0], m => [0], dow => [0, 6] }, | |
92 | [ | |
93 | [0, 2*86400], | |
94 | [2*86400, 3*86400], | |
95 | [3*86400, 9*86400], | |
96 | ] | |
97 | ], | |
98 | [ | |
99 | 'sun..sat', | |
100 | { h => [0], m => [0], dow => $alldays }, | |
101 | ], | |
102 | [ | |
103 | 'Fri..Mon', | |
104 | { error => "wrong order in range 'Fri..Mon'" }, | |
105 | ], | |
106 | [ | |
107 | 'wed,mon..tue,fri', | |
108 | { h => [0], m => [0], dow => [ 1, 2, 3, 5] }, | |
109 | ], | |
110 | [ | |
111 | 'mon */15', | |
112 | { h => '*', m => [0, 15, 30, 45], dow => [1]}, | |
113 | ], | |
a4200306 DC |
114 | [ |
115 | '22/1:0', | |
116 | { h => [22, 23], m => [0], dow => $alldays }, | |
117 | [ | |
118 | [0, 22*60*60], | |
119 | [22*60*60, 23*60*60], | |
120 | [22*60*60 + 59*60, 23*60*60] | |
121 | ], | |
122 | ], | |
123 | [ | |
124 | '*/2:*', | |
125 | { h => [0,2,4,6,8,10,12,14,16,18,20,22], m => '*', dow => $alldays }, | |
126 | [ | |
127 | [0, 60], | |
128 | [60*60, 2*60*60], | |
129 | [2*60*60, 2*60*60 + 60] | |
130 | ] | |
131 | ], | |
132 | [ | |
133 | '20..22:*/30', | |
134 | { h => [20,21,22], m => [0,30], dow => $alldays }, | |
135 | [ | |
136 | [0, 20*60*60], | |
137 | [20*60*60, 20*60*60 + 30*60], | |
138 | [22*60*60 + 30*60, 44*60*60] | |
139 | ] | |
057c619a DC |
140 | ], |
141 | [ | |
142 | '61', | |
143 | { error => "value '61' out of range" }, | |
144 | ], | |
145 | [ | |
146 | '*/61', | |
147 | { error => "repetition '61' out of range" }, | |
148 | ], | |
149 | [ | |
150 | '0..80', | |
151 | { error => "range end '80' out of range" }, | |
152 | ], | |
a5ffa49f DC |
153 | [ |
154 | ' mon 0 0 0', | |
155 | { error => "unable to parse calendar event - unused parts" }, | |
156 | ], | |
157 | [ | |
158 | '', | |
159 | { error => "unable to parse calendar event - event is empty" }, | |
160 | ], | |
161 | [ | |
162 | ' mon 0 0', | |
163 | { error => "unable to parse calendar event - unused parts" }, | |
164 | ], | |
e2c29de7 DC |
165 | [ |
166 | '0,1,3..5', | |
167 | { h => '*', m => [0,1,3,4,5], dow => $alldays }, | |
168 | [ | |
169 | [0, 60], | |
170 | [60, 3*60], | |
171 | [5*60, 60*60] | |
172 | ] | |
173 | ], | |
174 | [ | |
175 | '2,4:0,1,3..5', | |
176 | { h => [2,4], m => [0,1,3,4,5], dow => $alldays }, | |
177 | [ | |
178 | [0, 2*60*60], | |
179 | [2*60*60 + 60, 2*60*60 + 3*60], | |
180 | [2*60*60 + 5*60, 4*60*60] | |
181 | ] | |
182 | ], | |
3ebebd19 DM |
183 | ]; |
184 | ||
185 | foreach my $test (@$tests) { | |
186 | my ($t, $expect, $nextsync) = @$test; | |
187 | ||
188 | my $timespec; | |
189 | eval { $timespec = PVE::CalendarEvent::parse_calendar_event($t); }; | |
190 | my $err = $@; | |
f236e576 | 191 | delete $timespec->{utc}; |
3ebebd19 DM |
192 | |
193 | if ($expect->{error}) { | |
194 | chomp $err if $err; | |
195 | $timespec = { error => $err } if $err; | |
196 | is_deeply($timespec, $expect, "expect parse error on '$t' - $expect->{error}"); | |
197 | die "unable to execute nextsync tests" if $nextsync; | |
198 | } else { | |
199 | is_deeply($timespec, $expect, "parse '$t'"); | |
200 | } | |
201 | ||
202 | next if !$nextsync; | |
203 | ||
204 | foreach my $nt (@$nextsync) { | |
205 | my ($last, $expect_next) = @$nt; | |
3ebebd19 | 206 | my $msg = "next event '$t' $last => ${expect_next}"; |
f236e576 WB |
207 | $timespec->{utc} = 1; |
208 | my $next = PVE::CalendarEvent::compute_next_event($timespec, $last); | |
3ebebd19 DM |
209 | is($next, $expect_next, $msg); |
210 | } | |
211 | }; | |
212 | ||
f236e576 WB |
213 | sub tztest { |
214 | my ($calspec, $last) = @_; | |
215 | my $spec = PVE::CalendarEvent::parse_calendar_event($calspec); | |
216 | return PVE::CalendarEvent::compute_next_event($spec, $last); | |
217 | } | |
218 | ||
219 | # Test loop termination at CEST/CET switch (cannot happen here in UTC) | |
220 | is(tztest('mon..fri', timelocal(0, 0, 0, 28, 9, 2018)), | |
221 | timelocal(0, 0, 0, 29, 9, 2018)); | |
222 | is(tztest('mon..fri UTC', timelocal(0, 0, 0, 28, 9, 2018)), | |
223 | timelocal(0, 0, 0, 29, 9, 2018)); | |
224 | ||
225 | # Now in the affected time zone | |
226 | $ENV{TZ} = ':Europe/Vienna'; | |
227 | POSIX::tzset(); | |
228 | is(tztest('mon..fri', timelocal(0, 0, 0, 28, 9, 2018)), | |
229 | timelocal(0, 0, 0, 29, 9, 2018)); | |
230 | # Specifically requesting UTC in the calendar spec means the resulting output | |
231 | # time as seen locally (timelocal() as opposed to timegm()) is shifted by 1 | |
232 | # hour. | |
233 | is(tztest('mon..fri UTC', timelocal(0, 0, 0, 28, 9, 2018)), | |
234 | timelocal(0, 0, 1, 29, 9, 2018)); | |
235 | $ENV{TZ} = 'UTC'; | |
236 | POSIX::tzset(); | |
237 | ||
3ebebd19 | 238 | done_testing(); |