]> git.basschouten.com Git - openhab-addons.git/blob
c33b70ffcbf025a9393f168259b005aa3b974550
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.icalendar.internal.logic;
14
15 import static org.junit.jupiter.api.Assertions.*;
16
17 import java.io.FileInputStream;
18 import java.io.IOException;
19 import java.time.Instant;
20 import java.time.LocalDate;
21 import java.time.ZoneId;
22 import java.util.List;
23
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
26 import org.openhab.core.library.types.DecimalType;
27 import org.openhab.core.library.types.HSBType;
28 import org.openhab.core.library.types.OnOffType;
29 import org.openhab.core.library.types.OpenClosedType;
30 import org.openhab.core.library.types.PercentType;
31 import org.openhab.core.library.types.PlayPauseType;
32 import org.openhab.core.library.types.QuantityType;
33 import org.openhab.core.library.types.RewindFastforwardType;
34 import org.openhab.core.library.types.StringType;
35 import org.openhab.core.library.types.UpDownType;
36 import org.openhab.core.types.Command;
37
38 /**
39  * Tests for presentable calendar.
40  *
41  * @author Michael Wodniok - Initial contribution.
42  * @author Andrew Fiddian-Green - Tests for Command Tag code
43  * @author Michael Wodniok - Extended Tests for filtered Events
44  * @author Michael Wodniok - Extended Test for parallel current events
45  */
46 public class BiweeklyPresentableCalendarTest {
47     private AbstractPresentableCalendar calendar;
48     private AbstractPresentableCalendar calendar2;
49     private AbstractPresentableCalendar calendar3;
50     private AbstractPresentableCalendar calendar_issue9647;
51     private AbstractPresentableCalendar calendar_issue10808;
52     private AbstractPresentableCalendar calendar_issue11084;
53
54     @BeforeEach
55     public void setUp() throws IOException, CalendarException {
56         calendar = new BiweeklyPresentableCalendar(new FileInputStream("src/test/resources/test.ics"));
57         calendar2 = new BiweeklyPresentableCalendar(new FileInputStream("src/test/resources/test2.ics"));
58         calendar3 = new BiweeklyPresentableCalendar(new FileInputStream("src/test/resources/test3.ics"));
59         calendar_issue9647 = new BiweeklyPresentableCalendar(
60                 new FileInputStream("src/test/resources/test-issue9647.ics"));
61         calendar_issue10808 = new BiweeklyPresentableCalendar(
62                 new FileInputStream("src/test/resources/test-issue10808.ics"));
63         calendar_issue11084 = new BiweeklyPresentableCalendar(
64                 new FileInputStream("src/test/resources/test-issue11084.ics"));
65     }
66
67     /**
68      * Tests recurrence and whether TimeZone is interpolated in a right way.
69      */
70     @Test
71     public void testIsEventPresent() {
72         // Test series
73         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-08T09:04:00Z")));
74         assertTrue(calendar.isEventPresent(Instant.parse("2019-09-08T09:08:00Z")));
75         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-08T09:11:00Z")));
76
77         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-09T09:04:00Z")));
78         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-09T09:08:00Z")));
79         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-09T09:11:00Z")));
80
81         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-10T09:04:00Z")));
82         assertTrue(calendar.isEventPresent(Instant.parse("2019-09-10T09:08:00Z")));
83         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-10T09:11:00Z")));
84
85         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-11T09:04:00Z")));
86         assertTrue(calendar.isEventPresent(Instant.parse("2019-09-11T09:08:00Z")));
87         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-11T09:11:00Z")));
88
89         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-12T09:04:00Z")));
90         assertTrue(calendar.isEventPresent(Instant.parse("2019-09-12T09:08:00Z")));
91         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-12T09:11:00Z")));
92
93         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-13T09:04:00Z")));
94         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-13T09:08:00Z")));
95         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-13T09:11:00Z")));
96
97         // Test in CEST (UTC+2)
98         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-14T07:59:00Z")));
99         assertTrue(calendar.isEventPresent(Instant.parse("2019-09-14T08:03:00Z")));
100         assertFalse(calendar.isEventPresent(Instant.parse("2019-09-14T09:01:00Z")));
101
102         // Test Series with cancelled event by Davdroid
103         assertFalse(calendar2.isEventPresent(Instant.parse("2019-11-03T09:55:00Z")));
104         assertTrue(calendar2.isEventPresent(Instant.parse("2019-11-03T10:01:00Z")));
105         assertFalse(calendar2.isEventPresent(Instant.parse("2019-11-03T13:00:00Z")));
106
107         assertFalse(calendar2.isEventPresent(Instant.parse("2019-11-24T09:55:00Z")));
108         assertFalse(calendar2.isEventPresent(Instant.parse("2019-11-24T10:01:00Z")));
109         assertFalse(calendar2.isEventPresent(Instant.parse("2019-11-24T13:00:00Z")));
110     }
111
112     /**
113      * This test relies on a working isEventPresent and assumes the calculation
114      * of recurrence is done the same way.
115      */
116     @Test
117     public void testGetCurrentEvent() {
118         Event currentEvent = calendar.getCurrentEvent(Instant.parse("2019-09-10T09:07:00Z"));
119         assertNotNull(currentEvent);
120         assertTrue("Test Series in UTC".contentEquals(currentEvent.title));
121         assertEquals(0, Instant.parse("2019-09-10T09:05:00Z").compareTo(currentEvent.start));
122         assertEquals(0, Instant.parse("2019-09-10T09:10:00Z").compareTo(currentEvent.end));
123
124         Event nonExistingEvent = calendar.getCurrentEvent(Instant.parse("2019-09-09T09:07:00Z"));
125         assertNull(nonExistingEvent);
126
127         Event currentEvent2 = calendar_issue10808.getCurrentEvent(Instant.parse("2021-06-05T17:10:05Z"));
128         assertNotNull(currentEvent2);
129         assertTrue("Test event 1".contentEquals(currentEvent2.title));
130
131         Event currentEvent3 = calendar_issue10808.getCurrentEvent(Instant.parse("2021-06-05T17:13:05Z"));
132         assertNotNull(currentEvent3);
133         assertTrue("Test event 2".contentEquals(currentEvent3.title));
134
135         Event currentEvent4 = calendar_issue10808.getCurrentEvent(Instant.parse("2021-06-05T17:18:05Z"));
136         assertNotNull(currentEvent4);
137         assertTrue("Test event 1".contentEquals(currentEvent4.title));
138
139         Event currentEvent5 = calendar_issue11084.getCurrentEvent(Instant.parse("2021-08-16T16:30:05Z"));
140         assertNull(currentEvent5);
141
142         Event currentEvent6 = calendar_issue11084.getCurrentEvent(Instant.parse("2021-08-16T16:45:05Z"));
143         assertNotNull(currentEvent6);
144         assertTrue("TEST_REPEATING_EVENT_3".contentEquals(currentEvent6.title));
145     }
146
147     /**
148      * This test relies on a working isEventPresent and assumes the calculation
149      * of recurrence is done the same way.
150      */
151     @Test
152     public void testGetNextEvent() {
153         // positive case: next event of series
154         Event nextEventOfSeries = calendar.getNextEvent(Instant.parse("2019-09-10T09:07:00Z"));
155         assertNotNull(nextEventOfSeries);
156         assertTrue("Test Series in UTC".contentEquals(nextEventOfSeries.title));
157         assertEquals(0, Instant.parse("2019-09-11T09:05:00Z").compareTo(nextEventOfSeries.start));
158         assertEquals(0, Instant.parse("2019-09-11T09:10:00Z").compareTo(nextEventOfSeries.end));
159
160         // positive case: next event after series
161         Event nextEventOutsideSeries = calendar.getNextEvent(Instant.parse("2019-09-12T09:07:00Z"));
162         assertNotNull(nextEventOutsideSeries);
163         assertTrue("Test Event in UTC+2".contentEquals(nextEventOutsideSeries.title));
164         assertEquals(0, Instant.parse("2019-09-14T08:00:00Z").compareTo(nextEventOutsideSeries.start));
165         assertEquals(0, Instant.parse("2019-09-14T09:00:00Z").compareTo(nextEventOutsideSeries.end));
166
167         // positive case: next event should be also set if currently none is present
168         Event nextEventIndependent = calendar.getNextEvent(Instant.parse("2019-09-13T09:07:00Z"));
169         assertTrue(nextEventOutsideSeries.equals(nextEventIndependent));
170
171         // negative case: after last event there is no next
172         Event nonExistingEvent = calendar.getNextEvent(Instant.parse("2019-09-14T12:00:00Z"));
173         assertNull(nonExistingEvent);
174
175         // mixed case: cancelled events also not show up as next
176         Event nextEventAfterCancelled = calendar2.getNextEvent(Instant.parse("2019-11-24T09:55:00Z"));
177         assertNotNull(nextEventAfterCancelled);
178         assertEquals(0, Instant.parse("2019-12-01T10:00:00Z").compareTo(nextEventAfterCancelled.start));
179     }
180
181     /**
182      * This test checks for Events that have just begun or ended, and if so it checks for Command Tags
183      * and checks if these tags are valid
184      */
185     @SuppressWarnings("null")
186     @Test
187     public void testCommandTagCode() {
188         List<Event> events = null;
189         int eventCount = 2;
190         int tagsPerEvent = 8;
191
192         // test just begun events: first in the series
193         events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T15:55:00Z"),
194                 Instant.parse("2020-01-28T16:05:00Z"));
195         assertNotNull(events);
196         assertEquals(eventCount, events.size());
197         for (Event event : events) {
198             List<CommandTag> cmdTags = event.commandTags;
199             assertEquals(tagsPerEvent, cmdTags.size());
200             int beginTags = 0;
201             for (CommandTag cmdTag : cmdTags) {
202                 if (cmdTag.getTagType() == CommandTagType.BEGIN) {
203                     assertTrue(cmdTag.isAuthorized("abc"));
204                     assertTrue(cmdTag.getItemName().matches("^\\w+$"));
205                     assertTrue(cmdTag.getCommand() != null);
206                     beginTags++;
207                 }
208             }
209             assertEquals(tagsPerEvent / 2, beginTags);
210         }
211
212         // test just begun events: third in the series
213         events = calendar3.getJustBegunEvents(Instant.parse("2020-01-30T15:55:00Z"),
214                 Instant.parse("2020-01-30T16:05:00Z"));
215         assertNotNull(events);
216         assertEquals(eventCount, events.size());
217         for (Event event : events) {
218             List<CommandTag> cmdTags = event.commandTags;
219             assertEquals(tagsPerEvent, cmdTags.size());
220             int beginTags = 0;
221             for (CommandTag cmdTag : cmdTags) {
222                 if (cmdTag.getTagType() == CommandTagType.BEGIN) {
223                     assertTrue(cmdTag.isAuthorized("abc"));
224                     assertTrue(cmdTag.getItemName().matches("^\\w+$"));
225                     assertTrue(cmdTag.getCommand() != null);
226                     beginTags++;
227                 }
228             }
229             assertEquals(tagsPerEvent / 2, beginTags);
230         }
231
232         // test outside of window: begun events, too early
233         events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T15:50:00Z"),
234                 Instant.parse("2020-01-28T15:55:00Z"));
235         assertNotNull(events);
236         assertEquals(0, events.size());
237
238         // test outside of window: begun events, too late
239         events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T16:05:00Z"),
240                 Instant.parse("2020-01-28T16:10:00Z"));
241         assertNotNull(events);
242         assertEquals(0, events.size());
243
244         // test just ended events: first in the series
245         events = calendar3.getJustEndedEvents(Instant.parse("2020-01-28T16:25:00Z"),
246                 Instant.parse("2020-01-28T16:35:00Z"));
247         assertNotNull(events);
248         assertEquals(eventCount, events.size());
249         for (Event event : events) {
250             List<CommandTag> cmdTags = event.commandTags;
251             assertEquals(tagsPerEvent, cmdTags.size());
252             int endTags = 0;
253             for (CommandTag cmdTag : cmdTags) {
254                 if (cmdTag.getTagType() == CommandTagType.END) {
255                     assertTrue(cmdTag.isAuthorized("abc"));
256                     assertTrue(cmdTag.getItemName().matches("^\\w+$"));
257                     assertTrue(cmdTag.getCommand() != null);
258                     endTags++;
259                 }
260             }
261             assertEquals(tagsPerEvent / 2, endTags);
262         }
263
264         // test outside of window: ended events, too early
265         events = calendar3.getJustEndedEvents(Instant.parse("2020-01-28T16:20:00Z"),
266                 Instant.parse("2020-01-28T16:25:00Z"));
267         assertNotNull(events);
268         assertEquals(0, events.size());
269
270         // test outside of window: ended events, too late
271         events = calendar3.getJustEndedEvents(Instant.parse("2020-01-28T16:35:00Z"),
272                 Instant.parse("2020-01-28T16:40:00Z"));
273         assertNotNull(events);
274         assertEquals(0, events.size());
275
276         // test a valid just begun event with both good and bad authorization codes
277         events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T15:55:00Z"),
278                 Instant.parse("2020-01-28T16:05:00Z"));
279         assertNotNull(events);
280         assertTrue(!events.isEmpty());
281         List<CommandTag> cmdTags = events.get(0).commandTags;
282         assertTrue(!cmdTags.isEmpty());
283         CommandTag cmd = cmdTags.get(0);
284         // accept correct, empty or null configuration codes
285         assertTrue(cmd.isAuthorized("abc"));
286         assertTrue(cmd.isAuthorized(""));
287         assertTrue(cmd.isAuthorized(null));
288         // reject incorrect configuration code
289         assertFalse(cmd.isAuthorized("123"));
290
291         // test tag syntax: Test Series #1
292         events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T19:25:00Z"),
293                 Instant.parse("2020-01-28T19:35:00Z"));
294         assertNotNull(events);
295         assertEquals(1, events.size());
296         cmdTags = events.get(0).commandTags;
297         assertEquals(11, cmdTags.size());
298
299         // BEGIN:Calendar_Test_Color:ON:abc
300         assertEquals("Calendar_Test_Color", cmdTags.get(0).getItemName());
301         assertTrue(cmdTags.get(0).isAuthorized("abc"));
302         Command cmd0 = cmdTags.get(0).getCommand();
303         assertNotNull(cmd0);
304         assertEquals(OnOffType.class, cmd0.getClass());
305
306         // BEGIN:Calendar_Test_Contact:OPEN:abc
307         Command cmd1 = cmdTags.get(1).getCommand();
308         assertNotNull(cmd1);
309         assertEquals(OpenClosedType.class, cmd1.getClass());
310
311         // BEGIN:Calendar_Test_Dimmer:ON:abc
312         Command cmd2 = cmdTags.get(2).getCommand();
313         assertNotNull(cmd2);
314         assertEquals(OnOffType.class, cmd2.getClass());
315
316         // BEGIN:Calendar_Test_Number:12.3:abc
317         Command cmd3 = cmdTags.get(3).getCommand();
318         assertNotNull(cmd3);
319         assertEquals(DecimalType.class, cmd3.getClass());
320
321         // BEGIN:Calendar_Test_Temperature:12.3°C:abc
322         Command cmd4 = cmdTags.get(4).getCommand();
323         assertNotNull(cmd4);
324         assertEquals(QuantityType.class, cmd4.getClass());
325
326         // BEGIN:Calendar_Test_Pressure:12.3hPa:abc
327         Command cmd5 = cmdTags.get(5).getCommand();
328         assertNotNull(cmd5);
329         assertEquals(QuantityType.class, cmd5.getClass());
330
331         // BEGIN:Calendar_Test_Speed:12.3m/s:abc
332         Command cmd6 = cmdTags.get(6).getCommand();
333         assertNotNull(cmd6);
334         assertEquals(QuantityType.class, cmd6.getClass());
335
336         // BEGIN:Calendar_Test_Player:PLAY:abc
337         Command cmd7 = cmdTags.get(7).getCommand();
338         assertNotNull(cmd7);
339         assertEquals(PlayPauseType.class, cmd7.getClass());
340
341         // BEGIN:Calendar_Test_RollerShutter:UP:abc
342         Command cmd8 = cmdTags.get(8).getCommand();
343         assertNotNull(cmd8);
344         assertEquals(UpDownType.class, cmd8.getClass());
345
346         // BEGIN:Calendar_Test_String:Test Series #1:abc
347         Command cmd9 = cmdTags.get(9).getCommand();
348         assertNotNull(cmd9);
349         assertEquals(StringType.class, cmd9.getClass());
350
351         // BEGIN:Calendar_Test_Switch:ON:abc
352         Command cmd10 = cmdTags.get(10).getCommand();
353         assertNotNull(cmd10);
354         assertEquals(OnOffType.class, cmd10.getClass());
355
356         // test tag syntax: Test Series #4
357         events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T20:10:00Z"),
358                 Instant.parse("2020-01-28T20:20:00Z"));
359         assertNotNull(events);
360         assertEquals(1, events.size());
361         cmdTags = events.get(0).commandTags;
362         assertEquals(11, cmdTags.size());
363
364         // BEGIN:Calendar_Test_Color:0%:abc
365         cmd0 = cmdTags.get(0).getCommand();
366         assertNotNull(cmd0);
367         assertEquals(PercentType.class, cmd0.getClass());
368
369         // BEGIN:Calendar_Test_Contact:CLOSED:abc
370         cmd1 = cmdTags.get(1).getCommand();
371         assertNotNull(cmd1);
372         assertEquals(OpenClosedType.class, cmd1.getClass());
373
374         // BEGIN:Calendar_Test_Dimmer:0%:abc
375         cmd2 = cmdTags.get(2).getCommand();
376         assertNotNull(cmd2);
377         assertEquals(PercentType.class, cmd2.getClass());
378
379         // BEGIN:Calendar_Test_Number:-12.3:abc
380         cmd3 = cmdTags.get(3).getCommand();
381         assertNotNull(cmd3);
382         assertEquals(DecimalType.class, cmd3.getClass());
383
384         // BEGIN:Calendar_Test_Temperature:-12.3°C:abc
385         cmd4 = cmdTags.get(4).getCommand();
386         assertNotNull(cmd4);
387         assertEquals(QuantityType.class, cmd4.getClass());
388
389         // BEGIN:Calendar_Test_Pressure:500mmHg:abc
390         cmd5 = cmdTags.get(5).getCommand();
391         assertNotNull(cmd5);
392         assertEquals(QuantityType.class, cmd5.getClass());
393
394         // BEGIN:Calendar_Test_Speed:12300000mm/h:abc
395         cmd6 = cmdTags.get(6).getCommand();
396         assertNotNull(cmd6);
397         assertEquals(QuantityType.class, cmd6.getClass());
398
399         // BEGIN:Calendar_Test_Player:REWIND:abc
400         cmd7 = cmdTags.get(7).getCommand();
401         assertNotNull(cmd7);
402         assertEquals(RewindFastforwardType.class, cmd7.getClass());
403
404         // BEGIN:Calendar_Test_RollerShutter:100%:abc
405         cmd8 = cmdTags.get(8).getCommand();
406         assertNotNull(cmd8);
407         assertEquals(PercentType.class, cmd8.getClass());
408
409         // BEGIN:Calendar_Test_String:Test Series #4:abc
410         cmd9 = cmdTags.get(9).getCommand();
411         assertNotNull(cmd9);
412         assertEquals(StringType.class, cmd9.getClass());
413
414         // BEGIN:Calendar_Test_Switch:OFF:abc
415         cmd10 = cmdTags.get(10).getCommand();
416         assertNotNull(cmd10);
417         assertEquals(OnOffType.class, cmd10.getClass());
418
419         // test tag syntax: Test Series #5
420         events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T20:25:00Z"),
421                 Instant.parse("2020-01-28T20:35:00Z"));
422         assertNotNull(events);
423         assertEquals(1, events.size());
424         cmdTags = events.get(0).commandTags;
425         assertEquals(11, cmdTags.size());
426
427         // BEGIN:Calendar_Test_Color:240,100,100:abc
428         cmd0 = cmdTags.get(0).getCommand();
429         assertNotNull(cmd0);
430         assertEquals(HSBType.class, cmd0.getClass());
431
432         // BEGIN:Calendar_Test_Contact:OPEN:abc
433         cmd1 = cmdTags.get(1).getCommand();
434         assertNotNull(cmd1);
435         assertEquals(OpenClosedType.class, cmd1.getClass());
436
437         // BEGIN:Calendar_Test_Dimmer:50%:abc
438         cmd2 = cmdTags.get(2).getCommand();
439         assertNotNull(cmd2);
440         assertEquals(PercentType.class, cmd2.getClass());
441
442         // BEGIN:Calendar_Test_Number:-0:abc
443         cmd3 = cmdTags.get(3).getCommand();
444         assertNotNull(cmd3);
445         assertEquals(DecimalType.class, cmd3.getClass());
446
447         // BEGIN:Calendar_Test_Temperature:0K:abc
448         cmd4 = cmdTags.get(4).getCommand();
449         assertNotNull(cmd4);
450         assertEquals(QuantityType.class, cmd4.getClass());
451
452         // BEGIN:Calendar_Test_Pressure:12.3hPa:abc
453         cmd5 = cmdTags.get(5).getCommand();
454         assertNotNull(cmd5);
455         assertEquals(QuantityType.class, cmd5.getClass());
456
457         // BEGIN:Calendar_Test_Speed:12.3km/h:abc
458         cmd6 = cmdTags.get(6).getCommand();
459         assertNotNull(cmd6);
460         assertEquals(QuantityType.class, cmd6.getClass());
461
462         // BEGIN:Calendar_Test_Player:PLAY:abc
463         cmd7 = cmdTags.get(7).getCommand();
464         assertNotNull(cmd7);
465         assertEquals(PlayPauseType.class, cmd7.getClass());
466
467         // BEGIN:Calendar_Test_RollerShutter:50%:abc
468         cmd8 = cmdTags.get(8).getCommand();
469         assertNotNull(cmd8);
470         assertEquals(PercentType.class, cmd8.getClass());
471
472         // BEGIN:Calendar_Test_String:Test Series #5:abc
473         cmd9 = cmdTags.get(9).getCommand();
474         assertNotNull(cmd9);
475         assertEquals(StringType.class, cmd9.getClass());
476
477         // BEGIN:Calendar_Test_Switch:ON:abc
478         cmd10 = cmdTags.get(10).getCommand();
479         assertNotNull(cmd10);
480         assertEquals(OnOffType.class, cmd10.getClass());
481
482         // test bad command tag syntax: Test Series #6
483         events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T20:40:00Z"),
484                 Instant.parse("2020-01-28T20:50:00Z"));
485         assertNotNull(events);
486         assertEquals(1, events.size());
487         cmdTags = events.get(0).commandTags;
488         // Test Series #6 contains only "bad" command tags as follows..
489
490         // tags with wrong case prefix..
491         // begin
492         // Begin
493         // BEGIn
494
495         // tags that are missing ":" field delimiters..
496         // BEGIN
497
498         // tags with too few field delimiters..
499         // BEGIN:www
500
501         // tags with too many field delimiters..
502         // BEGIN:www:xxx:yyy:zzz
503
504         // tags with an invalid prefix..
505         // BEGINX:xxx:yyy:zzz
506         // ENDX:xxx:yyy:zzz
507         // BEGIN :xxx:yyy:zzz
508         // BEGIN :xxx:yyy:zzz
509
510         // tags with an empty Item Name
511         // BEGIN::yyy:zzz
512         // BEGIN: :yyy:zzz
513         // BEGIN: :yyy:zzz
514
515         // tags with bad Item Name
516         // BEGIN:!:yyy:zzz
517         // BEGIN:@:yyy:zzz
518         // BEGIN:£:yyy:zzz
519
520         // tags with an empty Target State value
521         // BEGIN:xxx::zzz
522         // BEGIN:xxx: :zzz
523         // BEGIN:xxx: :zzz
524
525         // Note: All of the above tags must be rejected! => Assert cmdTags.size() == 0 !
526
527         assertEquals(0, cmdTags.size());
528
529         // test HTML command tag syntax: Test Series #7
530         events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T20:55:00Z"),
531                 Instant.parse("2020-01-28T21:05:00Z"));
532         assertNotNull(events);
533         assertEquals(1, events.size());
534         cmdTags = events.get(0).commandTags;
535         assertEquals(8, cmdTags.size());
536
537         // <p>BEGIN:Calendar_Test_Temperature:12.3°C:abc</p>
538         cmd0 = cmdTags.get(0).getCommand();
539         assertNotNull(cmd0);
540         assertEquals(QuantityType.class, cmd0.getClass());
541
542         // <p>END:Calendar_Test_Temperature:23.4°C:abc</p>
543         cmd1 = cmdTags.get(1).getCommand();
544         assertNotNull(cmd1);
545         assertEquals(QuantityType.class, cmd1.getClass());
546
547         // <p>BEGIN:Calendar_Test_Switch:ON:abc</p>
548         cmd2 = cmdTags.get(2).getCommand();
549         assertNotNull(cmd2);
550         assertEquals(OnOffType.class, cmd2.getClass());
551
552         // <p>END:Calendar_Test_Switch:OFF:abc</p>
553         cmd3 = cmdTags.get(3).getCommand();
554         assertNotNull(cmd3);
555         assertEquals(OnOffType.class, cmd3.getClass());
556
557         // <p>BEGIN:Calendar_Test_String:the quick:abc</p>
558         cmd4 = cmdTags.get(4).getCommand();
559         assertNotNull(cmd4);
560         assertEquals(StringType.class, cmd4.getClass());
561
562         // <p>END:Calendar_Test_String:brown fox:abc</p>
563         cmd5 = cmdTags.get(5).getCommand();
564         assertNotNull(cmd5);
565         assertEquals(StringType.class, cmd5.getClass());
566
567         // </p><p>BEGIN:Calendar_Test_Number:12.3:abc</p>
568         cmd6 = cmdTags.get(6).getCommand();
569         assertNotNull(cmd6);
570         assertEquals(DecimalType.class, cmd6.getClass());
571
572         // <p>END:Calendar_Test_Number:23.4:abc</p>
573         cmd7 = cmdTags.get(7).getCommand();
574         assertNotNull(cmd7);
575         assertEquals(DecimalType.class, cmd7.getClass());
576
577         // issue 11084: Command tags from moved events are also executed
578         List<Event> events2 = calendar_issue11084.getJustBegunEvents(Instant.parse("2021-08-16T16:29:55Z"),
579                 Instant.parse("2021-08-16T17:00:05Z"));
580         assertEquals(1, events2.size());
581         assertEquals(Instant.parse("2021-08-16T16:45:00Z"), events2.get(0).start);
582
583         List<Event> events3 = calendar_issue11084.getJustEndedEvents(Instant.parse("2021-08-16T16:29:55Z"),
584                 Instant.parse("2021-08-16T17:00:05Z"));
585         assertEquals(1, events3.size());
586         assertEquals(Instant.parse("2021-08-16T17:00:00Z"), events3.get(0).end);
587     }
588
589     @SuppressWarnings("null")
590     @Test
591     public void testGetFilteredEventsBetween() {
592         Event[] expectedFilteredEvents1 = new Event[] {
593                 new Event("Test Series in UTC", Instant.parse("2019-09-12T09:05:00Z"),
594                         Instant.parse("2019-09-12T09:10:00Z"), ""),
595                 new Event("Test Event in UTC+2", Instant.parse("2019-09-14T08:00:00Z"),
596                         Instant.parse("2019-09-14T09:00:00Z"), "") };
597         List<Event> realFilteredEvents1 = calendar.getFilteredEventsBetween(Instant.parse("2019-09-12T06:00:00Z"),
598                 Instant.parse("2019-09-15T06:00:00Z"), null, 3);
599         assertArrayEquals(expectedFilteredEvents1, realFilteredEvents1.toArray(new Event[0]));
600
601         Event[] expectedFilteredEvents2 = new Event[] {
602                 new Event("Evt", Instant.parse("2019-11-10T10:00:00Z"), Instant.parse("2019-11-10T11:45:00Z"), ""),
603                 new Event("Evt", Instant.parse("2019-11-17T10:00:00Z"), Instant.parse("2019-11-17T11:45:00Z"), ""),
604                 new Event("Evt", Instant.parse("2019-12-01T10:00:00Z"), Instant.parse("2019-12-01T11:45:00Z"), "") };
605         List<Event> realFilteredEvents2 = calendar2.getFilteredEventsBetween(Instant.parse("2019-11-08T06:00:00Z"),
606                 Instant.parse("2019-12-31T06:00:00Z"), null, 3);
607         assertArrayEquals(expectedFilteredEvents2, realFilteredEvents2.toArray(new Event[] {}));
608
609         Event[] expectedFilteredEvents3 = new Event[] { new Event("Test Event in UTC+2",
610                 Instant.parse("2019-09-14T08:00:00Z"), Instant.parse("2019-09-14T09:00:00Z"), "") };
611         List<Event> realFilteredEvents3 = calendar.getFilteredEventsBetween(Instant.parse("2019-09-12T06:00:00Z"),
612                 Instant.parse("2019-09-15T06:00:00Z"),
613                 new EventTextFilter(EventTextFilter.Field.SUMMARY, "utc+2", EventTextFilter.Type.TEXT), 3);
614         assertArrayEquals(expectedFilteredEvents3, realFilteredEvents3.toArray(new Event[] {}));
615
616         Event[] expectedFilteredEvents4 = new Event[] { new Event("Test Series in UTC",
617                 Instant.parse("2019-09-12T09:05:00Z"), Instant.parse("2019-09-12T09:10:00Z"), "") };
618         List<Event> realFilteredEvents4 = calendar.getFilteredEventsBetween(Instant.parse("2019-09-12T06:00:00Z"),
619                 Instant.parse("2019-09-15T06:00:00Z"),
620                 new EventTextFilter(EventTextFilter.Field.SUMMARY, ".*UTC$", EventTextFilter.Type.REGEX), 3);
621         assertArrayEquals(expectedFilteredEvents4, realFilteredEvents4.toArray(new Event[] {}));
622
623         List<Event> realFilteredEvents5 = calendar.getFilteredEventsBetween(Instant.parse("2019-09-15T06:00:00Z"),
624                 Instant.parse("2019-09-12T06:00:00Z"), null, 3);
625         assertEquals(0, realFilteredEvents5.size());
626
627         List<Event> realFilteredEvents6 = calendar.getFilteredEventsBetween(Instant.parse("2019-09-15T06:00:00Z"),
628                 Instant.parse("2019-12-31T00:00:00Z"), null, 3);
629         assertEquals(0, realFilteredEvents6.size());
630
631         List<Event> realFilteredEvents7 = calendar_issue9647.getFilteredEventsBetween(
632                 LocalDate.parse("2021-01-01").atStartOfDay(ZoneId.systemDefault()).toInstant(),
633                 LocalDate.parse("2021-01-02").atStartOfDay(ZoneId.systemDefault()).toInstant(), null, 3);
634         assertEquals(0, realFilteredEvents7.size());
635
636         Event[] expectedFilteredEvents8 = new Event[] {
637                 new Event("Restabfall", LocalDate.parse("2021-01-04").atStartOfDay(ZoneId.systemDefault()).toInstant(),
638                         LocalDate.parse("2021-01-05").atStartOfDay(ZoneId.systemDefault()).toInstant(), ""),
639                 new Event("Gelbe Tonne", LocalDate.parse("2021-01-04").atStartOfDay(ZoneId.systemDefault()).toInstant(),
640                         LocalDate.parse("2021-01-05").atStartOfDay(ZoneId.systemDefault()).toInstant(), "") };
641         List<Event> realFilteredEvents8 = calendar_issue9647.getFilteredEventsBetween(
642                 LocalDate.parse("2021-01-04").atStartOfDay(ZoneId.systemDefault()).toInstant(),
643                 LocalDate.parse("2021-01-05").atStartOfDay(ZoneId.systemDefault()).toInstant(), null, 3);
644         assertArrayEquals(expectedFilteredEvents8, realFilteredEvents8.toArray(new Event[] {}));
645
646         List<Event> realFilteredEvents9 = calendar_issue11084.getFilteredEventsBetween(
647                 Instant.parse("2021-08-16T16:45:00.123456Z"), Instant.parse("2021-08-16T16:46:00.768643Z"), null, 3);
648         assertEquals(0, realFilteredEvents9.size());
649     }
650 }