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