diff options
Diffstat (limited to 'test/lisp')
100 files changed, 7216 insertions, 229 deletions
diff --git a/test/lisp/align-tests.el b/test/lisp/align-tests.el index 92605a7f4aa..43660f8de87 100644 --- a/test/lisp/align-tests.el +++ b/test/lisp/align-tests.el | |||
| @@ -36,6 +36,53 @@ | |||
| 36 | (ert-test-erts-file (ert-resource-file "c-mode.erts") | 36 | (ert-test-erts-file (ert-resource-file "c-mode.erts") |
| 37 | (test-align-transform-fun #'c-mode))) | 37 | (test-align-transform-fun #'c-mode))) |
| 38 | 38 | ||
| 39 | (ert-deftest align-c-multi-section () | ||
| 40 | "Test alignment of multiple sections in C code. | ||
| 41 | Regression test for bug where positions become stale after earlier | ||
| 42 | sections are aligned, causing incorrect alignment in later sections." | ||
| 43 | (let ((input "int main(void) | ||
| 44 | { | ||
| 45 | long signed int foo = 5; | ||
| 46 | int bar = 7; | ||
| 47 | { | ||
| 48 | int a1 = 4; | ||
| 49 | int b1 = 2; | ||
| 50 | long signed int junk1 = 2; | ||
| 51 | } | ||
| 52 | { | ||
| 53 | int a2 = 4; /* comment */ | ||
| 54 | int b2 = 2; | ||
| 55 | long signed int junk2 = 2; /* another comment */ | ||
| 56 | } | ||
| 57 | |||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | ") | ||
| 61 | (expected "int main(void) | ||
| 62 | { | ||
| 63 | long signed int foo = 5; | ||
| 64 | int bar = 7; | ||
| 65 | { | ||
| 66 | int a1 = 4; | ||
| 67 | int b1 = 2; | ||
| 68 | long signed int junk1 = 2; | ||
| 69 | } | ||
| 70 | { | ||
| 71 | int a2 = 4; /* comment */ | ||
| 72 | int b2 = 2; | ||
| 73 | long signed int junk2 = 2; /* another comment */ | ||
| 74 | } | ||
| 75 | |||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | ")) | ||
| 79 | (with-temp-buffer | ||
| 80 | (c-mode) | ||
| 81 | (setq indent-tabs-mode nil) | ||
| 82 | (insert input) | ||
| 83 | (align (point-min) (point-max)) | ||
| 84 | (should (equal (buffer-string) expected))))) | ||
| 85 | |||
| 39 | (ert-deftest align-css () | 86 | (ert-deftest align-css () |
| 40 | (let ((indent-tabs-mode nil)) | 87 | (let ((indent-tabs-mode nil)) |
| 41 | (ert-test-erts-file (ert-resource-file "css-mode.erts") | 88 | (ert-test-erts-file (ert-resource-file "css-mode.erts") |
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-11473.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-bug-11473.diary-american new file mode 100644 index 00000000000..3f810d31f3b --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-11473.diary-american | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | &5/15/2012 15:00-15:30 Query | ||
| 2 | Location: phone | ||
| 3 | Status: confirmed | ||
| 4 | Organizer: A. Luser <a.luser@foo.com> | ||
| 5 | Attendee: Luser, Other <other.luser@foo.com> (needs-action) | ||
| 6 | Access: public | ||
| 7 | UID: 040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000010000000575268034ECDB649A15349B1BF240F15 | ||
| 8 | Description: Whassup? | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-11473.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-bug-11473.diary-european new file mode 100644 index 00000000000..0555ea90364 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-11473.diary-european | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | &15/5/2012 15:00-15:30 Query | ||
| 2 | Location: phone | ||
| 3 | Status: confirmed | ||
| 4 | Organizer: A. Luser <a.luser@foo.com> | ||
| 5 | Attendee: Luser, Other <other.luser@foo.com> (needs-action) | ||
| 6 | Access: public | ||
| 7 | UID: 040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000010000000575268034ECDB649A15349B1BF240F15 | ||
| 8 | Description: Whassup? | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-11473.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-bug-11473.diary-iso new file mode 100644 index 00000000000..0e3a3fb8715 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-11473.diary-iso | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | &2012/5/15 15:00-15:30 Query | ||
| 2 | Location: phone | ||
| 3 | Status: confirmed | ||
| 4 | Organizer: A. Luser <a.luser@foo.com> | ||
| 5 | Attendee: Luser, Other <other.luser@foo.com> (needs-action) | ||
| 6 | Access: public | ||
| 7 | UID: 040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000010000000575268034ECDB649A15349B1BF240F15 | ||
| 8 | Description: Whassup? | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-22092.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-bug-22092.diary-american new file mode 100644 index 00000000000..d7866ddb899 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-22092.diary-american | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | &12/8/2014 18:30-22:55 Norwegian til Tromsoe-Langnes - | ||
| 2 | Location: Stavanger-Sola | ||
| 3 | Category: Appointment | ||
| 4 | Access: public | ||
| 5 | UID: RFCALITEM1 | ||
| 6 | Description: Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390 \ No newline at end of file | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-22092.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-bug-22092.diary-european new file mode 100644 index 00000000000..ce9933aa5f8 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-22092.diary-european | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | &8/12/2014 18:30-22:55 Norwegian til Tromsoe-Langnes - | ||
| 2 | Location: Stavanger-Sola | ||
| 3 | Category: Appointment | ||
| 4 | Access: public | ||
| 5 | UID: RFCALITEM1 | ||
| 6 | Description: Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390 \ No newline at end of file | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-22092.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-bug-22092.diary-iso new file mode 100644 index 00000000000..9c45f848e76 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-22092.diary-iso | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | &2014/12/8 18:30-22:55 Norwegian til Tromsoe-Langnes - | ||
| 2 | Location: Stavanger-Sola | ||
| 3 | Category: Appointment | ||
| 4 | Access: public | ||
| 5 | UID: RFCALITEM1 | ||
| 6 | Description: Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390 \ No newline at end of file | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-24199.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-bug-24199.diary-all new file mode 100644 index 00000000000..cf3e5884710 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-24199.diary-all | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ MONTHLY) (BYDAY ((3 . 1))) (INTERVAL 1)) | ||
| 2 | :exclude | ||
| 3 | '((0 46 11 6 1 2016 3 -1 0) (0 46 11 3 2 2016 3 -1 0) | ||
| 4 | (0 46 11 2 3 2016 3 -1 0) (0 46 10 4 5 2016 3 -1 0) | ||
| 5 | (0 46 10 1 6 2016 3 -1 0)) | ||
| 6 | :start '(0 46 12 2 12 2015 3 -1 nil) :duration | ||
| 7 | '(0 14 3 0 nil nil nil -1 nil)) Summary | ||
| 8 | Location: Loc | ||
| 9 | Access: private | ||
| 10 | UID: 9188710a-08a7-4061-bae3-d4cf4972599a | ||
| 11 | Description: Desc | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-33277.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-bug-33277.diary-american new file mode 100644 index 00000000000..c546fa9a97c --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-33277.diary-american | |||
| @@ -0,0 +1 @@ | |||
| &11/5/2018 21:00 event with same start/end time | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-33277.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-bug-33277.diary-european new file mode 100644 index 00000000000..28e53960536 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-33277.diary-european | |||
| @@ -0,0 +1 @@ | |||
| &5/11/2018 21:00 event with same start/end time | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-33277.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-bug-33277.diary-iso new file mode 100644 index 00000000000..faa7aeafeb5 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-33277.diary-iso | |||
| @@ -0,0 +1 @@ | |||
| &2018/11/5 21:00 event with same start/end time | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-bug-6766.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-bug-6766.diary-all new file mode 100644 index 00000000000..4e1b69158c9 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-bug-6766.diary-all | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ WEEKLY) (INTERVAL 1) (BYDAY (1 3 4 5))) | ||
| 2 | :start '(0 30 11 21 4 2010 3 -1 nil) :duration | ||
| 3 | '(0 30 0 0 nil nil nil -1 nil)) Scrum | ||
| 4 | Status: confirmed | ||
| 5 | Access: public | ||
| 6 | UID: 8814e3f9-7482-408f-996c-3bfe486a1262 | ||
| 7 | |||
| 8 | &%%(diary-rrule :rule '((FREQ WEEKLY) (INTERVAL 1) (BYDAY (2 4))) :start | ||
| 9 | '(4 22 2010) :duration | ||
| 10 | '(nil nil nil 1 nil nil nil -1 nil)) Tues + Thurs thinking | ||
| 11 | Access: public | ||
| 12 | UID: 8814e3f9-7482-408f-996c-3bfe486a1263 | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-duration-2.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-duration-2.diary-all new file mode 100644 index 00000000000..5d018c1cb6e --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-duration-2.diary-all | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | &%%(diary-rrule :rule | ||
| 2 | '((FREQ DAILY) (UNTIL (12 29 2001)) (INTERVAL 1) (WKST 0)) | ||
| 3 | :start '(12 21 2001)) Urlaub | ||
| 4 | Access: public | ||
| 5 | UID: 20041127T183329Z-18215-1001-4536-49109@andromeda | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-duration.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-duration.diary-american new file mode 100644 index 00000000000..b44b4aed72c --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-duration.diary-american | |||
| @@ -0,0 +1 @@ | |||
| &%%(diary-block 2 17 2005 2 23 2005) duration | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-duration.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-duration.diary-european new file mode 100644 index 00000000000..caee11e0a38 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-duration.diary-european | |||
| @@ -0,0 +1 @@ | |||
| &%%(diary-block 17 2 2005 23 2 2005) duration | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-duration.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-duration.diary-iso new file mode 100644 index 00000000000..573121644d5 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-duration.diary-iso | |||
| @@ -0,0 +1 @@ | |||
| &%%(diary-block 2005 2 17 2005 2 23) duration | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-legacy-function.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-legacy-function.diary-all new file mode 100644 index 00000000000..e0d27f4d1b0 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-legacy-function.diary-all | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | SUMMARY: Testing legacy `icalendar-import-format' function | ||
| 2 | DESCRIPTION: described | ||
| 3 | CLASS: private | ||
| 4 | LOCATION: somewhere | ||
| 5 | ORGANIZER: mailto:baz@example.com | ||
| 6 | STATUS: CONFIRMED | ||
| 7 | URL: http://example.com/foo/baz | ||
| 8 | UID: some-unique-id-here | ||
| 9 | DTSTART: 20250919T090000 | ||
| 10 | DTEND: 20250919T113000 | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-legacy-vars.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-legacy-vars.diary-american new file mode 100644 index 00000000000..42076a32138 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-legacy-vars.diary-american | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | 9/19/2025 09:00-11:30 Testing legacy `icalendar-import-format*' vars | ||
| 2 | CLASS=private | ||
| 3 | DESCRIPTION=described | ||
| 4 | LOCATION=somewhere | ||
| 5 | ORGANIZER=mailto:baz@example.com | ||
| 6 | STATUS=confirmed | ||
| 7 | URL=http://example.com/foo/baz | ||
| 8 | UID=some-unique-id-here \ No newline at end of file | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-legacy-vars.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-legacy-vars.diary-european new file mode 100644 index 00000000000..699c627e2f9 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-legacy-vars.diary-european | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | 19/9/2025 09:00-11:30 Testing legacy `icalendar-import-format*' vars | ||
| 2 | CLASS=private | ||
| 3 | DESCRIPTION=described | ||
| 4 | LOCATION=somewhere | ||
| 5 | ORGANIZER=mailto:baz@example.com | ||
| 6 | STATUS=confirmed | ||
| 7 | URL=http://example.com/foo/baz | ||
| 8 | UID=some-unique-id-here \ No newline at end of file | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-legacy-vars.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-legacy-vars.diary-iso new file mode 100644 index 00000000000..f6d69805c19 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-legacy-vars.diary-iso | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | 2025/9/19 09:00-11:30 Testing legacy `icalendar-import-format*' vars | ||
| 2 | CLASS=private | ||
| 3 | DESCRIPTION=described | ||
| 4 | LOCATION=somewhere | ||
| 5 | ORGANIZER=mailto:baz@example.com | ||
| 6 | STATUS=confirmed | ||
| 7 | URL=http://example.com/foo/baz | ||
| 8 | UID=some-unique-id-here \ No newline at end of file | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-multiple-vcalendars.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-multiple-vcalendars.diary-american new file mode 100644 index 00000000000..ef28f1abfc1 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-multiple-vcalendars.diary-american | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | &7/23/2011 event-1 | ||
| 2 | |||
| 3 | &7/24/2011 event-2 | ||
| 4 | |||
| 5 | &7/25/2011 event-3a | ||
| 6 | |||
| 7 | &7/25/2011 event-3b | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-multiple-vcalendars.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-multiple-vcalendars.diary-european new file mode 100644 index 00000000000..db9625f390d --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-multiple-vcalendars.diary-european | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | &23/7/2011 event-1 | ||
| 2 | |||
| 3 | &24/7/2011 event-2 | ||
| 4 | |||
| 5 | &25/7/2011 event-3a | ||
| 6 | |||
| 7 | &25/7/2011 event-3b | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-multiple-vcalendars.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-multiple-vcalendars.diary-iso new file mode 100644 index 00000000000..bbe009c200e --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-multiple-vcalendars.diary-iso | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | &2011/7/23 event-1 | ||
| 2 | |||
| 3 | &2011/7/24 event-2 | ||
| 4 | |||
| 5 | &2011/7/25 event-3a | ||
| 6 | |||
| 7 | &2011/7/25 event-3b | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-1.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-1.diary-american new file mode 100644 index 00000000000..780e3a8ce64 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-1.diary-american | |||
| @@ -0,0 +1 @@ | |||
| &9/19/2003 09:00-11:30 non-recurring | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-1.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-1.diary-european new file mode 100644 index 00000000000..7e0cd21b784 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-1.diary-european | |||
| @@ -0,0 +1 @@ | |||
| &19/9/2003 09:00-11:30 non-recurring | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-1.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-1.diary-iso new file mode 100644 index 00000000000..c7311286619 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-1.diary-iso | |||
| @@ -0,0 +1 @@ | |||
| &2003/9/19 09:00-11:30 non-recurring | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-all-day.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-all-day.diary-american new file mode 100644 index 00000000000..1d4bb6a337e --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-all-day.diary-american | |||
| @@ -0,0 +1 @@ | |||
| &9/19/2003 non-recurring allday | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-all-day.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-all-day.diary-european new file mode 100644 index 00000000000..b56c7f4e17f --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-all-day.diary-european | |||
| @@ -0,0 +1 @@ | |||
| &19/9/2003 non-recurring allday | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-all-day.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-all-day.diary-iso new file mode 100644 index 00000000000..f1c70ab34c3 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-all-day.diary-iso | |||
| @@ -0,0 +1 @@ | |||
| &2003/9/19 non-recurring allday | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-another-example.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-another-example.diary-american new file mode 100644 index 00000000000..847e7cf6cab --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-another-example.diary-american | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &11/23/2004 14:45-15:45 another example | ||
| 2 | Status: tentative | ||
| 3 | Access: private | ||
| 4 | UID: 6161a312-3902-11d9-b512-f764153bb28b | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-another-example.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-another-example.diary-european new file mode 100644 index 00000000000..5c70e58f4d0 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-another-example.diary-european | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &23/11/2004 14:45-15:45 another example | ||
| 2 | Status: tentative | ||
| 3 | Access: private | ||
| 4 | UID: 6161a312-3902-11d9-b512-f764153bb28b | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-another-example.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-another-example.diary-iso new file mode 100644 index 00000000000..d663965404b --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-another-example.diary-iso | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &2004/11/23 14:45-15:45 another example | ||
| 2 | Status: tentative | ||
| 3 | Access: private | ||
| 4 | UID: 6161a312-3902-11d9-b512-f764153bb28b | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-block.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-block.diary-american new file mode 100644 index 00000000000..c795ebf2abc --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-block.diary-american | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &%%(diary-block 7 19 2004 8 27 2004) Sommerferien | ||
| 2 | Status: tentative | ||
| 3 | Access: private | ||
| 4 | UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61 | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-block.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-block.diary-european new file mode 100644 index 00000000000..4d6b71600a8 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-block.diary-european | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &%%(diary-block 19 7 2004 27 8 2004) Sommerferien | ||
| 2 | Status: tentative | ||
| 3 | Access: private | ||
| 4 | UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61 | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-block.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-block.diary-iso new file mode 100644 index 00000000000..f6d23b049ed --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-block.diary-iso | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &%%(diary-block 2004 7 19 2004 8 27) Sommerferien | ||
| 2 | Status: tentative | ||
| 3 | Access: private | ||
| 4 | UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61 | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-folded-summary.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-folded-summary.diary-american new file mode 100644 index 00000000000..a86f560fb08 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-folded-summary.diary-american | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &11/23/2004 14:00-14:30 folded summary | ||
| 2 | Status: tentative | ||
| 3 | Access: private | ||
| 4 | UID: 04979712-3902-11d9-93dd-8f9f4afe08da | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-folded-summary.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-folded-summary.diary-european new file mode 100644 index 00000000000..0c5e640a615 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-folded-summary.diary-european | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &23/11/2004 14:00-14:30 folded summary | ||
| 2 | Status: tentative | ||
| 3 | Access: private | ||
| 4 | UID: 04979712-3902-11d9-93dd-8f9f4afe08da | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-folded-summary.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-folded-summary.diary-iso new file mode 100644 index 00000000000..699358dc504 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-folded-summary.diary-iso | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &2004/11/23 14:00-14:30 folded summary | ||
| 2 | Status: tentative | ||
| 3 | Access: private | ||
| 4 | UID: 04979712-3902-11d9-93dd-8f9f4afe08da | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-long-summary.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-long-summary.diary-american new file mode 100644 index 00000000000..84cd464c568 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-long-summary.diary-american | |||
| @@ -0,0 +1 @@ | |||
| &9/19/2003 long summary | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-long-summary.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-long-summary.diary-european new file mode 100644 index 00000000000..5d6524202c3 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-long-summary.diary-european | |||
| @@ -0,0 +1 @@ | |||
| &19/9/2003 long summary | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-long-summary.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-long-summary.diary-iso new file mode 100644 index 00000000000..d2300522d9a --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-non-recurring-long-summary.diary-iso | |||
| @@ -0,0 +1 @@ | |||
| &2003/9/19 long summary | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-05-29.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-05-29.diary-american new file mode 100644 index 00000000000..53711dc68ed --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-05-29.diary-american | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | &5/9/2003 10:30-15:30 On-Site Interview | ||
| 2 | Location: Cccc | ||
| 3 | Status: confirmed | ||
| 4 | Organizer: Aaaaaa Aaaaa <aaaaaaa@aaaaaaa.com> | ||
| 5 | Attendees: | ||
| 6 | Xxxxxxxx Xxxxxxxxxxxx <xxxxxxxx@xxxxxxx.com> (needs-action) | ||
| 7 | Yyyyyyy Yyyyy <yyyyyyy@yyyyyyy.com> (needs-action) | ||
| 8 | Zzzz Zzzzzz <zzzzzz@zzzzzzz.com> (needs-action) | ||
| 9 | UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9 | ||
| 10 | Description: 10:30am - Blah | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-05-29.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-05-29.diary-european new file mode 100644 index 00000000000..17efbd64c18 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-05-29.diary-european | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | &9/5/2003 10:30-15:30 On-Site Interview | ||
| 2 | Location: Cccc | ||
| 3 | Status: confirmed | ||
| 4 | Organizer: Aaaaaa Aaaaa <aaaaaaa@aaaaaaa.com> | ||
| 5 | Attendees: | ||
| 6 | Xxxxxxxx Xxxxxxxxxxxx <xxxxxxxx@xxxxxxx.com> (needs-action) | ||
| 7 | Yyyyyyy Yyyyy <yyyyyyy@yyyyyyy.com> (needs-action) | ||
| 8 | Zzzz Zzzzzz <zzzzzz@zzzzzzz.com> (needs-action) | ||
| 9 | UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9 | ||
| 10 | Description: 10:30am - Blah | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18a.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18a.diary-american new file mode 100644 index 00000000000..1b819404abf --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18a.diary-american | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | &6/23/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX | ||
| 2 | Location: 555 or TN 555-5555 ID 5555 & NochWas (see below) | ||
| 3 | Status: confirmed | ||
| 4 | Organizer: ABCD,TECHTRAINING(A-Americas,exgen1) <xxx@xxxxx.com> | ||
| 5 | Attendee: | ||
| 6 | AAAAA,AAAAA (A-AAAAAAA,ex1) <aaaaa_aaaaa@aaaaa.com> (needs-action) | ||
| 7 | UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E | ||
| 8 | Description: 753 Zeichen hier radiert | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18a.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18a.diary-european new file mode 100644 index 00000000000..379c612419f --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18a.diary-european | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | &23/6/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX | ||
| 2 | Location: 555 or TN 555-5555 ID 5555 & NochWas (see below) | ||
| 3 | Status: confirmed | ||
| 4 | Organizer: ABCD,TECHTRAINING(A-Americas,exgen1) <xxx@xxxxx.com> | ||
| 5 | Attendee: | ||
| 6 | AAAAA,AAAAA (A-AAAAAAA,ex1) <aaaaa_aaaaa@aaaaa.com> (needs-action) | ||
| 7 | UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E | ||
| 8 | Description: 753 Zeichen hier radiert | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18b.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18b.diary-american new file mode 100644 index 00000000000..0e34b5d7fa9 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18b.diary-american | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | &6/23/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15 | ||
| 2 | Desc: Viele Zeichen standen hier früher | ||
| 3 | Location: 123 or TN 123-1234 ID abcd & SonstWo (see below) | ||
| 4 | Organizer: MAILTO:bbb@bbbbb.com | ||
| 5 | Status: CONFIRMED | ||
| 6 | UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E \ No newline at end of file | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18b.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18b.diary-european new file mode 100644 index 00000000000..e6151c78dce --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2003-06-18b.diary-european | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | &23/6/2003 09:00-10:00 Updated: Dress Rehearsal for ABC01-15 | ||
| 2 | Location: 123 or TN 123-1234 ID abcd & SonstWo (see below) | ||
| 3 | Status: confirmed | ||
| 4 | UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E | ||
| 5 | Description: Viele Zeichen standen hier früher \ No newline at end of file | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2004-11-19.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2004-11-19.diary-american new file mode 100644 index 00000000000..17dff899314 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2004-11-19.diary-american | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ WEEKLY) (INTERVAL 1) (BYDAY (1))) :start | ||
| 2 | '(11 1 2004) :duration | ||
| 3 | '(nil nil nil 1 nil nil nil -1 nil)) Wwww aa hhhh | ||
| 4 | Status: tentative | ||
| 5 | Access: private | ||
| 6 | |||
| 7 | &%%(diary-rrule :rule '((FREQ WEEKLY) (INTERVAL 2) (BYDAY (5))) :start | ||
| 8 | '(0 0 14 12 11 2004 5 -1 nil) :duration | ||
| 9 | '(0 30 4 0 nil nil nil -1 nil)) MMM Aaaaaaaaa | ||
| 10 | Status: tentative | ||
| 11 | Access: private | ||
| 12 | |||
| 13 | &%%(diary-block 11 19 2004 11 19 2004) Rrrr/Cccccc ii Aaaaaaaa | ||
| 14 | Status: tentative | ||
| 15 | Access: private | ||
| 16 | Description: Vvvvv Rrrr aaa Cccccc | ||
| 17 | |||
| 18 | &11/23/2004 11:00-12:00 Hhhhhhhh | ||
| 19 | Status: tentative | ||
| 20 | Access: private | ||
| 21 | |||
| 22 | &11/23/2004 14:00-14:30 Jjjjj & Wwwww | ||
| 23 | Status: tentative | ||
| 24 | Access: private | ||
| 25 | |||
| 26 | &11/23/2004 14:45-15:45 BB Aaaaaaaa Bbbbb | ||
| 27 | Status: tentative | ||
| 28 | Access: private | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2004-11-19.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2004-11-19.diary-european new file mode 100644 index 00000000000..cfd3a43d55c --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2004-11-19.diary-european | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ WEEKLY) (INTERVAL 1) (BYDAY (1))) :start | ||
| 2 | '(11 1 2004) :duration | ||
| 3 | '(nil nil nil 1 nil nil nil -1 nil)) Wwww aa hhhh | ||
| 4 | Status: tentative | ||
| 5 | Access: private | ||
| 6 | |||
| 7 | &%%(diary-rrule :rule '((FREQ WEEKLY) (INTERVAL 2) (BYDAY (5))) :start | ||
| 8 | '(0 0 14 12 11 2004 5 -1 nil) :duration | ||
| 9 | '(0 30 4 0 nil nil nil -1 nil)) MMM Aaaaaaaaa | ||
| 10 | Status: tentative | ||
| 11 | Access: private | ||
| 12 | |||
| 13 | &%%(diary-block 19 11 2004 19 11 2004) Rrrr/Cccccc ii Aaaaaaaa | ||
| 14 | Status: tentative | ||
| 15 | Access: private | ||
| 16 | Description: Vvvvv Rrrr aaa Cccccc | ||
| 17 | |||
| 18 | &23/11/2004 11:00-12:00 Hhhhhhhh | ||
| 19 | Status: tentative | ||
| 20 | Access: private | ||
| 21 | |||
| 22 | &23/11/2004 14:00-14:30 Jjjjj & Wwwww | ||
| 23 | Status: tentative | ||
| 24 | Access: private | ||
| 25 | |||
| 26 | &23/11/2004 14:45-15:45 BB Aaaaaaaa Bbbbb | ||
| 27 | Status: tentative | ||
| 28 | Access: private | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-02-07.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-02-07.diary-american new file mode 100644 index 00000000000..f7518918f30 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-02-07.diary-american | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | &%%(diary-block 2 6 2005 2 6 2005) Waitangi Day | ||
| 2 | Status: confirmed | ||
| 3 | Category: Public Holiday | ||
| 4 | Access: private | ||
| 5 | UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4 | ||
| 6 | Description: abcdef | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-02-07.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-02-07.diary-european new file mode 100644 index 00000000000..c65526a5551 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-02-07.diary-european | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | &%%(diary-block 6 2 2005 6 2 2005) Waitangi Day | ||
| 2 | Status: confirmed | ||
| 3 | Category: Public Holiday | ||
| 4 | Access: private | ||
| 5 | UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4 | ||
| 6 | Description: abcdef | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-03-01.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-03-01.diary-american new file mode 100644 index 00000000000..9290254f1ce --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-03-01.diary-american | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | &%%(diary-block 2 17 2005 2 23 2005) Hhhhhh Aaaaa ii Aaaaaaaa | ||
| 2 | UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-03-01.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-03-01.diary-european new file mode 100644 index 00000000000..61cbbc726d3 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-2005-03-01.diary-european | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | &%%(diary-block 17 2 2005 23 2 2005) Hhhhhh Aaaaa ii Aaaaaaaa | ||
| 2 | UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-no-dst.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-real-world-no-dst.diary-american new file mode 100644 index 00000000000..6c1d6667e63 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-no-dst.diary-american | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &11/16/2014 07:00-08:00 NoDST | ||
| 2 | Location: Everywhere | ||
| 3 | UID: 20141116T171439Z-678877132@marudot.com | ||
| 4 | Description: Test event from timezone without DST | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-real-world-no-dst.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-real-world-no-dst.diary-european new file mode 100644 index 00000000000..b710b4c61e5 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-real-world-no-dst.diary-european | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &16/11/2014 07:00-08:00 NoDST | ||
| 2 | Location: Everywhere | ||
| 3 | UID: 20141116T171439Z-678877132@marudot.com | ||
| 4 | Description: Test event from timezone without DST | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-anniversary.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-anniversary.diary-all new file mode 100644 index 00000000000..ce87095c080 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-anniversary.diary-all | |||
| @@ -0,0 +1 @@ | |||
| &%%(diary-rrule :rule '((FREQ YEARLY)) :start '(8 15 2004)) Maria Himmelfahrt | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-bi-weekly.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-bi-weekly.diary-all new file mode 100644 index 00000000000..9c5cb38ddb8 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-bi-weekly.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ WEEKLY) (COUNT 3) (INTERVAL 2)) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule count bi-weekly 3 times \ No newline at end of file | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-daily-long.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-daily-long.diary-all new file mode 100644 index 00000000000..3b7b4532506 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-daily-long.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ DAILY) (COUNT 14) (INTERVAL 1)) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule count daily long | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-daily-short.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-daily-short.diary-all new file mode 100644 index 00000000000..08051f0d015 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-daily-short.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ DAILY) (COUNT 1) (INTERVAL 1)) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule count daily short | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-every-second-month.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-every-second-month.diary-all new file mode 100644 index 00000000000..e5063cfed3b --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-every-second-month.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ MONTHLY) (INTERVAL 2) (COUNT 5)) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule count every second month | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-every-second-year.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-every-second-year.diary-all new file mode 100644 index 00000000000..74fbc93986c --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-every-second-year.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ YEARLY) (INTERVAL 2) (COUNT 5)) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule count every second year | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-monthly.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-monthly.diary-all new file mode 100644 index 00000000000..af145bbdee9 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-monthly.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ MONTHLY) (INTERVAL 1) (COUNT 5)) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule count monthly | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-yearly.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-yearly.diary-all new file mode 100644 index 00000000000..5b78f608f12 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-count-yearly.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ YEARLY) (INTERVAL 1) (COUNT 5)) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule count yearly | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-daily-two-day.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-daily-two-day.diary-all new file mode 100644 index 00000000000..9017c06900b --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-daily-two-day.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ DAILY) (INTERVAL 2)) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule daily | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-daily-with-exceptions.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-daily-with-exceptions.diary-all new file mode 100644 index 00000000000..0407aa81b21 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-daily-with-exceptions.diary-all | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ DAILY) (INTERVAL 2)) :exclude | ||
| 2 | '((9 21 2003) (9 25 2003)) :start | ||
| 3 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 4 | '(0 30 2 0 nil nil nil -1 nil)) rrule daily with exceptions | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-daily.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-daily.diary-all new file mode 100644 index 00000000000..993d3b9bb5e --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-daily.diary-all | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ DAILY)) :start '(0 0 9 19 9 2003 5 -1 nil) | ||
| 2 | :duration '(0 30 2 0 nil nil nil -1 nil)) rrule daily | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-monthly-no-end.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-monthly-no-end.diary-all new file mode 100644 index 00000000000..e69a6ec690c --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-monthly-no-end.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ MONTHLY)) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule monthly no end | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-monthly-with-end.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-monthly-with-end.diary-all new file mode 100644 index 00000000000..a699498be77 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-monthly-with-end.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ MONTHLY) (UNTIL (8 19 2005))) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule monthly with end | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-weekly.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-weekly.diary-all new file mode 100644 index 00000000000..89ba3e96149 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-weekly.diary-all | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ WEEKLY)) :start '(0 0 9 19 9 2003 5 -1 nil) | ||
| 2 | :duration '(0 30 2 0 nil nil nil -1 nil)) rrule weekly | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-rrule-yearly.diary-all b/test/lisp/calendar/diary-icalendar-resources/import-rrule-yearly.diary-all new file mode 100644 index 00000000000..81220aac0cd --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-rrule-yearly.diary-all | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &%%(diary-rrule :rule '((FREQ YEARLY) (INTERVAL 2)) :start | ||
| 2 | '(0 0 9 19 9 2003 5 -1 nil) :duration | ||
| 3 | '(0 30 2 0 nil nil nil -1 nil)) rrule yearly | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-time-format-12hr-blank.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-time-format-12hr-blank.diary-iso new file mode 100644 index 00000000000..0945cfc0b60 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-time-format-12hr-blank.diary-iso | |||
| @@ -0,0 +1 @@ | |||
| &2003/9/19 9.00h-11.30h 12hr blank-padded | |||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-with-attachment.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-with-attachment.diary-iso new file mode 100644 index 00000000000..b16022908d9 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-with-attachment.diary-iso | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &2003/9/19 09:00 Has an attachment | ||
| 2 | Attachment: R3Jl.plain | ||
| 3 | UID: f9fee9a0-1231-4984-9078-f1357db352db | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-with-timezone.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-with-timezone.diary-iso new file mode 100644 index 00000000000..56f91066f73 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-with-timezone.diary-iso | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | &2012/1/15 15:00-15:30 standardtime | ||
| 2 | |||
| 3 | &2012/12/15 11:00-11:30 daylightsavingtime | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-with-uid.diary-american b/test/lisp/calendar/diary-icalendar-resources/import-with-uid.diary-american new file mode 100644 index 00000000000..9b2f06afc26 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-with-uid.diary-american | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | &9/19/2003 09:00-11:30 non-recurring | ||
| 2 | UID: 1234567890uid | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-with-uid.diary-european b/test/lisp/calendar/diary-icalendar-resources/import-with-uid.diary-european new file mode 100644 index 00000000000..95db4d40151 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-with-uid.diary-european | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | &19/9/2003 09:00-11:30 non-recurring | ||
| 2 | UID: 1234567890uid | ||
diff --git a/test/lisp/calendar/diary-icalendar-resources/import-with-uid.diary-iso b/test/lisp/calendar/diary-icalendar-resources/import-with-uid.diary-iso new file mode 100644 index 00000000000..d372e5a3d1f --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-resources/import-with-uid.diary-iso | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | &2003/9/19 09:00-11:30 non-recurring | ||
| 2 | UID: 1234567890uid | ||
diff --git a/test/lisp/calendar/diary-icalendar-tests.el b/test/lisp/calendar/diary-icalendar-tests.el new file mode 100644 index 00000000000..b502dc72059 --- /dev/null +++ b/test/lisp/calendar/diary-icalendar-tests.el | |||
| @@ -0,0 +1,1278 @@ | |||
| 1 | ;;; diary-icalendar-tests.el --- Tests for diary-icalendar -*- lexical-binding: t; -*- | ||
| 2 | ;; Copyright (C) 2025 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | ;; This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 7 | ;; it under the terms of the GNU General Public License as published by | ||
| 8 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 9 | ;; (at your option) any later version. | ||
| 10 | |||
| 11 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;; GNU General Public License for more details. | ||
| 15 | |||
| 16 | ;; You should have received a copy of the GNU General Public License | ||
| 17 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | ;;; Code: | ||
| 20 | |||
| 21 | (eval-when-compile (require 'cl-lib)) | ||
| 22 | (eval-when-compile (require 'icalendar-macs)) | ||
| 23 | (require 'diary-icalendar) | ||
| 24 | (require 'icalendar-parser) | ||
| 25 | (require 'icalendar-utils) | ||
| 26 | (require 'icalendar) | ||
| 27 | (require 'ert) | ||
| 28 | (require 'ert-x) | ||
| 29 | (require 'seq) | ||
| 30 | |||
| 31 | |||
| 32 | ;; Tests for diary import functions | ||
| 33 | (defconst icalendar-resources-directory | ||
| 34 | (expand-file-name "test/lisp/calendar/icalendar-resources" | ||
| 35 | source-directory)) | ||
| 36 | |||
| 37 | (defconst diary-icalendar-resources-directory | ||
| 38 | (expand-file-name "test/lisp/calendar/diary-icalendar-resources" | ||
| 39 | source-directory)) | ||
| 40 | |||
| 41 | (defun dit:icalendar-resource-file (filename) | ||
| 42 | ;; Return a filename from the ./icalendar-resources directory: | ||
| 43 | (file-name-concat icalendar-resources-directory filename)) | ||
| 44 | |||
| 45 | (defun dit:resource-file (filename) | ||
| 46 | ;; Return a filename from the ./diary-icalendar-resources directory: | ||
| 47 | (file-name-concat diary-icalendar-resources-directory filename)) | ||
| 48 | |||
| 49 | (defun dit:file-contents (filename) | ||
| 50 | "Return literal contents of FILENAME." | ||
| 51 | (with-temp-buffer | ||
| 52 | (let ((coding-system-for-read 'raw-text) | ||
| 53 | (inhibit-eol-conversion t)) | ||
| 54 | (insert-file-contents-literally filename) | ||
| 55 | (buffer-string)))) | ||
| 56 | |||
| 57 | (defmacro dit:with-tz (tz &rest body) | ||
| 58 | "Evaluate BODY with time zone TZ in effect." | ||
| 59 | `(let ((old-tz (getenv "TZ"))) | ||
| 60 | (unwind-protect | ||
| 61 | (progn | ||
| 62 | (setenv "TZ" ,tz) | ||
| 63 | ,@body) | ||
| 64 | (setenv "TZ" old-tz)))) | ||
| 65 | |||
| 66 | (defun dit:import-file (ics-file) | ||
| 67 | "Test diary import of ICS-FILE. | ||
| 68 | |||
| 69 | ICS-FILE names a .ics file in icalendar-resources directory. The | ||
| 70 | calendar in ICS-FILE is parsed and imported in ISO, European, and | ||
| 71 | American date styles. The output of each import is compared against the | ||
| 72 | contents of any diary files with the same base name as ICS-FILE and | ||
| 73 | extensions \".diary-all\", \".diary-american\", \".diary-european\", or | ||
| 74 | \".diary-iso\"." | ||
| 75 | (let* ((basename (file-name-base ics-file)) | ||
| 76 | (ics-file (dit:icalendar-resource-file ics-file)) | ||
| 77 | (import-buffer (icalendar-unfolded-buffer-from-file ics-file)) | ||
| 78 | (all-file (dit:resource-file (concat basename ".diary-all"))) | ||
| 79 | (iso-file (dit:resource-file (concat basename ".diary-iso"))) | ||
| 80 | (european-file (dit:resource-file (concat basename ".diary-european"))) | ||
| 81 | (american-file (dit:resource-file (concat basename ".diary-american")))) | ||
| 82 | (with-current-buffer import-buffer | ||
| 83 | (when (file-exists-p all-file) | ||
| 84 | (calendar-set-date-style 'american) ; because it's the default | ||
| 85 | (dit:-do-test-import all-file)) | ||
| 86 | (when (file-exists-p iso-file) | ||
| 87 | (calendar-set-date-style 'iso) | ||
| 88 | (dit:-do-test-import iso-file)) | ||
| 89 | (when (file-exists-p european-file) | ||
| 90 | (calendar-set-date-style 'european) | ||
| 91 | (dit:-do-test-import european-file)) | ||
| 92 | (when (file-exists-p american-file) | ||
| 93 | (calendar-set-date-style 'american) | ||
| 94 | (dit:-do-test-import american-file)) | ||
| 95 | (set-buffer-modified-p nil)) ; so we can kill it without being asked | ||
| 96 | (kill-buffer import-buffer))) | ||
| 97 | |||
| 98 | (defun dit:-do-test-import (diary-filename) | ||
| 99 | "Import iCalendar in current buffer and compare the result with DIARY-FILENAME." | ||
| 100 | (ert-with-temp-file temp-file | ||
| 101 | :suffix "icalendar-test-diary" | ||
| 102 | (dit:with-tz "Europe/Vienna" | ||
| 103 | ;; There's no way to make the test data independent of the system | ||
| 104 | ;; time zone unless diary gains time zone awareness/syntax, so we have | ||
| 105 | ;; to choose some time zone or other to standardize on for the import | ||
| 106 | ;; tests. "Europe/Vienna" is an arbitrary choice; it's simply the one | ||
| 107 | ;; I originally generated the test data files in. | ||
| 108 | ;; N.B. "Europe/Vienna" = "CET-1CEST,M3.5.0/02:00,M10.5.0/03:00" | ||
| 109 | (di:import-buffer temp-file t t)) | ||
| 110 | (save-excursion | ||
| 111 | (find-file temp-file) | ||
| 112 | (let ((result (buffer-substring-no-properties (point-min) (point-max))) | ||
| 113 | (expected (dit:file-contents diary-filename))) | ||
| 114 | ;; Trim the result so that whitespace produced by the importer | ||
| 115 | ;; need not be committed in the test data files: | ||
| 116 | (should (equal (string-trim result) | ||
| 117 | (string-trim expected))) | ||
| 118 | ;; This is useful for debugging differences when tests are failing: | ||
| 119 | ;; (unless (equal (string-trim result) | ||
| 120 | ;; (string-trim expected)) | ||
| 121 | ;; (let ((result-buf (current-buffer)) | ||
| 122 | ;; (diary-buf (find-file diary-filename))) | ||
| 123 | ;; (ediff-buffers result-buf ; actual output | ||
| 124 | ;; diary-buf) | ||
| 125 | ;; (switch-to-buffer-other-frame "*Ediff Control Panel*") | ||
| 126 | ;; (error "Unexpected result; see ediff"))) | ||
| 127 | )) | ||
| 128 | (kill-buffer (find-buffer-visiting temp-file)))) | ||
| 129 | |||
| 130 | (ert-deftest dit:import-non-recurring () | ||
| 131 | "Import tests for standard, non-recurring events." | ||
| 132 | (dit:import-file "import-non-recurring-1.ics") | ||
| 133 | (dit:import-file "import-non-recurring-all-day.ics") | ||
| 134 | (dit:import-file "import-non-recurring-long-summary.ics") | ||
| 135 | (dit:import-file "import-non-recurring-block.ics") | ||
| 136 | (dit:import-file "import-non-recurring-folded-summary.ics") | ||
| 137 | (dit:import-file "import-non-recurring-another-example.ics")) | ||
| 138 | |||
| 139 | (ert-deftest dit:import-w/legacy-vars () | ||
| 140 | "Import tests using legacy import variables" | ||
| 141 | (let ((icalendar-import-format "%s%c%d%l%o%t%u%U") | ||
| 142 | (icalendar-import-format-summary "%s") | ||
| 143 | (icalendar-import-format-class "\n CLASS=%s") | ||
| 144 | (icalendar-import-format-description "\n DESCRIPTION=%s") | ||
| 145 | (icalendar-import-format-location "\n LOCATION=%s") | ||
| 146 | (icalendar-import-format-organizer "\n ORGANIZER=%s") | ||
| 147 | (icalendar-import-format-status "\n STATUS=%s") | ||
| 148 | (icalendar-import-format-url "\n URL=%s") | ||
| 149 | (icalendar-import-format-uid "\n UID=%s")) | ||
| 150 | (dit:import-file "import-legacy-vars.ics"))) | ||
| 151 | |||
| 152 | (defun dit:legacy-import-function (vevent) | ||
| 153 | "Example function value for `icalendar-import-format'" | ||
| 154 | (let ((props (nth 2 (car vevent)))) | ||
| 155 | (mapconcat | ||
| 156 | (lambda (prop) | ||
| 157 | (format " %s: %s\n" | ||
| 158 | (symbol-name (nth 0 prop)) | ||
| 159 | (nth 2 prop))) | ||
| 160 | props))) | ||
| 161 | |||
| 162 | (ert-deftest dit:import-w/legacy-function () | ||
| 163 | "Import tests using legacy import variables" | ||
| 164 | (let ((icalendar-import-format 'dit:legacy-import-function)) | ||
| 165 | (dit:import-file "import-legacy-function.ics"))) | ||
| 166 | |||
| 167 | (ert-deftest dit:import-w/time-format () | ||
| 168 | "Import tests for customized `diary-icalendar-time-format'" | ||
| 169 | (let ((diary-icalendar-time-format "%l.%Mh")) | ||
| 170 | (dit:import-file "import-time-format-12hr-blank.ics"))) | ||
| 171 | |||
| 172 | (ert-deftest dit:import-rrule () | ||
| 173 | "Import tests for recurring events." | ||
| 174 | (dit:import-file "import-rrule-daily.ics") | ||
| 175 | (dit:import-file "import-rrule-daily-two-day.ics") | ||
| 176 | (dit:import-file "import-rrule-daily-with-exceptions.ics") | ||
| 177 | (dit:import-file "import-rrule-weekly.ics") | ||
| 178 | (dit:import-file "import-rrule-monthly-no-end.ics") | ||
| 179 | (dit:import-file "import-rrule-monthly-with-end.ics") | ||
| 180 | (dit:import-file "import-rrule-anniversary.ics") | ||
| 181 | (dit:import-file "import-rrule-yearly.ics") | ||
| 182 | (dit:import-file "import-rrule-count-bi-weekly.ics") | ||
| 183 | (dit:import-file "import-rrule-count-daily-short.ics") | ||
| 184 | (dit:import-file "import-rrule-count-daily-long.ics") | ||
| 185 | (dit:import-file "import-rrule-count-monthly.ics") | ||
| 186 | (dit:import-file "import-rrule-count-every-second-month.ics") | ||
| 187 | (dit:import-file "import-rrule-count-yearly.ics") | ||
| 188 | (dit:import-file "import-rrule-count-every-second-year.ics")) | ||
| 189 | |||
| 190 | (ert-deftest dit:import-duration () | ||
| 191 | (dit:import-file "import-duration.ics") | ||
| 192 | ;; duration-2: this is actually an rrule test | ||
| 193 | (dit:import-file "import-duration-2.ics")) | ||
| 194 | |||
| 195 | (ert-deftest dit:import-multiple-vcalendars () | ||
| 196 | (dit:import-file "import-multiple-vcalendars.ics")) | ||
| 197 | |||
| 198 | (ert-deftest dit:import-with-uid () | ||
| 199 | "Perform import test with uid." | ||
| 200 | (dit:import-file "import-with-uid.ics")) | ||
| 201 | |||
| 202 | (ert-deftest dit:import-with-attachment () | ||
| 203 | "Test importing an attached file to `icalendar-attachment-directory'" | ||
| 204 | (ert-with-temp-directory temp-dir | ||
| 205 | (let ((di:attachment-directory temp-dir) | ||
| 206 | (uid-dir (file-name-concat temp-dir | ||
| 207 | ;; Event's UID: | ||
| 208 | "f9fee9a0-1231-4984-9078-f1357db352db"))) | ||
| 209 | (dit:import-file "import-with-attachment.ics") | ||
| 210 | (should (file-directory-p uid-dir)) | ||
| 211 | (let ((files (directory-files uid-dir t | ||
| 212 | ;; First 4 chars of base64-string: | ||
| 213 | "R3Jl"))) | ||
| 214 | (should (length= files 1)) | ||
| 215 | (with-temp-buffer | ||
| 216 | (insert-file-contents (car files)) | ||
| 217 | (should (equal "Greetings! I am a base64-encoded file" | ||
| 218 | (buffer-string)))))))) | ||
| 219 | |||
| 220 | (ert-deftest dit:import-with-timezone () | ||
| 221 | (dit:import-file "import-with-timezone.ics")) | ||
| 222 | |||
| 223 | (ert-deftest dit:import-real-world () | ||
| 224 | "Import tests of other real world data" | ||
| 225 | ;; N.B. Not all data from these files is expected to be imported | ||
| 226 | ;; without any pre-parsing cleanup, since they are in some cases | ||
| 227 | ;; malformed. The test data matches what the importer should produce | ||
| 228 | ;; in its default configuration. | ||
| 229 | (dit:with-tz "Asia/Kolkata" | ||
| 230 | ;; Indian Standard Time, used in this file, does not adjust for | ||
| 231 | ;; daylight savings; so we use that time zone to keep this test | ||
| 232 | ;; from failing on systems in a time zone that does: | ||
| 233 | (dit:import-file "import-real-world-2003-05-29.ics")) | ||
| 234 | (dit:with-tz "Asia/Tehran" | ||
| 235 | ;; For the same reason, we use "Asia/Tehran" here: | ||
| 236 | (dit:import-file "import-real-world-no-dst.ics")) | ||
| 237 | (dit:import-file "import-real-world-2003-06-18a.ics") | ||
| 238 | ;; FIXME: this test seems to be failing due to an invisible unicode | ||
| 239 | ;; error of some sort. The import result and the expected output are | ||
| 240 | ;; visually identical and ediff shows no differences in the buffers, | ||
| 241 | ;; but the strings are apparently not `equal', and comparing them | ||
| 242 | ;; character-by-character shows that they somehow differ at the "ü" in | ||
| 243 | ;; "früher". But `describe-char' there shows no differences so far as | ||
| 244 | ;; I can see. | ||
| 245 | ;(dit:import-file "import-real-world-2003-06-18b.ics") | ||
| 246 | (dit:import-file "import-real-world-2004-11-19.ics") | ||
| 247 | (dit:import-file "import-real-world-2005-02-07.ics") | ||
| 248 | (dit:import-file "import-real-world-2005-03-01.ics")) | ||
| 249 | |||
| 250 | (ert-deftest dit:import-bug-6766 () | ||
| 251 | ;;bug#6766 -- multiple byday values in a weekly rrule | ||
| 252 | (dit:import-file "import-bug-6766.ics")) | ||
| 253 | |||
| 254 | (ert-deftest dit:import-bug-11473 () | ||
| 255 | ;; bug#11473 -- illegal tzid | ||
| 256 | (dit:import-file "import-bug-11473.ics")) | ||
| 257 | |||
| 258 | (ert-deftest dit:import-bug-22092 () | ||
| 259 | ;; bug#22092 -- mixed line endings | ||
| 260 | (let ((ical:pre-unfolding-hook '(ical:fix-line-endings))) | ||
| 261 | (dit:import-file "import-bug-22092.ics"))) | ||
| 262 | |||
| 263 | (ert-deftest dit:import-bug-24199 () | ||
| 264 | ;;bug#24199 -- monthly rule with byday-clause | ||
| 265 | (dit:import-file "import-bug-24199.ics")) | ||
| 266 | |||
| 267 | (ert-deftest dit:import-bug-33277 () | ||
| 268 | ;;bug#33277 -- start time equals end time | ||
| 269 | (dit:import-file "import-bug-33277.ics")) | ||
| 270 | |||
| 271 | |||
| 272 | |||
| 273 | |||
| 274 | ;; Tests for diary export functions | ||
| 275 | (cl-defmacro dit:parse-test (entry &key parser type number | ||
| 276 | bindings tests | ||
| 277 | source) | ||
| 278 | "Create a test which parses data from ENTRY. | ||
| 279 | |||
| 280 | PARSER should be a zero-argument function which parses data of TYPE in a | ||
| 281 | buffer containing ENTRY. The defined test passes if PARSER returns a | ||
| 282 | list of NUMBER objects which satisfy TYPE. If NUMBER is nil, the return | ||
| 283 | value of parser must be a single value satisfying TYPE. | ||
| 284 | |||
| 285 | BINDINGS, if given, will be evaluated and made available in the lexical | ||
| 286 | environment where PARSER is called; this can be used to temporarily set | ||
| 287 | variables that affect parsing. | ||
| 288 | |||
| 289 | TESTS, if given, is an additional test form that will be evaluated after | ||
| 290 | the main tests. The variable `parsed' will be bound to the return value | ||
| 291 | of PARSER when TESTS are evaluated. | ||
| 292 | |||
| 293 | SOURCE, if given, should be a symbol; it is used to name the test." | ||
| 294 | (let ((parser-form `(funcall (function ,parser)))) | ||
| 295 | `(ert-deftest | ||
| 296 | ,(intern (concat "diary-icalendar-test-" | ||
| 297 | (string-replace "diary-icalendar-" "" | ||
| 298 | (symbol-name parser)) | ||
| 299 | (if source (concat "/" (symbol-name source)) ""))) | ||
| 300 | () | ||
| 301 | ,(format "Does `%s' correctly parse `%s' in diary entries?" parser type) | ||
| 302 | (let* ((parse-buf (get-buffer-create "*iCalendar Parse Test*")) | ||
| 303 | (unparsed ,entry)) | ||
| 304 | (set-buffer parse-buf) | ||
| 305 | (erase-buffer) | ||
| 306 | (insert unparsed) | ||
| 307 | (goto-char (point-min)) | ||
| 308 | (let* (,@bindings | ||
| 309 | (parsed ,parser-form)) | ||
| 310 | (when ,number | ||
| 311 | (should (length= parsed ,number)) | ||
| 312 | (should (seq-every-p (lambda (val) (cl-typep val ,type)) | ||
| 313 | parsed))) | ||
| 314 | (unless ,number | ||
| 315 | (should (cl-typep parsed ,type))) | ||
| 316 | ,tests))))) | ||
| 317 | |||
| 318 | (dit:parse-test | ||
| 319 | "2025-04-01 A basic entry | ||
| 320 | Other data" | ||
| 321 | :parser di:parse-entry-type | ||
| 322 | :type 'symbol | ||
| 323 | :source vevent | ||
| 324 | :tests (should (eq parsed 'ical:vevent))) | ||
| 325 | |||
| 326 | (dit:parse-test | ||
| 327 | "&2025-04-01 A nonmarking journal entry | ||
| 328 | Other data" | ||
| 329 | :parser di:parse-entry-type | ||
| 330 | :bindings ((di:export-nonmarking-as-vjournal t)) | ||
| 331 | :type 'symbol | ||
| 332 | :source vjournal | ||
| 333 | :tests (should (eq parsed 'ical:vjournal))) | ||
| 334 | |||
| 335 | (dit:parse-test | ||
| 336 | "2025-04-01 Due: some task | ||
| 337 | Other data" | ||
| 338 | :parser di:parse-entry-type | ||
| 339 | :bindings ((di:todo-regexp "Due: ")) | ||
| 340 | :type 'symbol | ||
| 341 | :source vtodo | ||
| 342 | :tests (should (eq parsed 'ical:vtodo))) | ||
| 343 | |||
| 344 | (defun dit:parse-vevent-transparency () | ||
| 345 | "Call `di:parse-transparency' with \\='icalendar-vevent" | ||
| 346 | (di:parse-transparency 'ical:vevent)) | ||
| 347 | |||
| 348 | (dit:parse-test | ||
| 349 | "&%%(diary-anniversary 7 28 1985) A transparent anniversary" | ||
| 350 | :parser dit:parse-vevent-transparency | ||
| 351 | :type 'ical:transp | ||
| 352 | :number 1 | ||
| 353 | :source nonmarking | ||
| 354 | :tests | ||
| 355 | (ical:with-property (car parsed) nil | ||
| 356 | (should (equal value "TRANSPARENT")))) | ||
| 357 | |||
| 358 | (dit:parse-test | ||
| 359 | "2025-04-01 Team Meeting | ||
| 360 | Some data | ||
| 361 | Organizer: Mr. Foo <foo@example.com> | ||
| 362 | Attendees: Baz Bar <baz@example.com> | ||
| 363 | Alice Unternehmer <alice@example.com> (some other data) | ||
| 364 | Other data" | ||
| 365 | :parser di:parse-attendees-and-organizer | ||
| 366 | :number 3 | ||
| 367 | :type '(or ical:attendee ical:organizer) | ||
| 368 | :tests | ||
| 369 | (dolist (p parsed) | ||
| 370 | (ical:with-property p | ||
| 371 | ((ical:cnparam :value name)) | ||
| 372 | (cond ((equal value "mailto:foo@example.com") | ||
| 373 | (should (equal name "Mr. Foo")) | ||
| 374 | (should (ical:organizer-property-p p))) | ||
| 375 | ((equal value "mailto:baz@example.com") | ||
| 376 | (should (equal name "Baz Bar")) | ||
| 377 | (should (ical:attendee-property-p p))) | ||
| 378 | ((equal value "mailto:alice@example.com") | ||
| 379 | (should (equal name "Alice Unternehmer")) | ||
| 380 | (should (ical:attendee-property-p p))) | ||
| 381 | (t (error "Incorrectly parsed attendee address: %s" value)))))) | ||
| 382 | |||
| 383 | (dit:parse-test | ||
| 384 | "2025-04-01 An event with a UID | ||
| 385 | Some data | ||
| 386 | UID: emacs174560213714413195191 | ||
| 387 | Other data" | ||
| 388 | :parser di:parse-uid | ||
| 389 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 390 | :type 'ical:uid | ||
| 391 | :tests | ||
| 392 | (ical:with-property (car parsed) nil | ||
| 393 | (should (equal "emacs174560213714413195191" value)))) | ||
| 394 | |||
| 395 | (dit:parse-test | ||
| 396 | "2025-04-01 An event with a different style of UID | ||
| 397 | Some data | ||
| 398 | UID: 197846d7-51be-4d8e-837f-7e132286e7cf | ||
| 399 | Other data" | ||
| 400 | :parser di:parse-uid | ||
| 401 | :source with-org-id-uuid | ||
| 402 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 403 | :type 'ical:uid | ||
| 404 | :tests | ||
| 405 | (ical:with-property (car parsed) nil | ||
| 406 | (should (equal "197846d7-51be-4d8e-837f-7e132286e7cf" value)))) | ||
| 407 | |||
| 408 | (dit:parse-test | ||
| 409 | "2025-04-01 An event with a status | ||
| 410 | Some data | ||
| 411 | Status: confirmed | ||
| 412 | Other data" | ||
| 413 | :parser di:parse-status | ||
| 414 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 415 | :type 'ical:status | ||
| 416 | :tests | ||
| 417 | (ical:with-property (car parsed) nil | ||
| 418 | (should (equal "CONFIRMED" value)))) | ||
| 419 | |||
| 420 | (dit:parse-test | ||
| 421 | "2025-04-01 An event with an access classification | ||
| 422 | Some data | ||
| 423 | Class: private | ||
| 424 | Other data" | ||
| 425 | :parser di:parse-class | ||
| 426 | :source private | ||
| 427 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 428 | :type 'ical:class | ||
| 429 | :tests | ||
| 430 | (ical:with-property (car parsed) nil | ||
| 431 | (should (equal "PRIVATE" value)))) | ||
| 432 | |||
| 433 | (dit:parse-test | ||
| 434 | "2025-04-01 An event with an access classification | ||
| 435 | Some data | ||
| 436 | Access: public | ||
| 437 | Other data" | ||
| 438 | :parser di:parse-class | ||
| 439 | :source public | ||
| 440 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 441 | :type 'ical:class | ||
| 442 | :tests | ||
| 443 | (ical:with-property (car parsed) nil | ||
| 444 | (should (equal "PUBLIC" value)))) | ||
| 445 | |||
| 446 | (dit:parse-test | ||
| 447 | "2025-04-01 An event with a location | ||
| 448 | Some data | ||
| 449 | Location: Sesamstraße 13 | ||
| 450 | Other data" | ||
| 451 | :parser di:parse-location | ||
| 452 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 453 | :type 'ical:location | ||
| 454 | :tests | ||
| 455 | (ical:with-property (car parsed) nil | ||
| 456 | (should (equal "Sesamstraße 13" value)))) | ||
| 457 | |||
| 458 | (dit:parse-test | ||
| 459 | "2025-04-01 An event with an URL | ||
| 460 | Some data | ||
| 461 | URL: http://example.com/foo/bar?q=baz | ||
| 462 | Other data" | ||
| 463 | :parser di:parse-url | ||
| 464 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 465 | :type 'ical:url | ||
| 466 | :tests | ||
| 467 | (ical:with-property (car parsed) nil | ||
| 468 | (should (equal "http://example.com/foo/bar?q=baz" value)))) | ||
| 469 | |||
| 470 | |||
| 471 | ;; N.B. There is no date at the start of the entry in the following two | ||
| 472 | ;; tests because di:parse-summary-and-description assumes that the date | ||
| 473 | ;; parsing functions have already moved the start of the restriction | ||
| 474 | ;; beyond it. | ||
| 475 | (dit:parse-test | ||
| 476 | "Event summary | ||
| 477 | Some data | ||
| 478 | Other data" | ||
| 479 | :parser di:parse-summary-and-description | ||
| 480 | :number 2 | ||
| 481 | :type '(or ical:summary ical:description) | ||
| 482 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 483 | :tests | ||
| 484 | (ical:with-property (car parsed) nil (should (equal "Event summary" value)))) | ||
| 485 | |||
| 486 | (dit:parse-test | ||
| 487 | "Some data | ||
| 488 | Summary: Event summary | ||
| 489 | Other data" | ||
| 490 | :parser di:parse-summary-and-description | ||
| 491 | :number 2 | ||
| 492 | :bindings ((di:summary-regexp "^[[:space:]]+Summary: \\(.*\\)$")) | ||
| 493 | :type '(or ical:summary ical:description) | ||
| 494 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 495 | :source with-summary-regexp | ||
| 496 | :tests | ||
| 497 | (ical:with-property (car parsed) nil (should (equal "Event summary" value)))) | ||
| 498 | |||
| 499 | (dit:parse-test | ||
| 500 | "2025/04/01 Some entry" | ||
| 501 | :parser di:parse-date-form | ||
| 502 | :type 'ical:date | ||
| 503 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 504 | :source iso-date | ||
| 505 | :tests | ||
| 506 | (progn | ||
| 507 | (should (= 2025 (calendar-extract-year parsed))) | ||
| 508 | (should (= 4 (calendar-extract-month parsed))) | ||
| 509 | (should (= 1 (calendar-extract-day parsed))))) | ||
| 510 | |||
| 511 | (dit:parse-test | ||
| 512 | "2025-04-01 Some entry" | ||
| 513 | :parser di:parse-date-form | ||
| 514 | :type 'ical:date | ||
| 515 | :bindings ((diary-date-forms diary-iso-date-forms)) | ||
| 516 | :source iso-date-dashes | ||
| 517 | :tests | ||
| 518 | (progn | ||
| 519 | (should (= 2025 (calendar-extract-year parsed))) | ||
| 520 | (should (= 4 (calendar-extract-month parsed))) | ||
| 521 | (should (= 1 (calendar-extract-day parsed))))) | ||
| 522 | |||
| 523 | (dit:parse-test | ||
| 524 | "1/4/2025 Some entry" | ||
| 525 | :parser di:parse-date-form | ||
| 526 | :type 'ical:date | ||
| 527 | :bindings ((diary-date-forms diary-european-date-forms)) | ||
| 528 | :source european-date | ||
| 529 | :tests | ||
| 530 | (progn | ||
| 531 | (should (= 2025 (calendar-extract-year parsed))) | ||
| 532 | (should (= 4 (calendar-extract-month parsed))) | ||
| 533 | (should (= 1 (calendar-extract-day parsed))))) | ||
| 534 | |||
| 535 | (dit:parse-test | ||
| 536 | "4/1/2025 Some entry" | ||
| 537 | :parser di:parse-date-form | ||
| 538 | :type 'ical:date | ||
| 539 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 540 | :source american-date | ||
| 541 | :tests | ||
| 542 | (progn | ||
| 543 | (should (= 2025 (calendar-extract-year parsed))) | ||
| 544 | (should (= 4 (calendar-extract-month parsed))) | ||
| 545 | (should (= 1 (calendar-extract-day parsed))))) | ||
| 546 | |||
| 547 | (dit:parse-test | ||
| 548 | "4/1 April Fool's" | ||
| 549 | :parser di:parse-date-form | ||
| 550 | :type 'list | ||
| 551 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 552 | :source generic-year-american | ||
| 553 | :tests | ||
| 554 | (progn | ||
| 555 | (should (eq t (calendar-extract-year parsed))) | ||
| 556 | (should (= 4 (calendar-extract-month parsed))) | ||
| 557 | (should (= 1 (calendar-extract-day parsed))))) | ||
| 558 | |||
| 559 | (dit:parse-test | ||
| 560 | "1/5 Tag der Arbeit" | ||
| 561 | :parser di:parse-date-form | ||
| 562 | :type 'list | ||
| 563 | :bindings ((diary-date-forms diary-european-date-forms)) | ||
| 564 | :source generic-year-european | ||
| 565 | :tests | ||
| 566 | (progn | ||
| 567 | (should (eq t (calendar-extract-year parsed))) | ||
| 568 | (should (= 5 (calendar-extract-month parsed))) | ||
| 569 | (should (= 1 (calendar-extract-day parsed))))) | ||
| 570 | |||
| 571 | (dit:parse-test | ||
| 572 | "1/*/2025 Rent due" | ||
| 573 | :parser di:parse-date-form | ||
| 574 | :type 'list | ||
| 575 | :bindings ((diary-date-forms diary-european-date-forms)) | ||
| 576 | :source generic-month | ||
| 577 | :tests | ||
| 578 | (progn | ||
| 579 | (should (= 2025 (calendar-extract-year parsed))) | ||
| 580 | (should (eq t (calendar-extract-month parsed))) | ||
| 581 | (should (= 1 (calendar-extract-day parsed))))) | ||
| 582 | |||
| 583 | (dit:parse-test | ||
| 584 | "*/2/2025 Every day in February: go running" | ||
| 585 | :parser di:parse-date-form | ||
| 586 | :type 'list | ||
| 587 | :bindings ((diary-date-forms diary-european-date-forms)) | ||
| 588 | :source generic-day | ||
| 589 | :tests | ||
| 590 | (progn | ||
| 591 | (should (= 2025 (calendar-extract-year parsed))) | ||
| 592 | (should (= 2 (calendar-extract-month parsed))) | ||
| 593 | (should (eq t (calendar-extract-day parsed))))) | ||
| 594 | |||
| 595 | (dit:parse-test | ||
| 596 | "Friday | ||
| 597 | Lab meeting | ||
| 598 | Backup data" | ||
| 599 | :parser di:parse-weekday-name | ||
| 600 | :type 'integer | ||
| 601 | :tests | ||
| 602 | (should (= 5 parsed))) | ||
| 603 | |||
| 604 | ;;; Examples from the Emacs manual: | ||
| 605 | (dit:parse-test | ||
| 606 | "12/22/2015 Twentieth wedding anniversary!" | ||
| 607 | :parser di:parse-date-form | ||
| 608 | :type 'ical:date | ||
| 609 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 610 | :source emacs-manual-sec33.10.1/1 | ||
| 611 | :tests | ||
| 612 | (progn | ||
| 613 | (should (= 2015 (calendar-extract-year parsed))) | ||
| 614 | (should (= 12 (calendar-extract-month parsed))) | ||
| 615 | (should (= 22 (calendar-extract-day parsed))))) | ||
| 616 | |||
| 617 | (dit:parse-test | ||
| 618 | ;; Generic date via unspecified year: | ||
| 619 | "10/22 Ruth's birthday." | ||
| 620 | :parser di:parse-date-form | ||
| 621 | :type 'list | ||
| 622 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 623 | :source emacs-manual-sec33.10.1/2 | ||
| 624 | :tests | ||
| 625 | (progn | ||
| 626 | (should (eq t (calendar-extract-year parsed))) | ||
| 627 | (should (= 10 (calendar-extract-month parsed))) | ||
| 628 | (should (= 22 (calendar-extract-day parsed))))) | ||
| 629 | |||
| 630 | (dit:parse-test | ||
| 631 | ;; Generic date via unspecified year: | ||
| 632 | "4/30 Results for April are due" | ||
| 633 | :parser di:parse-date-form | ||
| 634 | :type 'list | ||
| 635 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 636 | :source emacs-manual-sec33.10.3/3 | ||
| 637 | :tests | ||
| 638 | (progn | ||
| 639 | (should (eq t (calendar-extract-year parsed))) | ||
| 640 | (should (= 4 (calendar-extract-month parsed))) | ||
| 641 | (should (= 30 (calendar-extract-day parsed))))) | ||
| 642 | |||
| 643 | (dit:parse-test | ||
| 644 | ;; Generic date with asterisks: | ||
| 645 | "* 21, *: Payday" | ||
| 646 | :parser di:parse-date-form | ||
| 647 | :type 'list | ||
| 648 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 649 | :source emacs-manual-sec33.10.1/3 | ||
| 650 | :tests | ||
| 651 | (progn | ||
| 652 | (should (eq t (calendar-extract-year parsed))) | ||
| 653 | (should (eq t (calendar-extract-month parsed))) | ||
| 654 | (should (= 21 (calendar-extract-day parsed))))) | ||
| 655 | |||
| 656 | (dit:parse-test | ||
| 657 | ;; Generic date with asterisks: | ||
| 658 | "*/25 Monthly cycle finishes" | ||
| 659 | :parser di:parse-date-form | ||
| 660 | :type 'list | ||
| 661 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 662 | :source emacs-manual-sec33.10.3/4 | ||
| 663 | :tests | ||
| 664 | (progn | ||
| 665 | (should (eq t (calendar-extract-year parsed))) | ||
| 666 | (should (eq t (calendar-extract-month parsed))) | ||
| 667 | (should (= 25 (calendar-extract-day parsed))))) | ||
| 668 | |||
| 669 | (dit:parse-test | ||
| 670 | ;; Weekday name: | ||
| 671 | "Tuesday--weekly meeting with grad students at 10am | ||
| 672 | Supowit, Shen, Bitner, and Kapoor to attend." | ||
| 673 | :parser di:parse-weekday-name | ||
| 674 | :type 'integer | ||
| 675 | :source emacs-manual-sec33.10.1/4 | ||
| 676 | :tests | ||
| 677 | (should (= 2 parsed))) | ||
| 678 | |||
| 679 | (dit:parse-test | ||
| 680 | ;; Weekday name: | ||
| 681 | "Friday Don't leave without backing up files" | ||
| 682 | :parser di:parse-weekday-name | ||
| 683 | :type 'integer | ||
| 684 | :source emacs-manual-sec33.10.3/5 | ||
| 685 | :tests | ||
| 686 | (should (= 5 parsed))) | ||
| 687 | |||
| 688 | (dit:parse-test | ||
| 689 | ;; Date with two-digit year: | ||
| 690 | "1/13/89 Friday the thirteenth!!" | ||
| 691 | :parser di:parse-date-form | ||
| 692 | :type 'list | ||
| 693 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 694 | :source emacs-manual-sec33.10.1/5 | ||
| 695 | :tests | ||
| 696 | (progn | ||
| 697 | (should (= 1989 (calendar-extract-year parsed))) | ||
| 698 | (should (= 1 (calendar-extract-month parsed))) | ||
| 699 | (should (= 13 (calendar-extract-day parsed))))) | ||
| 700 | |||
| 701 | (dit:parse-test | ||
| 702 | ;; Date with two-digit year: | ||
| 703 | "4/20/12 Switch-over to new tabulation system" | ||
| 704 | :parser di:parse-date-form | ||
| 705 | :type 'list | ||
| 706 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 707 | :source emacs-manual-sec33.10.3/1 | ||
| 708 | :tests | ||
| 709 | (progn | ||
| 710 | (should (= 2012 (calendar-extract-year parsed))) | ||
| 711 | (should (= 4 (calendar-extract-month parsed))) | ||
| 712 | (should (= 20 (calendar-extract-day parsed))))) | ||
| 713 | |||
| 714 | (dit:parse-test | ||
| 715 | ;; Abbreviated weekday name: | ||
| 716 | "thu 4pm squash game with Lloyd." | ||
| 717 | :parser di:parse-weekday-name | ||
| 718 | :type 'integer | ||
| 719 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 720 | :source emacs-manual-sec33.10.1/6 | ||
| 721 | :tests | ||
| 722 | (should (= 4 parsed))) | ||
| 723 | |||
| 724 | (dit:parse-test | ||
| 725 | ;; Abbreviated month name: | ||
| 726 | "mar 16 Dad's birthday" | ||
| 727 | :parser di:parse-date-form | ||
| 728 | :type 'list | ||
| 729 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 730 | :source emacs-manual-sec33.10.1/7 | ||
| 731 | :tests | ||
| 732 | (progn | ||
| 733 | (should (eq t (calendar-extract-year parsed))) | ||
| 734 | (should (= 3 (calendar-extract-month parsed))) | ||
| 735 | (should (= 16 (calendar-extract-day parsed))))) | ||
| 736 | |||
| 737 | (dit:parse-test | ||
| 738 | ;; Abbreviated month name with following period: | ||
| 739 | "apr. 25 Start tabulating annual results" | ||
| 740 | :parser di:parse-date-form | ||
| 741 | :type 'list | ||
| 742 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 743 | :source emacs-manual-sec33.10.3/2 | ||
| 744 | :tests | ||
| 745 | (progn | ||
| 746 | (should (eq t (calendar-extract-year parsed))) | ||
| 747 | (should (= 4 (calendar-extract-month parsed))) | ||
| 748 | (should (= 25 (calendar-extract-day parsed))))) | ||
| 749 | |||
| 750 | (dit:parse-test | ||
| 751 | ;; Long form date: | ||
| 752 | "April 15, 2016 Income tax due." | ||
| 753 | :parser di:parse-date-form | ||
| 754 | :type 'ical:date | ||
| 755 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 756 | :source emacs-manual-sec33.10.1/8 | ||
| 757 | :tests | ||
| 758 | (progn | ||
| 759 | (should (= 2016 (calendar-extract-year parsed))) | ||
| 760 | (should (= 4 (calendar-extract-month parsed))) | ||
| 761 | (should (= 15 (calendar-extract-day parsed))))) | ||
| 762 | |||
| 763 | (dit:parse-test | ||
| 764 | ;; Generic monthly date: | ||
| 765 | "* 15 time cards due." | ||
| 766 | :parser di:parse-date-form | ||
| 767 | :type 'list | ||
| 768 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 769 | :source emacs-manual-sec33.10.1/9 | ||
| 770 | :tests | ||
| 771 | (progn | ||
| 772 | (should (eq t (calendar-extract-year parsed))) | ||
| 773 | (should (eq t (calendar-extract-month parsed))) | ||
| 774 | (should (= 15 (calendar-extract-day parsed))))) | ||
| 775 | |||
| 776 | (dit:parse-test | ||
| 777 | "%%(diary-anniversary 5 28 1995) A birthday" | ||
| 778 | :parser di:parse-sexp | ||
| 779 | :type 'list | ||
| 780 | :tests (should (eq 'diary-anniversary (car parsed)))) | ||
| 781 | |||
| 782 | (dit:parse-test | ||
| 783 | "%%(diary-time-block :start (0 0 13 2 4 2025 6 t 7200) | ||
| 784 | :end (0 0 11 4 4 2025 6 t 7200)) | ||
| 785 | A multiday event with different start and end times" | ||
| 786 | :parser di:parse-sexp | ||
| 787 | :type 'list | ||
| 788 | :source multiline-sexp | ||
| 789 | :tests (should (eq 'diary-time-block (car parsed)))) | ||
| 790 | |||
| 791 | (defun dit:entry-parser () | ||
| 792 | "Call `di:parse-entry' on the full test buffer" | ||
| 793 | (let ((tz | ||
| 794 | (cond | ||
| 795 | ((eq 'local di:time-zone-export-strategy) | ||
| 796 | (di:current-tz-to-vtimezone)) | ||
| 797 | ((listp di:time-zone-export-strategy) | ||
| 798 | (di:current-tz-to-vtimezone di:time-zone-export-strategy))))) | ||
| 799 | |||
| 800 | (di:parse-entry (point-min) (point-max) tz))) | ||
| 801 | |||
| 802 | (dit:parse-test | ||
| 803 | ;; Weekly event, abbreviated weekday name: | ||
| 804 | "thu 4pm squash game with Lloyd." | ||
| 805 | :parser dit:entry-parser | ||
| 806 | :type 'ical:vevent | ||
| 807 | :number 1 | ||
| 808 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 809 | :source emacs-manual-sec33.10.1/6 | ||
| 810 | :tests | ||
| 811 | (ical:with-component (car parsed) | ||
| 812 | ((ical:dtstart :value dtstart) | ||
| 813 | (ical:rrule :value rrule) | ||
| 814 | (ical:summary :value summary)) | ||
| 815 | (should (equal summary "squash game with Lloyd.")) | ||
| 816 | (should (equal (ical:date-time-to-date dtstart) | ||
| 817 | (calendar-nth-named-day 1 4 1 di:recurring-start-year))) | ||
| 818 | (should (= 16 (decoded-time-hour dtstart))) | ||
| 819 | (should (eq (ical:recur-freq rrule) 'WEEKLY)) | ||
| 820 | (should (equal (ical:recur-by* 'BYDAY rrule) (list 4))))) | ||
| 821 | |||
| 822 | (dit:parse-test | ||
| 823 | ;; Multiline entry, parsed as one event: | ||
| 824 | "2025-05-03 | ||
| 825 | 9AM Lab meeting | ||
| 826 | Gunther to present on new assay | ||
| 827 | 12:30-1:30PM Lunch with Phil | ||
| 828 | 16:00 Experiment A finishes; move to freezer" | ||
| 829 | :parser dit:entry-parser | ||
| 830 | :source multiline-single | ||
| 831 | :type 'ical:vevent | ||
| 832 | :number 1 | ||
| 833 | :bindings ((diary-date-forms diary-iso-date-forms))) | ||
| 834 | |||
| 835 | (dit:parse-test | ||
| 836 | ;; Multiline entry, parsed linewise as three events: | ||
| 837 | "2025-05-03 | ||
| 838 | 9AM Lab meeting | ||
| 839 | Gunther to present on new assay | ||
| 840 | 12:30-1:30PM Lunch with Phil | ||
| 841 | 16:00 Experiment A finishes; move to freezer" | ||
| 842 | :parser dit:entry-parser | ||
| 843 | :source multiline-linewise | ||
| 844 | :type 'ical:vevent | ||
| 845 | :number 3 | ||
| 846 | :bindings ((diary-date-forms diary-iso-date-forms) | ||
| 847 | (diary-icalendar-export-linewise t)) | ||
| 848 | :tests | ||
| 849 | (progn | ||
| 850 | (dolist (event parsed) | ||
| 851 | (ical:with-component event | ||
| 852 | ((ical:dtstart :value-type start-type :value dtstart) | ||
| 853 | (ical:dtend :value-type end-type :value dtend) | ||
| 854 | (ical:summary :value summary)) | ||
| 855 | (should (eq start-type 'ical:date-time)) | ||
| 856 | (should (= 2025 (decoded-time-year dtstart))) | ||
| 857 | (should (= 5 (decoded-time-month dtstart))) | ||
| 858 | (should (= 3 (decoded-time-day dtstart))) | ||
| 859 | (when dtend | ||
| 860 | (should (eq end-type 'ical:date-time)) | ||
| 861 | (should (= 2025 (decoded-time-year dtend))) | ||
| 862 | (should (= 5 (decoded-time-month dtend))) | ||
| 863 | (should (= 3 (decoded-time-day dtend)))) | ||
| 864 | (cond ((equal summary "Lab meeting") | ||
| 865 | (should (= 9 (decoded-time-hour dtstart)))) | ||
| 866 | ((equal summary "Lunch with Phil") | ||
| 867 | (should (= 12 (decoded-time-hour dtstart))) | ||
| 868 | (should (= 30 (decoded-time-minute dtstart))) | ||
| 869 | (should (= 13 (decoded-time-hour dtend))) | ||
| 870 | (should (= 30 (decoded-time-minute dtend)))) | ||
| 871 | ((equal summary "Experiment A finishes; move to freezer") | ||
| 872 | (should (= 16 (decoded-time-hour dtstart)))) | ||
| 873 | (t (error "Unknown event: %s" summary))))))) | ||
| 874 | |||
| 875 | (dit:parse-test | ||
| 876 | ;; Multiline entry from the manual, parsed linewise: | ||
| 877 | ;; TODO: I've left the times verbatim in the example | ||
| 878 | ;; and in the tests, even though "2:30", "5:30" and "8:00" | ||
| 879 | ;; would most naturally be understood as PM times. | ||
| 880 | ;; Should probably fix the manual, then revise here. | ||
| 881 | "02/11/2012 | ||
| 882 | Bill B. visits Princeton today | ||
| 883 | 2pm Cognitive Studies Committee meeting | ||
| 884 | 2:30-5:30 Liz at Lawrenceville | ||
| 885 | 4:00pm Dentist appt | ||
| 886 | 7:30pm Dinner at George's | ||
| 887 | 8:00-10:00pm concert" | ||
| 888 | :parser dit:entry-parser | ||
| 889 | :type 'ical:vevent | ||
| 890 | :number 6 | ||
| 891 | :bindings ((diary-date-forms diary-american-date-forms) | ||
| 892 | (diary-icalendar-export-linewise t)) | ||
| 893 | :source emacs-manual-sec33.10.1/10 | ||
| 894 | :tests | ||
| 895 | (progn | ||
| 896 | (dolist (event parsed) | ||
| 897 | (ical:with-component event | ||
| 898 | ((ical:dtstart :value-type start-type :value dtstart) | ||
| 899 | (ical:dtend :value-type end-type :value dtend) | ||
| 900 | (ical:summary :value summary)) | ||
| 901 | (when (eq start-type 'ical:date) | ||
| 902 | (should (= 2012 (calendar-extract-year dtstart))) | ||
| 903 | (should (= 2 (calendar-extract-month dtstart))) | ||
| 904 | (should (= 11 (calendar-extract-day dtstart)))) | ||
| 905 | (when (eq start-type 'ical:date-time) | ||
| 906 | (should (= 2012 (decoded-time-year dtstart))) | ||
| 907 | (should (= 2 (decoded-time-month dtstart))) | ||
| 908 | (should (= 11 (decoded-time-day dtstart)))) | ||
| 909 | (when dtend | ||
| 910 | (should (eq end-type 'ical:date-time)) | ||
| 911 | (should (= 2012 (decoded-time-year dtend))) | ||
| 912 | (should (= 2 (decoded-time-month dtend))) | ||
| 913 | (should (= 11 (decoded-time-day dtend)))) | ||
| 914 | (cond ((equal summary "Bill B. visits Princeton today") | ||
| 915 | (should (eq start-type 'ical:date))) | ||
| 916 | ((equal summary "Cognitive Studies Committee meeting") | ||
| 917 | (should (= 14 (decoded-time-hour dtstart))) | ||
| 918 | (should (= 0 (decoded-time-minute dtstart)))) | ||
| 919 | ((equal summary "Liz at Lawrenceville") | ||
| 920 | (should (= 2 (decoded-time-hour dtstart))) | ||
| 921 | (should (= 30 (decoded-time-minute dtstart))) | ||
| 922 | (should (= 5 (decoded-time-hour dtend))) | ||
| 923 | (should (= 30 (decoded-time-minute dtend)))) | ||
| 924 | ((equal summary "Dentist appt") | ||
| 925 | (should (= 16 (decoded-time-hour dtstart))) | ||
| 926 | (should (= 0 (decoded-time-minute dtstart)))) | ||
| 927 | ((equal summary "Dinner at George's") | ||
| 928 | (should (= 19 (decoded-time-hour dtstart))) | ||
| 929 | (should (= 30 (decoded-time-minute dtstart)))) | ||
| 930 | ((equal summary "concert") | ||
| 931 | (should (= 8 (decoded-time-hour dtstart))) | ||
| 932 | (should (= 0 (decoded-time-minute dtstart))) | ||
| 933 | (should (= 22 (decoded-time-hour dtend))) | ||
| 934 | (should (= 0 (decoded-time-minute dtend)))) | ||
| 935 | (t (error "Unknown event: %s" summary))))))) | ||
| 936 | |||
| 937 | (dit:parse-test | ||
| 938 | ;; Same as the last, but with ignored data on the same line as the date | ||
| 939 | "02/11/2012 Ignored | ||
| 940 | 2pm Cognitive Studies Committee meeting | ||
| 941 | 2:30-5:30 Liz at Lawrenceville | ||
| 942 | 4:00pm Dentist appt | ||
| 943 | 7:30pm Dinner at George's | ||
| 944 | 8:00-10:00pm concert" | ||
| 945 | :parser dit:entry-parser | ||
| 946 | :type 'ical:vevent | ||
| 947 | :number 5 | ||
| 948 | :bindings ((diary-date-forms diary-american-date-forms) | ||
| 949 | (diary-icalendar-export-linewise t)) | ||
| 950 | :source emacs-manual-sec33.10.1/10-first-line) | ||
| 951 | |||
| 952 | (dit:parse-test | ||
| 953 | "%%(diary-anniversary 5 28 1995) H's birthday" | ||
| 954 | :parser dit:entry-parser | ||
| 955 | :type 'ical:vevent | ||
| 956 | :number 1 | ||
| 957 | :bindings ((diary-date-forms diary-american-date-forms) | ||
| 958 | (calendar-date-style 'american)) | ||
| 959 | :source diary-anniversary-recurrence | ||
| 960 | :tests | ||
| 961 | (ical:with-component (car parsed) | ||
| 962 | ((ical:dtstart :value dtstart) | ||
| 963 | (ical:rrule :value recur-value) | ||
| 964 | (ical:summary :value summary)) | ||
| 965 | (should (equal dtstart '(5 28 1995))) | ||
| 966 | (should (eq (ical:recur-freq recur-value) 'YEARLY)) | ||
| 967 | (should (equal summary "H's birthday")))) | ||
| 968 | |||
| 969 | (dit:parse-test | ||
| 970 | "%%(diary-block 6 24 2012 7 10 2012) Vacation" | ||
| 971 | :parser dit:entry-parser | ||
| 972 | :type 'ical:vevent | ||
| 973 | :number 1 | ||
| 974 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 975 | :source diary-block-recurrence | ||
| 976 | :tests | ||
| 977 | (ical:with-component (car parsed) | ||
| 978 | ((ical:dtstart :value dtstart) | ||
| 979 | (ical:rrule :value recur-value) | ||
| 980 | (ical:summary :value summary)) | ||
| 981 | (should (equal dtstart '(6 24 2012))) | ||
| 982 | (should (equal (ical:recur-freq recur-value) 'DAILY)) | ||
| 983 | (should (equal (ical:recur-until recur-value) '(7 10 2012))) | ||
| 984 | (should (equal summary "Vacation")))) | ||
| 985 | |||
| 986 | (dit:parse-test | ||
| 987 | "%%(diary-cyclic 50 3 1 2012) Renew medication" | ||
| 988 | :parser dit:entry-parser | ||
| 989 | :type 'ical:vevent | ||
| 990 | :number 1 | ||
| 991 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 992 | :source diary-cyclic-recurrence | ||
| 993 | :tests | ||
| 994 | (ical:with-component (car parsed) | ||
| 995 | ((ical:dtstart :value dtstart) | ||
| 996 | (ical:rrule :value recur-value) | ||
| 997 | (ical:summary :value summary)) | ||
| 998 | (should (equal dtstart '(3 1 2012))) | ||
| 999 | (should (eq (ical:recur-freq recur-value) 'DAILY)) | ||
| 1000 | (should (eq (ical:recur-interval-size recur-value) 50)) | ||
| 1001 | (should (equal summary "Renew medication")))) | ||
| 1002 | |||
| 1003 | (dit:parse-test | ||
| 1004 | "%%(diary-float 11 4 4) American Thanksgiving" | ||
| 1005 | :parser dit:entry-parser | ||
| 1006 | :type 'ical:vevent | ||
| 1007 | :number 1 | ||
| 1008 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 1009 | :source diary-float-recurrence | ||
| 1010 | :tests | ||
| 1011 | (ical:with-component (car parsed) | ||
| 1012 | ((ical:dtstart :value dtstart) | ||
| 1013 | (ical:rrule :value recur-value) | ||
| 1014 | (ical:summary :value summary)) | ||
| 1015 | (should (equal dtstart | ||
| 1016 | (calendar-nth-named-day 4 4 11 di:recurring-start-year))) | ||
| 1017 | (should (eq (ical:recur-freq recur-value) 'MONTHLY)) | ||
| 1018 | (should (equal (ical:recur-by* 'BYMONTH recur-value) (list 11))) | ||
| 1019 | (should (equal (ical:recur-by* 'BYDAY recur-value) (list '(4 . 4)))) | ||
| 1020 | (should (equal summary "American Thanksgiving")))) | ||
| 1021 | |||
| 1022 | (dit:parse-test | ||
| 1023 | "%%(diary-offset '(diary-float t 3 4) 2) Monthly committee meeting" | ||
| 1024 | :parser dit:entry-parser | ||
| 1025 | :type 'ical:vevent | ||
| 1026 | :number 1 | ||
| 1027 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 1028 | :source diary-offset-recurrence | ||
| 1029 | :tests | ||
| 1030 | (ical:with-component (car parsed) | ||
| 1031 | ((ical:dtstart :value dtstart) | ||
| 1032 | (ical:rrule :value recur-value) | ||
| 1033 | (ical:summary :value summary)) | ||
| 1034 | (should (equal dtstart | ||
| 1035 | (calendar-nth-named-day 4 5 1 di:recurring-start-year))) | ||
| 1036 | (should (eq (ical:recur-freq recur-value) 'MONTHLY)) | ||
| 1037 | ;; day 3 is Wednesday, so offset of 2 means Friday (=5): | ||
| 1038 | (should (equal (ical:recur-by* 'BYDAY recur-value) (list '(5 . 4)))) | ||
| 1039 | (should (equal summary "Monthly committee meeting")))) | ||
| 1040 | |||
| 1041 | (dit:parse-test | ||
| 1042 | "%%(diary-rrule :start '(11 11 2024) | ||
| 1043 | :rule '((FREQ WEEKLY)) | ||
| 1044 | :exclude '((12 23 2024) (12 30 2024)) | ||
| 1045 | ) Reading group" | ||
| 1046 | :parser dit:entry-parser | ||
| 1047 | :type 'ical:vevent | ||
| 1048 | :number 1 | ||
| 1049 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 1050 | :source diary-rrule-recurrence | ||
| 1051 | :tests | ||
| 1052 | (ical:with-component (car parsed) | ||
| 1053 | ((ical:dtstart :value dtstart) | ||
| 1054 | (ical:rrule :value recur-value) | ||
| 1055 | (ical:exdate :values exdates) | ||
| 1056 | (ical:summary :value summary)) | ||
| 1057 | (should (equal dtstart '(11 11 2024))) | ||
| 1058 | (should (eq (ical:recur-freq recur-value) 'WEEKLY)) | ||
| 1059 | (should (equal exdates '((12 23 2024) (12 30 2024)))) | ||
| 1060 | (should (equal summary "Reading group")))) | ||
| 1061 | |||
| 1062 | (dit:parse-test | ||
| 1063 | "%%(diary-date '(10 11 12) 22 t) Rake leaves" | ||
| 1064 | :parser dit:entry-parser | ||
| 1065 | :type 'ical:vevent | ||
| 1066 | :number 1 | ||
| 1067 | :bindings ((diary-date-forms diary-american-date-forms)) | ||
| 1068 | :source diary-date-recurrence | ||
| 1069 | :tests | ||
| 1070 | (ical:with-component (car parsed) | ||
| 1071 | ((ical:dtstart :value dtstart) | ||
| 1072 | (ical:rrule :value recur-value) | ||
| 1073 | (ical:summary :value summary)) | ||
| 1074 | (should (equal dtstart (list 10 22 di:recurring-start-year))) | ||
| 1075 | (should (eq (ical:recur-freq recur-value) 'YEARLY)) | ||
| 1076 | (should (equal (ical:recur-by* 'BYMONTH recur-value) (list 10 11 12))) | ||
| 1077 | (should (equal (ical:recur-by* 'BYMONTHDAY recur-value) (list 22))) | ||
| 1078 | (should (equal summary "Rake leaves")))) | ||
| 1079 | |||
| 1080 | (dit:parse-test | ||
| 1081 | ;; From the manual: "Suppose you get paid on the 21st of the month if | ||
| 1082 | ;; it is a weekday, and on the Friday before if the 21st is on a | ||
| 1083 | ;; weekend..." | ||
| 1084 | "%%(let ((dayname (calendar-day-of-week date)) | ||
| 1085 | (day (cadr date))) | ||
| 1086 | (or (and (= day 21) (memq dayname '(1 2 3 4 5))) | ||
| 1087 | (and (memq day '(19 20)) (= dayname 5))) | ||
| 1088 | ) Pay check deposited" | ||
| 1089 | :parser dit:entry-parser | ||
| 1090 | :type 'ical:vevent | ||
| 1091 | :number 1 | ||
| 1092 | :bindings ((diary-date-forms diary-american-date-forms) | ||
| 1093 | (di:export-sexp-enumeration-days 366)) | ||
| 1094 | :source emacs-manual-sec33.13.10.7 | ||
| 1095 | :tests | ||
| 1096 | (ical:with-component (car parsed) | ||
| 1097 | ((ical:dtstart :value dtstart) | ||
| 1098 | (ical:rdate :values rdates) | ||
| 1099 | (ical:summary :value summary)) | ||
| 1100 | (should (equal summary "Pay check deposited")) | ||
| 1101 | (mapc | ||
| 1102 | (lambda (date) | ||
| 1103 | (should (or (and (= 21 (calendar-extract-day date)) | ||
| 1104 | (memq (calendar-day-of-week date) (list 1 2 3 4 5))) | ||
| 1105 | (and (memq (calendar-extract-day date) (list 19 20)) | ||
| 1106 | (= 5 (calendar-day-of-week date)))))) | ||
| 1107 | (cons dtstart rdates)))) | ||
| 1108 | |||
| 1109 | (dit:parse-test | ||
| 1110 | "02/11/2012 4:00pm Exported with 'local strategy" | ||
| 1111 | :parser dit:entry-parser | ||
| 1112 | :type 'ical:vevent | ||
| 1113 | :number 1 | ||
| 1114 | :bindings ((tz (getenv "TZ")) | ||
| 1115 | ;; Refresh output from `calendar-current-time-zone': | ||
| 1116 | (calendar-current-time-zone-cache nil) | ||
| 1117 | ;; Assume Eastern European Time (UTC+2, UTC+3 daylight saving) | ||
| 1118 | (_ (setenv "TZ" "EET-2EEST,M3.5.0/3,M10.5.0/4")) | ||
| 1119 | ;; ...and use this TZ when exporting: | ||
| 1120 | (diary-icalendar-time-zone-export-strategy 'local) | ||
| 1121 | (diary-date-forms diary-european-date-forms)) | ||
| 1122 | :source tz-strategy-local | ||
| 1123 | :tests | ||
| 1124 | (unwind-protect | ||
| 1125 | (let ((vtimezone (di:current-tz-to-vtimezone))) | ||
| 1126 | (ical:with-component vtimezone | ||
| 1127 | ((ical:standard :first std) | ||
| 1128 | (ical:daylight :first dst)) | ||
| 1129 | (should (= (* 2 60 60) (ical:with-property-of std 'ical:tzoffsetto))) | ||
| 1130 | (should (= (* 3 60 60) (ical:with-property-of dst 'ical:tzoffsetto)))) | ||
| 1131 | (ical:with-component (car parsed) | ||
| 1132 | ((ical:dtstart :first start-node :value start)) | ||
| 1133 | (should (= (* 2 60 60) (decoded-time-zone start))) | ||
| 1134 | (should (= 16 (decoded-time-hour start))) | ||
| 1135 | (should (ical:with-param-of start-node 'ical:tzidparam)))) | ||
| 1136 | ;; restore time zone | ||
| 1137 | (setenv "TZ" tz))) | ||
| 1138 | |||
| 1139 | (dit:parse-test | ||
| 1140 | "02/11/2012 4:00pm Exported with 'to-utc strategy" | ||
| 1141 | :parser dit:entry-parser | ||
| 1142 | :type 'ical:vevent | ||
| 1143 | :number 1 | ||
| 1144 | :bindings ((tz (getenv "TZ")) | ||
| 1145 | ;; Assume Eastern European Time (UTC+2, UTC+3 daylight saving) | ||
| 1146 | (_ (setenv "TZ" "EET-2EEST,M3.5.0/3,M10.5.0/4")) | ||
| 1147 | ;; ...and convert times to UTC on export: | ||
| 1148 | (diary-icalendar-time-zone-export-strategy 'to-utc) | ||
| 1149 | (diary-date-forms diary-european-date-forms)) | ||
| 1150 | :source tz-strategy-to-utc | ||
| 1151 | :tests | ||
| 1152 | (unwind-protect | ||
| 1153 | (ical:with-component (car parsed) | ||
| 1154 | ((ical:dtstart :first start-node :value start)) | ||
| 1155 | (should (= 0 (decoded-time-zone start))) | ||
| 1156 | (should (= (- 16 2) (decoded-time-hour start))) | ||
| 1157 | (should-not (ical:with-param-of start-node 'ical:tzidparam))) | ||
| 1158 | ;; restore time zone | ||
| 1159 | (setenv "TZ" tz))) | ||
| 1160 | |||
| 1161 | (dit:parse-test | ||
| 1162 | "02/11/2012 4:00pm Exported with 'floating strategy" | ||
| 1163 | :parser dit:entry-parser | ||
| 1164 | :type 'ical:vevent | ||
| 1165 | :number 1 | ||
| 1166 | :bindings ((tz (getenv "TZ")) | ||
| 1167 | ;; Assume Eastern European Time (UTC+2, UTC+3 daylight saving) | ||
| 1168 | (_ (setenv "TZ" "EET-2EEST,M3.5.0/3,M10.5.0/4")) | ||
| 1169 | ;; ...but use floating times: | ||
| 1170 | (diary-icalendar-time-zone-export-strategy 'floating) | ||
| 1171 | (diary-date-forms diary-european-date-forms)) | ||
| 1172 | :source tz-strategy-floating | ||
| 1173 | :tests | ||
| 1174 | (unwind-protect | ||
| 1175 | (ical:with-component (car parsed) | ||
| 1176 | ((ical:dtstart :first start-node :value start)) | ||
| 1177 | (should (null (decoded-time-zone start))) | ||
| 1178 | (should (= 16 (decoded-time-hour start))) | ||
| 1179 | (should-not (ical:with-param-of start-node 'ical:tzidparam))) | ||
| 1180 | |||
| 1181 | ;; restore time zone | ||
| 1182 | (setenv "TZ" tz))) | ||
| 1183 | |||
| 1184 | (dit:parse-test | ||
| 1185 | "02/11/2012 4:00pm Exported with tz info list" | ||
| 1186 | :parser dit:entry-parser | ||
| 1187 | :type 'ical:vevent | ||
| 1188 | :number 1 | ||
| 1189 | :bindings (;; Encode Eastern European Time (UTC+2, UTC+3 daylight saving) | ||
| 1190 | ;; directly in the variable: | ||
| 1191 | (diary-icalendar-time-zone-export-strategy | ||
| 1192 | '(120 60 "EET" "EEST" | ||
| 1193 | (calendar-nth-named-day -1 0 3 year) ; last Sunday of March | ||
| 1194 | (calendar-nth-named-day -1 0 10 year) ; last Sunday of October | ||
| 1195 | 240 180)) | ||
| 1196 | (diary-date-forms diary-european-date-forms)) | ||
| 1197 | :source tz-strategy-sexp | ||
| 1198 | :tests | ||
| 1199 | (let ((vtimezone (di:current-tz-to-vtimezone | ||
| 1200 | diary-icalendar-time-zone-export-strategy | ||
| 1201 | "EET"))) | ||
| 1202 | (ical:with-component vtimezone | ||
| 1203 | ((ical:standard :first std) | ||
| 1204 | (ical:daylight :first dst)) | ||
| 1205 | (should (= (* 2 60 60) (ical:with-property-of std 'ical:tzoffsetto))) | ||
| 1206 | (should (= (* 3 60 60) (ical:with-property-of dst 'ical:tzoffsetto)))) | ||
| 1207 | (ical:with-component (car parsed) | ||
| 1208 | ((ical:dtstart :first start-node :value start)) | ||
| 1209 | (should (= 7200 (decoded-time-zone start))) | ||
| 1210 | (should (= 16 (decoded-time-hour start))) | ||
| 1211 | (should (ical:with-param-of start-node 'ical:tzidparam))))) | ||
| 1212 | |||
| 1213 | (defun dit:parse-@-location (type properties) | ||
| 1214 | "Example user function for parsing additional properties. | ||
| 1215 | Parses anything following \"@\" to end of line as the entry's LOCATION." | ||
| 1216 | (ignore type properties) | ||
| 1217 | (goto-char (point-min)) | ||
| 1218 | (when (re-search-forward "@\\([^\n]+\\)" nil t) | ||
| 1219 | (list (ical:make-property ical:location | ||
| 1220 | (string-trim (match-string 1)))))) | ||
| 1221 | |||
| 1222 | (dit:parse-test | ||
| 1223 | "2025/08/02 BBQ @ John's" | ||
| 1224 | :parser dit:entry-parser | ||
| 1225 | :type 'ical:vevent | ||
| 1226 | :number 1 | ||
| 1227 | :bindings ((diary-icalendar-other-properties-parser #'dit:parse-@-location) | ||
| 1228 | (diary-date-forms diary-iso-date-forms)) | ||
| 1229 | :source other-properties-parser | ||
| 1230 | :tests | ||
| 1231 | (ical:with-component (car parsed) | ||
| 1232 | ((ical:location :value location)) | ||
| 1233 | (should (equal location "John's")))) | ||
| 1234 | |||
| 1235 | (dit:parse-test | ||
| 1236 | "2025/05/15 11AM Department meeting | ||
| 1237 | Attendee: <mydept@example.com>" | ||
| 1238 | :parser dit:entry-parser | ||
| 1239 | :type 'ical:vevent | ||
| 1240 | :number 1 | ||
| 1241 | :bindings ((diary-icalendar-export-alarms | ||
| 1242 | '((audio 10) | ||
| 1243 | (display 20 "In %t minutes: %s") | ||
| 1244 | (email 60 "In %t minutes: %s" ("myemail@example.com" from-entry)))) | ||
| 1245 | (diary-date-forms diary-iso-date-forms)) | ||
| 1246 | :source alarms-export | ||
| 1247 | :tests | ||
| 1248 | (ical:with-component (car parsed) | ||
| 1249 | ((ical:valarm :all valarms)) | ||
| 1250 | (should (length= valarms 3)) | ||
| 1251 | (dolist (valarm valarms) | ||
| 1252 | (ical:with-component valarm | ||
| 1253 | ((ical:action :value action) | ||
| 1254 | (ical:trigger :value trigger) | ||
| 1255 | (ical:summary :value summary) | ||
| 1256 | (ical:attendee :all attendee-nodes)) | ||
| 1257 | (cond ((equal action "AUDIO") | ||
| 1258 | (should (eql -10 (decoded-time-minute trigger)))) | ||
| 1259 | ((equal action "DISPLAY") | ||
| 1260 | (should (eql -20 (decoded-time-minute trigger))) | ||
| 1261 | (should (equal summary "In 20 minutes: Department meeting"))) | ||
| 1262 | ((equal action "EMAIL") | ||
| 1263 | (should (eql -60 (decoded-time-minute trigger))) | ||
| 1264 | (should (equal summary "In 60 minutes: Department meeting")) | ||
| 1265 | (should (length= attendee-nodes 2)) | ||
| 1266 | (let ((addrs (mapcar (lambda (n) (ical:with-node-value n)) | ||
| 1267 | attendee-nodes))) | ||
| 1268 | (should (member "mailto:myemail@example.com" addrs)) | ||
| 1269 | (should (member "mailto:mydept@example.com" addrs)))) | ||
| 1270 | (t (error "Unknown alarm action %s" action))))))) | ||
| 1271 | |||
| 1272 | |||
| 1273 | |||
| 1274 | ;; Local Variables: | ||
| 1275 | ;; read-symbol-shorthands: (("dit:" . "diary-icalendar-test-") ("di:" . "diary-icalendar-") ("ical:" . "icalendar-")) | ||
| 1276 | ;; byte-compile-warnings: (not obsolete) | ||
| 1277 | ;; End: | ||
| 1278 | ;;; diary-icalendar-tests.el ends here | ||
diff --git a/test/lisp/calendar/icalendar-ast-tests.el b/test/lisp/calendar/icalendar-ast-tests.el new file mode 100644 index 00000000000..b4107b139a5 --- /dev/null +++ b/test/lisp/calendar/icalendar-ast-tests.el | |||
| @@ -0,0 +1,112 @@ | |||
| 1 | ;;; tests/icalendar-ast.el --- Tests for icalendar-ast -*- lexical-binding: t; -*- | ||
| 2 | ;; Copyright (C) 2025 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | ;; This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 7 | ;; it under the terms of the GNU General Public License as published by | ||
| 8 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 9 | ;; (at your option) any later version. | ||
| 10 | |||
| 11 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;; GNU General Public License for more details. | ||
| 15 | |||
| 16 | ;; You should have received a copy of the GNU General Public License | ||
| 17 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | ;;; Code: | ||
| 20 | (require 'icalendar-ast) | ||
| 21 | (require 'icalendar-parser) | ||
| 22 | (require 'cl-lib) | ||
| 23 | (eval-when-compile (require 'icalendar-macs)) | ||
| 24 | |||
| 25 | |||
| 26 | ;; Tests for the high-level construction macros: | ||
| 27 | (ert-deftest iat:make-param/nonlist () | ||
| 28 | "Test that `icalendar-make-param' works as documented with a single value." | ||
| 29 | (let ((cnparam-node (ical:make-param ical:cnparam "John Doe"))) | ||
| 30 | (should (ical:param-node-p cnparam-node)) | ||
| 31 | (should (eq 'ical:cnparam (ical:ast-node-type cnparam-node))) | ||
| 32 | (ical:with-param cnparam-node | ||
| 33 | (should (cl-typep value 'ical:text)) | ||
| 34 | (should (equal value "John Doe"))))) | ||
| 35 | |||
| 36 | (ert-deftest iat:make-param/list () | ||
| 37 | "Test that `icalendar-make-param' works as documented with a list of values." | ||
| 38 | (let ((deltoparam-node (ical:make-param ical:deltoparam | ||
| 39 | (list "mailto:minionA@example.com" | ||
| 40 | "mailto:minionB@example.com")))) | ||
| 41 | (should (ical:param-node-p deltoparam-node)) | ||
| 42 | (should (eq 'ical:deltoparam (ical:ast-node-type deltoparam-node))) | ||
| 43 | (ical:with-param deltoparam-node | ||
| 44 | (should (and (listp value-nodes) (length= value-nodes 2))) | ||
| 45 | (should (seq-every-p | ||
| 46 | (lambda (n) (eq 'ical:cal-address (ical:ast-node-type n))) | ||
| 47 | value-nodes)) | ||
| 48 | (should (equal "mailto:minionA@example.com" (car values))) | ||
| 49 | (should (equal "mailto:minionB@example.com" (cadr values)))))) | ||
| 50 | |||
| 51 | (ert-deftest iat:make-property/nonlist () | ||
| 52 | "Test that `icalendar-make-property' works as documented with a single value." | ||
| 53 | (let ((attendee-node | ||
| 54 | (ical:make-property ical:attendee "mailto:hermes@planetexpress.com" | ||
| 55 | (ical:cnparam "H. Conrad")))) | ||
| 56 | (should (ical:property-node-p attendee-node)) | ||
| 57 | (should (eq 'ical:attendee (ical:ast-node-type attendee-node))) | ||
| 58 | (ical:with-property attendee-node | ||
| 59 | ((ical:cnparam :first cnparam-node :value cn)) | ||
| 60 | (should (eq value-type 'ical:cal-address)) | ||
| 61 | (should (equal value "mailto:hermes@planetexpress.com")) | ||
| 62 | (should (eq 'ical:cnparam (ical:ast-node-type cnparam-node))) | ||
| 63 | (should (equal cn "H. Conrad"))))) | ||
| 64 | |||
| 65 | (ert-deftest iat:make-property/list () | ||
| 66 | "Test that `icalendar-make-property' works as documented with a list of values." | ||
| 67 | (let ((rdate-node (icalendar-make-property icalendar-rdate | ||
| 68 | (list '(2 1 2025) '(3 1 2025))))) | ||
| 69 | (should (ical:property-node-p rdate-node)) | ||
| 70 | (should (eq 'ical:rdate (ical:ast-node-type rdate-node))) | ||
| 71 | (ical:with-property rdate-node | ||
| 72 | ((ical:valuetypeparam :first valtype-node :value valtype)) | ||
| 73 | (should (and (listp value-nodes) (length= value-nodes 2))) | ||
| 74 | (should (seq-every-p | ||
| 75 | (lambda (n) (eq 'ical:date (ical:ast-node-type n))) | ||
| 76 | value-nodes)) | ||
| 77 | (should (equal '(2 1 2025) (car values))) | ||
| 78 | (should (equal '(3 1 2025) (cadr values))) | ||
| 79 | (should (ical:ast-node-p valtype-node)) | ||
| 80 | (should (eq 'ical:valuetypeparam (ical:ast-node-type valtype-node))) | ||
| 81 | (should (eq 'ical:date valtype))))) | ||
| 82 | |||
| 83 | (ert-deftest iat:make-component () | ||
| 84 | "Test that `icalendar-make-component' works as documented." | ||
| 85 | (let* ((others (list (icalendar-make-property ical:dtstart '(9 6 3003)) | ||
| 86 | (icalendar-make-property ical:rrule '((FREQ DAILY))))) | ||
| 87 | (vevent-node (icalendar-make-component ical:vevent | ||
| 88 | (ical:summary "Party") | ||
| 89 | (ical:location "Robot House") | ||
| 90 | (@ others)))) | ||
| 91 | (should (ical:component-node-p vevent-node)) | ||
| 92 | (should (eq 'ical:vevent (ical:ast-node-type vevent-node))) | ||
| 93 | (ical:with-component vevent-node | ||
| 94 | ((ical:uid :first uid-node) | ||
| 95 | (ical:dtstamp :first dtstamp-node) | ||
| 96 | (ical:summary :value summary) | ||
| 97 | (ical:location :value location) | ||
| 98 | (ical:dtstart :first dtstart-node :value dtstart) | ||
| 99 | (ical:rrule :first rrule-node :value rrule)) | ||
| 100 | (should (and (ical:ast-node-p uid-node) | ||
| 101 | (ical:ast-node-p dtstamp-node))) | ||
| 102 | (should (equal summary "Party")) | ||
| 103 | (should (equal location "Robot House")) | ||
| 104 | (should (equal dtstart '(9 6 3003))) | ||
| 105 | (should (equal rrule '((FREQ DAILY))))))) | ||
| 106 | |||
| 107 | ;; TODO: properties, components too | ||
| 108 | |||
| 109 | ;; Local Variables: | ||
| 110 | ;; read-symbol-shorthands: (("iat:" . "icalendar-ast-test-") ("ical:" . "icalendar-")) | ||
| 111 | ;; End: | ||
| 112 | ;;; icalendar-ast-tests.el ends here | ||
diff --git a/test/lisp/calendar/icalendar-parser-tests.el b/test/lisp/calendar/icalendar-parser-tests.el new file mode 100644 index 00000000000..f3c5de35c87 --- /dev/null +++ b/test/lisp/calendar/icalendar-parser-tests.el | |||
| @@ -0,0 +1,2032 @@ | |||
| 1 | ;;; tests/icalendar-parser.el --- Tests for icalendar-parser -*- lexical-binding: t; -*- | ||
| 2 | ;; Copyright (C) 2025 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | ;; This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 7 | ;; it under the terms of the GNU General Public License as published by | ||
| 8 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 9 | ;; (at your option) any later version. | ||
| 10 | |||
| 11 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;; GNU General Public License for more details. | ||
| 15 | |||
| 16 | ;; You should have received a copy of the GNU General Public License | ||
| 17 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | ;;; Code: | ||
| 20 | |||
| 21 | (eval-when-compile (require 'cl-lib)) | ||
| 22 | (eval-when-compile (require 'icalendar-macs)) | ||
| 23 | (require 'ert) | ||
| 24 | (require 'ert-x) | ||
| 25 | (require 'icalendar-parser) | ||
| 26 | (require 'icalendar-utils) | ||
| 27 | |||
| 28 | (cl-defmacro ipt:parse/print-test (string &key expected parser type printer source) | ||
| 29 | "Create a test which parses STRING, prints the resulting parse | ||
| 30 | tree, and compares the printed version with STRING (or with | ||
| 31 | EXPECTED, if given). If they are the same, the test passes. | ||
| 32 | PARSER and PRINTER should be the parser and printer functions | ||
| 33 | appropriate to STRING. TYPE, if given, should be the type of | ||
| 34 | object PARSER is expected to parse; it will be passed as PARSER's | ||
| 35 | first argument. SOURCE should be a symbol; it is used to name the | ||
| 36 | test." | ||
| 37 | (let ((parser-form | ||
| 38 | (if type | ||
| 39 | `(funcall (function ,parser) (quote ,type) (point-max)) | ||
| 40 | `(funcall (function ,parser) (point-max))))) | ||
| 41 | `(ert-deftest ,(intern (concat "ipt:parse/print-" (symbol-name source))) () | ||
| 42 | ,(format "Parse and reprint example from `%s'; pass if they match" source) | ||
| 43 | (let* ((parse-buf (get-buffer-create "*iCalendar Parse Test*")) | ||
| 44 | (print-buf (get-buffer-create "*iCalendar Print Test*")) | ||
| 45 | (unparsed ,string) | ||
| 46 | (expected (or ,expected unparsed)) | ||
| 47 | (printed nil)) | ||
| 48 | (set-buffer parse-buf) | ||
| 49 | (erase-buffer) | ||
| 50 | (insert unparsed) | ||
| 51 | (goto-char (point-min)) | ||
| 52 | (let ((parsed ,parser-form)) | ||
| 53 | (should (icalendar-ast-node-valid-p parsed)) | ||
| 54 | (set-buffer print-buf) | ||
| 55 | (erase-buffer) | ||
| 56 | (insert (funcall (function ,printer) parsed)) | ||
| 57 | ;; this may need adjusting if printers become coding-system aware: | ||
| 58 | (decode-coding-region (point-min) (point-max) 'utf-8-dos) | ||
| 59 | (setq printed (buffer-substring-no-properties (point-min) (point-max))) | ||
| 60 | (should (equal expected printed))))))) | ||
| 61 | |||
| 62 | (ipt:parse/print-test | ||
| 63 | "ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT:mailto:jsmith@example.com\n" | ||
| 64 | :parser icalendar-parse-property | ||
| 65 | :printer icalendar-print-property-node | ||
| 66 | :source rfc5545-sec3.1.1/1) | ||
| 67 | |||
| 68 | (ipt:parse/print-test | ||
| 69 | "RDATE;VALUE=DATE:19970304,19970504,19970704,19970904\n" | ||
| 70 | :parser icalendar-parse-property | ||
| 71 | :printer icalendar-print-property-node | ||
| 72 | :source rfc5545-sec3.1.1/2) | ||
| 73 | |||
| 74 | (ipt:parse/print-test | ||
| 75 | "ATTACH:http://example.com/public/quarterly-report.doc\n" | ||
| 76 | :parser icalendar-parse-property | ||
| 77 | :printer icalendar-print-property-node | ||
| 78 | :source rfc5545-sec3.1.3/1) | ||
| 79 | |||
| 80 | (ipt:parse/print-test | ||
| 81 | ;; Corrected. The original contains invalid base64 data; it was | ||
| 82 | ;; missing the final "=", as noted in errata ID 5602. | ||
| 83 | ;; The decoded string should read: | ||
| 84 | ;; The quick brown fox jumps over the lazy dog. | ||
| 85 | "ATTACH;FMTTYPE=text/plain;ENCODING=BASE64;VALUE=BINARY:VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4=\n" | ||
| 86 | :parser icalendar-parse-property | ||
| 87 | :printer icalendar-print-property-node | ||
| 88 | :source rfc5545-sec3.1.3/2) | ||
| 89 | |||
| 90 | (ipt:parse/print-test | ||
| 91 | "DESCRIPTION;ALTREP=\"cid:part1.0001@example.org\":The Fall'98 Wild Wizards Conference - - Las Vegas\\, NV\\, USA\n" | ||
| 92 | :parser icalendar-parse-property | ||
| 93 | :printer icalendar-print-property-node | ||
| 94 | :source rfc5545-sec3.2/1) | ||
| 95 | |||
| 96 | (ipt:parse/print-test | ||
| 97 | "DESCRIPTION;ALTREP=\"CID:part3.msg.970415T083000@example.com\": Project XYZ Review Meeting will include the following agenda items: (a) Market Overview\\, (b) Finances\\, (c) Project Management\n" | ||
| 98 | :parser icalendar-parse-property | ||
| 99 | :printer icalendar-print-property-node | ||
| 100 | :source rfc5545-sec3.2.1/1) | ||
| 101 | |||
| 102 | (ipt:parse/print-test | ||
| 103 | "ORGANIZER;CN=\"John Smith\":mailto:jsmith@example.com\n" | ||
| 104 | ;; CN param value does not require quotes, so they're missing when | ||
| 105 | ;; re-printed: | ||
| 106 | :expected "ORGANIZER;CN=John Smith:mailto:jsmith@example.com\n" | ||
| 107 | :parser icalendar-parse-property | ||
| 108 | :printer icalendar-print-property-node | ||
| 109 | :source rfc5545-sec3.2.2/1) | ||
| 110 | |||
| 111 | (ipt:parse/print-test | ||
| 112 | "ATTENDEE;CUTYPE=GROUP:mailto:ietf-calsch@example.org\n" | ||
| 113 | :parser icalendar-parse-property | ||
| 114 | :printer icalendar-print-property-node | ||
| 115 | :source rfc5545-sec3.2.3/1) | ||
| 116 | |||
| 117 | (ipt:parse/print-test | ||
| 118 | "ATTENDEE;DELEGATED-FROM=\"mailto:jsmith@example.com\":mailto:jdoe@example.com\n" | ||
| 119 | :parser icalendar-parse-property | ||
| 120 | :printer icalendar-print-property-node | ||
| 121 | :source rfc5545-sec3.2.4/1) | ||
| 122 | |||
| 123 | (ipt:parse/print-test | ||
| 124 | "ATTENDEE;DELEGATED-TO=\"mailto:jdoe@example.com\",\"mailto:jqpublic@example.com\":mailto:jsmith@example.com\n" | ||
| 125 | :parser icalendar-parse-property | ||
| 126 | :printer icalendar-print-property-node | ||
| 127 | :source rfc5545-sec3.2.5/1) | ||
| 128 | |||
| 129 | (ipt:parse/print-test | ||
| 130 | "ORGANIZER;DIR=\"ldap://example.com:6666/o=ABC%20Industries,c=US???(cn=Jim%20Dolittle)\":mailto:jimdo@example.com\n" | ||
| 131 | :parser icalendar-parse-property | ||
| 132 | :printer icalendar-print-property-node | ||
| 133 | :source rfc5545-sec3.2.6/1) | ||
| 134 | |||
| 135 | (ipt:parse/print-test | ||
| 136 | "ATTACH;FMTTYPE=text/plain;ENCODING=BASE64;VALUE=BINARY:TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2ljaW5nIGVsaXQsIHNlZCBkbyBlaXVzbW9kIHRlbXBvciBpbmNpZGlkdW50IHV0IGxhYm9yZSBldCBkb2xvcmUgbWFnbmEgYWxpcXVhLiBVdCBlbmltIGFkIG1pbmltIHZlbmlhbSwgcXVpcyBub3N0cnVkIGV4ZXJjaXRhdGlvbiB1bGxhbWNvIGxhYm9yaXMgbmlzaSB1dCBhbGlxdWlwIGV4IGVhIGNvbW1vZG8gY29uc2VxdWF0LiBEdWlzIGF1dGUgaXJ1cmUgZG9sb3IgaW4gcmVwcmVoZW5kZXJpdCBpbiB2b2x1cHRhdGUgdmVsaXQgZXNzZSBjaWxsdW0gZG9sb3JlIGV1IGZ1Z2lhdCBudWxsYSBwYXJpYXR1ci4gRXhjZXB0ZXVyIHNpbnQgb2NjYWVjYXQgY3VwaWRhdGF0IG5vbiBwcm9pZGVudCwgc3VudCBpbiBjdWxwYSBxdWkgb2ZmaWNpYSBkZXNlcnVudCBtb2xsaXQgYW5pbSBpZCBlc3QgbGFib3J1bS4=\n" | ||
| 137 | :parser icalendar-parse-property | ||
| 138 | :printer icalendar-print-property-node | ||
| 139 | :source rfc5545-sec3.2.7/1) | ||
| 140 | |||
| 141 | (ipt:parse/print-test | ||
| 142 | "ATTACH;FMTTYPE=application/msword:ftp://example.com/pub/docs/agenda.doc\n" | ||
| 143 | :parser icalendar-parse-property | ||
| 144 | :printer icalendar-print-property-node | ||
| 145 | :source rfc5545-sec3.2.8/1) | ||
| 146 | |||
| 147 | (ipt:parse/print-test | ||
| 148 | "FREEBUSY;FBTYPE=BUSY:19980415T133000Z/19980415T170000Z\n" | ||
| 149 | :parser icalendar-parse-property | ||
| 150 | :printer icalendar-print-property-node | ||
| 151 | :source rfc5545-sec3.2.9/1) | ||
| 152 | |||
| 153 | (ipt:parse/print-test | ||
| 154 | "SUMMARY;LANGUAGE=en-US:Company Holiday Party\n" | ||
| 155 | :parser icalendar-parse-property | ||
| 156 | :printer icalendar-print-property-node | ||
| 157 | :source rfc5545-sec3.2.10/1) | ||
| 158 | |||
| 159 | (ipt:parse/print-test | ||
| 160 | "LOCATION;LANGUAGE=en:Germany\n" | ||
| 161 | :parser icalendar-parse-property | ||
| 162 | :printer icalendar-print-property-node | ||
| 163 | :source rfc5545-sec3.2.10/2) | ||
| 164 | |||
| 165 | (ipt:parse/print-test | ||
| 166 | "LOCATION;LANGUAGE=no:Tyskland\n" | ||
| 167 | :parser icalendar-parse-property | ||
| 168 | :printer icalendar-print-property-node | ||
| 169 | :source rfc5545-sec3.2.10/3) | ||
| 170 | |||
| 171 | (ipt:parse/print-test | ||
| 172 | "ATTENDEE;MEMBER=\"mailto:ietf-calsch@example.org\":mailto:jsmith@example.com\n" | ||
| 173 | :parser icalendar-parse-property | ||
| 174 | :printer icalendar-print-property-node | ||
| 175 | :source rfc5545-sec3.2.11/1) | ||
| 176 | |||
| 177 | (ipt:parse/print-test | ||
| 178 | "ATTENDEE;MEMBER=\"mailto:projectA@example.com\",\"mailto:projectB@example.com\":mailto:janedoe@example.com\n" | ||
| 179 | :parser icalendar-parse-property | ||
| 180 | :printer icalendar-print-property-node | ||
| 181 | :source rfc5545-sec3.2.11/2) | ||
| 182 | |||
| 183 | (ipt:parse/print-test | ||
| 184 | "ATTENDEE;PARTSTAT=DECLINED:mailto:jsmith@example.com\n" | ||
| 185 | :parser icalendar-parse-property | ||
| 186 | :printer icalendar-print-property-node | ||
| 187 | :source rfc5545-sec3.2.12/1) | ||
| 188 | |||
| 189 | (ipt:parse/print-test | ||
| 190 | "RECURRENCE-ID;RANGE=THISANDFUTURE:19980401T133000Z\n" | ||
| 191 | :parser icalendar-parse-property | ||
| 192 | :printer icalendar-print-property-node | ||
| 193 | :source rfc5545-sec3.2.13/1) | ||
| 194 | |||
| 195 | (ipt:parse/print-test | ||
| 196 | "TRIGGER;RELATED=END:PT5M\n" | ||
| 197 | :parser icalendar-parse-property | ||
| 198 | :printer icalendar-print-property-node | ||
| 199 | :source rfc5545-sec3.2.14/1) | ||
| 200 | |||
| 201 | (ipt:parse/print-test | ||
| 202 | "RELATED-TO;RELTYPE=SIBLING:19960401-080045-4000F192713@example.com\n" | ||
| 203 | :parser icalendar-parse-property | ||
| 204 | :printer icalendar-print-property-node | ||
| 205 | :source rfc5545-sec3.2.15/1) | ||
| 206 | |||
| 207 | (ipt:parse/print-test | ||
| 208 | "ATTENDEE;ROLE=CHAIR:mailto:mrbig@example.com\n" | ||
| 209 | :parser icalendar-parse-property | ||
| 210 | :printer icalendar-print-property-node | ||
| 211 | :source rfc5545-sec3.2.16/1) | ||
| 212 | |||
| 213 | (ipt:parse/print-test | ||
| 214 | "ATTENDEE;RSVP=TRUE:mailto:jsmith@example.com\n" | ||
| 215 | :parser icalendar-parse-property | ||
| 216 | :printer icalendar-print-property-node | ||
| 217 | :source rfc5545-sec3.2.17/1) | ||
| 218 | |||
| 219 | (ipt:parse/print-test | ||
| 220 | "ORGANIZER;SENT-BY=\"mailto:sray@example.com\":mailto:jsmith@example.com\n" | ||
| 221 | :parser icalendar-parse-property | ||
| 222 | :printer icalendar-print-property-node | ||
| 223 | :source rfc5545-sec3.2.18/1) | ||
| 224 | |||
| 225 | (ipt:parse/print-test | ||
| 226 | "DTSTART;TZID=America/New_York:19980119T020000\n" | ||
| 227 | :parser icalendar-parse-property | ||
| 228 | :printer icalendar-print-property-node | ||
| 229 | :source rfc5545-sec3.2.19/1) | ||
| 230 | |||
| 231 | (ipt:parse/print-test | ||
| 232 | "DTEND;TZID=America/New_York:19980119T030000\n" | ||
| 233 | :parser icalendar-parse-property | ||
| 234 | :printer icalendar-print-property-node | ||
| 235 | :source rfc5545-sec3.2.19/2) | ||
| 236 | |||
| 237 | (ipt:parse/print-test | ||
| 238 | "ATTACH;FMTTYPE=image/vnd.microsoft.icon;ENCODING=BASE64;VALUE=BINARY:AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAgIAAAICAgADAwMAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAAAAAABNEMQAAAAAAAkQgAAAAAAJEREQgAAACECQ0QgEgAAQxQzM0E0AABERCRCREQAADRDJEJEQwAAAhA0QwEQAAAAAEREAAAAAAAAREQAAAAAAAAkQgAAAAAAAAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" | ||
| 239 | :parser icalendar-parse-property | ||
| 240 | :printer icalendar-print-property-node | ||
| 241 | :source rfc5545-sec3.3.1/1) | ||
| 242 | |||
| 243 | (ipt:parse/print-test | ||
| 244 | "TRUE" | ||
| 245 | :type icalendar-boolean | ||
| 246 | :parser icalendar-parse-value-node | ||
| 247 | :printer icalendar-print-value-node | ||
| 248 | :source rfc5545-sec3.3.2/1) | ||
| 249 | |||
| 250 | (ipt:parse/print-test | ||
| 251 | "mailto:jane_doe@example.com" | ||
| 252 | :type icalendar-cal-address | ||
| 253 | :parser icalendar-parse-value-node | ||
| 254 | :printer icalendar-print-value-node | ||
| 255 | :source rfc5545-sec3.3.3/1) | ||
| 256 | |||
| 257 | (ipt:parse/print-test | ||
| 258 | "19970714" | ||
| 259 | :type icalendar-date | ||
| 260 | :parser icalendar-parse-value-node | ||
| 261 | :printer icalendar-print-value-node | ||
| 262 | :source rfc5545-sec3.3.4/1) | ||
| 263 | |||
| 264 | (ipt:parse/print-test | ||
| 265 | ;; 'Floating' time: | ||
| 266 | "19980118T230000" | ||
| 267 | :type icalendar-date-time | ||
| 268 | :parser icalendar-parse-value-node | ||
| 269 | :printer icalendar-print-value-node | ||
| 270 | :source rfc5545-sec3.3.5/1) | ||
| 271 | |||
| 272 | (ipt:parse/print-test | ||
| 273 | ;; UTC time: | ||
| 274 | "19980119T070000Z" | ||
| 275 | :type icalendar-date-time | ||
| 276 | :parser icalendar-parse-value-node | ||
| 277 | :printer icalendar-print-value-node | ||
| 278 | :source rfc5545-sec3.3.5/2) | ||
| 279 | |||
| 280 | (ipt:parse/print-test | ||
| 281 | ;; Leap second (seconds = 60) | ||
| 282 | "19970630T235960Z" | ||
| 283 | :type icalendar-date-time | ||
| 284 | :parser icalendar-parse-value-node | ||
| 285 | :printer icalendar-print-value-node | ||
| 286 | :source rfc5545-sec3.3.5/3) | ||
| 287 | |||
| 288 | (ipt:parse/print-test | ||
| 289 | ;; Local time: | ||
| 290 | "DTSTART:19970714T133000\n" | ||
| 291 | :parser icalendar-parse-property | ||
| 292 | :printer icalendar-print-property-node | ||
| 293 | :source rfc5545-sec3.3.5/4) | ||
| 294 | |||
| 295 | (ipt:parse/print-test | ||
| 296 | ;; UTC time: | ||
| 297 | "DTSTART:19970714T173000Z\n" | ||
| 298 | :parser icalendar-parse-property | ||
| 299 | :printer icalendar-print-property-node | ||
| 300 | :source rfc5545-sec3.3.5/5) | ||
| 301 | |||
| 302 | (ipt:parse/print-test | ||
| 303 | ;; Local time with TZ identifier: | ||
| 304 | "DTSTART;TZID=America/New_York:19970714T133000\n" | ||
| 305 | :parser icalendar-parse-property | ||
| 306 | :printer icalendar-print-property-node | ||
| 307 | :source rfc5545-sec3.3.5/6) | ||
| 308 | |||
| 309 | (ipt:parse/print-test | ||
| 310 | "P15DT5H0M20S" | ||
| 311 | :expected "P15DT5H20S" | ||
| 312 | :type icalendar-dur-value | ||
| 313 | :parser icalendar-parse-value-node | ||
| 314 | :printer icalendar-print-value-node | ||
| 315 | :source rfc5545-sec3.3.6/1) | ||
| 316 | |||
| 317 | (ipt:parse/print-test | ||
| 318 | "P7W" | ||
| 319 | :type icalendar-dur-value | ||
| 320 | :parser icalendar-parse-value-node | ||
| 321 | :printer icalendar-print-value-node | ||
| 322 | :source rfc5545-sec3.3.6/2) | ||
| 323 | |||
| 324 | (ipt:parse/print-test | ||
| 325 | "1000000.0000001" | ||
| 326 | :type icalendar-float | ||
| 327 | :parser icalendar-parse-value-node | ||
| 328 | :printer icalendar-print-value-node | ||
| 329 | :source rfc5545-sec3.3.7/1) | ||
| 330 | |||
| 331 | (ipt:parse/print-test | ||
| 332 | "1.333" | ||
| 333 | :type icalendar-float | ||
| 334 | :parser icalendar-parse-value-node | ||
| 335 | :printer icalendar-print-value-node | ||
| 336 | :source rfc5545-sec3.3.7/2) | ||
| 337 | |||
| 338 | (ipt:parse/print-test | ||
| 339 | "-3.14" | ||
| 340 | :type icalendar-float | ||
| 341 | :parser icalendar-parse-value-node | ||
| 342 | :printer icalendar-print-value-node | ||
| 343 | :source rfc5545-sec3.3.7/3) | ||
| 344 | |||
| 345 | (ipt:parse/print-test | ||
| 346 | "1234567890" | ||
| 347 | :type icalendar-integer | ||
| 348 | :parser icalendar-parse-value-node | ||
| 349 | :printer icalendar-print-value-node | ||
| 350 | :source rfc5545-sec3.3.8/1) | ||
| 351 | |||
| 352 | (ipt:parse/print-test | ||
| 353 | "-1234567890" | ||
| 354 | :type icalendar-integer | ||
| 355 | :parser icalendar-parse-value-node | ||
| 356 | :printer icalendar-print-value-node | ||
| 357 | :source rfc5545-sec3.3.8/2) | ||
| 358 | |||
| 359 | (ipt:parse/print-test | ||
| 360 | "+1234567890" | ||
| 361 | ;; "+" sign isn't required, so it's not re-printed: | ||
| 362 | :expected "1234567890" | ||
| 363 | :type icalendar-integer | ||
| 364 | :parser icalendar-parse-value-node | ||
| 365 | :printer icalendar-print-value-node | ||
| 366 | :source rfc5545-sec3.3.8/3) | ||
| 367 | |||
| 368 | (ipt:parse/print-test | ||
| 369 | "432109876" | ||
| 370 | :type icalendar-integer | ||
| 371 | :parser icalendar-parse-value-node | ||
| 372 | :printer icalendar-print-value-node | ||
| 373 | :source rfc5545-sec3.3.8/4) | ||
| 374 | |||
| 375 | (ipt:parse/print-test | ||
| 376 | "19970101T180000Z/19970102T070000Z" | ||
| 377 | :type icalendar-period | ||
| 378 | :parser icalendar-parse-value-node | ||
| 379 | :printer icalendar-print-value-node | ||
| 380 | :source rfc5545-sec3.3.9/1) | ||
| 381 | |||
| 382 | (ipt:parse/print-test | ||
| 383 | "19970101T180000Z/PT5H30M" | ||
| 384 | :type icalendar-period | ||
| 385 | :parser icalendar-parse-value-node | ||
| 386 | :printer icalendar-print-value-node | ||
| 387 | :source rfc5545-sec3.3.9/2) | ||
| 388 | |||
| 389 | (ipt:parse/print-test | ||
| 390 | "FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1" | ||
| 391 | :type icalendar-recur | ||
| 392 | :parser icalendar-parse-value-node | ||
| 393 | :printer icalendar-print-value-node | ||
| 394 | :source rfc5545-sec3.3.10/1) | ||
| 395 | |||
| 396 | (ipt:parse/print-test | ||
| 397 | "FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30" | ||
| 398 | :type icalendar-recur | ||
| 399 | :parser icalendar-parse-value-node | ||
| 400 | :printer icalendar-print-value-node | ||
| 401 | :source rfc5545-sec3.3.10/2) | ||
| 402 | |||
| 403 | (ipt:parse/print-test | ||
| 404 | "FREQ=DAILY;COUNT=10;INTERVAL=2" | ||
| 405 | :type icalendar-recur | ||
| 406 | :parser icalendar-parse-value-node | ||
| 407 | :printer icalendar-print-value-node | ||
| 408 | :source rfc5545-sec3.3.10/3) | ||
| 409 | |||
| 410 | (ipt:parse/print-test | ||
| 411 | "Project XYZ Final Review\\nConference Room - 3B\\nCome Prepared." | ||
| 412 | :type icalendar-text | ||
| 413 | :parser icalendar-parse-value-node | ||
| 414 | :printer icalendar-print-value-node | ||
| 415 | :source rfc5545-sec3.3.11/1) | ||
| 416 | |||
| 417 | (ipt:parse/print-test | ||
| 418 | ;; Local time: | ||
| 419 | "230000" | ||
| 420 | :type icalendar-time | ||
| 421 | :parser icalendar-parse-value-node | ||
| 422 | :printer icalendar-print-value-node | ||
| 423 | :source rfc5545-sec3.3.12/1) | ||
| 424 | |||
| 425 | (ipt:parse/print-test | ||
| 426 | ;; UTC time: | ||
| 427 | "070000Z" | ||
| 428 | :type icalendar-time | ||
| 429 | :parser icalendar-parse-value-node | ||
| 430 | :printer icalendar-print-value-node | ||
| 431 | :source rfc5545-sec3.3.12/2) | ||
| 432 | |||
| 433 | (ipt:parse/print-test | ||
| 434 | ;; Local time: | ||
| 435 | "083000" | ||
| 436 | :type icalendar-time | ||
| 437 | :parser icalendar-parse-value-node | ||
| 438 | :printer icalendar-print-value-node | ||
| 439 | :source rfc5545-sec3.3.12/3) | ||
| 440 | |||
| 441 | (ipt:parse/print-test | ||
| 442 | ;; UTC time: | ||
| 443 | "133000Z" | ||
| 444 | :type icalendar-time | ||
| 445 | :parser icalendar-parse-value-node | ||
| 446 | :printer icalendar-print-value-node | ||
| 447 | :source rfc5545-sec3.3.12/4) | ||
| 448 | |||
| 449 | (ipt:parse/print-test | ||
| 450 | ;; Local time with TZ identifier: | ||
| 451 | "SOMETIMEPROP;TZID=America/New_York;VALUE=TIME:083000\n" | ||
| 452 | :parser icalendar-parse-property | ||
| 453 | :printer icalendar-print-property-node | ||
| 454 | :source rfc5545-sec3.3.12/5) | ||
| 455 | |||
| 456 | (ipt:parse/print-test | ||
| 457 | "http://example.com/my-report.txt" | ||
| 458 | :type icalendar-uri | ||
| 459 | :parser icalendar-parse-value-node | ||
| 460 | :printer icalendar-print-value-node | ||
| 461 | :source rfc5545-sec3.3.13/1) | ||
| 462 | |||
| 463 | (ipt:parse/print-test | ||
| 464 | "-0500" | ||
| 465 | :type icalendar-utc-offset | ||
| 466 | :parser icalendar-parse-value-node | ||
| 467 | :printer icalendar-print-value-node | ||
| 468 | :source rfc5545-sec3.3.14/1) | ||
| 469 | |||
| 470 | (ipt:parse/print-test | ||
| 471 | "+0100" | ||
| 472 | :type icalendar-utc-offset | ||
| 473 | :parser icalendar-parse-value-node | ||
| 474 | :printer icalendar-print-value-node | ||
| 475 | :source rfc55453.3.14/1) | ||
| 476 | |||
| 477 | (ipt:parse/print-test | ||
| 478 | "BEGIN:VCALENDAR | ||
| 479 | VERSION:2.0 | ||
| 480 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN | ||
| 481 | BEGIN:VEVENT | ||
| 482 | UID:19970610T172345Z-AF23B2@example.com | ||
| 483 | DTSTAMP:19970610T172345Z | ||
| 484 | DTSTART:19970714T170000Z | ||
| 485 | DTEND:19970715T040000Z | ||
| 486 | SUMMARY:Bastille Day Party | ||
| 487 | END:VEVENT | ||
| 488 | END:VCALENDAR | ||
| 489 | " | ||
| 490 | :parser icalendar-parse-calendar | ||
| 491 | :printer icalendar-print-calendar-node | ||
| 492 | :source rfc5545-sec3.4/1) | ||
| 493 | |||
| 494 | (ipt:parse/print-test | ||
| 495 | "DTSTART:19960415T133000Z\n" | ||
| 496 | :parser icalendar-parse-property | ||
| 497 | :printer icalendar-print-property-node | ||
| 498 | :source rfc5545-sec3.5/1) | ||
| 499 | |||
| 500 | (ipt:parse/print-test | ||
| 501 | "BEGIN:VEVENT | ||
| 502 | UID:19970901T130000Z-123401@example.com | ||
| 503 | DTSTAMP:19970901T130000Z | ||
| 504 | DTSTART:19970903T163000Z | ||
| 505 | DTEND:19970903T190000Z | ||
| 506 | SUMMARY:Annual Employee Review | ||
| 507 | CLASS:PRIVATE | ||
| 508 | CATEGORIES:BUSINESS,HUMAN RESOURCES | ||
| 509 | END:VEVENT | ||
| 510 | " | ||
| 511 | :parser icalendar-parse-component | ||
| 512 | :printer icalendar-print-component-node | ||
| 513 | :source rfc5545-sec3.6.1/1) | ||
| 514 | |||
| 515 | (ipt:parse/print-test | ||
| 516 | "BEGIN:VEVENT | ||
| 517 | UID:19970901T130000Z-123402@example.com | ||
| 518 | DTSTAMP:19970901T130000Z | ||
| 519 | DTSTART:19970401T163000Z | ||
| 520 | DTEND:19970402T010000Z | ||
| 521 | SUMMARY:Laurel is in sensitivity awareness class. | ||
| 522 | CLASS:PUBLIC | ||
| 523 | CATEGORIES:BUSINESS,HUMAN RESOURCES | ||
| 524 | TRANSP:TRANSPARENT | ||
| 525 | END:VEVENT | ||
| 526 | " | ||
| 527 | :parser icalendar-parse-component | ||
| 528 | :printer icalendar-print-component-node | ||
| 529 | :source rfc5545-sec3.6.1/2) | ||
| 530 | |||
| 531 | (ipt:parse/print-test | ||
| 532 | "BEGIN:VEVENT | ||
| 533 | UID:19970901T130000Z-123403@example.com | ||
| 534 | DTSTAMP:19970901T130000Z | ||
| 535 | DTSTART;VALUE=DATE:19971102 | ||
| 536 | SUMMARY:Our Blissful Anniversary | ||
| 537 | TRANSP:TRANSPARENT | ||
| 538 | CLASS:CONFIDENTIAL | ||
| 539 | CATEGORIES:ANNIVERSARY,PERSONAL,SPECIAL OCCASION | ||
| 540 | RRULE:FREQ=YEARLY | ||
| 541 | END:VEVENT | ||
| 542 | " | ||
| 543 | :parser icalendar-parse-component | ||
| 544 | :printer icalendar-print-component-node | ||
| 545 | :source rfc5545-sec3.6.1/3) | ||
| 546 | |||
| 547 | (ipt:parse/print-test | ||
| 548 | "BEGIN:VEVENT | ||
| 549 | UID:20070423T123432Z-541111@example.com | ||
| 550 | DTSTAMP:20070423T123432Z | ||
| 551 | DTSTART;VALUE=DATE:20070628 | ||
| 552 | DTEND;VALUE=DATE:20070709 | ||
| 553 | SUMMARY:Festival International de Jazz de Montreal | ||
| 554 | TRANSP:TRANSPARENT | ||
| 555 | END:VEVENT | ||
| 556 | " | ||
| 557 | :parser icalendar-parse-component | ||
| 558 | :printer icalendar-print-component-node | ||
| 559 | :source rfc5545-sec3.6.1/4) | ||
| 560 | |||
| 561 | (ipt:parse/print-test | ||
| 562 | "BEGIN:VTODO | ||
| 563 | UID:20070313T123432Z-456553@example.com | ||
| 564 | DTSTAMP:20070313T123432Z | ||
| 565 | DUE;VALUE=DATE:20070501 | ||
| 566 | SUMMARY:Submit Quebec Income Tax Return for 2006 | ||
| 567 | CLASS:CONFIDENTIAL | ||
| 568 | CATEGORIES:FAMILY,FINANCE | ||
| 569 | STATUS:NEEDS-ACTION | ||
| 570 | END:VTODO | ||
| 571 | " | ||
| 572 | :parser icalendar-parse-component | ||
| 573 | :printer icalendar-print-component-node | ||
| 574 | :source rfc5545-sec3.6.2/1) | ||
| 575 | |||
| 576 | (ipt:parse/print-test | ||
| 577 | "BEGIN:VTODO | ||
| 578 | UID:20070514T103211Z-123404@example.com | ||
| 579 | DTSTAMP:20070514T103211Z | ||
| 580 | DTSTART:20070514T110000Z | ||
| 581 | DUE:20070709T130000Z | ||
| 582 | COMPLETED:20070707T100000Z | ||
| 583 | SUMMARY:Submit Revised Internet-Draft | ||
| 584 | PRIORITY:1 | ||
| 585 | STATUS:NEEDS-ACTION | ||
| 586 | END:VTODO | ||
| 587 | " | ||
| 588 | :parser icalendar-parse-component | ||
| 589 | :printer icalendar-print-component-node | ||
| 590 | :source rfc5545-sec3.6.2/2) | ||
| 591 | |||
| 592 | (ipt:parse/print-test | ||
| 593 | "BEGIN:VJOURNAL | ||
| 594 | UID:19970901T130000Z-123405@example.com | ||
| 595 | DTSTAMP:19970901T130000Z | ||
| 596 | DTSTART;VALUE=DATE:19970317 | ||
| 597 | SUMMARY:Staff meeting minutes | ||
| 598 | DESCRIPTION:1. Staff meeting: Participants include Joe\\,Lisa\\, and Bob. Aurora project plans were reviewed. There is currently no budget reserves for this project. Lisa will escalate to management. Next meeting on Tuesday.\\n 2. Telephone Conference: ABC Corp. sales representative called to discuss new printer. Promised to get us a demo by Friday.\\n3. Henry Miller (Handsoff Insurance): Car was totaled by tree. Is looking into a loaner car. 555-2323 (tel). | ||
| 599 | END:VJOURNAL | ||
| 600 | " | ||
| 601 | :parser icalendar-parse-component | ||
| 602 | :printer icalendar-print-component-node | ||
| 603 | :source rfc5545-sec3.6.3/1) | ||
| 604 | |||
| 605 | (ipt:parse/print-test | ||
| 606 | "BEGIN:VFREEBUSY | ||
| 607 | UID:19970901T082949Z-FA43EF@example.com | ||
| 608 | ORGANIZER:mailto:jane_doe@example.com | ||
| 609 | ATTENDEE:mailto:john_public@example.com | ||
| 610 | DTSTART:19971015T050000Z | ||
| 611 | DTEND:19971016T050000Z | ||
| 612 | DTSTAMP:19970901T083000Z | ||
| 613 | END:VFREEBUSY | ||
| 614 | " | ||
| 615 | :parser icalendar-parse-component | ||
| 616 | :printer icalendar-print-component-node | ||
| 617 | :source rfc5545-sec3.6.4/1) | ||
| 618 | |||
| 619 | (ipt:parse/print-test | ||
| 620 | "BEGIN:VFREEBUSY | ||
| 621 | UID:19970901T095957Z-76A912@example.com | ||
| 622 | ORGANIZER:mailto:jane_doe@example.com | ||
| 623 | ATTENDEE:mailto:john_public@example.com | ||
| 624 | DTSTAMP:19970901T100000Z | ||
| 625 | FREEBUSY:19971015T050000Z/PT8H30M,19971015T160000Z/PT5H30M,19971015T223000Z/PT6H30M | ||
| 626 | URL:http://example.com/pub/busy/jpublic-01.ifb | ||
| 627 | COMMENT:This iCalendar file contains busy time information for the next three months. | ||
| 628 | END:VFREEBUSY | ||
| 629 | " | ||
| 630 | :parser icalendar-parse-component | ||
| 631 | :printer icalendar-print-component-node | ||
| 632 | :source rfc5545-sec3.6.4/2) | ||
| 633 | |||
| 634 | (ipt:parse/print-test | ||
| 635 | ;; Corrected. Original has invalid value in ORGANIZER | ||
| 636 | "BEGIN:VFREEBUSY | ||
| 637 | UID:19970901T115957Z-76A912@example.com | ||
| 638 | DTSTAMP:19970901T120000Z | ||
| 639 | ORGANIZER:mailto:jsmith@example.com | ||
| 640 | DTSTART:19980313T141711Z | ||
| 641 | DTEND:19980410T141711Z | ||
| 642 | FREEBUSY:19980314T233000Z/19980315T003000Z | ||
| 643 | FREEBUSY:19980316T153000Z/19980316T163000Z | ||
| 644 | FREEBUSY:19980318T030000Z/19980318T040000Z | ||
| 645 | URL:http://www.example.com/calendar/busytime/jsmith.ifb | ||
| 646 | END:VFREEBUSY | ||
| 647 | " | ||
| 648 | :parser icalendar-parse-component | ||
| 649 | :printer icalendar-print-component-node | ||
| 650 | :source rfc5545-sec3.6.4/3) | ||
| 651 | |||
| 652 | (ipt:parse/print-test | ||
| 653 | "BEGIN:VTIMEZONE | ||
| 654 | TZID:America/New_York | ||
| 655 | LAST-MODIFIED:20050809T050000Z | ||
| 656 | BEGIN:DAYLIGHT | ||
| 657 | DTSTART:19670430T020000 | ||
| 658 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19730429T070000Z | ||
| 659 | TZOFFSETFROM:-0500 | ||
| 660 | TZOFFSETTO:-0400 | ||
| 661 | TZNAME:EDT | ||
| 662 | END:DAYLIGHT | ||
| 663 | BEGIN:STANDARD | ||
| 664 | DTSTART:19671029T020000 | ||
| 665 | RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU;UNTIL=20061029T060000Z | ||
| 666 | TZOFFSETFROM:-0400 | ||
| 667 | TZOFFSETTO:-0500 | ||
| 668 | TZNAME:EST | ||
| 669 | END:STANDARD | ||
| 670 | BEGIN:DAYLIGHT | ||
| 671 | DTSTART:19740106T020000 | ||
| 672 | RDATE:19750223T020000 | ||
| 673 | TZOFFSETFROM:-0500 | ||
| 674 | TZOFFSETTO:-0400 | ||
| 675 | TZNAME:EDT | ||
| 676 | END:DAYLIGHT | ||
| 677 | BEGIN:DAYLIGHT | ||
| 678 | DTSTART:19760425T020000 | ||
| 679 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19860427T070000Z | ||
| 680 | TZOFFSETFROM:-0500 | ||
| 681 | TZOFFSETTO:-0400 | ||
| 682 | TZNAME:EDT | ||
| 683 | END:DAYLIGHT | ||
| 684 | BEGIN:DAYLIGHT | ||
| 685 | DTSTART:19870405T020000 | ||
| 686 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU;UNTIL=20060402T070000Z | ||
| 687 | TZOFFSETFROM:-0500 | ||
| 688 | TZOFFSETTO:-0400 | ||
| 689 | TZNAME:EDT | ||
| 690 | END:DAYLIGHT | ||
| 691 | BEGIN:DAYLIGHT | ||
| 692 | DTSTART:20070311T020000 | ||
| 693 | RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU | ||
| 694 | TZOFFSETFROM:-0500 | ||
| 695 | TZOFFSETTO:-0400 | ||
| 696 | TZNAME:EDT | ||
| 697 | END:DAYLIGHT | ||
| 698 | BEGIN:STANDARD | ||
| 699 | DTSTART:20071104T020000 | ||
| 700 | RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU | ||
| 701 | TZOFFSETFROM:-0400 | ||
| 702 | TZOFFSETTO:-0500 | ||
| 703 | TZNAME:EST | ||
| 704 | END:STANDARD | ||
| 705 | END:VTIMEZONE | ||
| 706 | " | ||
| 707 | :parser icalendar-parse-component | ||
| 708 | :printer icalendar-print-component-node | ||
| 709 | :source rfc5545-sec3.6.5/1) | ||
| 710 | |||
| 711 | (ipt:parse/print-test | ||
| 712 | "BEGIN:VTIMEZONE | ||
| 713 | TZID:America/New_York | ||
| 714 | LAST-MODIFIED:20050809T050000Z | ||
| 715 | BEGIN:STANDARD | ||
| 716 | DTSTART:20071104T020000 | ||
| 717 | TZOFFSETFROM:-0400 | ||
| 718 | TZOFFSETTO:-0500 | ||
| 719 | TZNAME:EST | ||
| 720 | END:STANDARD | ||
| 721 | BEGIN:DAYLIGHT | ||
| 722 | DTSTART:20070311T020000 | ||
| 723 | TZOFFSETFROM:-0500 | ||
| 724 | TZOFFSETTO:-0400 | ||
| 725 | TZNAME:EDT | ||
| 726 | END:DAYLIGHT | ||
| 727 | END:VTIMEZONE | ||
| 728 | " | ||
| 729 | :parser icalendar-parse-component | ||
| 730 | :printer icalendar-print-component-node | ||
| 731 | :source rfc5545-sec3.6.5/2) | ||
| 732 | |||
| 733 | (ipt:parse/print-test | ||
| 734 | "BEGIN:VTIMEZONE | ||
| 735 | TZID:America/New_York | ||
| 736 | LAST-MODIFIED:20050809T050000Z | ||
| 737 | TZURL:http://zones.example.com/tz/America-New_York.ics | ||
| 738 | BEGIN:STANDARD | ||
| 739 | DTSTART:20071104T020000 | ||
| 740 | RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU | ||
| 741 | TZOFFSETFROM:-0400 | ||
| 742 | TZOFFSETTO:-0500 | ||
| 743 | TZNAME:EST | ||
| 744 | END:STANDARD | ||
| 745 | BEGIN:DAYLIGHT | ||
| 746 | DTSTART:20070311T020000 | ||
| 747 | RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU | ||
| 748 | TZOFFSETFROM:-0500 | ||
| 749 | TZOFFSETTO:-0400 | ||
| 750 | TZNAME:EDT | ||
| 751 | END:DAYLIGHT | ||
| 752 | END:VTIMEZONE | ||
| 753 | " | ||
| 754 | :parser icalendar-parse-component | ||
| 755 | :printer icalendar-print-component-node | ||
| 756 | :source rfc5545-sec3.6.5/3) | ||
| 757 | |||
| 758 | (ipt:parse/print-test | ||
| 759 | "BEGIN:VTIMEZONE | ||
| 760 | TZID:Fictitious | ||
| 761 | LAST-MODIFIED:19870101T000000Z | ||
| 762 | BEGIN:STANDARD | ||
| 763 | DTSTART:19671029T020000 | ||
| 764 | RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 | ||
| 765 | TZOFFSETFROM:-0400 | ||
| 766 | TZOFFSETTO:-0500 | ||
| 767 | TZNAME:EST | ||
| 768 | END:STANDARD | ||
| 769 | BEGIN:DAYLIGHT | ||
| 770 | DTSTART:19870405T020000 | ||
| 771 | RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=19980404T070000Z | ||
| 772 | TZOFFSETFROM:-0500 | ||
| 773 | TZOFFSETTO:-0400 | ||
| 774 | TZNAME:EDT | ||
| 775 | END:DAYLIGHT | ||
| 776 | END:VTIMEZONE | ||
| 777 | " | ||
| 778 | :parser icalendar-parse-component | ||
| 779 | :printer icalendar-print-component-node | ||
| 780 | :source rfc5545-sec3.6.5/4) | ||
| 781 | |||
| 782 | (ipt:parse/print-test | ||
| 783 | "BEGIN:VTIMEZONE | ||
| 784 | TZID:Fictitious | ||
| 785 | LAST-MODIFIED:19870101T000000Z | ||
| 786 | BEGIN:STANDARD | ||
| 787 | DTSTART:19671029T020000 | ||
| 788 | RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 | ||
| 789 | TZOFFSETFROM:-0400 | ||
| 790 | TZOFFSETTO:-0500 | ||
| 791 | TZNAME:EST | ||
| 792 | END:STANDARD | ||
| 793 | BEGIN:DAYLIGHT | ||
| 794 | DTSTART:19870405T020000 | ||
| 795 | RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=19980404T070000Z | ||
| 796 | TZOFFSETFROM:-0500 | ||
| 797 | TZOFFSETTO:-0400 | ||
| 798 | TZNAME:EDT | ||
| 799 | END:DAYLIGHT | ||
| 800 | BEGIN:DAYLIGHT | ||
| 801 | DTSTART:19990424T020000 | ||
| 802 | RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=4 | ||
| 803 | TZOFFSETFROM:-0500 | ||
| 804 | TZOFFSETTO:-0400 | ||
| 805 | TZNAME:EDT | ||
| 806 | END:DAYLIGHT | ||
| 807 | END:VTIMEZONE | ||
| 808 | " | ||
| 809 | :parser icalendar-parse-component | ||
| 810 | :printer icalendar-print-component-node | ||
| 811 | :source rfc5545-sec3.6.5/5) | ||
| 812 | |||
| 813 | (ipt:parse/print-test | ||
| 814 | "BEGIN:VALARM | ||
| 815 | TRIGGER;VALUE=DATE-TIME:19970317T133000Z | ||
| 816 | REPEAT:4 | ||
| 817 | DURATION:PT15M | ||
| 818 | ACTION:AUDIO | ||
| 819 | ATTACH;FMTTYPE=audio/basic:ftp://example.com/pub/sounds/bell-01.aud | ||
| 820 | END:VALARM | ||
| 821 | " | ||
| 822 | :parser icalendar-parse-component | ||
| 823 | :printer icalendar-print-component-node | ||
| 824 | :source rfc5545-sec3.6.6/1) | ||
| 825 | |||
| 826 | (ipt:parse/print-test | ||
| 827 | "BEGIN:VALARM | ||
| 828 | TRIGGER:-PT30M | ||
| 829 | REPEAT:2 | ||
| 830 | DURATION:PT15M | ||
| 831 | ACTION:DISPLAY | ||
| 832 | DESCRIPTION:Breakfast meeting with executive\\nteam at 8:30 AM EST. | ||
| 833 | END:VALARM | ||
| 834 | " | ||
| 835 | :parser icalendar-parse-component | ||
| 836 | :printer icalendar-print-component-node | ||
| 837 | :source rfc5545-sec3.6.6/2) | ||
| 838 | |||
| 839 | (ipt:parse/print-test | ||
| 840 | "BEGIN:VALARM | ||
| 841 | TRIGGER;RELATED=END:-P2D | ||
| 842 | ACTION:EMAIL | ||
| 843 | ATTENDEE:mailto:john_doe@example.com | ||
| 844 | SUMMARY:*** REMINDER: SEND AGENDA FOR WEEKLY STAFF MEETING *** | ||
| 845 | DESCRIPTION:A draft agenda needs to be sent out to the attendees to the weekly managers meeting (MGR-LIST). Attached is a pointer the document template for the agenda file. | ||
| 846 | ATTACH;FMTTYPE=application/msword:http://example.com/templates/agenda.doc | ||
| 847 | END:VALARM | ||
| 848 | " | ||
| 849 | :parser icalendar-parse-component | ||
| 850 | :printer icalendar-print-component-node | ||
| 851 | :source rfc5545-sec3.6.6/3) | ||
| 852 | |||
| 853 | (ipt:parse/print-test | ||
| 854 | "CALSCALE:GREGORIAN\n" | ||
| 855 | :parser icalendar-parse-property | ||
| 856 | :printer icalendar-print-property-node | ||
| 857 | :source rfc5545-sec3.7.1/1) | ||
| 858 | |||
| 859 | (ipt:parse/print-test | ||
| 860 | "METHOD:REQUEST\n" | ||
| 861 | :parser icalendar-parse-property | ||
| 862 | :printer icalendar-print-property-node | ||
| 863 | :source rfc5545-sec3.7.2/1) | ||
| 864 | |||
| 865 | (ipt:parse/print-test | ||
| 866 | "PRODID:-//ABC Corporation//NONSGML My Product//EN\n" | ||
| 867 | :parser icalendar-parse-property | ||
| 868 | :printer icalendar-print-property-node | ||
| 869 | :source rfc5545-sec3.7.3/1) | ||
| 870 | |||
| 871 | (ipt:parse/print-test | ||
| 872 | "VERSION:2.0\n" | ||
| 873 | :parser icalendar-parse-property | ||
| 874 | :printer icalendar-print-property-node | ||
| 875 | :source rfc5545-sec3.7./1) | ||
| 876 | |||
| 877 | (ipt:parse/print-test | ||
| 878 | "ATTACH:CID:jsmith.part3.960817T083000.xyzMail@example.com\n" | ||
| 879 | :parser icalendar-parse-property | ||
| 880 | :printer icalendar-print-property-node | ||
| 881 | :source rfc5545-sec3.8.1.1/1) | ||
| 882 | |||
| 883 | (ipt:parse/print-test | ||
| 884 | "ATTACH;FMTTYPE=application/postscript:ftp://example.com/pub/reports/r-960812.ps\n" | ||
| 885 | :parser icalendar-parse-property | ||
| 886 | :printer icalendar-print-property-node | ||
| 887 | :source rfc5545-sec3.8.1.1/2) | ||
| 888 | |||
| 889 | (ipt:parse/print-test | ||
| 890 | "CATEGORIES:APPOINTMENT,EDUCATION\n" | ||
| 891 | :parser icalendar-parse-property | ||
| 892 | :printer icalendar-print-property-node | ||
| 893 | :source rfc5545-sec3.8.1.2/1) | ||
| 894 | |||
| 895 | (ipt:parse/print-test | ||
| 896 | "CATEGORIES:MEETING\n" | ||
| 897 | :parser icalendar-parse-property | ||
| 898 | :printer icalendar-print-property-node | ||
| 899 | :source rfc5545-sec3.8.1.2/2) | ||
| 900 | |||
| 901 | (ipt:parse/print-test | ||
| 902 | "CLASS:PUBLIC\n" | ||
| 903 | :parser icalendar-parse-property | ||
| 904 | :printer icalendar-print-property-node | ||
| 905 | :source rfc5545-sec3.8.1.3/1) | ||
| 906 | |||
| 907 | (ipt:parse/print-test | ||
| 908 | "COMMENT:The meeting really needs to include both ourselves and the customer. We can't hold this meeting without them. As a matter of fact\\, the venue for the meeting ought to be at their site. - - John\n" | ||
| 909 | :parser icalendar-parse-property | ||
| 910 | :printer icalendar-print-property-node | ||
| 911 | :source rfc5545-sec3.8.1.4/1) | ||
| 912 | |||
| 913 | (ipt:parse/print-test | ||
| 914 | "DESCRIPTION:Meeting to provide technical review for \"Phoenix\" design.\\nHappy Face Conference Room. Phoenix design team MUST attend this meeting.\\nRSVP to team leader.\n" | ||
| 915 | :parser icalendar-parse-property | ||
| 916 | :printer icalendar-print-property-node | ||
| 917 | :source rfc5545-sec3.8.1.5/1) | ||
| 918 | |||
| 919 | (ipt:parse/print-test | ||
| 920 | "GEO:37.386013;-122.082932\n" | ||
| 921 | :parser icalendar-parse-property | ||
| 922 | :printer icalendar-print-property-node | ||
| 923 | :source rfc5545-sec3.8.1.6/1) | ||
| 924 | |||
| 925 | (ipt:parse/print-test | ||
| 926 | "LOCATION:Conference Room - F123\\, Bldg. 002\n" | ||
| 927 | :parser icalendar-parse-property | ||
| 928 | :printer icalendar-print-property-node | ||
| 929 | :source rfc5545-sec3.8.1.7/1) | ||
| 930 | |||
| 931 | (ipt:parse/print-test | ||
| 932 | "LOCATION;ALTREP=\"http://xyzcorp.com/conf-rooms/f123.vcf\":Conference Room - F123\\, Bldg. 002\n" | ||
| 933 | :parser icalendar-parse-property | ||
| 934 | :printer icalendar-print-property-node | ||
| 935 | :source rfc5545-sec3.8.1.7/2) | ||
| 936 | |||
| 937 | (ipt:parse/print-test | ||
| 938 | "PERCENT-COMPLETE:39\n" | ||
| 939 | :parser icalendar-parse-property | ||
| 940 | :printer icalendar-print-property-node | ||
| 941 | :source rfc5545-sec3.8.1.8/1) | ||
| 942 | |||
| 943 | (ipt:parse/print-test | ||
| 944 | "PRIORITY:1\n" | ||
| 945 | :parser icalendar-parse-property | ||
| 946 | :printer icalendar-print-property-node | ||
| 947 | :source rfc5545-sec3.8.1.9/1) | ||
| 948 | |||
| 949 | (ipt:parse/print-test | ||
| 950 | "PRIORITY:2\n" | ||
| 951 | :parser icalendar-parse-property | ||
| 952 | :printer icalendar-print-property-node | ||
| 953 | :source rfc5545-sec3.8.1.9/2) | ||
| 954 | |||
| 955 | (ipt:parse/print-test | ||
| 956 | "PRIORITY:0\n" | ||
| 957 | :parser icalendar-parse-property | ||
| 958 | :printer icalendar-print-property-node | ||
| 959 | :source rfc5545-sec3.8.1.9/3) | ||
| 960 | |||
| 961 | (ipt:parse/print-test | ||
| 962 | "RESOURCES:EASEL,PROJECTOR,VCR\n" | ||
| 963 | :parser icalendar-parse-property | ||
| 964 | :printer icalendar-print-property-node | ||
| 965 | :source rfc5545-sec3.8.1.10/1) | ||
| 966 | |||
| 967 | (ipt:parse/print-test | ||
| 968 | "RESOURCES;LANGUAGE=fr:Nettoyeur haute pression\n" | ||
| 969 | :parser icalendar-parse-property | ||
| 970 | :printer icalendar-print-property-node | ||
| 971 | :source rfc5545-sec3.8.1.10/2) | ||
| 972 | |||
| 973 | (ipt:parse/print-test | ||
| 974 | "STATUS:TENTATIVE\n" | ||
| 975 | :parser icalendar-parse-property | ||
| 976 | :printer icalendar-print-property-node | ||
| 977 | :source rfc5545-sec3.8.1.11/1) | ||
| 978 | |||
| 979 | (ipt:parse/print-test | ||
| 980 | "STATUS:NEEDS-ACTION\n" | ||
| 981 | :parser icalendar-parse-property | ||
| 982 | :printer icalendar-print-property-node | ||
| 983 | :source rfc5545-sec3.8.1.11/2) | ||
| 984 | |||
| 985 | (ipt:parse/print-test | ||
| 986 | "STATUS:DRAFT\n" | ||
| 987 | :parser icalendar-parse-property | ||
| 988 | :printer icalendar-print-property-node | ||
| 989 | :source rfc5545-sec3.8.1.11/3) | ||
| 990 | |||
| 991 | (ipt:parse/print-test | ||
| 992 | "SUMMARY:Department Party\n" | ||
| 993 | :parser icalendar-parse-property | ||
| 994 | :printer icalendar-print-property-node | ||
| 995 | :source rfc5545-sec3.8.1.12/1) | ||
| 996 | |||
| 997 | (ipt:parse/print-test | ||
| 998 | "COMPLETED:19960401T150000Z\n" | ||
| 999 | :parser icalendar-parse-property | ||
| 1000 | :printer icalendar-print-property-node | ||
| 1001 | :source rfc5545-sec3.8.2.1/1) | ||
| 1002 | |||
| 1003 | (ipt:parse/print-test | ||
| 1004 | "DTEND:19960401T150000Z\n" | ||
| 1005 | :parser icalendar-parse-property | ||
| 1006 | :printer icalendar-print-property-node | ||
| 1007 | :source rfc5545-sec3.8.2.2/1) | ||
| 1008 | |||
| 1009 | (ipt:parse/print-test | ||
| 1010 | "DTEND;VALUE=DATE:19980704\n" | ||
| 1011 | :parser icalendar-parse-property | ||
| 1012 | :printer icalendar-print-property-node | ||
| 1013 | :source rfc5545-sec3.8.2.2/2) | ||
| 1014 | |||
| 1015 | (ipt:parse/print-test | ||
| 1016 | "DUE:19980430T000000Z\n" | ||
| 1017 | :parser icalendar-parse-property | ||
| 1018 | :printer icalendar-print-property-node | ||
| 1019 | :source rfc5545-sec3.8.2.3/1) | ||
| 1020 | |||
| 1021 | (ipt:parse/print-test | ||
| 1022 | "DTSTART:19980118T073000Z\n" | ||
| 1023 | :parser icalendar-parse-property | ||
| 1024 | :printer icalendar-print-property-node | ||
| 1025 | :source rfc5545-sec3.8.2.4/1) | ||
| 1026 | |||
| 1027 | (ipt:parse/print-test | ||
| 1028 | "DURATION:PT1H0M0S\n" | ||
| 1029 | ;; 0M and 0S are not re-printed because they don't contribute to the duration: | ||
| 1030 | :expected "DURATION:PT1H\n" | ||
| 1031 | :parser icalendar-parse-property | ||
| 1032 | :printer icalendar-print-property-node | ||
| 1033 | :source rfc5545-sec3.8.2.5/1) | ||
| 1034 | |||
| 1035 | (ipt:parse/print-test | ||
| 1036 | "DURATION:PT15M\n" | ||
| 1037 | :parser icalendar-parse-property | ||
| 1038 | :printer icalendar-print-property-node | ||
| 1039 | :source rfc5545-sec3.8.2.5/2) | ||
| 1040 | |||
| 1041 | (ipt:parse/print-test | ||
| 1042 | "FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:19970308T160000Z/PT8H30M\n" | ||
| 1043 | :parser icalendar-parse-property | ||
| 1044 | :printer icalendar-print-property-node | ||
| 1045 | :source rfc5545-sec3.8.2.6/1) | ||
| 1046 | |||
| 1047 | (ipt:parse/print-test | ||
| 1048 | "FREEBUSY;FBTYPE=FREE:19970308T160000Z/PT3H,19970308T200000Z/PT1H\n" | ||
| 1049 | :parser icalendar-parse-property | ||
| 1050 | :printer icalendar-print-property-node | ||
| 1051 | :source rfc5545-sec3.8.2.6/2) | ||
| 1052 | |||
| 1053 | (ipt:parse/print-test | ||
| 1054 | "FREEBUSY;FBTYPE=FREE:19970308T160000Z/PT3H,19970308T200000Z/PT1H,19970308T230000Z/19970309T000000Z\n" | ||
| 1055 | :parser icalendar-parse-property | ||
| 1056 | :printer icalendar-print-property-node | ||
| 1057 | :source rfc5545-sec3.8.2.6/3) | ||
| 1058 | |||
| 1059 | (ipt:parse/print-test | ||
| 1060 | "TRANSP:TRANSPARENT\n" | ||
| 1061 | :parser icalendar-parse-property | ||
| 1062 | :printer icalendar-print-property-node | ||
| 1063 | :source rfc5545-sec3.8.2.7/1) | ||
| 1064 | |||
| 1065 | (ipt:parse/print-test | ||
| 1066 | "TRANSP:OPAQUE\n" | ||
| 1067 | :parser icalendar-parse-property | ||
| 1068 | :printer icalendar-print-property-node | ||
| 1069 | :source rfc5545-sec3.8.2.7/2) | ||
| 1070 | |||
| 1071 | (ipt:parse/print-test | ||
| 1072 | "TZID:America/New_York\n" | ||
| 1073 | :parser icalendar-parse-property | ||
| 1074 | :printer icalendar-print-property-node | ||
| 1075 | :source rfc5545-sec3.8.3.1/1) | ||
| 1076 | |||
| 1077 | (ipt:parse/print-test | ||
| 1078 | "TZID:America/New_York\n" | ||
| 1079 | :parser icalendar-parse-property | ||
| 1080 | :printer icalendar-print-property-node | ||
| 1081 | :source rfc5545-sec3.8.3.1/2) | ||
| 1082 | |||
| 1083 | (ipt:parse/print-test | ||
| 1084 | "TZID:/example.org/America/New_York\n" | ||
| 1085 | :parser icalendar-parse-property | ||
| 1086 | :printer icalendar-print-property-node | ||
| 1087 | :source rfc5545-sec3.8.3.1/3) | ||
| 1088 | |||
| 1089 | (ipt:parse/print-test | ||
| 1090 | "TZNAME:EST\n" | ||
| 1091 | :parser icalendar-parse-property | ||
| 1092 | :printer icalendar-print-property-node | ||
| 1093 | :source rfc5545-sec3.8.3.2/1) | ||
| 1094 | |||
| 1095 | (ipt:parse/print-test | ||
| 1096 | "TZNAME;LANGUAGE=fr-CA:HNE\n" | ||
| 1097 | :parser icalendar-parse-property | ||
| 1098 | :printer icalendar-print-property-node | ||
| 1099 | :source rfc5545-sec3.8.3.2/2) | ||
| 1100 | |||
| 1101 | (ipt:parse/print-test | ||
| 1102 | "TZOFFSETFROM:-0500\n" | ||
| 1103 | :parser icalendar-parse-property | ||
| 1104 | :printer icalendar-print-property-node | ||
| 1105 | :source rfc5545-sec3.8.3.3/1) | ||
| 1106 | |||
| 1107 | (ipt:parse/print-test | ||
| 1108 | "TZOFFSETFROM:+1345\n" | ||
| 1109 | :parser icalendar-parse-property | ||
| 1110 | :printer icalendar-print-property-node | ||
| 1111 | :source rfc5545-sec3.8.3.3/2) | ||
| 1112 | |||
| 1113 | (ipt:parse/print-test | ||
| 1114 | "TZOFFSETTO:-0400\n" | ||
| 1115 | :parser icalendar-parse-property | ||
| 1116 | :printer icalendar-print-property-node | ||
| 1117 | :source rfc5545-sec3.8.3.4/1) | ||
| 1118 | |||
| 1119 | (ipt:parse/print-test | ||
| 1120 | "TZOFFSETTO:+1245\n" | ||
| 1121 | :parser icalendar-parse-property | ||
| 1122 | :printer icalendar-print-property-node | ||
| 1123 | :source rfc5545-sec3.8.3.4/2) | ||
| 1124 | |||
| 1125 | (ipt:parse/print-test | ||
| 1126 | "TZURL:http://timezones.example.org/tz/America-Los_Angeles.ics\n" | ||
| 1127 | :parser icalendar-parse-property | ||
| 1128 | :printer icalendar-print-property-node | ||
| 1129 | :source rfc5545-sec3.8.3.5/1) | ||
| 1130 | |||
| 1131 | (ipt:parse/print-test | ||
| 1132 | "ATTENDEE;MEMBER=\"mailto:DEV-GROUP@example.com\":mailto:joecool@example.com\n" | ||
| 1133 | :parser icalendar-parse-property | ||
| 1134 | :printer icalendar-print-property-node | ||
| 1135 | :source rfc5545-sec3.8.4.1/1) | ||
| 1136 | |||
| 1137 | (ipt:parse/print-test | ||
| 1138 | "ATTENDEE;DELEGATED-FROM=\"mailto:immud@example.com\":mailto:ildoit@example.com\n" | ||
| 1139 | :parser icalendar-parse-property | ||
| 1140 | :printer icalendar-print-property-node | ||
| 1141 | :source rfc5545-sec3.8.4.1/2) | ||
| 1142 | |||
| 1143 | (ipt:parse/print-test | ||
| 1144 | "ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=TENTATIVE;CN=Henry Cabot:mailto:hcabot@example.com\n" | ||
| 1145 | :parser icalendar-parse-property | ||
| 1146 | :printer icalendar-print-property-node | ||
| 1147 | :source rfc5545-sec3.8.4.1/3) | ||
| 1148 | |||
| 1149 | (ipt:parse/print-test | ||
| 1150 | "ATTENDEE;ROLE=REQ-PARTICIPANT;DELEGATED-FROM=\"mailto:bob@example.com\";PARTSTAT=ACCEPTED;CN=Jane Doe:mailto:jdoe@example.com\n" | ||
| 1151 | :parser icalendar-parse-property | ||
| 1152 | :printer icalendar-print-property-node | ||
| 1153 | :source rfc5545-sec3.8.4.1/4) | ||
| 1154 | |||
| 1155 | (ipt:parse/print-test | ||
| 1156 | "ATTENDEE;CN=John Smith;DIR=\"ldap://example.com:6666/o=ABC%20Industries,c=US???(cn=Jim%20Dolittle)\":mailto:jimdo@example.com\n" | ||
| 1157 | :parser icalendar-parse-property | ||
| 1158 | :printer icalendar-print-property-node | ||
| 1159 | :source rfc5545-sec3.8.4.1/5) | ||
| 1160 | |||
| 1161 | (ipt:parse/print-test | ||
| 1162 | "ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=TENTATIVE;DELEGATED-FROM=\"mailto:iamboss@example.com\";CN=Henry Cabot:mailto:hcabot@example.com\n" | ||
| 1163 | :parser icalendar-parse-property | ||
| 1164 | :printer icalendar-print-property-node | ||
| 1165 | :source rfc5545-sec3.8.4.1/6) | ||
| 1166 | |||
| 1167 | (ipt:parse/print-test | ||
| 1168 | "ATTENDEE;ROLE=NON-PARTICIPANT;PARTSTAT=DELEGATED;DELEGATED-TO=\"mailto:hcabot@example.com\";CN=The Big Cheese:mailto:iamboss@example.com\n" | ||
| 1169 | :parser icalendar-parse-property | ||
| 1170 | :printer icalendar-print-property-node | ||
| 1171 | :source rfc5545-sec3.8.4.1/7) | ||
| 1172 | |||
| 1173 | (ipt:parse/print-test | ||
| 1174 | "ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=Jane Doe:mailto:jdoe@example.com\n" | ||
| 1175 | :parser icalendar-parse-property | ||
| 1176 | :printer icalendar-print-property-node | ||
| 1177 | :source rfc5545-sec3.8.4.1/8) | ||
| 1178 | |||
| 1179 | (ipt:parse/print-test | ||
| 1180 | ;; Corrected. Original lacks quotes around SENT-BY address. | ||
| 1181 | "ATTENDEE;SENT-BY=\"mailto:jan_doe@example.com\";CN=John Smith:mailto:jsmith@example.com\n" | ||
| 1182 | :parser icalendar-parse-property | ||
| 1183 | :printer icalendar-print-property-node | ||
| 1184 | :source rfc5545-sec3.8.4.1/9) | ||
| 1185 | |||
| 1186 | (ipt:parse/print-test | ||
| 1187 | "CONTACT:Jim Dolittle\\, ABC Industries\\, +1-919-555-1234\n" | ||
| 1188 | :parser icalendar-parse-property | ||
| 1189 | :printer icalendar-print-property-node | ||
| 1190 | :source rfc5545-sec3.8.4.2/1) | ||
| 1191 | |||
| 1192 | (ipt:parse/print-test | ||
| 1193 | ;; Corrected. Original contained unallowed backslash in ldap: URI | ||
| 1194 | "CONTACT;ALTREP=\"ldap://example.com:6666/o=ABC%20Industries,c=US???(cn=Jim%20Dolittle)\":Jim Dolittle\\, ABC Industries\\,+1-919-555-1234\n" | ||
| 1195 | :parser icalendar-parse-property | ||
| 1196 | :printer icalendar-print-property-node | ||
| 1197 | :source rfc5545-sec3.8.4.2/2) | ||
| 1198 | |||
| 1199 | (ipt:parse/print-test | ||
| 1200 | "CONTACT;ALTREP=\"CID:part3.msg970930T083000SILVER@example.com\":Jim Dolittle\\, ABC Industries\\, +1-919-555-1234\n" | ||
| 1201 | :parser icalendar-parse-property | ||
| 1202 | :printer icalendar-print-property-node | ||
| 1203 | :source rfc5545-sec3.8.4.2/3) | ||
| 1204 | |||
| 1205 | (ipt:parse/print-test | ||
| 1206 | "CONTACT;ALTREP=\"http://example.com/pdi/jdoe.vcf\":Jim Dolittle\\, ABC Industries\\, +1-919-555-1234\n" | ||
| 1207 | :parser icalendar-parse-property | ||
| 1208 | :printer icalendar-print-property-node | ||
| 1209 | :source rfc5545-sec3.8.4.2/4) | ||
| 1210 | |||
| 1211 | (ipt:parse/print-test | ||
| 1212 | "ORGANIZER;CN=John Smith:mailto:jsmith@example.com\n" | ||
| 1213 | :parser icalendar-parse-property | ||
| 1214 | :printer icalendar-print-property-node | ||
| 1215 | :source rfc5545-sec3.8.4.3/1) | ||
| 1216 | |||
| 1217 | (ipt:parse/print-test | ||
| 1218 | "ORGANIZER;CN=JohnSmith;DIR=\"ldap://example.com:6666/o=DC%20Associates,c=US???(cn=John%20Smith)\":mailto:jsmith@example.com\n" | ||
| 1219 | :parser icalendar-parse-property | ||
| 1220 | :printer icalendar-print-property-node | ||
| 1221 | :source rfc5545-sec3.8.4.3/2) | ||
| 1222 | |||
| 1223 | (ipt:parse/print-test | ||
| 1224 | "ORGANIZER;SENT-BY=\"mailto:jane_doe@example.com\":mailto:jsmith@example.com\n" | ||
| 1225 | :parser icalendar-parse-property | ||
| 1226 | :printer icalendar-print-property-node | ||
| 1227 | :source rfc5545-sec3.8.4.3/3) | ||
| 1228 | |||
| 1229 | (ipt:parse/print-test | ||
| 1230 | "RECURRENCE-ID;VALUE=DATE:19960401\n" | ||
| 1231 | :parser icalendar-parse-property | ||
| 1232 | :printer icalendar-print-property-node | ||
| 1233 | :source rfc5545-sec3.8.4.4/1) | ||
| 1234 | |||
| 1235 | (ipt:parse/print-test | ||
| 1236 | "RECURRENCE-ID;RANGE=THISANDFUTURE:19960120T120000Z\n" | ||
| 1237 | :parser icalendar-parse-property | ||
| 1238 | :printer icalendar-print-property-node | ||
| 1239 | :source rfc5545-sec3.8.4.4/2) | ||
| 1240 | |||
| 1241 | (ipt:parse/print-test | ||
| 1242 | "RELATED-TO:jsmith.part7.19960817T083000.xyzMail@example.com\n" | ||
| 1243 | :parser icalendar-parse-property | ||
| 1244 | :printer icalendar-print-property-node | ||
| 1245 | :source rfc5545-sec3.8.4.5/1) | ||
| 1246 | |||
| 1247 | (ipt:parse/print-test | ||
| 1248 | "RELATED-TO:19960401-080045-4000F192713-0052@example.com\n" | ||
| 1249 | :parser icalendar-parse-property | ||
| 1250 | :printer icalendar-print-property-node | ||
| 1251 | :source rfc5545-sec3.8.4.5/2) | ||
| 1252 | |||
| 1253 | (ipt:parse/print-test | ||
| 1254 | "URL:http://example.com/pub/calendars/jsmith/mytime.ics\n" | ||
| 1255 | :parser icalendar-parse-property | ||
| 1256 | :printer icalendar-print-property-node | ||
| 1257 | :source rfc5545-sec3.8.4.6/1) | ||
| 1258 | |||
| 1259 | (ipt:parse/print-test | ||
| 1260 | "UID:19960401T080045Z-4000F192713-0052@example.com\n" | ||
| 1261 | :parser icalendar-parse-property | ||
| 1262 | :printer icalendar-print-property-node | ||
| 1263 | :source rfc5545-sec3.8.4.7/1) | ||
| 1264 | |||
| 1265 | (ipt:parse/print-test | ||
| 1266 | "EXDATE:19960402T010000Z,19960403T010000Z,19960404T010000Z\n" | ||
| 1267 | :parser icalendar-parse-property | ||
| 1268 | :printer icalendar-print-property-node | ||
| 1269 | :source rfc5545-sec3.8.5.1/1) | ||
| 1270 | |||
| 1271 | (ipt:parse/print-test | ||
| 1272 | "RDATE:19970714T123000Z\n" | ||
| 1273 | :parser icalendar-parse-property | ||
| 1274 | :printer icalendar-print-property-node | ||
| 1275 | :source rfc5545-sec3.8.5.2/1) | ||
| 1276 | |||
| 1277 | (ipt:parse/print-test | ||
| 1278 | "RDATE;TZID=America/New_York:19970714T083000\n" | ||
| 1279 | :parser icalendar-parse-property | ||
| 1280 | :printer icalendar-print-property-node | ||
| 1281 | :source rfc5545-sec3.8.5.2/2) | ||
| 1282 | |||
| 1283 | (ipt:parse/print-test | ||
| 1284 | "RDATE;VALUE=PERIOD:19960403T020000Z/19960403T040000Z,19960404T010000Z/PT3H\n" | ||
| 1285 | :parser icalendar-parse-property | ||
| 1286 | :printer icalendar-print-property-node | ||
| 1287 | :source rfc5545-sec3.8.5.2/3) | ||
| 1288 | |||
| 1289 | (ipt:parse/print-test | ||
| 1290 | "RDATE;VALUE=DATE:19970101,19970120,19970217,19970421,19970526,19970704,19970901,19971014,19971128,19971129,19971225\n" | ||
| 1291 | :parser icalendar-parse-property | ||
| 1292 | :printer icalendar-print-property-node | ||
| 1293 | :source rfc5545-sec3.8.5.2/4) | ||
| 1294 | |||
| 1295 | (ipt:parse/print-test | ||
| 1296 | "RRULE:FREQ=DAILY;COUNT=10\n" | ||
| 1297 | :parser icalendar-parse-property | ||
| 1298 | :printer icalendar-print-property-node | ||
| 1299 | :source rfc5545-sec3.8.5.3/1) | ||
| 1300 | |||
| 1301 | (ipt:parse/print-test | ||
| 1302 | "RRULE:FREQ=DAILY;UNTIL=19971224T000000Z\n" | ||
| 1303 | :parser icalendar-parse-property | ||
| 1304 | :printer icalendar-print-property-node | ||
| 1305 | :source rfc5545-sec3.8.5.3/2) | ||
| 1306 | |||
| 1307 | (ipt:parse/print-test | ||
| 1308 | "RRULE:FREQ=DAILY;INTERVAL=2\n" | ||
| 1309 | :parser icalendar-parse-property | ||
| 1310 | :printer icalendar-print-property-node | ||
| 1311 | :source rfc5545-sec3.8.5.3/3) | ||
| 1312 | |||
| 1313 | (ipt:parse/print-test | ||
| 1314 | "RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5\n" | ||
| 1315 | :parser icalendar-parse-property | ||
| 1316 | :printer icalendar-print-property-node | ||
| 1317 | :source rfc5545-sec3.8.5.3/4) | ||
| 1318 | |||
| 1319 | (ipt:parse/print-test | ||
| 1320 | "RRULE:FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA\n" | ||
| 1321 | :parser icalendar-parse-property | ||
| 1322 | :printer icalendar-print-property-node | ||
| 1323 | :source rfc5545-sec3.8.5.3/5) | ||
| 1324 | |||
| 1325 | (ipt:parse/print-test | ||
| 1326 | "RRULE:FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1\n" | ||
| 1327 | :parser icalendar-parse-property | ||
| 1328 | :printer icalendar-print-property-node | ||
| 1329 | :source rfc5545-sec3.8.5.3/6) | ||
| 1330 | |||
| 1331 | (ipt:parse/print-test | ||
| 1332 | "RRULE:FREQ=WEEKLY;COUNT=10\n" | ||
| 1333 | :parser icalendar-parse-property | ||
| 1334 | :printer icalendar-print-property-node | ||
| 1335 | :source rfc5545-sec3.8.5.3/7) | ||
| 1336 | |||
| 1337 | (ipt:parse/print-test | ||
| 1338 | "RRULE:FREQ=WEEKLY;UNTIL=19971224T000000Z\n" | ||
| 1339 | :parser icalendar-parse-property | ||
| 1340 | :printer icalendar-print-property-node | ||
| 1341 | :source rfc5545-sec3.8.5.3/8) | ||
| 1342 | |||
| 1343 | (ipt:parse/print-test | ||
| 1344 | "RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU\n" | ||
| 1345 | :parser icalendar-parse-property | ||
| 1346 | :printer icalendar-print-property-node | ||
| 1347 | :source rfc5545-sec3.8.5.3/9) | ||
| 1348 | |||
| 1349 | (ipt:parse/print-test | ||
| 1350 | "RRULE:FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH\n" | ||
| 1351 | :parser icalendar-parse-property | ||
| 1352 | :printer icalendar-print-property-node | ||
| 1353 | :source rfc5545-sec3.8.5.3/10) | ||
| 1354 | |||
| 1355 | (ipt:parse/print-test | ||
| 1356 | "RRULE:FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH\n" | ||
| 1357 | :parser icalendar-parse-property | ||
| 1358 | :printer icalendar-print-property-node | ||
| 1359 | :source rfc5545-sec3.8.5.3/11) | ||
| 1360 | |||
| 1361 | (ipt:parse/print-test | ||
| 1362 | "RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR\n" | ||
| 1363 | :parser icalendar-parse-property | ||
| 1364 | :printer icalendar-print-property-node | ||
| 1365 | :source rfc5545-sec3.8.5.3/12) | ||
| 1366 | |||
| 1367 | (ipt:parse/print-test | ||
| 1368 | "RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH\n" | ||
| 1369 | :parser icalendar-parse-property | ||
| 1370 | :printer icalendar-print-property-node | ||
| 1371 | :source rfc5545-sec3.8.5.3/13) | ||
| 1372 | |||
| 1373 | (ipt:parse/print-test | ||
| 1374 | "RRULE:FREQ=MONTHLY;COUNT=10;BYDAY=1FR\n" | ||
| 1375 | :parser icalendar-parse-property | ||
| 1376 | :printer icalendar-print-property-node | ||
| 1377 | :source rfc5545-sec3.8.5.3/14) | ||
| 1378 | |||
| 1379 | (ipt:parse/print-test | ||
| 1380 | "RRULE:FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR\n" | ||
| 1381 | :parser icalendar-parse-property | ||
| 1382 | :printer icalendar-print-property-node | ||
| 1383 | :source rfc5545-sec3.8.5.3/15) | ||
| 1384 | |||
| 1385 | (ipt:parse/print-test | ||
| 1386 | "RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU\n" | ||
| 1387 | :parser icalendar-parse-property | ||
| 1388 | :printer icalendar-print-property-node | ||
| 1389 | :source rfc5545-sec3.8.5.3/16) | ||
| 1390 | |||
| 1391 | (ipt:parse/print-test | ||
| 1392 | "RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO\n" | ||
| 1393 | :parser icalendar-parse-property | ||
| 1394 | :printer icalendar-print-property-node | ||
| 1395 | :source rfc5545-sec3.8.5.3/17) | ||
| 1396 | |||
| 1397 | (ipt:parse/print-test | ||
| 1398 | "RRULE:FREQ=MONTHLY;BYMONTHDAY=-3\n" | ||
| 1399 | :parser icalendar-parse-property | ||
| 1400 | :printer icalendar-print-property-node | ||
| 1401 | :source rfc5545-sec3.8.5.3/18) | ||
| 1402 | |||
| 1403 | (ipt:parse/print-test | ||
| 1404 | "RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15\n" | ||
| 1405 | :parser icalendar-parse-property | ||
| 1406 | :printer icalendar-print-property-node | ||
| 1407 | :source rfc5545-sec3.8.5.3/19) | ||
| 1408 | |||
| 1409 | (ipt:parse/print-test | ||
| 1410 | "RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1\n" | ||
| 1411 | :parser icalendar-parse-property | ||
| 1412 | :printer icalendar-print-property-node | ||
| 1413 | :source rfc5545-sec3.8.5.3/20) | ||
| 1414 | |||
| 1415 | (ipt:parse/print-test | ||
| 1416 | "RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15\n" | ||
| 1417 | :parser icalendar-parse-property | ||
| 1418 | :printer icalendar-print-property-node | ||
| 1419 | :source rfc5545-sec3.8.5.3/21) | ||
| 1420 | |||
| 1421 | (ipt:parse/print-test | ||
| 1422 | "RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU\n" | ||
| 1423 | :parser icalendar-parse-property | ||
| 1424 | :printer icalendar-print-property-node | ||
| 1425 | :source rfc5545-sec3.8.5.3/22) | ||
| 1426 | |||
| 1427 | (ipt:parse/print-test | ||
| 1428 | "RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7\n" | ||
| 1429 | :parser icalendar-parse-property | ||
| 1430 | :printer icalendar-print-property-node | ||
| 1431 | :source rfc5545-sec3.8.5.3/23) | ||
| 1432 | |||
| 1433 | (ipt:parse/print-test | ||
| 1434 | "RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3\n" | ||
| 1435 | :parser icalendar-parse-property | ||
| 1436 | :printer icalendar-print-property-node | ||
| 1437 | :source rfc5545-sec3.8.5.3/24) | ||
| 1438 | |||
| 1439 | (ipt:parse/print-test | ||
| 1440 | "RRULE:FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200\n" | ||
| 1441 | :parser icalendar-parse-property | ||
| 1442 | :printer icalendar-print-property-node | ||
| 1443 | :source rfc5545-sec3.8.5.3/25) | ||
| 1444 | |||
| 1445 | (ipt:parse/print-test | ||
| 1446 | "RRULE:FREQ=YEARLY;BYDAY=20MO\n" | ||
| 1447 | :parser icalendar-parse-property | ||
| 1448 | :printer icalendar-print-property-node | ||
| 1449 | :source rfc5545-sec3.8.5.3/26) | ||
| 1450 | |||
| 1451 | (ipt:parse/print-test | ||
| 1452 | "RRULE:FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO\n" | ||
| 1453 | :parser icalendar-parse-property | ||
| 1454 | :printer icalendar-print-property-node | ||
| 1455 | :source rfc5545-sec3.8.5.3/27) | ||
| 1456 | |||
| 1457 | (ipt:parse/print-test | ||
| 1458 | "RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH\n" | ||
| 1459 | :parser icalendar-parse-property | ||
| 1460 | :printer icalendar-print-property-node | ||
| 1461 | :source rfc5545-sec3.8.5.3/28) | ||
| 1462 | |||
| 1463 | (ipt:parse/print-test | ||
| 1464 | "RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8\n" | ||
| 1465 | :parser icalendar-parse-property | ||
| 1466 | :printer icalendar-print-property-node | ||
| 1467 | :source rfc5545-sec3.8.5.3/29) | ||
| 1468 | |||
| 1469 | (ipt:parse/print-test | ||
| 1470 | "RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13\n" | ||
| 1471 | :parser icalendar-parse-property | ||
| 1472 | :printer icalendar-print-property-node | ||
| 1473 | :source rfc5545-sec3.8.5.3/30) | ||
| 1474 | |||
| 1475 | (ipt:parse/print-test | ||
| 1476 | "RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13\n" | ||
| 1477 | :parser icalendar-parse-property | ||
| 1478 | :printer icalendar-print-property-node | ||
| 1479 | :source rfc5545-sec3.8.5.3/31) | ||
| 1480 | |||
| 1481 | (ipt:parse/print-test | ||
| 1482 | "RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8\n" | ||
| 1483 | :parser icalendar-parse-property | ||
| 1484 | :printer icalendar-print-property-node | ||
| 1485 | :source rfc5545-sec3.8.5.3/32) | ||
| 1486 | |||
| 1487 | (ipt:parse/print-test | ||
| 1488 | "RRULE:FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3\n" | ||
| 1489 | :parser icalendar-parse-property | ||
| 1490 | :printer icalendar-print-property-node | ||
| 1491 | :source rfc5545-sec3.8.5.3/33) | ||
| 1492 | |||
| 1493 | (ipt:parse/print-test | ||
| 1494 | "RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2\n" | ||
| 1495 | :parser icalendar-parse-property | ||
| 1496 | :printer icalendar-print-property-node | ||
| 1497 | :source rfc5545-sec3.8.5.3/34) | ||
| 1498 | |||
| 1499 | (ipt:parse/print-test | ||
| 1500 | "RRULE:FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T170000Z\n" | ||
| 1501 | :parser icalendar-parse-property | ||
| 1502 | :printer icalendar-print-property-node | ||
| 1503 | :source rfc5545-sec3.8.5.3/35) | ||
| 1504 | |||
| 1505 | (ipt:parse/print-test | ||
| 1506 | "RRULE:FREQ=MINUTELY;INTERVAL=15;COUNT=6\n" | ||
| 1507 | :parser icalendar-parse-property | ||
| 1508 | :printer icalendar-print-property-node | ||
| 1509 | :source rfc5545-sec3.8.5.3/36) | ||
| 1510 | |||
| 1511 | (ipt:parse/print-test | ||
| 1512 | "RRULE:FREQ=MINUTELY;INTERVAL=90;COUNT=4\n" | ||
| 1513 | :parser icalendar-parse-property | ||
| 1514 | :printer icalendar-print-property-node | ||
| 1515 | :source rfc5545-sec3.8.5.3/37) | ||
| 1516 | |||
| 1517 | (ipt:parse/print-test | ||
| 1518 | "RRULE:FREQ=DAILY;BYHOUR=9,10,11,12,13,14,15,16;BYMINUTE=0,20,40\n" | ||
| 1519 | :parser icalendar-parse-property | ||
| 1520 | :printer icalendar-print-property-node | ||
| 1521 | :source rfc5545-sec3.8.5.3/38) | ||
| 1522 | |||
| 1523 | (ipt:parse/print-test | ||
| 1524 | "RRULE:FREQ=MINUTELY;INTERVAL=20;BYHOUR=9,10,11,12,13,14,15,16\n" | ||
| 1525 | :parser icalendar-parse-property | ||
| 1526 | :printer icalendar-print-property-node | ||
| 1527 | :source rfc5545-sec3.8.5.3/39) | ||
| 1528 | |||
| 1529 | (ipt:parse/print-test | ||
| 1530 | "RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO\n" | ||
| 1531 | :parser icalendar-parse-property | ||
| 1532 | :printer icalendar-print-property-node | ||
| 1533 | :source rfc5545-sec3.8.5.3/40) | ||
| 1534 | |||
| 1535 | (ipt:parse/print-test | ||
| 1536 | "RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU\n" | ||
| 1537 | :parser icalendar-parse-property | ||
| 1538 | :printer icalendar-print-property-node | ||
| 1539 | :source rfc5545-sec3.8.5.3/41) | ||
| 1540 | |||
| 1541 | (ipt:parse/print-test | ||
| 1542 | "RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5\n" | ||
| 1543 | :parser icalendar-parse-property | ||
| 1544 | :printer icalendar-print-property-node | ||
| 1545 | :source rfc5545-sec3.8.5.3/42) | ||
| 1546 | |||
| 1547 | (ipt:parse/print-test | ||
| 1548 | "ACTION:AUDIO\n" | ||
| 1549 | :parser icalendar-parse-property | ||
| 1550 | :printer icalendar-print-property-node | ||
| 1551 | :source rfc5545-sec3.8.6.1/1) | ||
| 1552 | |||
| 1553 | (ipt:parse/print-test | ||
| 1554 | "ACTION:DISPLAY\n" | ||
| 1555 | :parser icalendar-parse-property | ||
| 1556 | :printer icalendar-print-property-node | ||
| 1557 | :source rfc5545-sec3.8.6.1/2) | ||
| 1558 | |||
| 1559 | (ipt:parse/print-test | ||
| 1560 | "REPEAT:4\n" | ||
| 1561 | :parser icalendar-parse-property | ||
| 1562 | :printer icalendar-print-property-node | ||
| 1563 | :source rfc5545-sec3.8.6.2/1) | ||
| 1564 | |||
| 1565 | (ipt:parse/print-test | ||
| 1566 | "TRIGGER:-PT15M\n" | ||
| 1567 | :parser icalendar-parse-property | ||
| 1568 | :printer icalendar-print-property-node | ||
| 1569 | :source rfc5545-sec3.8.6.3/1) | ||
| 1570 | |||
| 1571 | (ipt:parse/print-test | ||
| 1572 | "TRIGGER;RELATED=END:PT5M\n" | ||
| 1573 | :parser icalendar-parse-property | ||
| 1574 | :printer icalendar-print-property-node | ||
| 1575 | :source rfc5545-sec3.8.6.3/2) | ||
| 1576 | |||
| 1577 | (ipt:parse/print-test | ||
| 1578 | "TRIGGER;VALUE=DATE-TIME:19980101T050000Z\n" | ||
| 1579 | :parser icalendar-parse-property | ||
| 1580 | :printer icalendar-print-property-node | ||
| 1581 | :source rfc5545-sec3.8.6.3/3) | ||
| 1582 | |||
| 1583 | (ipt:parse/print-test | ||
| 1584 | "CREATED:19960329T133000Z\n" | ||
| 1585 | :parser icalendar-parse-property | ||
| 1586 | :printer icalendar-print-property-node | ||
| 1587 | :source rfc5545-sec3.8.7.1/1) | ||
| 1588 | |||
| 1589 | (ipt:parse/print-test | ||
| 1590 | "DTSTAMP:19971210T080000Z\n" | ||
| 1591 | :parser icalendar-parse-property | ||
| 1592 | :printer icalendar-print-property-node | ||
| 1593 | :source rfc5545-sec3.8.7.2/1) | ||
| 1594 | |||
| 1595 | (ipt:parse/print-test | ||
| 1596 | "LAST-MODIFIED:19960817T133000Z\n" | ||
| 1597 | :parser icalendar-parse-property | ||
| 1598 | :printer icalendar-print-property-node | ||
| 1599 | :source rfc5545-sec3.8.7.3/1) | ||
| 1600 | |||
| 1601 | (ipt:parse/print-test | ||
| 1602 | "SEQUENCE:0\n" | ||
| 1603 | :parser icalendar-parse-property | ||
| 1604 | :printer icalendar-print-property-node | ||
| 1605 | :source rfc5545-sec3.8.7.4/1) | ||
| 1606 | |||
| 1607 | (ipt:parse/print-test | ||
| 1608 | "SEQUENCE:2\n" | ||
| 1609 | :parser icalendar-parse-property | ||
| 1610 | :printer icalendar-print-property-node | ||
| 1611 | :source rfc5545-sec3.8.7.4/2) | ||
| 1612 | |||
| 1613 | (ipt:parse/print-test | ||
| 1614 | "DRESSCODE:CASUAL\n" | ||
| 1615 | :parser icalendar-parse-property | ||
| 1616 | :printer icalendar-print-property-node | ||
| 1617 | :source rfc5545-sec3.8.8.1/1) | ||
| 1618 | |||
| 1619 | (ipt:parse/print-test | ||
| 1620 | "NON-SMOKING;VALUE=BOOLEAN:TRUE\n" | ||
| 1621 | :parser icalendar-parse-property | ||
| 1622 | :printer icalendar-print-property-node | ||
| 1623 | :source rfc5545-sec3.8.8.1/2) | ||
| 1624 | |||
| 1625 | (ipt:parse/print-test | ||
| 1626 | "X-ABC-MMSUBJ;VALUE=URI;FMTTYPE=audio/basic:http://www.example.org/mysubj.au\n" | ||
| 1627 | :parser icalendar-parse-property | ||
| 1628 | :printer icalendar-print-property-node | ||
| 1629 | :source rfc5545-sec3.8.8.2/1) | ||
| 1630 | |||
| 1631 | (ipt:parse/print-test | ||
| 1632 | "REQUEST-STATUS:2.0;Success\n" | ||
| 1633 | :parser icalendar-parse-property | ||
| 1634 | :printer icalendar-print-property-node | ||
| 1635 | :source rfc5545-sec3.8.8.3/1) | ||
| 1636 | |||
| 1637 | (ipt:parse/print-test | ||
| 1638 | "REQUEST-STATUS:3.1;Invalid property value;DTSTART:96-Apr-01\n" | ||
| 1639 | :parser icalendar-parse-property | ||
| 1640 | :printer icalendar-print-property-node | ||
| 1641 | :source rfc5545-sec3.8.8.3/2) | ||
| 1642 | |||
| 1643 | (ipt:parse/print-test | ||
| 1644 | "REQUEST-STATUS:2.8; Success\\, repeating event ignored. Scheduled as a single event.;RRULE:FREQ=WEEKLY\\;INTERVAL=2\n" | ||
| 1645 | :parser icalendar-parse-property | ||
| 1646 | :printer icalendar-print-property-node | ||
| 1647 | :source rfc5545-sec3.8.8.3/3) | ||
| 1648 | |||
| 1649 | (ipt:parse/print-test | ||
| 1650 | "REQUEST-STATUS:4.1;Event conflict. Date-time is busy.\n" | ||
| 1651 | :parser icalendar-parse-property | ||
| 1652 | :printer icalendar-print-property-node | ||
| 1653 | :source rfc5545-sec3.8.8.3/4) | ||
| 1654 | |||
| 1655 | (ipt:parse/print-test | ||
| 1656 | "REQUEST-STATUS:3.7;Invalid calendar user;ATTENDEE:mailto:jsmith@example.com\n" | ||
| 1657 | :parser icalendar-parse-property | ||
| 1658 | :printer icalendar-print-property-node | ||
| 1659 | :source rfc5545-sec3.8.8.3/5) | ||
| 1660 | |||
| 1661 | (ipt:parse/print-test | ||
| 1662 | "BEGIN:VCALENDAR | ||
| 1663 | PRODID:-//xyz Corp//NONSGML PDA Calendar Version 1.0//EN | ||
| 1664 | VERSION:2.0 | ||
| 1665 | BEGIN:VEVENT | ||
| 1666 | DTSTAMP:19960704T120000Z | ||
| 1667 | UID:uid1@example.com | ||
| 1668 | ORGANIZER:mailto:jsmith@example.com | ||
| 1669 | DTSTART:19960918T143000Z | ||
| 1670 | DTEND:19960920T220000Z | ||
| 1671 | STATUS:CONFIRMED | ||
| 1672 | CATEGORIES:CONFERENCE | ||
| 1673 | SUMMARY:Networld+Interop Conference | ||
| 1674 | DESCRIPTION:Networld+Interop Conference and Exhibit\\nAtlanta World Congress Center\\nAtlanta\\, Georgia | ||
| 1675 | END:VEVENT | ||
| 1676 | END:VCALENDAR | ||
| 1677 | " | ||
| 1678 | :parser icalendar-parse-calendar | ||
| 1679 | :printer icalendar-print-calendar-node | ||
| 1680 | :source rfc5545-sec4/1) | ||
| 1681 | |||
| 1682 | (ipt:parse/print-test | ||
| 1683 | "BEGIN:VCALENDAR | ||
| 1684 | PRODID:-//RDU Software//NONSGML HandCal//EN | ||
| 1685 | VERSION:2.0 | ||
| 1686 | BEGIN:VTIMEZONE | ||
| 1687 | TZID:America/New_York | ||
| 1688 | BEGIN:STANDARD | ||
| 1689 | DTSTART:19981025T020000 | ||
| 1690 | TZOFFSETFROM:-0400 | ||
| 1691 | TZOFFSETTO:-0500 | ||
| 1692 | TZNAME:EST | ||
| 1693 | END:STANDARD | ||
| 1694 | BEGIN:DAYLIGHT | ||
| 1695 | DTSTART:19990404T020000 | ||
| 1696 | TZOFFSETFROM:-0500 | ||
| 1697 | TZOFFSETTO:-0400 | ||
| 1698 | TZNAME:EDT | ||
| 1699 | END:DAYLIGHT | ||
| 1700 | END:VTIMEZONE | ||
| 1701 | BEGIN:VEVENT | ||
| 1702 | DTSTAMP:19980309T231000Z | ||
| 1703 | UID:guid-1.example.com | ||
| 1704 | ORGANIZER:mailto:mrbig@example.com | ||
| 1705 | ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:mailto:employee-A@example.com | ||
| 1706 | DESCRIPTION:Project XYZ Review Meeting | ||
| 1707 | CATEGORIES:MEETING | ||
| 1708 | CLASS:PUBLIC | ||
| 1709 | CREATED:19980309T130000Z | ||
| 1710 | SUMMARY:XYZ Project Review | ||
| 1711 | DTSTART;TZID=America/New_York:19980312T083000 | ||
| 1712 | DTEND;TZID=America/New_York:19980312T093000 | ||
| 1713 | LOCATION:1CP Conference Room 4350 | ||
| 1714 | END:VEVENT | ||
| 1715 | END:VCALENDAR | ||
| 1716 | " | ||
| 1717 | :parser icalendar-parse-calendar | ||
| 1718 | :printer icalendar-print-calendar-node | ||
| 1719 | :source rfc5545-sec4/2) | ||
| 1720 | |||
| 1721 | (ipt:parse/print-test | ||
| 1722 | "BEGIN:VCALENDAR | ||
| 1723 | METHOD:xyz | ||
| 1724 | VERSION:2.0 | ||
| 1725 | PRODID:-//ABC Corporation//NONSGML My Product//EN | ||
| 1726 | BEGIN:VEVENT | ||
| 1727 | DTSTAMP:19970324T120000Z | ||
| 1728 | SEQUENCE:0 | ||
| 1729 | UID:uid3@example.com | ||
| 1730 | ORGANIZER:mailto:jdoe@example.com | ||
| 1731 | ATTENDEE;RSVP=TRUE:mailto:jsmith@example.com | ||
| 1732 | DTSTART:19970324T123000Z | ||
| 1733 | DTEND:19970324T210000Z | ||
| 1734 | CATEGORIES:MEETING,PROJECT | ||
| 1735 | CLASS:PUBLIC | ||
| 1736 | SUMMARY:Calendaring Interoperability Planning Meeting | ||
| 1737 | DESCRIPTION:Discuss how we can test c&s interoperability\\nusing iCalendar and other IETF standards. | ||
| 1738 | LOCATION:LDB Lobby | ||
| 1739 | ATTACH;FMTTYPE=application/postscript:ftp://example.com/pub/conf/bkgrnd.ps | ||
| 1740 | END:VEVENT | ||
| 1741 | END:VCALENDAR | ||
| 1742 | " | ||
| 1743 | :parser icalendar-parse-calendar | ||
| 1744 | :printer icalendar-print-calendar-node | ||
| 1745 | :source rfc5545-sec4/3) | ||
| 1746 | |||
| 1747 | (ipt:parse/print-test | ||
| 1748 | ;; Corrected. The TRIGGER property originally did not specify | ||
| 1749 | ;; VALUE=DATE-TIME, which is required since it is not the default type. | ||
| 1750 | ;; See https://www.rfc-editor.org/errata/eid2039 | ||
| 1751 | "BEGIN:VCALENDAR | ||
| 1752 | VERSION:2.0 | ||
| 1753 | PRODID:-//ABC Corporation//NONSGML My Product//EN | ||
| 1754 | BEGIN:VTODO | ||
| 1755 | DTSTAMP:19980130T134500Z | ||
| 1756 | SEQUENCE:2 | ||
| 1757 | UID:uid4@example.com | ||
| 1758 | ORGANIZER:mailto:unclesam@example.com | ||
| 1759 | ATTENDEE;PARTSTAT=ACCEPTED:mailto:jqpublic@example.com | ||
| 1760 | DUE:19980415T000000 | ||
| 1761 | STATUS:NEEDS-ACTION | ||
| 1762 | SUMMARY:Submit Income Taxes | ||
| 1763 | BEGIN:VALARM | ||
| 1764 | ACTION:AUDIO | ||
| 1765 | TRIGGER;VALUE=DATE-TIME:19980403T120000Z | ||
| 1766 | ATTACH;FMTTYPE=audio/basic:http://example.com/pub/audio-files/ssbanner.aud | ||
| 1767 | REPEAT:4 | ||
| 1768 | DURATION:PT1H | ||
| 1769 | END:VALARM | ||
| 1770 | END:VTODO | ||
| 1771 | END:VCALENDAR | ||
| 1772 | " | ||
| 1773 | :parser icalendar-parse-calendar | ||
| 1774 | :printer icalendar-print-calendar-node | ||
| 1775 | :source rfc5545-sec4/4) | ||
| 1776 | |||
| 1777 | (ipt:parse/print-test | ||
| 1778 | "BEGIN:VCALENDAR | ||
| 1779 | VERSION:2.0 | ||
| 1780 | PRODID:-//ABC Corporation//NONSGML My Product//EN | ||
| 1781 | BEGIN:VJOURNAL | ||
| 1782 | DTSTAMP:19970324T120000Z | ||
| 1783 | UID:uid5@example.com | ||
| 1784 | ORGANIZER:mailto:jsmith@example.com | ||
| 1785 | STATUS:DRAFT | ||
| 1786 | CLASS:PUBLIC | ||
| 1787 | CATEGORIES:Project Report,XYZ,Weekly Meeting | ||
| 1788 | DESCRIPTION:Project xyz Review Meeting Minutes\\nAgenda\\n1. Review of project version 1.0 requirements.\\n2.Definitionof project processes.\\n3. Review of project schedule.\\nParticipants: John Smith\\, Jane Doe\\, Jim Dandy\\n-It was decided that the requirements need to be signed off byproduct marketing.\\n-P roject processes were accepted.\\n-Project schedule needs to account for scheduled holidaysand employee vacation time. Check with HR for specificdates.\\n-New schedule will be distributed by Friday.\\n-Next weeks meeting is cancelled. No meeting until 3/23. | ||
| 1789 | END:VJOURNAL | ||
| 1790 | END:VCALENDAR | ||
| 1791 | " | ||
| 1792 | :parser icalendar-parse-calendar | ||
| 1793 | :printer icalendar-print-calendar-node | ||
| 1794 | :source rfc5545-sec4/5) | ||
| 1795 | |||
| 1796 | (ipt:parse/print-test | ||
| 1797 | ;; Corrected. Original text in the standard is missing UID and DTSTAMP. | ||
| 1798 | ;; See https://www.rfc-editor.org/errata/eid4149 | ||
| 1799 | "BEGIN:VCALENDAR | ||
| 1800 | VERSION:2.0 | ||
| 1801 | PRODID:-//RDU Software//NONSGML HandCal//EN | ||
| 1802 | BEGIN:VFREEBUSY | ||
| 1803 | UID:19970901T115957Z-76A912@example.com | ||
| 1804 | DTSTAMP:19970901T120000Z | ||
| 1805 | ORGANIZER:mailto:jsmith@example.com | ||
| 1806 | DTSTART:19980313T141711Z | ||
| 1807 | DTEND:19980410T141711Z | ||
| 1808 | FREEBUSY:19980314T233000Z/19980315T003000Z | ||
| 1809 | FREEBUSY:19980316T153000Z/19980316T163000Z | ||
| 1810 | FREEBUSY:19980318T030000Z/19980318T040000Z | ||
| 1811 | URL:http://www.example.com/calendar/busytime/jsmith.ifb | ||
| 1812 | END:VFREEBUSY | ||
| 1813 | END:VCALENDAR | ||
| 1814 | " | ||
| 1815 | :parser icalendar-parse-calendar | ||
| 1816 | :printer icalendar-print-calendar-node | ||
| 1817 | :source rfc5545-sec4/6) | ||
| 1818 | |||
| 1819 | |||
| 1820 | ;; Tests from real world data: | ||
| 1821 | (ert-deftest ipt:bad-organizer-params () | ||
| 1822 | "Real example: bad ORGANIZER property with params introduced by colon" | ||
| 1823 | (let ((bad "ORGANIZER:CN=ORGANIZER:mailto:anonymized@domain.example\n") | ||
| 1824 | (ok "ORGANIZER;CN=ORGANIZER:mailto:anonymized@domain.example\n")) | ||
| 1825 | (should-error (ical:parse-from-string 'ical:organizer bad)) | ||
| 1826 | (should (ical:ast-node-p (ical:parse-from-string 'ical:organizer ok))))) | ||
| 1827 | |||
| 1828 | (ert-deftest ipt:bad-attendee () | ||
| 1829 | "Real example: bad ATTENDEE property missing mailto: prefix" | ||
| 1830 | (let ((bad "ATTENDEE;ROLE=REQ-PARTICIPANT;CN=TRAVELLER:anonymized@domain.example\n") | ||
| 1831 | (ok "ATTENDEE;ROLE=REQ-PARTICIPANT;CN=TRAVELLER:mailto:anonymized@domain.example\n")) | ||
| 1832 | (should-error (ical:parse-from-string 'ical:attendee bad)) | ||
| 1833 | (should (ical:ast-node-p (ical:parse-from-string 'ical:attendee ok))))) | ||
| 1834 | |||
| 1835 | (ert-deftest ipt:bad-attach () | ||
| 1836 | "Real example: bad ATTACH property containing broken URI" | ||
| 1837 | (let ((bad "ATTACH;VALUE=URI:Glass\n") | ||
| 1838 | (ok "ATTACH;VALUE=URI:https://example.com\n")) | ||
| 1839 | (should-error (ical:parse-from-string 'ical:attach bad)) | ||
| 1840 | (should (ical:ast-node-p (ical:parse-from-string 'ical:attach ok))))) | ||
| 1841 | |||
| 1842 | (ert-deftest ipt:bad-cnparam () | ||
| 1843 | "Real example: bad unquoted CN parameter containing a comma" | ||
| 1844 | (let ((bad "ORGANIZER;CN=Hartlauer Geschäft Wien, Taborstr. 18:mailto:anonymized@domain.example\n") | ||
| 1845 | (ok "ORGANIZER;CN=\"Hartlauer Geschäft Wien, Taborstr. 18\":mailto:anonymized@domain.example\n")) | ||
| 1846 | ;; strict parser should reject bad but accept ok: | ||
| 1847 | (let ((ical:parse-strictly t)) | ||
| 1848 | (should (ical:ast-node-p (ical:parse-from-string 'ical:organizer ok))) | ||
| 1849 | (should-error (ical:parse-from-string 'ical:organizer bad))) | ||
| 1850 | ;; relaxed parser should accept bad: | ||
| 1851 | (let ((ical:parse-strictly nil)) | ||
| 1852 | (should (ical:ast-node-p (ical:parse-from-string 'ical:organizer bad)))))) | ||
| 1853 | |||
| 1854 | (ert-deftest ipt:fix-bad-description () | ||
| 1855 | "Real example: bad DESCRIPTION property containing blank lines, | ||
| 1856 | fixed by `icalendar-fix-blank-lines'." | ||
| 1857 | (let ((bad "BEGIN:VCALENDAR | ||
| 1858 | VERSION:2.0 | ||
| 1859 | CALSCALE:GREGORIAN | ||
| 1860 | METHOD:REQUEST | ||
| 1861 | BEGIN:VEVENT | ||
| 1862 | UID:45dd7698-5c53-47e3-9280-19c5dff62571 | ||
| 1863 | PRIORITY:1 | ||
| 1864 | DTSTART:20210721T175200 | ||
| 1865 | DTEND:20210721T192400 | ||
| 1866 | LOCATION:Verona Porta Nuova | ||
| 1867 | DESCRIPTION:Verona Porta Nuova-Firenze S. M. Novella;Train: Frecciarossa 8527, departing from Verona Porta Nuova Hours: 17:52; arriving at Firenze S. M. Novella Hours: 19:24 Coach 8, Position 7A; pnr code CLS345 | ||
| 1868 | |||
| 1869 | |||
| 1870 | SUMMARY:Trip Verona Porta Nuova-Firenze S. M. Novella, Train Frecciarossa 8527, Coach 8, Position 7A, PNR CLS345, | ||
| 1871 | ORGANIZER;CN=ORGANIZER:mailto:anonymized@domain.example | ||
| 1872 | ATTENDEE;ROLE=REQ-PARTICIPANT;CN=BUYER:mailto:anonymized@domain.example | ||
| 1873 | ATTENDEE;ROLE=REQ-PARTICIPANT;CN=TRAVELLER:mailto:anonymized@domain.example | ||
| 1874 | END:VEVENT | ||
| 1875 | END:VCALENDAR | ||
| 1876 | ")) | ||
| 1877 | ;; The default parser should produce an error on the blank lines in | ||
| 1878 | ;; DESCRIPTION: | ||
| 1879 | (let ((ical:pre-parsing-hook nil)) | ||
| 1880 | (with-temp-buffer | ||
| 1881 | (ical:init-error-buffer) | ||
| 1882 | (insert bad) | ||
| 1883 | (goto-char (point-min)) | ||
| 1884 | (ical:parse) | ||
| 1885 | ;; Parsing should produce error at the bad description property: | ||
| 1886 | (should (ical:errors-p)))) | ||
| 1887 | ;; cleaning up the blank lines before parsing should correct this: | ||
| 1888 | (let ((ical:pre-parsing-hook '(ical:fix-blank-lines))) | ||
| 1889 | (with-temp-buffer | ||
| 1890 | (ical:init-error-buffer) | ||
| 1891 | (insert bad) | ||
| 1892 | (goto-char (point-min)) | ||
| 1893 | (let ((vcal (ical:parse))) | ||
| 1894 | (should (not (ical:errors-p))) | ||
| 1895 | (ical:with-component vcal | ||
| 1896 | ((ical:vevent vevent)) | ||
| 1897 | (ical:with-component vevent | ||
| 1898 | ((ical:description :value description)) | ||
| 1899 | (let* ((expected "CLS345") | ||
| 1900 | (end (length description)) | ||
| 1901 | (start (- end (length expected)))) | ||
| 1902 | (should (equal expected | ||
| 1903 | (substring description start end))))))))))) | ||
| 1904 | |||
| 1905 | (ert-deftest ipt:bad-hyphenated-dates () | ||
| 1906 | "Real example: bad date values containing hyphens, fixed by | ||
| 1907 | `icalendar-fix-hyphenated-dates'." | ||
| 1908 | (let ((bad "BEGIN:VCALENDAR | ||
| 1909 | X-LOTUS-CHARSET:UTF-8 | ||
| 1910 | VERSION:2.0 | ||
| 1911 | PRODID:http://www.bahn.de | ||
| 1912 | METHOD:PUBLISH | ||
| 1913 | BEGIN:VTIMEZONE | ||
| 1914 | TZID:Europe/Berlin | ||
| 1915 | X-LIC-LOCATION:Europe/Berlin | ||
| 1916 | BEGIN:DAYLIGHT | ||
| 1917 | TZOFFSETFROM:+0100 | ||
| 1918 | TZOFFSETTO:+0200 | ||
| 1919 | TZNAME:CEST | ||
| 1920 | DTSTART:19700329T020000 | ||
| 1921 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3 | ||
| 1922 | END:DAYLIGHT | ||
| 1923 | BEGIN:STANDARD | ||
| 1924 | TZOFFSETFROM:+0200 | ||
| 1925 | TZOFFSETTO:+0100 | ||
| 1926 | TZNAME:CET | ||
| 1927 | DTSTART:19701025T030000 | ||
| 1928 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10 | ||
| 1929 | END:STANDARD | ||
| 1930 | END:VTIMEZONE | ||
| 1931 | BEGIN:VEVENT | ||
| 1932 | UID:bahn2023-08-29141400 | ||
| 1933 | CLASS:PUBLIC | ||
| 1934 | SUMMARY:Frankfurt(Main)Hbf -> Hamburg Hbf | ||
| 1935 | DTSTART;TZID=Europe/Berlin:2023-08-29T141400 | ||
| 1936 | DTEND;TZID=Europe/Berlin:2023-08-29T183600 | ||
| 1937 | DTSTAMP:2023-07-30T194700Z | ||
| 1938 | END:VEVENT | ||
| 1939 | END:VCALENDAR | ||
| 1940 | ")) | ||
| 1941 | ;; default parser should skip the invalid DTSTART, DTEND, and DTSTAMP values: | ||
| 1942 | (let ((ical:pre-parsing-hook nil)) | ||
| 1943 | (with-temp-buffer | ||
| 1944 | (ical:init-error-buffer) | ||
| 1945 | (insert bad) | ||
| 1946 | (goto-char (point-min)) | ||
| 1947 | (let ((vcal (ical:parse))) | ||
| 1948 | ;; Parsing should produce errors as the bad properties are | ||
| 1949 | ;; skipped: | ||
| 1950 | (should (ical:errors-p)) | ||
| 1951 | ;; The resulting calendar is invalid because the VEVENT | ||
| 1952 | ;; contains no DTSTAMP: | ||
| 1953 | (should-error (ical:ast-node-valid-p vcal t))))) | ||
| 1954 | ;; cleaning up the hyphenated dates before parsing should correct | ||
| 1955 | ;; these problems: | ||
| 1956 | (let ((ical:pre-parsing-hook '(ical:fix-hyphenated-dates))) | ||
| 1957 | (with-temp-buffer | ||
| 1958 | (ical:init-error-buffer) | ||
| 1959 | (insert bad) | ||
| 1960 | (goto-char (point-min)) | ||
| 1961 | (let ((vcal (ical:parse)) | ||
| 1962 | (expected-dtstamp | ||
| 1963 | (ical:make-date-time :year 2023 :month 7 :day 30 | ||
| 1964 | :hour 19 :minute 47 :second 0 | ||
| 1965 | :zone 0))) | ||
| 1966 | (should (not (ical:errors-p))) | ||
| 1967 | (should (ical:ast-node-valid-p vcal t)) | ||
| 1968 | (ical:with-component vcal | ||
| 1969 | ((ical:vevent vevent)) | ||
| 1970 | (ical:with-component vevent | ||
| 1971 | ((ical:dtstamp :value dtstamp)) | ||
| 1972 | (should (equal dtstamp expected-dtstamp))))))))) | ||
| 1973 | |||
| 1974 | (ert-deftest ipt:bad-user-addresses () | ||
| 1975 | "Real example: bad calendar user addresses missing \"mailto:\", fixed by | ||
| 1976 | `icalendar-fix-missing-mailtos'." | ||
| 1977 | (let ((bad "BEGIN:VCALENDAR | ||
| 1978 | VERSION:2.0 | ||
| 1979 | PRODID:missing | ||
| 1980 | CALSCALE:GREGORIAN | ||
| 1981 | METHOD:REQUEST | ||
| 1982 | BEGIN:VEVENT | ||
| 1983 | UID:45dd7698-5c53-47e3-9280-19c5dff62571 | ||
| 1984 | PRIORITY:1 | ||
| 1985 | DTSTART:20210721T175200 | ||
| 1986 | DTEND:20210721T192400 | ||
| 1987 | LOCATION:Verona Porta Nuova | ||
| 1988 | SUMMARY:Trip Verona Porta Nuova-Firenze S. M. Novella | ||
| 1989 | ORGANIZER;SENT-BY=\"other@domain.example\":anonymized@domain.example | ||
| 1990 | ATTENDEE;ROLE=REQ-PARTICIPANT;CN=TRAVELER:traveler@domain.example | ||
| 1991 | END:VEVENT | ||
| 1992 | END:VCALENDAR | ||
| 1993 | ")) | ||
| 1994 | (let ((ical:pre-parsing-hook nil)) | ||
| 1995 | (with-temp-buffer | ||
| 1996 | (ical:init-error-buffer) | ||
| 1997 | (insert bad) | ||
| 1998 | (goto-char (point-min)) | ||
| 1999 | (ical:parse) | ||
| 2000 | ;; Parsing should produce errors as the bad properties are | ||
| 2001 | ;; skipped: | ||
| 2002 | (should (ical:errors-p)))) | ||
| 2003 | ;; cleaning up the addresses before parsing should correct | ||
| 2004 | ;; these problems: | ||
| 2005 | (let ((ical:pre-parsing-hook '(ical:fix-missing-mailtos))) | ||
| 2006 | (with-temp-buffer | ||
| 2007 | (ical:init-error-buffer) | ||
| 2008 | (insert bad) | ||
| 2009 | (goto-char (point-min)) | ||
| 2010 | (let ((vcal (ical:parse)) | ||
| 2011 | (expected-attendee "mailto:traveler@domain.example") | ||
| 2012 | (expected-organizer "mailto:anonymized@domain.example") | ||
| 2013 | (expected-sender "mailto:other@domain.example")) | ||
| 2014 | (should (not (ical:errors-p))) | ||
| 2015 | (ical:with-component vcal | ||
| 2016 | ((ical:vevent vevent)) | ||
| 2017 | (ical:with-component vevent | ||
| 2018 | ((ical:attendee :value attendee) | ||
| 2019 | (ical:organizer :value organizer)) | ||
| 2020 | (should (equal attendee expected-attendee)) | ||
| 2021 | (should (equal organizer expected-organizer)) | ||
| 2022 | (ical:with-property organizer | ||
| 2023 | ((ical:sentbyparam :value sent-by)) | ||
| 2024 | (should (equal sent-by expected-sender)))))))))) | ||
| 2025 | |||
| 2026 | |||
| 2027 | |||
| 2028 | |||
| 2029 | ;; Local Variables: | ||
| 2030 | ;; read-symbol-shorthands: (("ipt:" . "icalendar-parser-test-") ("ical:" . "icalendar-")) | ||
| 2031 | ;; End: | ||
| 2032 | ;;; icalendar-parser-tests.el ends here | ||
diff --git a/test/lisp/calendar/icalendar-recur-tests.el b/test/lisp/calendar/icalendar-recur-tests.el new file mode 100644 index 00000000000..1df2c5b17e5 --- /dev/null +++ b/test/lisp/calendar/icalendar-recur-tests.el | |||
| @@ -0,0 +1,2880 @@ | |||
| 1 | ;;; icalendar-recur-tests.el --- Tests for icalendar-recur -*- lexical-binding: t; -*- | ||
| 2 | ;; Copyright (C) 2025 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | ;; This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 7 | ;; it under the terms of the GNU General Public License as published by | ||
| 8 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 9 | ;; (at your option) any later version. | ||
| 10 | |||
| 11 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;; GNU General Public License for more details. | ||
| 15 | |||
| 16 | ;; You should have received a copy of the GNU General Public License | ||
| 17 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | ;;; Code: | ||
| 20 | |||
| 21 | (eval-when-compile (require 'cl-lib)) | ||
| 22 | (require 'ert) | ||
| 23 | (eval-when-compile (require 'icalendar-macs)) | ||
| 24 | (require 'icalendar-recur) | ||
| 25 | (require 'icalendar-utils) | ||
| 26 | (require 'icalendar-parser) | ||
| 27 | (require 'icalendar-ast) | ||
| 28 | |||
| 29 | ;; Some constants for tests that use time zones: | ||
| 30 | (defconst ict:tz-eastern | ||
| 31 | (ical:parse-from-string 'ical:vtimezone | ||
| 32 | "BEGIN:VTIMEZONE | ||
| 33 | TZID:America/New_York | ||
| 34 | LAST-MODIFIED:20050809T050000Z | ||
| 35 | BEGIN:DAYLIGHT | ||
| 36 | DTSTART:19670430T020000 | ||
| 37 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19730429T070000Z | ||
| 38 | TZOFFSETFROM:-0500 | ||
| 39 | TZOFFSETTO:-0400 | ||
| 40 | TZNAME:EDT | ||
| 41 | END:DAYLIGHT | ||
| 42 | BEGIN:STANDARD | ||
| 43 | DTSTART:19671029T020000 | ||
| 44 | RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU;UNTIL=20061029T060000Z | ||
| 45 | TZOFFSETFROM:-0400 | ||
| 46 | TZOFFSETTO:-0500 | ||
| 47 | TZNAME:EST | ||
| 48 | END:STANDARD | ||
| 49 | BEGIN:DAYLIGHT | ||
| 50 | DTSTART:19740106T020000 | ||
| 51 | RDATE:19750223T020000 | ||
| 52 | TZOFFSETFROM:-0500 | ||
| 53 | TZOFFSETTO:-0400 | ||
| 54 | TZNAME:EDT | ||
| 55 | END:DAYLIGHT | ||
| 56 | BEGIN:DAYLIGHT | ||
| 57 | DTSTART:19760425T020000 | ||
| 58 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19860427T070000Z | ||
| 59 | TZOFFSETFROM:-0500 | ||
| 60 | TZOFFSETTO:-0400 | ||
| 61 | TZNAME:EDT | ||
| 62 | END:DAYLIGHT | ||
| 63 | BEGIN:DAYLIGHT | ||
| 64 | DTSTART:19870405T020000 | ||
| 65 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU;UNTIL=20060402T070000Z | ||
| 66 | TZOFFSETFROM:-0500 | ||
| 67 | TZOFFSETTO:-0400 | ||
| 68 | TZNAME:EDT | ||
| 69 | END:DAYLIGHT | ||
| 70 | BEGIN:DAYLIGHT | ||
| 71 | DTSTART:20070311T020000 | ||
| 72 | RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU | ||
| 73 | TZOFFSETFROM:-0500 | ||
| 74 | TZOFFSETTO:-0400 | ||
| 75 | TZNAME:EDT | ||
| 76 | END:DAYLIGHT | ||
| 77 | BEGIN:STANDARD | ||
| 78 | DTSTART:20071104T020000 | ||
| 79 | RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU | ||
| 80 | TZOFFSETFROM:-0400 | ||
| 81 | TZOFFSETTO:-0500 | ||
| 82 | TZNAME:EST | ||
| 83 | END:STANDARD | ||
| 84 | END:VTIMEZONE | ||
| 85 | ") | ||
| 86 | "`icalendar-vtimezone' representing America/New_York (Eastern) time.") | ||
| 87 | |||
| 88 | (defconst ict:est-latest | ||
| 89 | (ical:with-component ict:tz-eastern | ||
| 90 | ((ical:standard :all stds)) | ||
| 91 | (seq-find (lambda (obs) | ||
| 92 | (ical:date-time= | ||
| 93 | (ical:make-date-time :year 2007 :month 11 :day 4 | ||
| 94 | :hour 2 :minute 0 :second 0) | ||
| 95 | (ical:with-property-of obs 'ical:dtstart nil value))) | ||
| 96 | stds)) | ||
| 97 | "The observance of Eastern Standard Time which began 2007-11-04") | ||
| 98 | |||
| 99 | (defconst ict:edt-latest | ||
| 100 | (ical:with-component ict:tz-eastern | ||
| 101 | ((ical:daylight :all dls)) | ||
| 102 | (seq-find (lambda (obs) | ||
| 103 | (ical:date-time= | ||
| 104 | (ical:make-date-time :year 2007 :month 3 :day 11 | ||
| 105 | :hour 2 :minute 0 :second 0) | ||
| 106 | (ical:with-property-of obs 'ical:dtstart nil value))) | ||
| 107 | dls)) | ||
| 108 | "The observance of Eastern Daylight Time which began 2007-03-11") | ||
| 109 | |||
| 110 | (defconst ict:est -18000 ;; = -0500 | ||
| 111 | "UTC offset for Eastern Standard Time") | ||
| 112 | |||
| 113 | (defconst ict:edt -14400 ;; = -0400 | ||
| 114 | "UTC offset for Eastern Daylight Time") | ||
| 115 | |||
| 116 | |||
| 117 | ;; Tests for basic functions: | ||
| 118 | |||
| 119 | (ert-deftest ict:recur-bysetpos-filter () | ||
| 120 | "Test that `icr:make-bysetpos-filter' filters correctly by position" | ||
| 121 | (let* ((t1 (list 1 1 2024)) | ||
| 122 | (t2 (list 2 1 2024)) | ||
| 123 | (t3 (list 12 30 2024)) | ||
| 124 | (dts (list t1 t2 t3)) | ||
| 125 | (filter (icr:make-bysetpos-filter (list 1 -1))) | ||
| 126 | (filtered (funcall filter dts))) | ||
| 127 | (should (member t1 filtered)) | ||
| 128 | (should (member t3 filtered)) | ||
| 129 | (should-not (member t2 filtered)))) | ||
| 130 | |||
| 131 | (ert-deftest ict:recur-yearday-number () | ||
| 132 | "Test that `calendar-date-from-day-of-year' finds correct dates" | ||
| 133 | (let* ((year 2025) | ||
| 134 | (daynos (list '(1 . (1 1 2025)) | ||
| 135 | '(8 . (1 8 2025)) | ||
| 136 | '(-1 . (12 31 2025)) | ||
| 137 | '(363 . (12 29 2025))))) | ||
| 138 | (dolist (d daynos) | ||
| 139 | (let ((dayno (car d)) | ||
| 140 | (date (cdr d))) | ||
| 141 | (should | ||
| 142 | (equal date (calendar-date-from-day-of-year year dayno))))))) | ||
| 143 | |||
| 144 | (ert-deftest ict:date-time-add () | ||
| 145 | "Does `ical:date-time-add' correctly handle time zone transitions?" | ||
| 146 | ;; A sum that does not use a time zone at all: | ||
| 147 | (let* ((dt (ical:make-date-time :year 2007 :month 1 :day 1 | ||
| 148 | :hour 12 :minute 0 :second 0)) | ||
| 149 | (delta (make-decoded-time :day 2)) | ||
| 150 | (expected (ical:date-time-variant dt :day 3))) | ||
| 151 | (should (equal expected (ical:date-time-add dt delta)))) | ||
| 152 | |||
| 153 | ;; A sum that does not cross an observance boundary: | ||
| 154 | (let* ((dt (ical:make-date-time :year 2007 :month 2 :day 1 | ||
| 155 | :hour 12 :minute 0 :second 0 | ||
| 156 | :zone ict:est :dst nil)) | ||
| 157 | (delta (make-decoded-time :day 2)) | ||
| 158 | (expected (ical:date-time-variant dt :day 3 :tz 'preserve))) | ||
| 159 | (should (equal expected (ical:date-time-add dt delta ict:tz-eastern)))) | ||
| 160 | |||
| 161 | ;; A sum that crosses the Std->DST boundary and should preserve clock time: | ||
| 162 | (let* ((dt (ical:make-date-time :year 2007 :month 3 :day 10 | ||
| 163 | :hour 12 :minute 0 :second 0 | ||
| 164 | :zone ict:est :dst nil)) | ||
| 165 | (delta (make-decoded-time :day 2)) | ||
| 166 | (expected (ical:date-time-variant dt :day 12 :zone ict:edt :dst t))) | ||
| 167 | (should (equal expected (ical:date-time-add dt delta ict:tz-eastern)))) | ||
| 168 | |||
| 169 | ;; A sum that crosses the Std->DST boundary and should be exactly 48 hours later: | ||
| 170 | (let* ((dt (ical:make-date-time :year 2007 :month 3 :day 10 | ||
| 171 | :hour 12 :minute 0 :second 0 | ||
| 172 | :zone ict:est :dst nil)) | ||
| 173 | (delta (make-decoded-time :hour 48)) | ||
| 174 | (expected (ical:date-time-variant dt :day 12 :hour 13 | ||
| 175 | :zone ict:edt :dst t))) | ||
| 176 | (should (equal expected (ical:date-time-add dt delta ict:tz-eastern)))) | ||
| 177 | |||
| 178 | ;; A sum that crosses the DST->Std boundary and should preserve clock time: | ||
| 179 | (let* ((dt (ical:make-date-time :year 2007 :month 11 :day 3 | ||
| 180 | :hour 12 :minute 0 :second 0 | ||
| 181 | :zone ict:edt :dst t)) | ||
| 182 | (delta (make-decoded-time :day 2)) | ||
| 183 | (expected (ical:date-time-variant dt :day 5 :zone ict:est :dst nil))) | ||
| 184 | (should (equal expected (ical:date-time-add dt delta ict:tz-eastern)))) | ||
| 185 | |||
| 186 | ;; A sum that crosses the DST->Std boundary and should be exactly 48 hours later: | ||
| 187 | (let* ((dt (ical:make-date-time :year 2007 :month 11 :day 3 | ||
| 188 | :hour 12 :minute 0 :second 0 | ||
| 189 | :zone ict:edt :dst t)) | ||
| 190 | (delta (make-decoded-time :hour 48)) | ||
| 191 | (expected (ical:date-time-variant dt :day 5 :hour 11 | ||
| 192 | :zone ict:est :dst nil))) | ||
| 193 | (should (equal expected (ical:date-time-add dt delta ict:tz-eastern)))) | ||
| 194 | |||
| 195 | ;; A sum that lands exactly on the Std->DST boundary and should result | ||
| 196 | ;; in a clock time one hour later: | ||
| 197 | (let* ((dt (ical:make-date-time :year 2007 :month 3 :day 10 | ||
| 198 | :hour 2 :minute 0 :second 0 | ||
| 199 | :zone ict:est :dst nil)) | ||
| 200 | (delta (make-decoded-time :hour 24)) | ||
| 201 | (expected (ical:date-time-variant dt :day 11 :hour 3 | ||
| 202 | :zone ict:edt :dst t))) | ||
| 203 | (should (equal expected (ical:date-time-add dt delta ict:tz-eastern)))) | ||
| 204 | |||
| 205 | ;; A sum that lands exactly on the DST->Std boundary and should result | ||
| 206 | ;; in a clock time one hour earlier: | ||
| 207 | (let* ((dt (ical:make-date-time :year 2007 :month 11 :day 3 | ||
| 208 | :hour 2 :minute 0 :second 0 | ||
| 209 | :zone ict:edt :dst t)) | ||
| 210 | (delta (make-decoded-time :hour 24)) | ||
| 211 | (expected (ical:date-time-variant dt :day 4 :hour 1 | ||
| 212 | :zone ict:est :dst nil))) | ||
| 213 | (should (equal expected (ical:date-time-add dt delta ict:tz-eastern))))) | ||
| 214 | |||
| 215 | (ert-deftest ict:recur-nonexistent-date-time-p () | ||
| 216 | "Does `icr:nonexistent-date-time-p' correctly identify nonexistent times?" | ||
| 217 | (let* ((dst-onset (ical:make-date-time :year 2025 :month 3 :day 9 | ||
| 218 | :hour 2 :minute 0 :second 0 | ||
| 219 | :zone ict:est :dst nil)) | ||
| 220 | ;; 2:30 AM falls into the gap when shifting from 2AM EST to 3AM EDT: | ||
| 221 | (nonexistent1 (ical:make-date-time :year 2025 :month 3 :day 9 | ||
| 222 | :hour 2 :minute 30 :second 0 | ||
| 223 | :zone ict:est :dst nil)) | ||
| 224 | (nonexistent2 (ical:date-time-variant nonexistent1 | ||
| 225 | :zone ict:edt :dst t)) | ||
| 226 | (std-onset (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 227 | :hour 2 :minute 0 :second 0 | ||
| 228 | :zone ict:edt :dst t)) | ||
| 229 | ;; 1:30AM around the shift back to EST exists twice (once in | ||
| 230 | ;; EDT, once in EST) and should not be nonexistent: | ||
| 231 | (existent1 (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 232 | :hour 1 :minute 30 :second 0 | ||
| 233 | :zone ict:edt :dst t)) | ||
| 234 | (existent2 (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 235 | :hour 1 :minute 30 :second 0 | ||
| 236 | :zone ict:est :dst nil))) | ||
| 237 | (should (icr:nonexistent-date-time-p nonexistent1 dst-onset ict:edt-latest)) | ||
| 238 | (should (icr:nonexistent-date-time-p nonexistent2 dst-onset ict:edt-latest)) | ||
| 239 | (should-not | ||
| 240 | (icr:nonexistent-date-time-p existent1 std-onset ict:est-latest)) | ||
| 241 | (should-not | ||
| 242 | (icr:nonexistent-date-time-p existent2 std-onset ict:est-latest)))) | ||
| 243 | |||
| 244 | (ert-deftest ict:recur-date-time-occurs-twice-p () | ||
| 245 | "Does `icr:date-time-occurs-twice-p' correctly identify times that occur twice?" | ||
| 246 | (let* ((std-onset (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 247 | :hour 2 :minute 0 :second 0 | ||
| 248 | :zone ict:edt :dst t)) | ||
| 249 | ;; 1:00, 1:30 AM occur twice when shifting from 2AM EDT to 1AM EST: | ||
| 250 | (twice1 (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 251 | :hour 1 :minute 0 :second 0)) | ||
| 252 | (twice2 (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 253 | :hour 1 :minute 30 :second 0)) | ||
| 254 | ;; 12:59 AM, 2AM should not occur twice: | ||
| 255 | (once1 (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 256 | :hour 0 :minute 59 :second 0 | ||
| 257 | :zone ict:edt :dst t)) | ||
| 258 | (once2 (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 259 | :hour 2 :minute 0 :second 0 | ||
| 260 | :zone ict:est :dst nil))) | ||
| 261 | (should (icr:date-time-occurs-twice-p twice1 std-onset ict:est-latest)) | ||
| 262 | (should (icr:date-time-occurs-twice-p twice2 std-onset ict:est-latest)) | ||
| 263 | (should-not | ||
| 264 | (icr:date-time-occurs-twice-p once1 std-onset ict:est-latest)) | ||
| 265 | (should-not | ||
| 266 | (icr:date-time-occurs-twice-p once2 std-onset ict:est-latest)))) | ||
| 267 | |||
| 268 | (ert-deftest ict:recur-find-secondly-interval () | ||
| 269 | "Does `icr:find-secondly-interval' find correct intervals?" | ||
| 270 | (let* ((dtstart (ical:make-date-time :year 2025 :month 1 :day 1 | ||
| 271 | :hour 0 :minute 0 :second 0 | ||
| 272 | ;; Use UTC for the tests with no | ||
| 273 | ;; time zone, so that the results | ||
| 274 | ;; don't depend on system's local time | ||
| 275 | :zone 0)) | ||
| 276 | (dtstart/tz (ical:date-time-variant dtstart :zone ict:est :dst nil))) | ||
| 277 | |||
| 278 | ;; Year numbers are monotonically increasing in the following test cases, | ||
| 279 | ;; to make it easy to tell which of them fails. | ||
| 280 | |||
| 281 | ;; No timezone, just clock time, around a target that doesn't fall on | ||
| 282 | ;; an interval boundary: | ||
| 283 | (let* ((target (ical:date-time-variant dtstart :year 2026 :second 5 :zone 0)) | ||
| 284 | (expected-int | ||
| 285 | (list | ||
| 286 | (ical:date-time-variant target :second 0 :tz 'preserve) | ||
| 287 | (ical:date-time-variant target :second 1 :tz 'preserve) | ||
| 288 | (ical:date-time-variant target :second 10 :tz 'preserve)))) | ||
| 289 | (should | ||
| 290 | (equal expected-int | ||
| 291 | (icr:find-secondly-interval target dtstart 10)))) | ||
| 292 | |||
| 293 | ;; No timezone, just clock time, around a target that does fall on | ||
| 294 | ;; an interval boundary: | ||
| 295 | (let* ((target (ical:date-time-variant dtstart :year 2027 :second 10 :zone 0)) | ||
| 296 | (expected-int | ||
| 297 | (list | ||
| 298 | (ical:date-time-variant target :second 10 :tz 'preserve) | ||
| 299 | (ical:date-time-variant target :second 11 :tz 'preserve) | ||
| 300 | (ical:date-time-variant target :second 20 :tz 'preserve)))) | ||
| 301 | (should | ||
| 302 | (equal expected-int | ||
| 303 | (icr:find-secondly-interval target dtstart 10)))) | ||
| 304 | |||
| 305 | ;; With timezone, around a target that falls on an interval | ||
| 306 | ;; boundary, in the same observance: | ||
| 307 | (let* ((target (ical:date-time-variant dtstart/tz | ||
| 308 | :year 2028 :month 2 :second 20 | ||
| 309 | :zone ict:est :dst nil)) | ||
| 310 | (expected-int | ||
| 311 | (list | ||
| 312 | (ical:date-time-variant target :second 20 :tz 'preserve) | ||
| 313 | (ical:date-time-variant target :second 21 :tz 'preserve) | ||
| 314 | (ical:date-time-variant target :second 30 :tz 'preserve)))) | ||
| 315 | (should | ||
| 316 | (equal expected-int | ||
| 317 | (icr:find-secondly-interval target dtstart/tz 10 | ||
| 318 | ict:tz-eastern)))) | ||
| 319 | |||
| 320 | ;; With timezone, around a target that does not fall on an interval | ||
| 321 | ;; boundary, and after the time zone observance shift: | ||
| 322 | (let* ((target (ical:date-time-variant dtstart/tz | ||
| 323 | :year 2029 :month 5 :second 30 | ||
| 324 | :zone ict:edt :dst t)) | ||
| 325 | (expected-int | ||
| 326 | (list | ||
| 327 | (ical:date-time-variant target :second 30 :tz 'preserve) | ||
| 328 | (ical:date-time-variant target :second 31 :tz 'preserve) | ||
| 329 | (ical:date-time-variant target :second 40 :tz 'preserve)))) | ||
| 330 | (should | ||
| 331 | (equal expected-int | ||
| 332 | (icr:find-secondly-interval target dtstart/tz 10 ict:tz-eastern)))) | ||
| 333 | |||
| 334 | ;; With timezone, around a target that falls into the gap in local | ||
| 335 | ;; times and thus does not exist as a local time. In this case, what | ||
| 336 | ;; is supposed to happen is that the clock time value in the [observance] | ||
| 337 | ;; recurrences "is interpreted using the UTC offset before the gap | ||
| 338 | ;; in local times." So we should get the same absolute times back, | ||
| 339 | ;; but re-decoded into the new observance, i.e., one hour later. | ||
| 340 | (let* ((target (ical:date-time-variant dtstart/tz | ||
| 341 | :year 2030 :month 3 :day 10 | ||
| 342 | :hour 2 :minute 30 :second 0 | ||
| 343 | :zone ict:est :dst nil)) | ||
| 344 | (expected-int | ||
| 345 | (list | ||
| 346 | (ical:date-time-variant target :hour 3 :second 0 | ||
| 347 | :zone ict:edt :dst t) | ||
| 348 | (ical:date-time-variant target :hour 3 :second 1 | ||
| 349 | :zone ict:edt :dst t) | ||
| 350 | (ical:date-time-variant target | ||
| 351 | :hour 3 :second 10 | ||
| 352 | :zone ict:edt :dst t)))) | ||
| 353 | (should | ||
| 354 | (equal expected-int | ||
| 355 | (icr:find-secondly-interval target dtstart/tz 10 ict:tz-eastern)))) | ||
| 356 | |||
| 357 | ;; With timezone, with a "pathological" interval size of 59 seconds. | ||
| 358 | ;; There should be no problem with this case, because the interval | ||
| 359 | ;; bounds calculation is done in absolute time, but it's annoying to | ||
| 360 | ;; calculate the expected interval by hand: | ||
| 361 | (let* ((target (ical:date-time-variant dtstart/tz | ||
| 362 | :year 2031 :month 4 :day 15 | ||
| 363 | :hour 12 :minute 0 :second 0 | ||
| 364 | :zone ict:edt :dst t)) | ||
| 365 | (intsize 59) | ||
| 366 | (expected-int | ||
| 367 | (list | ||
| 368 | (ical:date-time-variant target :hour 11 :minute 59 :second 16 | ||
| 369 | :tz 'preserve) | ||
| 370 | (ical:date-time-variant target :hour 11 :minute 59 :second 17 | ||
| 371 | :tz 'preserve) | ||
| 372 | (ical:date-time-variant target :hour 12 :minute 0 :second 15 | ||
| 373 | :tz 'preserve)))) | ||
| 374 | (should | ||
| 375 | (equal expected-int | ||
| 376 | (icr:find-secondly-interval target dtstart/tz intsize | ||
| 377 | ict:tz-eastern)))))) | ||
| 378 | |||
| 379 | (ert-deftest ict:recur-find-minutely-interval () | ||
| 380 | "Does `icr:find-minutely-interval' find correct intervals?" | ||
| 381 | (let* ((dtstart (ical:make-date-time :year 2025 :month 1 :day 1 | ||
| 382 | :hour 0 :minute 0 | ||
| 383 | ;; make sure intervals are | ||
| 384 | ;; bounded on whole minutes: | ||
| 385 | :second 23)) | ||
| 386 | (dtstart/tz (ical:date-time-variant dtstart :zone ict:est :dst nil))) | ||
| 387 | |||
| 388 | ;; Year numbers are monotonically increasing in the following test cases, | ||
| 389 | ;; to make it easy to tell which of them fails. | ||
| 390 | |||
| 391 | ;; No timezone, just a fixed offset, around a target that doesn't fall on | ||
| 392 | ;; an interval boundary: | ||
| 393 | (let* ((target (ical:date-time-variant dtstart :year 2026 :minute 5)) | ||
| 394 | (intsize 10) | ||
| 395 | (expected-int | ||
| 396 | (list | ||
| 397 | (ical:date-time-variant target :minute 0 :second 0) | ||
| 398 | (ical:date-time-variant target :minute 1 :second 0) | ||
| 399 | (ical:date-time-variant target :minute 10 :second 0)))) | ||
| 400 | (should | ||
| 401 | (equal expected-int | ||
| 402 | (icr:find-minutely-interval target dtstart intsize)))) | ||
| 403 | |||
| 404 | ;; No timezone, just clock time, around a target that does fall on | ||
| 405 | ;; an interval boundary: | ||
| 406 | (let* ((target (ical:date-time-variant dtstart :year 2027 :minute 10)) | ||
| 407 | (intsize 10) | ||
| 408 | (expected-int | ||
| 409 | (list | ||
| 410 | (ical:date-time-variant target :minute 10 :second 0) | ||
| 411 | (ical:date-time-variant target :minute 11 :second 0) | ||
| 412 | (ical:date-time-variant target :minute 20 :second 0)))) | ||
| 413 | (should | ||
| 414 | (equal expected-int | ||
| 415 | (icr:find-minutely-interval target dtstart intsize)))) | ||
| 416 | |||
| 417 | ;; With timezone, around a target that falls on an interval | ||
| 418 | ;; boundary, in the same observance: | ||
| 419 | (let* ((target (ical:date-time-variant dtstart/tz | ||
| 420 | :year 2028 :month 2 :minute 20 | ||
| 421 | :zone ict:est :dst nil)) | ||
| 422 | (intsize 10) | ||
| 423 | (expected-int | ||
| 424 | (list | ||
| 425 | (ical:date-time-variant target :minute 20 :second 0 | ||
| 426 | :zone ict:est :dst nil) | ||
| 427 | (ical:date-time-variant target :minute 21 :second 0 | ||
| 428 | :zone ict:est :dst nil) | ||
| 429 | (ical:date-time-variant target :minute 30 :second 0 | ||
| 430 | :zone ict:est :dst nil)))) | ||
| 431 | (should | ||
| 432 | (equal expected-int | ||
| 433 | (icr:find-minutely-interval target dtstart/tz intsize | ||
| 434 | ict:tz-eastern)))) | ||
| 435 | |||
| 436 | ;; With timezone, around a target that does not fall on an interval | ||
| 437 | ;; boundary, and after the time zone observance shift: | ||
| 438 | (let* ((target (ical:date-time-variant dtstart/tz | ||
| 439 | :year 2029 :month 5 :minute 30 | ||
| 440 | :zone ict:edt :dst t)) | ||
| 441 | (intsize 10) | ||
| 442 | (expected-int | ||
| 443 | (list | ||
| 444 | (ical:date-time-variant target :minute 30 :second 0 | ||
| 445 | :zone ict:edt :dst t) | ||
| 446 | (ical:date-time-variant target :minute 31 :second 0 | ||
| 447 | :zone ict:edt :dst t) | ||
| 448 | (ical:date-time-variant target :minute 40 :second 0 | ||
| 449 | :zone ict:edt :dst t)))) | ||
| 450 | (should | ||
| 451 | (equal expected-int | ||
| 452 | (icr:find-minutely-interval target dtstart/tz intsize | ||
| 453 | ict:tz-eastern)))) | ||
| 454 | |||
| 455 | ;; With timezone, around a target that falls into the gap in local | ||
| 456 | ;; times and thus does not exist as a local time. In this case, what | ||
| 457 | ;; is supposed to happen is that the clock time value in the [observance] | ||
| 458 | ;; recurrences "is interpreted using the UTC offset before the gap | ||
| 459 | ;; in local times." So we should get the same absolute times back, | ||
| 460 | ;; but re-decoded into the new observance, i.e., one hour later. | ||
| 461 | (let* ((target (ical:date-time-variant dtstart/tz | ||
| 462 | :year 2030 :month 3 :day 10 | ||
| 463 | :hour 2 :minute 30 :second 0 | ||
| 464 | :zone ict:est :dst nil)) | ||
| 465 | (intsize 10) | ||
| 466 | (expected-int | ||
| 467 | (list | ||
| 468 | (ical:date-time-variant target :hour 3 :minute 30 :second 0 | ||
| 469 | :zone ict:edt :dst t) | ||
| 470 | (ical:date-time-variant target :hour 3 :minute 31 :second 0 | ||
| 471 | :zone ict:edt :dst t) | ||
| 472 | (ical:date-time-variant target | ||
| 473 | :hour 3 :minute 40 :second 0 | ||
| 474 | :zone ict:edt :dst t)))) | ||
| 475 | (should | ||
| 476 | (equal expected-int | ||
| 477 | (icr:find-minutely-interval target dtstart/tz intsize | ||
| 478 | ict:tz-eastern)))))) | ||
| 479 | |||
| 480 | (ert-deftest ict:recur-find-hourly-interval () | ||
| 481 | "Does `icr:find-hourly-interval' find correct intervals?" | ||
| 482 | (let* ((dtstart (ical:make-date-time :year 2025 :month 1 :day 1 | ||
| 483 | :hour 0 | ||
| 484 | ;; make sure intervals are bounded on | ||
| 485 | ;; whole hours: | ||
| 486 | :minute 11 :second 23)) | ||
| 487 | (dtstart/tz (ical:date-time-variant dtstart :zone ict:est :dst nil))) | ||
| 488 | |||
| 489 | ;; Year numbers are monotonically increasing in the following test cases, | ||
| 490 | ;; to make it easy to tell which of them fails. | ||
| 491 | ;; No timezone, just clock time, around a target that doesn't fall on | ||
| 492 | ;; an interval boundary: | ||
| 493 | (let* ((target (ical:date-time-variant dtstart :year 2026 :hour 5)) | ||
| 494 | (intsize 10) | ||
| 495 | (expected-int | ||
| 496 | (list | ||
| 497 | (ical:date-time-variant target :hour 0 :minute 0 :second 0) | ||
| 498 | (ical:date-time-variant target :hour 1 :minute 0 :second 0) | ||
| 499 | (ical:date-time-variant target :hour 10 :minute 0 :second 0)))) | ||
| 500 | (should | ||
| 501 | (equal expected-int | ||
| 502 | (icr:find-hourly-interval target dtstart intsize)))) | ||
| 503 | |||
| 504 | ;; No timezone, just clock time, around a target that does fall on | ||
| 505 | ;; an interval boundary: | ||
| 506 | (let* ((target (ical:date-time-variant dtstart :year 2027 :hour 10)) | ||
| 507 | (intsize 10) | ||
| 508 | (expected-int | ||
| 509 | (list | ||
| 510 | (ical:date-time-variant target :hour 10 :minute 0 :second 0) | ||
| 511 | (ical:date-time-variant target :hour 11 :minute 0 :second 0) | ||
| 512 | (ical:date-time-variant target :hour 20 :minute 0 :second 0)))) | ||
| 513 | (should | ||
| 514 | (equal expected-int | ||
| 515 | (icr:find-hourly-interval target dtstart intsize)))) | ||
| 516 | |||
| 517 | ;; With timezone, around a target that falls on an interval | ||
| 518 | ;; boundary, in the same observance: | ||
| 519 | (let* ((target (ical:date-time-variant dtstart/tz | ||
| 520 | :year 2028 :month 2 :hour 10 | ||
| 521 | :zone ict:est :dst nil)) | ||
| 522 | (intsize 2) | ||
| 523 | (expected-int | ||
| 524 | (list | ||
| 525 | (ical:date-time-variant target :hour 10 :minute 0 :second 0 | ||
| 526 | :zone ict:est :dst nil) | ||
| 527 | (ical:date-time-variant target :hour 11 :minute 0 :second 0 | ||
| 528 | :zone ict:est :dst nil) | ||
| 529 | (ical:date-time-variant target :hour 12 :minute 0 :second 0 | ||
| 530 | :zone ict:est :dst nil)))) | ||
| 531 | (should | ||
| 532 | (equal expected-int | ||
| 533 | (icr:find-hourly-interval target dtstart/tz intsize | ||
| 534 | ict:tz-eastern)))) | ||
| 535 | |||
| 536 | ;; With time zone, around a target that does not fall on an interval | ||
| 537 | ;; boundary, and after the time zone observance shift. Note that | ||
| 538 | ;; because of our decision to calculate with absolute times in | ||
| 539 | ;; SECONDLY/MINUTELY/HOURLY rules (see `icr:find-secondly-recurrence-rule') | ||
| 540 | ;; the interval clock times shift an hour here: | ||
| 541 | (let* ((target (ical:date-time-variant dtstart/tz | ||
| 542 | :year 2029 :month 5 :hour 12 | ||
| 543 | :zone ict:edt :dst t)) | ||
| 544 | (intsize 2) | ||
| 545 | (expected-int | ||
| 546 | (list | ||
| 547 | (ical:date-time-variant target :hour 11 :minute 0 :second 0 | ||
| 548 | :zone ict:edt :dst t) | ||
| 549 | (ical:date-time-variant target :hour 12 :minute 0 :second 0 | ||
| 550 | :zone ict:edt :dst t) | ||
| 551 | (ical:date-time-variant target :hour 13 :minute 0 :second 0 | ||
| 552 | :zone ict:edt :dst t)))) | ||
| 553 | (should | ||
| 554 | (equal expected-int | ||
| 555 | (icr:find-hourly-interval target dtstart/tz intsize | ||
| 556 | ict:tz-eastern)))) | ||
| 557 | |||
| 558 | ;; With timezone, around a target that falls into the gap in local | ||
| 559 | ;; times and thus does not exist as a local time. In this case, what | ||
| 560 | ;; is supposed to happen is that the clock time value in the [observance] | ||
| 561 | ;; recurrences "is interpreted using the UTC offset before the gap | ||
| 562 | ;; in local times." So we should get the same absolute times back, | ||
| 563 | ;; but re-decoded into the new observance, i.e., one hour later. | ||
| 564 | (let* ((target (ical:make-date-time :year 2030 :month 3 :day 10 | ||
| 565 | :hour 2 :minute 30 :second 30 | ||
| 566 | :zone ict:est :dst nil)) | ||
| 567 | (intsize 2) | ||
| 568 | (expected-int | ||
| 569 | (list | ||
| 570 | (ical:date-time-variant target :hour 3 :minute 0 :second 0 | ||
| 571 | :zone ict:edt :dst t) | ||
| 572 | (ical:date-time-variant target :hour 4 :minute 0 :second 0 | ||
| 573 | :zone ict:edt :dst t) | ||
| 574 | (ical:date-time-variant target :hour 5 :minute 0 :second 0 | ||
| 575 | :zone ict:edt :dst t)))) | ||
| 576 | (should | ||
| 577 | (equal expected-int | ||
| 578 | (icr:find-hourly-interval target dtstart/tz intsize | ||
| 579 | ict:tz-eastern)))))) | ||
| 580 | |||
| 581 | (ert-deftest ict:recur-find-daily-interval-w/date () | ||
| 582 | "Does `icr:find-daily-interval' find correct date intervals?" | ||
| 583 | (let* ((dtstart (list 1 8 2025))) | ||
| 584 | ;; Since all the results should be the same after the initial | ||
| 585 | ;; calculation of the absolute dates DTSTART and TARGET, we just | ||
| 586 | ;; test one simple case here and test with date-times more | ||
| 587 | ;; thoroughly below. | ||
| 588 | |||
| 589 | ;; A target that doesn't fall on an interval boundary: | ||
| 590 | (let* ((target (list 1 9 2026)) | ||
| 591 | (intsize 7) | ||
| 592 | (expected-int | ||
| 593 | (list | ||
| 594 | (ical:make-date-time :year 2026 :month 1 :day 7 | ||
| 595 | :hour 0 :minute 0 :second 0) | ||
| 596 | (ical:make-date-time :year 2026 :month 1 :day 8 | ||
| 597 | :hour 0 :minute 0 :second 0) | ||
| 598 | (ical:make-date-time :year 2026 :month 1 :day 14 | ||
| 599 | :hour 0 :minute 0 :second 0)))) | ||
| 600 | (should (equal expected-int | ||
| 601 | (icr:find-daily-interval target dtstart intsize)))))) | ||
| 602 | |||
| 603 | (ert-deftest ict:recur-find-daily-interval-w/date-time () | ||
| 604 | "Does `icr:find-daily-interval' find correct date-time intervals?" | ||
| 605 | (let* ((dtstart (ical:make-date-time :year 2025 :month 1 :day 8 ; a Wednesday | ||
| 606 | ;; make sure intervals are bounded on | ||
| 607 | ;; whole days: | ||
| 608 | :hour 7 :minute 11 :second 23)) | ||
| 609 | (dtstart/tz (ical:date-time-variant dtstart :zone ict:est :dst nil))) | ||
| 610 | |||
| 611 | ;; Year numbers are monotonically increasing in the following test cases, | ||
| 612 | ;; to make it easy to tell which of them fails. | ||
| 613 | |||
| 614 | ;; No timezone, just clock time, around a target that doesn't fall on | ||
| 615 | ;; an interval boundary: | ||
| 616 | (let* ((target (ical:date-time-variant dtstart | ||
| 617 | :year 2026 :month 1 :day 9)) | ||
| 618 | (intsize 7) | ||
| 619 | (expected-int | ||
| 620 | (list | ||
| 621 | (ical:date-time-variant target :day 7 :hour 0 :minute 0 :second 0) | ||
| 622 | (ical:date-time-variant target :day 8 :hour 0 :minute 0 :second 0) | ||
| 623 | (ical:date-time-variant target :day 14 | ||
| 624 | :hour 0 :minute 0 :second 0)))) | ||
| 625 | (should | ||
| 626 | (equal expected-int | ||
| 627 | (icr:find-daily-interval target dtstart intsize)))) | ||
| 628 | |||
| 629 | ;; No timezone, just clock time, around a target that does fall on | ||
| 630 | ;; an interval boundary: | ||
| 631 | (let* ((target (ical:date-time-variant dtstart :year 2027 :month 1 :day 6)) | ||
| 632 | (intsize 7) | ||
| 633 | (expected-int | ||
| 634 | (list | ||
| 635 | (ical:date-time-variant target :day 6 :hour 0 :minute 0 :second 0) | ||
| 636 | (ical:date-time-variant target :day 7 :hour 0 :minute 0 :second 0) | ||
| 637 | (ical:date-time-variant target :day 13 :hour 0 :minute 0 :second 0)))) | ||
| 638 | (should | ||
| 639 | (equal expected-int | ||
| 640 | (icr:find-daily-interval target dtstart intsize)))) | ||
| 641 | |||
| 642 | ;; With timezone, around a target that falls on an interval | ||
| 643 | ;; boundary, in the same observance: | ||
| 644 | (let* ((target (ical:date-time-variant dtstart/tz :year 2028 :month 2 :day 2 | ||
| 645 | :zone ict:est :dst nil)) | ||
| 646 | (intsize 7) | ||
| 647 | (expected-int | ||
| 648 | (list | ||
| 649 | (ical:date-time-variant target :day 2 :hour 0 :minute 0 :second 0 | ||
| 650 | :tz 'preserve) | ||
| 651 | (ical:date-time-variant target :day 3 :hour 0 :minute 0 :second 0 | ||
| 652 | :tz 'preserve) | ||
| 653 | (ical:date-time-variant target :day 9 :hour 0 :minute 0 :second 0 | ||
| 654 | :tz 'preserve)))) | ||
| 655 | (should | ||
| 656 | (equal expected-int | ||
| 657 | (icr:find-daily-interval target dtstart/tz intsize ict:tz-eastern)))) | ||
| 658 | |||
| 659 | ;; With time zone, around a target that does not fall on an interval | ||
| 660 | ;; boundary, and after the time zone observance shift. | ||
| 661 | (let* ((target (ical:date-time-variant dtstart/tz | ||
| 662 | :year 2029 :month 5 :day 28 | ||
| 663 | :zone ict:edt :dst t)) | ||
| 664 | (intsize 7) | ||
| 665 | (expected-int | ||
| 666 | (list | ||
| 667 | (ical:date-time-variant target :day 23 :hour 0 :minute 0 :second 0 | ||
| 668 | :tz 'preserve) | ||
| 669 | (ical:date-time-variant target :day 24 :hour 0 :minute 0 :second 0 | ||
| 670 | :tz 'preserve) | ||
| 671 | (ical:date-time-variant target :day 30 :hour 0 :minute 0 :second 0 | ||
| 672 | :tz 'preserve)))) | ||
| 673 | (should | ||
| 674 | (equal expected-int | ||
| 675 | (icr:find-daily-interval target dtstart/tz intsize | ||
| 676 | ict:tz-eastern)))))) | ||
| 677 | |||
| 678 | (ert-deftest ict:recur-find-weekly-interval-w/date () | ||
| 679 | "Does `icr:find-weekly-interval' find correct date intervals?" | ||
| 680 | (let* ((dtstart '(1 8 2025))) | ||
| 681 | ;; Since all the results should be the same after the initial | ||
| 682 | ;; calculation of the absolute dates DTSTART and TARGET, we just | ||
| 683 | ;; test one simple case here and test with date-times more | ||
| 684 | ;; thoroughly below. | ||
| 685 | |||
| 686 | ;; A target that doesn't fall on an interval boundary: | ||
| 687 | (let* ((target '(1 9 2026)) | ||
| 688 | (intsize 2) | ||
| 689 | (expected-int-mon | ||
| 690 | (list | ||
| 691 | (ical:make-date-time :year 2026 :month 1 :day 5 | ||
| 692 | :hour 0 :minute 0 :second 0) | ||
| 693 | (ical:make-date-time :year 2026 :month 1 :day 12 | ||
| 694 | :hour 0 :minute 0 :second 0) | ||
| 695 | (ical:make-date-time :year 2026 :month 1 :day 19 | ||
| 696 | :hour 0 :minute 0 :second 0)))) | ||
| 697 | (should (equal expected-int-mon | ||
| 698 | (icr:find-weekly-interval target dtstart intsize)))))) | ||
| 699 | |||
| 700 | (ert-deftest ict:recur-find-weekly-interval-w/date-time () | ||
| 701 | "Does `icr:find-weekly-interval' find correct date-time intervals?" | ||
| 702 | (let* ((dtstart (ical:make-date-time :year 2025 :month 1 :day 8 ; a Wednesday | ||
| 703 | ;; make sure intervals are bounded on | ||
| 704 | ;; whole days: | ||
| 705 | :hour 7 :minute 11 :second 23))) | ||
| 706 | |||
| 707 | ;; Year numbers are monotonically increasing in the following test cases, | ||
| 708 | ;; to make it easy to tell which of them fails. | ||
| 709 | |||
| 710 | ;; No timezone, just clock time, around a target that doesn't fall on | ||
| 711 | ;; an interval boundary: | ||
| 712 | (let* ((target (ical:date-time-variant dtstart :year 2026 :month 1 :day 9)) | ||
| 713 | (intsize 2) | ||
| 714 | (weds 3) | ||
| 715 | ;; expected interval for Monday (default) week start: | ||
| 716 | (expected-int-mon | ||
| 717 | (list | ||
| 718 | (ical:date-time-variant target :day 5 :hour 0 :minute 0 :second 0) | ||
| 719 | (ical:date-time-variant target :day 12 :hour 0 :minute 0 :second 0) | ||
| 720 | (ical:date-time-variant target :day 19 :hour 0 :minute 0 :second 0))) | ||
| 721 | ;; expected interval for Wednesday week start: | ||
| 722 | (expected-int-wed | ||
| 723 | (list | ||
| 724 | (ical:date-time-variant target :day 7 :hour 0 :minute 0 :second 0) | ||
| 725 | (ical:date-time-variant target :day 14 :hour 0 :minute 0 :second 0) | ||
| 726 | (ical:date-time-variant target :day 21 :hour 0 :minute 0 :second 0)))) | ||
| 727 | (should | ||
| 728 | (equal expected-int-mon | ||
| 729 | (icr:find-weekly-interval target dtstart intsize))) | ||
| 730 | (should | ||
| 731 | (equal expected-int-wed | ||
| 732 | (icr:find-weekly-interval target dtstart intsize weds)))) | ||
| 733 | |||
| 734 | ;; Around a target that does fall on an interval boundary, Monday week start: | ||
| 735 | (let* ((target (ical:date-time-variant dtstart :year 2027 :month 1 :day 4)) | ||
| 736 | (intsize 3) | ||
| 737 | ;; expected interval for Monday (default) week start: | ||
| 738 | (expected-int-mon | ||
| 739 | (list | ||
| 740 | (ical:date-time-variant target :year 2026 :month 12 :day 21 | ||
| 741 | :hour 0 :minute 0 :second 0) | ||
| 742 | (ical:date-time-variant target :year 2026 :month 12 :day 28 | ||
| 743 | :hour 0 :minute 0 :second 0) | ||
| 744 | (ical:date-time-variant target :day 11 | ||
| 745 | :hour 0 :minute 0 :second 0)))) | ||
| 746 | (should | ||
| 747 | (equal expected-int-mon | ||
| 748 | (icr:find-weekly-interval target dtstart intsize)))) | ||
| 749 | |||
| 750 | ;; Around a target that does fall on an interval boundary, Sunday week start: | ||
| 751 | (let* ((target (ical:date-time-variant dtstart :year 2028 :month 1 :day 2)) | ||
| 752 | (intsize 3) | ||
| 753 | (sun 0) | ||
| 754 | ;; expected interval for Sunday week start: | ||
| 755 | (expected-int-sun | ||
| 756 | (list | ||
| 757 | (ical:date-time-variant target :day 2 :hour 0 :minute 0 :second 0) | ||
| 758 | (ical:date-time-variant target :day 9 :hour 0 :minute 0 :second 0) | ||
| 759 | (ical:date-time-variant target :day 23 :hour 0 :minute 0 :second 0)))) | ||
| 760 | (should | ||
| 761 | (equal expected-int-sun | ||
| 762 | (icr:find-weekly-interval target dtstart intsize sun)))))) | ||
| 763 | |||
| 764 | (ert-deftest ict:recur-find-monthly-interval () | ||
| 765 | "Does `icr:find-monthly-interval' find correct intervals?" | ||
| 766 | ;; Year numbers are monotonically increasing in the following test cases, | ||
| 767 | ;; to make it easy to tell which of them fails. | ||
| 768 | |||
| 769 | ;; One test with dates, to make sure that works: | ||
| 770 | (let* ((dtstart '(1 8 2025)) | ||
| 771 | (target '(10 9 2025)) | ||
| 772 | (intsize 5) | ||
| 773 | (expected-int | ||
| 774 | (list | ||
| 775 | (ical:make-date-time :year 2025 :month 6 :day 1 | ||
| 776 | :hour 0 :minute 0 :second 0) | ||
| 777 | (ical:make-date-time :year 2025 :month 7 :day 1 | ||
| 778 | :hour 0 :minute 0 :second 0) | ||
| 779 | (ical:make-date-time :year 2025 :month 11 :day 1 | ||
| 780 | :hour 0 :minute 0 :second 0)))) | ||
| 781 | (should (equal expected-int | ||
| 782 | (icr:find-monthly-interval target dtstart intsize)))) | ||
| 783 | |||
| 784 | ;; Around a target that doesn't fall on an interval boundary: | ||
| 785 | (let* ((dtstart (ical:make-date-time :year 2025 :month 1 :day 1 | ||
| 786 | ;; make sure intervals are bounded on | ||
| 787 | ;; whole days: | ||
| 788 | :hour 7 :minute 11 :second 23)) | ||
| 789 | (target (ical:date-time-variant dtstart :year 2026 :month 3 :day 9)) | ||
| 790 | (intsize 2) | ||
| 791 | (expected-int | ||
| 792 | (list | ||
| 793 | (ical:date-time-variant target :day 1 :hour 0 :minute 0 :second 0) | ||
| 794 | (ical:date-time-variant target :month 4 :day 1 | ||
| 795 | :hour 0 :minute 0 :second 0) | ||
| 796 | (ical:date-time-variant target :month 5 :day 1 | ||
| 797 | :hour 0 :minute 0 :second 0)))) | ||
| 798 | (should | ||
| 799 | (equal expected-int | ||
| 800 | (icr:find-monthly-interval target dtstart intsize)))) | ||
| 801 | |||
| 802 | ;; Around a target that does fall on an interval boundary: | ||
| 803 | (let* ((dtstart (ical:make-date-time :year 2025 :month 1 :day 1 | ||
| 804 | ;; make sure intervals are bounded on | ||
| 805 | ;; whole days: | ||
| 806 | :hour 7 :minute 11 :second 23)) | ||
| 807 | (target (ical:date-time-variant dtstart :year 2027 :month 5 :day 1)) | ||
| 808 | (intsize 7) | ||
| 809 | (expected-int | ||
| 810 | (list | ||
| 811 | (ical:date-time-variant target :year 2027 :month 5 :day 1 | ||
| 812 | :hour 0 :minute 0 :second 0) | ||
| 813 | (ical:date-time-variant target :year 2027 :month 6 :day 1 | ||
| 814 | :hour 0 :minute 0 :second 0) | ||
| 815 | (ical:date-time-variant target :year 2027 :month 12 :day 1 | ||
| 816 | :hour 0 :minute 0 :second 0)))) | ||
| 817 | (should | ||
| 818 | (equal expected-int | ||
| 819 | (icr:find-monthly-interval target dtstart intsize)))) | ||
| 820 | |||
| 821 | ;; Around a target that does not fall on an interval boundary, where | ||
| 822 | ;; start month > target month | ||
| 823 | (let* ((dtstart (ical:make-date-time :year 2028 :month 11 :day 11 | ||
| 824 | :hour 11 :minute 11 :second 11)) | ||
| 825 | (target (ical:date-time-variant dtstart | ||
| 826 | :year 2029 :month 4 :day 15)) | ||
| 827 | (intsize 2) | ||
| 828 | (expected-int | ||
| 829 | (list | ||
| 830 | (ical:date-time-variant target :year 2029 :month 3 :day 1 | ||
| 831 | :hour 0 :minute 0 :second 0) | ||
| 832 | (ical:date-time-variant target :year 2029 :month 4 :day 1 | ||
| 833 | :hour 0 :minute 0 :second 0) | ||
| 834 | (ical:date-time-variant target :year 2029 :month 5 :day 1 | ||
| 835 | :hour 0 :minute 0 :second 0)))) | ||
| 836 | (should | ||
| 837 | (equal expected-int | ||
| 838 | (icr:find-monthly-interval target dtstart intsize)))) | ||
| 839 | |||
| 840 | ;; Around a target that falls on an interval boundary, where | ||
| 841 | ;; start month > target month | ||
| 842 | (let* ((dtstart (ical:make-date-time :year 2029 :month 11 :day 11 | ||
| 843 | :hour 11 :minute 11 :second 11 )) | ||
| 844 | (target (ical:date-time-variant dtstart | ||
| 845 | :year 2030 :month 5 :day 1)) | ||
| 846 | (intsize 2) | ||
| 847 | (expected-int | ||
| 848 | (list | ||
| 849 | (ical:date-time-variant target :year 2030 :month 5 :day 1 | ||
| 850 | :hour 0 :minute 0 :second 0) | ||
| 851 | (ical:date-time-variant target :year 2030 :month 6 :day 1 | ||
| 852 | :hour 0 :minute 0 :second 0) | ||
| 853 | (ical:date-time-variant target :year 2030 :month 7 :day 1 | ||
| 854 | :hour 0 :minute 0 :second 0)))) | ||
| 855 | (should | ||
| 856 | (equal expected-int | ||
| 857 | (icr:find-monthly-interval target dtstart intsize)))) | ||
| 858 | |||
| 859 | ;; Around a target that falls on an interval boundary, where | ||
| 860 | ;; start month = target month | ||
| 861 | (let* ((dtstart (ical:make-date-time :year 2031 :month 11 :day 11 | ||
| 862 | :hour 11 :minute 11 :second 11 )) | ||
| 863 | (target (ical:date-time-variant dtstart :year 2032 :month 11 :day 11)) | ||
| 864 | (intsize 2) | ||
| 865 | (expected-int | ||
| 866 | (list | ||
| 867 | (ical:date-time-variant target :year 2032 :month 11 :day 1 | ||
| 868 | :hour 0 :minute 0 :second 0) | ||
| 869 | (ical:date-time-variant target :year 2032 :month 12 :day 1 | ||
| 870 | :hour 0 :minute 0 :second 0) | ||
| 871 | (ical:date-time-variant target :year 2033 :month 1 :day 1 | ||
| 872 | :hour 0 :minute 0 :second 0)))) | ||
| 873 | (should | ||
| 874 | (equal expected-int | ||
| 875 | (icr:find-monthly-interval target dtstart intsize))))) | ||
| 876 | |||
| 877 | (ert-deftest ict:recur-find-yearly-interval () | ||
| 878 | "Does `icr:find-yearly-interval' find correct date intervals?" | ||
| 879 | ;; Year numbers are monotonically increasing in the following test cases, | ||
| 880 | ;; to make it easy to tell which of them fails. | ||
| 881 | |||
| 882 | ;; One test with dates, to make sure that works: | ||
| 883 | (let* ((dtstart '(1 8 2025)) | ||
| 884 | (target '(10 9 2025)) | ||
| 885 | (intsize 2) | ||
| 886 | (expected-int | ||
| 887 | (list | ||
| 888 | (ical:make-date-time :year 2025 :month 1 :day 1 | ||
| 889 | :hour 0 :minute 0 :second 0) | ||
| 890 | (ical:make-date-time :year 2026 :month 1 :day 1 | ||
| 891 | :hour 0 :minute 0 :second 0) | ||
| 892 | (ical:make-date-time :year 2027 :month 1 :day 1 | ||
| 893 | :hour 0 :minute 0 :second 0)))) | ||
| 894 | (should (equal expected-int | ||
| 895 | (icr:find-yearly-interval target dtstart intsize)))) | ||
| 896 | |||
| 897 | ;; A target not on an interval boundary: | ||
| 898 | (let* ((dtstart (ical:make-date-time :year 2026 :month 3 :day 1 | ||
| 899 | :hour 1 :minute 2 :second 3)) | ||
| 900 | (target (ical:make-date-time :year 2026 :month 7 :day 28 | ||
| 901 | :hour 11 :minute 58 :second 0)) | ||
| 902 | (intsize 3) | ||
| 903 | (expected-int | ||
| 904 | (list | ||
| 905 | (ical:make-date-time :year 2026 :month 1 :day 1 | ||
| 906 | :hour 0 :minute 0 :second 0) | ||
| 907 | (ical:make-date-time :year 2027 :month 1 :day 1 | ||
| 908 | :hour 0 :minute 0 :second 0) | ||
| 909 | (ical:make-date-time :year 2029 :month 1 :day 1 | ||
| 910 | :hour 0 :minute 0 :second 0)))) | ||
| 911 | (should (equal expected-int | ||
| 912 | (icr:find-yearly-interval target dtstart intsize)))) | ||
| 913 | |||
| 914 | ;; A target on an interval boundary: | ||
| 915 | (let* ((dtstart (ical:make-date-time :year 2027 :month 3 :day 1 | ||
| 916 | :hour 1 :minute 2 :second 3)) | ||
| 917 | (target (ical:make-date-time :year 2028 :month 1 :day 1 | ||
| 918 | :hour 0 :minute 0 :second 0)) | ||
| 919 | (intsize 4) | ||
| 920 | (expected-int | ||
| 921 | (list | ||
| 922 | (ical:make-date-time :year 2027 :month 1 :day 1 | ||
| 923 | :hour 0 :minute 0 :second 0) | ||
| 924 | (ical:make-date-time :year 2028 :month 1 :day 1 | ||
| 925 | :hour 0 :minute 0 :second 0) | ||
| 926 | (ical:make-date-time :year 2031 :month 1 :day 1 | ||
| 927 | :hour 0 :minute 0 :second 0)))) | ||
| 928 | (should (equal expected-int | ||
| 929 | (icr:find-yearly-interval target dtstart intsize)))) | ||
| 930 | |||
| 931 | ;; A target earlier than dtstart but in the same year; | ||
| 932 | ;; it's important that this works when looking up recurrences of | ||
| 933 | ;; time zone observance onsets | ||
| 934 | (let* ((dtstart (ical:make-date-time :year 2029 :month 5 :day 28 | ||
| 935 | :hour 1 :minute 2 :second 3)) | ||
| 936 | (target (ical:make-date-time :year 2029 :month 2 :day 14 | ||
| 937 | :hour 11 :minute 58 :second 0)) | ||
| 938 | (intsize 1) | ||
| 939 | (expected-int | ||
| 940 | (list | ||
| 941 | (ical:make-date-time :year 2029 :month 1 :day 1 | ||
| 942 | :hour 0 :minute 0 :second 0) | ||
| 943 | (ical:make-date-time :year 2030 :month 1 :day 1 | ||
| 944 | :hour 0 :minute 0 :second 0) | ||
| 945 | (ical:make-date-time :year 2030 :month 1 :day 1 | ||
| 946 | :hour 0 :minute 0 :second 0)))) | ||
| 947 | (should (equal expected-int | ||
| 948 | (icr:find-yearly-interval target dtstart intsize))))) | ||
| 949 | |||
| 950 | ;; Subintervals: | ||
| 951 | |||
| 952 | (ert-deftest ict:recur-refine-byyearday () | ||
| 953 | "Does `icr:refine-byyearday' correctly refine by yeardays?" | ||
| 954 | (let* ((low (ical:make-date-time :year 2025 :month 1 :day 1 | ||
| 955 | :hour 0 :minute 0 :second 0)) | ||
| 956 | (high (ical:date/time-add low :year 1)) | ||
| 957 | (interval (list low high high)) | ||
| 958 | (yeardays (list 2 -7)) | ||
| 959 | (sub1 (list (ical:date-time-variant low :day 2) | ||
| 960 | (ical:date-time-variant low :day 3))) | ||
| 961 | (sub2 (list (ical:date-time-variant low :month 12 :day 25) | ||
| 962 | (ical:date-time-variant low :month 12 :day 26))) | ||
| 963 | (expected-subintervals (list sub1 sub2))) | ||
| 964 | (should (equal expected-subintervals | ||
| 965 | (icr:refine-byyearday interval yeardays))))) | ||
| 966 | |||
| 967 | (ert-deftest ict:recur-refine-bymonth () | ||
| 968 | "Does `icr:refine-bymonth' correctly refine by months?" | ||
| 969 | (let* ((low (ical:make-date-time :year 2025 :month 1 :day 1 | ||
| 970 | :hour 0 :minute 0 :second 0)) | ||
| 971 | (high (ical:date/time-add low :year 1)) | ||
| 972 | (interval (list low high high)) | ||
| 973 | (months (list 9 2)) | ||
| 974 | (sub1 (list (ical:date-time-variant low :month 2 :day 1) | ||
| 975 | (ical:date-time-variant low :month 3 :day 1))) | ||
| 976 | (sub2 (list (ical:date-time-variant low :month 9 :day 1) | ||
| 977 | (ical:date-time-variant low :month 10 :day 1))) | ||
| 978 | (expected-subintervals (list sub1 sub2))) | ||
| 979 | (should (equal expected-subintervals | ||
| 980 | (icr:refine-bymonth interval months))))) | ||
| 981 | |||
| 982 | (ert-deftest ict:recur-refine-bymonthday () | ||
| 983 | "Does `icr:refine-bymonthday' correctly refine by days of the month?" | ||
| 984 | (let* ((low (ical:make-date-time :year 2025 :month 2 :day 1 | ||
| 985 | :hour 0 :minute 0 :second 0)) | ||
| 986 | (high (ical:date/time-add low :month 1)) | ||
| 987 | (interval (list low high high)) | ||
| 988 | (monthdays (list -1 2 29)) | ||
| 989 | ;; N.B. we should get no subinterval for Feb. 29, 2025 | ||
| 990 | (sub1 (list (ical:date-time-variant low :day 2) | ||
| 991 | (ical:date-time-variant low :day 3))) | ||
| 992 | (sub2 (list (ical:date-time-variant low :day 28) | ||
| 993 | (ical:date-time-variant low :month 3 :day 1))) | ||
| 994 | (expected-subintervals (list sub1 sub2))) | ||
| 995 | (should (equal expected-subintervals | ||
| 996 | (icr:refine-bymonthday interval monthdays))))) | ||
| 997 | |||
| 998 | (ert-deftest ict:recur-refine-byday () | ||
| 999 | "Does `icr:refine-byday' correctly refine by days of the week?" | ||
| 1000 | ;; The simple case: just day names | ||
| 1001 | (let* ((low (ical:make-date-time :year 2025 :month 3 :day 3 ; a Monday | ||
| 1002 | :hour 0 :minute 0 :second 0)) | ||
| 1003 | (high (ical:date/time-add low :day 7)) | ||
| 1004 | (interval (list low high high)) | ||
| 1005 | (days (list 0 6)) ; just the weekend, please! | ||
| 1006 | (sub1 (list (ical:date-time-variant low :day 8) | ||
| 1007 | (ical:date-time-variant low :day 9))) | ||
| 1008 | (sub2 (list (ical:date-time-variant low :day 9) | ||
| 1009 | (ical:date-time-variant low :day 10))) | ||
| 1010 | (expected-subintervals (list sub1 sub2))) | ||
| 1011 | (should (equal expected-subintervals | ||
| 1012 | (icr:refine-byday interval days)))) | ||
| 1013 | |||
| 1014 | ;; Day names with offsets within the month | ||
| 1015 | (let* ((low (ical:make-date-time :year 2025 :month 3 :day 1 ; a Saturday | ||
| 1016 | :hour 0 :minute 0 :second 0)) | ||
| 1017 | (high (ical:date/time-add low :month 1)) | ||
| 1018 | (interval (list low high high)) | ||
| 1019 | (days (list '(1 . 2) '(1 . -1))) ; second and last Monday | ||
| 1020 | (sub1 (list (ical:date-time-variant low :day 10) | ||
| 1021 | (ical:date-time-variant low :day 11))) | ||
| 1022 | (sub2 (list (ical:date-time-variant low :day 31) | ||
| 1023 | (ical:date-time-variant low :month 4 :day 1))) | ||
| 1024 | (expected-subintervals (list sub1 sub2))) | ||
| 1025 | (should (equal expected-subintervals | ||
| 1026 | (icr:refine-byday interval days t)))) | ||
| 1027 | |||
| 1028 | ;; Day names with offsets within the year | ||
| 1029 | (let* ((low (ical:make-date-time :year 2025 :month 1 :day 1 | ||
| 1030 | :hour 0 :minute 0 :second 0)) | ||
| 1031 | (high (ical:date/time-add low :year 1)) | ||
| 1032 | (interval (list low high high)) | ||
| 1033 | (days (list '(5 . 1) '(5 . -1))) ; first and last Friday | ||
| 1034 | (sub1 (list (ical:date-time-variant low :day 3) | ||
| 1035 | (ical:date-time-variant low :day 4))) | ||
| 1036 | (sub2 (list (ical:date-time-variant low :month 12 :day 26) | ||
| 1037 | (ical:date-time-variant low :month 12 :day 27))) | ||
| 1038 | (expected-subintervals (list sub1 sub2))) | ||
| 1039 | (should (equal expected-subintervals | ||
| 1040 | (icr:refine-byday interval days nil))))) | ||
| 1041 | |||
| 1042 | (ert-deftest ict:recur-refine-byhour () | ||
| 1043 | "Does `icr:refine-byhour' correctly refine by hours?" | ||
| 1044 | ;; No time zone, just clock times: | ||
| 1045 | (let* ((low (ical:make-date-time :year 2025 :month 1 :day 1 | ||
| 1046 | :hour 0 :minute 0 :second 0)) | ||
| 1047 | (high (ical:date/time-add low :day 1)) | ||
| 1048 | (interval (list low high high)) | ||
| 1049 | (hours (list 2 19)) | ||
| 1050 | (sub1 (list (ical:date-time-variant low :hour 2) | ||
| 1051 | (ical:date-time-variant low :hour 3))) | ||
| 1052 | (sub2 (list (ical:date-time-variant low :hour 19) | ||
| 1053 | (ical:date-time-variant low :hour 20))) | ||
| 1054 | (expected-subintervals (list sub1 sub2))) | ||
| 1055 | (should (equal expected-subintervals | ||
| 1056 | (icr:refine-byhour interval hours)))) | ||
| 1057 | |||
| 1058 | ;; With time zone, but without crossing an observance boundary: | ||
| 1059 | (let* ((low (ical:make-date-time :year 2025 :month 2 :day 1 | ||
| 1060 | :hour 0 :minute 0 :second 0 | ||
| 1061 | :zone ict:est :dst nil)) | ||
| 1062 | (high (ical:date/time-add low :day 1 ict:tz-eastern)) | ||
| 1063 | (interval (list low high high)) | ||
| 1064 | (hours (list 2 19)) | ||
| 1065 | (sub1 (list (ical:date-time-variant low :hour 2 :tz 'preserve) | ||
| 1066 | (ical:date-time-variant low :hour 3 :tz 'preserve))) | ||
| 1067 | (sub2 (list (ical:date-time-variant low :hour 19 :tz 'preserve) | ||
| 1068 | (ical:date-time-variant low :hour 20 :tz 'preserve))) | ||
| 1069 | (expected-subintervals (list sub1 sub2))) | ||
| 1070 | (should (equal expected-subintervals | ||
| 1071 | (icr:refine-byhour interval hours ict:tz-eastern))))) | ||
| 1072 | |||
| 1073 | (ert-deftest ict:recur-refine-byminute () | ||
| 1074 | "Does `icr:refine-byminute' correctly refine by minutes?" | ||
| 1075 | ;; No time zone, just clock times: | ||
| 1076 | (let* ((low (ical:make-date-time :year 2025 :month 5 :day 1 | ||
| 1077 | :hour 13 :minute 0 :second 0)) | ||
| 1078 | (high (ical:date/time-add low :hour 1)) | ||
| 1079 | (interval (list low high high)) | ||
| 1080 | (minutes (list 7 59)) | ||
| 1081 | (sub1 (list (ical:date-time-variant low :minute 7) | ||
| 1082 | (ical:date-time-variant low :minute 8))) | ||
| 1083 | (sub2 (list (ical:date-time-variant low :minute 59) | ||
| 1084 | (ical:date-time-variant low :hour 14 :minute 0))) | ||
| 1085 | (expected-subintervals (list sub1 sub2))) | ||
| 1086 | (should (equal expected-subintervals | ||
| 1087 | (icr:refine-byminute interval minutes)))) | ||
| 1088 | |||
| 1089 | ;; With time zone, but without crossing an observance boundary: | ||
| 1090 | (let* ((low (ical:make-date-time :year 2025 :month 2 :day 1 | ||
| 1091 | :hour 13 :minute 0 :second 0 | ||
| 1092 | :zone ict:est :dst nil)) | ||
| 1093 | (high (ical:date/time-add low :hour 1 ict:tz-eastern)) | ||
| 1094 | (interval (list low high high)) | ||
| 1095 | (minutes (list 7 59)) | ||
| 1096 | (sub1 (list (ical:date-time-variant low :minute 7 :tz 'preserve) | ||
| 1097 | (ical:date-time-variant low :minute 8 :tz 'preserve))) | ||
| 1098 | (sub2 (list (ical:date-time-variant low :minute 59 :tz 'preserve) | ||
| 1099 | (ical:date-time-variant low :hour 14 :minute 0 | ||
| 1100 | :tz 'preserve))) | ||
| 1101 | (expected-subintervals (list sub1 sub2))) | ||
| 1102 | (should (equal expected-subintervals | ||
| 1103 | (icr:refine-byminute interval minutes ict:tz-eastern))))) | ||
| 1104 | |||
| 1105 | (ert-deftest ict:recur-refine-bysecond () | ||
| 1106 | "Does `icr:refine-bysecond' correctly refine by seconds?" | ||
| 1107 | ;; No time zone, just clock times: | ||
| 1108 | (let* ((low (ical:make-date-time :year 2025 :month 5 :day 1 | ||
| 1109 | :hour 13 :minute 59 :second 0)) | ||
| 1110 | (high (ical:date/time-add low :minute 1)) | ||
| 1111 | (interval (list low high high)) | ||
| 1112 | (seconds (list 24 59)) | ||
| 1113 | (sub1 (list (ical:date-time-variant low :second 24) | ||
| 1114 | (ical:date-time-variant low :second 25))) | ||
| 1115 | (sub2 (list (ical:date-time-variant low :second 59) | ||
| 1116 | (ical:date-time-variant low :hour 14 :minute 0 :second 0))) | ||
| 1117 | (expected-subintervals (list sub1 sub2))) | ||
| 1118 | (should (equal expected-subintervals | ||
| 1119 | (icr:refine-bysecond interval seconds)))) | ||
| 1120 | |||
| 1121 | ;; With time zone, but without crossing an observance boundary: | ||
| 1122 | (let* ((low (ical:make-date-time :year 2025 :month 2 :day 1 | ||
| 1123 | :hour 13 :minute 19 :second 0 | ||
| 1124 | :zone ict:est :dst nil)) | ||
| 1125 | (high (ical:date/time-add low :minute 1 ict:tz-eastern)) | ||
| 1126 | (interval (list low high high)) | ||
| 1127 | (seconds (list 24 59)) | ||
| 1128 | (sub1 (list (ical:date-time-variant low :second 24 :tz 'preserve) | ||
| 1129 | (ical:date-time-variant low :second 25 :tz 'preserve))) | ||
| 1130 | (sub2 (list (ical:date-time-variant low :second 59 :tz 'preserve) | ||
| 1131 | (ical:date-time-variant low :minute 20 :second 0 | ||
| 1132 | :tz 'preserve))) | ||
| 1133 | (expected-subintervals (list sub1 sub2))) | ||
| 1134 | (should (equal expected-subintervals | ||
| 1135 | (icr:refine-bysecond interval seconds ict:tz-eastern))))) | ||
| 1136 | |||
| 1137 | (ert-deftest ict:recur-subintervals-to-dates () | ||
| 1138 | "Does `icr:subintervals-to-dates' correctly generate recurrences?" | ||
| 1139 | ;; Two subintervals, the first three days long, the second less than a single day | ||
| 1140 | (let* ((low1 (ical:make-date-time :year 2025 :month 5 :day 1 | ||
| 1141 | :hour 13 :minute 59 :second 0)) | ||
| 1142 | (high1 (ical:date/time-add low1 :day 3)) | ||
| 1143 | (sub1 (list low1 high1)) | ||
| 1144 | (low2 (ical:make-date-time :year 2025 :month 5 :day 31 | ||
| 1145 | :hour 14 :minute 0 :second 0)) | ||
| 1146 | (high2 (ical:date/time-add low2 :hour 3)) ; later but on the same day | ||
| 1147 | (sub2 (list low2 high2)) | ||
| 1148 | (low-date1 (ical:date-time-to-date low1)) | ||
| 1149 | (low-date2 (ical:date-time-to-date low2)) | ||
| 1150 | (expected-recs (list low-date1 | ||
| 1151 | (ical:date/time-add low-date1 :day 1) | ||
| 1152 | (ical:date/time-add low-date1 :day 2) | ||
| 1153 | (ical:date/time-add low-date1 :day 3) | ||
| 1154 | low-date2))) | ||
| 1155 | (should (equal expected-recs | ||
| 1156 | (icr:subintervals-to-dates (list sub1 sub2)))))) | ||
| 1157 | |||
| 1158 | (ert-deftest ict:recur-subintervals-to-date-times () | ||
| 1159 | "Does `icr:subintervals-to-date-times' correctly generate recurrences?" | ||
| 1160 | ;; Two subintervals, each one second long, no time zone | ||
| 1161 | (let* ((low1 (ical:make-date-time :year 2025 :month 5 :day 1 | ||
| 1162 | :hour 13 :minute 59 :second 0)) | ||
| 1163 | (high1 (ical:date/time-add low1 :second 1)) | ||
| 1164 | (sub1 (list low1 high1)) | ||
| 1165 | (low2 (ical:make-date-time :year 2025 :month 5 :day 2 | ||
| 1166 | :hour 14 :minute 0 :second 0)) | ||
| 1167 | (high2 (ical:date/time-add low2 :second 1)) | ||
| 1168 | (sub2 (list low2 high2)) | ||
| 1169 | (expected-recs (list low1 low2))) | ||
| 1170 | (should (equal expected-recs | ||
| 1171 | (icr:subintervals-to-date-times (list sub1 sub2))))) | ||
| 1172 | |||
| 1173 | ;; A subinterval five seconds long, with time zone | ||
| 1174 | (let* ((low1 (ical:make-date-time :year 2025 :month 6 :day 1 | ||
| 1175 | :hour 13 :minute 59 :second 0 | ||
| 1176 | :zone ict:edt :dst t)) | ||
| 1177 | (high1 (ical:date/time-add low1 :second 5 ict:tz-eastern)) | ||
| 1178 | (sub1 (list low1 high1)) | ||
| 1179 | (expected-recs | ||
| 1180 | (list low1 | ||
| 1181 | (ical:date/time-add low1 :second 1 ict:tz-eastern) | ||
| 1182 | (ical:date/time-add low1 :second 2 ict:tz-eastern) | ||
| 1183 | (ical:date/time-add low1 :second 3 ict:tz-eastern) | ||
| 1184 | (ical:date/time-add low1 :second 4 ict:tz-eastern)))) | ||
| 1185 | (should (equal expected-recs | ||
| 1186 | (icr:subintervals-to-date-times (list sub1) ict:tz-eastern)))) | ||
| 1187 | |||
| 1188 | ;; A subinterval five seconds long, with time zone, which crosses an | ||
| 1189 | ;; observance boundary where the final three seconds occur after | ||
| 1190 | ;; clocks are set forward an hour; these seconds should therefore be in EDT: | ||
| 1191 | (let* ((low1 (ical:make-date-time :year 2025 :month 3 :day 9 | ||
| 1192 | :hour 1 :minute 59 :second 58 | ||
| 1193 | :zone ict:est :dst nil)) | ||
| 1194 | (high1 (ical:make-date-time :year 2025 :month 3 :day 9 | ||
| 1195 | :hour 3 :minute 0 :second 3 | ||
| 1196 | :zone ict:edt :dst t)) | ||
| 1197 | (sub1 (list low1 high1)) | ||
| 1198 | (expected-recs | ||
| 1199 | (list low1 | ||
| 1200 | (ical:date-time-variant low1 :second 59 :tz 'preserve) | ||
| 1201 | (ical:date-time-variant high1 :second 0 :tz 'preserve) | ||
| 1202 | (ical:date-time-variant high1 :second 1 :tz 'preserve) | ||
| 1203 | (ical:date-time-variant high1 :second 2 :tz 'preserve)))) | ||
| 1204 | (should (equal expected-recs | ||
| 1205 | (icr:subintervals-to-date-times (list sub1) ict:tz-eastern)))) | ||
| 1206 | |||
| 1207 | ;; A subinterval five seconds long, with time zone, which crosses an | ||
| 1208 | ;; observance boundary where the final three seconds occur after | ||
| 1209 | ;; clocks are set back an hour; these seconds should therefore be in | ||
| 1210 | ;; EST: | ||
| 1211 | (let* ((low1 (ical:make-date-time :year 2024 :month 11 :day 3 | ||
| 1212 | :hour 1 :minute 59 :second 58 | ||
| 1213 | :zone ict:edt :dst t)) | ||
| 1214 | (high1 (ical:make-date-time :year 2024 :month 11 :day 3 | ||
| 1215 | :hour 1 :minute 0 :second 2 | ||
| 1216 | :zone ict:est :dst nil)) | ||
| 1217 | (sub1 (list low1 high1)) | ||
| 1218 | (expected-recs | ||
| 1219 | (list low1 | ||
| 1220 | (ical:date-time-variant low1 :second 59 :tz 'preserve) | ||
| 1221 | (ical:date-time-variant high1 :second 0 :tz 'preserve) | ||
| 1222 | (ical:date-time-variant high1 :second 1 :tz 'preserve)))) | ||
| 1223 | (should (equal expected-recs | ||
| 1224 | (icr:subintervals-to-date-times (list sub1) ict:tz-eastern))))) | ||
| 1225 | |||
| 1226 | ;; Tests for time zone functions: | ||
| 1227 | |||
| 1228 | (ert-deftest ict:recur-tz-observance-on/nonexistent () | ||
| 1229 | "Does `icr:tz-observance-on' correctly interpret nonexistent times?" | ||
| 1230 | (let* ((onset-start (ical:make-date-time :year 2030 :month 3 :day 10 | ||
| 1231 | :hour 2 :minute 0 :second 0 | ||
| 1232 | :zone ict:est :dst nil)) | ||
| 1233 | (start-shifted (ical:date-time-variant onset-start :hour 3 | ||
| 1234 | :zone ict:edt :dst t)) | ||
| 1235 | ;; 2:30AM falls into the gap when the clock jumps from 2AM to 3AM: | ||
| 1236 | (nonexistent (ical:date-time-variant onset-start :minute 30 | ||
| 1237 | :zone ict:est :dst nil)) | ||
| 1238 | (nonexistent-shifted (ical:date-time-variant nonexistent :hour 3 | ||
| 1239 | :zone ict:edt :dst t))) | ||
| 1240 | (icr:tz-observance-on onset-start ict:tz-eastern t) ;; updates the time to EDT | ||
| 1241 | (icr:tz-observance-on nonexistent ict:tz-eastern t) ;; updates the time to EDT | ||
| 1242 | (should (equal onset-start start-shifted)) | ||
| 1243 | (should (equal nonexistent nonexistent-shifted)))) | ||
| 1244 | |||
| 1245 | (ert-deftest ict:recur-tz-observance-on/occurs-twice () | ||
| 1246 | "Does `icr:tz-observance-on' correctly interpret times that occur twice?" | ||
| 1247 | (let* ((onset-start (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 1248 | :hour 2 :minute 0 :second 0 | ||
| 1249 | :zone ict:edt :dst t)) | ||
| 1250 | ;; 1:30AM occurs twice when the clock is set back from 2AM to 1AM: | ||
| 1251 | (no-zone (ical:date-time-variant onset-start :hour 1 :minute 30)) | ||
| 1252 | (first (ical:date-time-variant onset-start :hour 1 :minute 30 | ||
| 1253 | :zone ict:edt :dst t)) | ||
| 1254 | (second (ical:date-time-variant first :zone ict:est :dst nil)) | ||
| 1255 | (first+1h (ical:date/time-add first :hour 1 ict:tz-eastern))) | ||
| 1256 | (icr:tz-observance-on no-zone ict:tz-eastern t) ;; sets zone | ||
| 1257 | (should (equal first no-zone)) | ||
| 1258 | (should (equal second first+1h)))) | ||
| 1259 | |||
| 1260 | (ert-deftest ict:recur-tz-observance-on () | ||
| 1261 | "Does `icr:tz-observance-on' correctly find observances?" | ||
| 1262 | |||
| 1263 | ;; A date before the start of all observances in the timezone. | ||
| 1264 | ;; In this case, there is no matching observance, so we should get nil. | ||
| 1265 | (let* ((dt (ical:make-date-time :year 1900 :month 1 :day 1 | ||
| 1266 | :hour 12 :minute 0 :second 0 | ||
| 1267 | :zone ict:est :dst nil)) | ||
| 1268 | (ts (encode-time dt))) | ||
| 1269 | (should (null (icr:tz-observance-on dt ict:tz-eastern))) | ||
| 1270 | (should (null (icr:tz-observance-on ts ict:tz-eastern)))) | ||
| 1271 | |||
| 1272 | ;; A date matching the start of one of the STANDARD observances: | ||
| 1273 | (let* ((dt (ical:make-date-time :year 1967 :month 10 :day 29 | ||
| 1274 | :hour 2 :minute 0 :second 0 | ||
| 1275 | :zone ict:edt :dst t)) | ||
| 1276 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1277 | (obs (car obs/onset)) | ||
| 1278 | (onset (cadr obs/onset)) | ||
| 1279 | ;; make sure we get the same result with an absolute time: | ||
| 1280 | (ts (encode-time dt)) | ||
| 1281 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1282 | (should (eq 'ical:standard (ical:ast-node-type obs))) | ||
| 1283 | (should (equal dt onset)) | ||
| 1284 | (should (equal obs/onset ts-obs/onset))) | ||
| 1285 | |||
| 1286 | ;; A date matching the start of a DAYLIGHT observance: | ||
| 1287 | (let* ((dt (ical:make-date-time :year 1967 :month 4 :day 30 | ||
| 1288 | :hour 2 :minute 0 :second 0 | ||
| 1289 | :zone ict:est :dst nil)) | ||
| 1290 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1291 | (obs (car obs/onset)) | ||
| 1292 | (onset (cadr obs/onset)) | ||
| 1293 | ;; make sure we get the same result with an absolute time: | ||
| 1294 | (ts (encode-time dt)) | ||
| 1295 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1296 | (should (eq 'ical:daylight (ical:ast-node-type obs))) | ||
| 1297 | (should (equal dt onset)) | ||
| 1298 | (should (equal obs/onset ts-obs/onset))) | ||
| 1299 | |||
| 1300 | ;; A date matching an RDATE of a DAYLIGHT observance: | ||
| 1301 | (let* ((dt (ical:make-date-time :year 1975 :month 2 :day 23 | ||
| 1302 | :hour 2 :minute 0 :second 0 | ||
| 1303 | :zone ict:est :dst nil)) | ||
| 1304 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1305 | (obs (car obs/onset)) | ||
| 1306 | (onset (cadr obs/onset)) | ||
| 1307 | ;; make sure we get the same result with an absolute time: | ||
| 1308 | (ts (encode-time dt)) | ||
| 1309 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1310 | (should (eq 'ical:daylight (ical:ast-node-type obs))) | ||
| 1311 | (should (equal dt onset)) | ||
| 1312 | (should (equal obs/onset ts-obs/onset))) | ||
| 1313 | |||
| 1314 | ;; A date matching the end of a STANDARD observance: | ||
| 1315 | (let* ((ut (ical:make-date-time :year 2006 :month 10 :day 29 | ||
| 1316 | :hour 6 :minute 0 :second 0 | ||
| 1317 | :zone 0 :dst nil)) ; UNTIL is in UTC | ||
| 1318 | (dt (ical:make-date-time :year 2006 :month 10 :day 29 | ||
| 1319 | :hour 2 :minute 0 :second 0 | ||
| 1320 | :zone ict:edt :dst t)) | ||
| 1321 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1322 | (obs (car obs/onset)) | ||
| 1323 | (onset (cadr obs/onset)) | ||
| 1324 | ;; make sure we get the same result with an absolute time: | ||
| 1325 | (ts (encode-time dt)) | ||
| 1326 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1327 | (should (ical:date-time-simultaneous-p ut dt)) | ||
| 1328 | (should (eq 'ical:standard (ical:ast-node-type obs))) | ||
| 1329 | (should (equal dt onset)) | ||
| 1330 | (should (equal obs/onset ts-obs/onset))) | ||
| 1331 | |||
| 1332 | ;; A date matching the end of a DAYLIGHT observance: | ||
| 1333 | (let* ((ut (ical:make-date-time :year 2006 :month 4 :day 2 | ||
| 1334 | :hour 7 :minute 0 :second 0 | ||
| 1335 | :zone 0 :dst nil)) ; UNTIL is in UTC | ||
| 1336 | (dt (ical:make-date-time :year 2006 :month 4 :day 2 | ||
| 1337 | :hour 2 :minute 0 :second 0 | ||
| 1338 | :zone ict:est :dst nil)) | ||
| 1339 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1340 | (obs (car obs/onset)) | ||
| 1341 | (onset (cadr obs/onset)) | ||
| 1342 | ;; make sure we get the same result with an absolute time: | ||
| 1343 | (ts (encode-time dt)) | ||
| 1344 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1345 | (should (ical:date-time-simultaneous-p ut dt)) | ||
| 1346 | (should (eq 'ical:daylight (ical:ast-node-type obs))) | ||
| 1347 | (should (equal dt onset)) | ||
| 1348 | (should (equal obs/onset ts-obs/onset))) | ||
| 1349 | |||
| 1350 | ;; A date matching an onset in the middle of a DAYLIGHT observance | ||
| 1351 | ;; which has ended: | ||
| 1352 | (let* ((dt (ical:make-date-time :year 1980 :month 4 :day 27 | ||
| 1353 | :hour 2 :minute 0 :second 0 | ||
| 1354 | :zone ict:est :dst nil)) | ||
| 1355 | (end (ical:make-date-time :year 1986 :month 4 :day 27 | ||
| 1356 | :hour 7 :minute 0 :second 0 | ||
| 1357 | :zone 0)) ; UNTIL is in UTC | ||
| 1358 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1359 | (obs (car obs/onset)) | ||
| 1360 | (onset (cadr obs/onset)) | ||
| 1361 | ;; make sure we get the same result with an absolute time: | ||
| 1362 | (ts (encode-time dt)) | ||
| 1363 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1364 | (should (eq 'ical:daylight (ical:ast-node-type obs))) | ||
| 1365 | (should (equal dt onset)) | ||
| 1366 | (should (equal end (ical:recur-until | ||
| 1367 | (ical:with-property-of obs 'ical:rrule nil value)))) | ||
| 1368 | (should (equal obs/onset ts-obs/onset))) | ||
| 1369 | |||
| 1370 | ;; A date matching an onset of the DAYLIGHT observance which is | ||
| 1371 | ;; ongoing: | ||
| 1372 | (let* ((dt (ical:make-date-time :year 2025 :month 3 :day 9 | ||
| 1373 | :hour 2 :minute 0 :second 0 | ||
| 1374 | :zone ict:est :dst nil)) | ||
| 1375 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1376 | (obs (car obs/onset)) | ||
| 1377 | (onset (cadr obs/onset)) | ||
| 1378 | ;; make sure we get the same result with an absolute time: | ||
| 1379 | (ts (encode-time dt)) | ||
| 1380 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1381 | (should (eq 'ical:daylight (ical:ast-node-type obs))) | ||
| 1382 | (should (equal dt onset)) | ||
| 1383 | (should (equal obs/onset ts-obs/onset))) | ||
| 1384 | |||
| 1385 | ;; A date in the middle of the DAYLIGHT observance which is ongoing: | ||
| 1386 | (let* ((start (ical:make-date-time :year 2025 :month 3 :day 9 | ||
| 1387 | :hour 2 :minute 0 :second 0 | ||
| 1388 | :zone ict:est :dst nil)) | ||
| 1389 | (dt (ical:make-date-time :year 2025 :month 5 :day 28 | ||
| 1390 | :hour 2 :minute 0 :second 0 | ||
| 1391 | :zone ict:edt :dst t)) | ||
| 1392 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1393 | (obs (car obs/onset)) | ||
| 1394 | (onset (cadr obs/onset)) | ||
| 1395 | ;; make sure we get the same result with an absolute time: | ||
| 1396 | (ts (encode-time dt)) | ||
| 1397 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1398 | (should (eq 'ical:daylight (ical:ast-node-type obs))) | ||
| 1399 | (should (equal start onset)) | ||
| 1400 | (should (equal obs/onset ts-obs/onset))) | ||
| 1401 | |||
| 1402 | ;; A date in the middle of the STANDARD observance which is ongoing: | ||
| 1403 | (let* ((start (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 1404 | :hour 2 :minute 0 :second 0 | ||
| 1405 | :zone ict:edt :dst t)) | ||
| 1406 | (dt (ical:make-date-time :year 2026 :month 1 :day 28 | ||
| 1407 | :hour 12 :minute 30 :second 0 | ||
| 1408 | :zone ict:est :dst nil)) | ||
| 1409 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1410 | (obs (car obs/onset)) | ||
| 1411 | (onset (cadr obs/onset)) | ||
| 1412 | ;; make sure we get the same result with an absolute time: | ||
| 1413 | (ts (encode-time dt)) | ||
| 1414 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1415 | (should (eq 'ical:standard (ical:ast-node-type obs))) | ||
| 1416 | (should (equal start onset)) | ||
| 1417 | (should (equal obs/onset ts-obs/onset))) | ||
| 1418 | |||
| 1419 | ;; The following two tests were useful in detecting a broken optimization: | ||
| 1420 | (let* ((start (ical:make-date-time :year 2006 :month 10 :day 29 | ||
| 1421 | :hour 2 :minute 0 :second 0 | ||
| 1422 | :zone ict:edt :dst t)) | ||
| 1423 | (dt (ical:make-date-time :year 2006 :month 11 :day 1 | ||
| 1424 | :hour 12 :minute 30 :second 0 | ||
| 1425 | :zone ict:est :dst nil)) | ||
| 1426 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1427 | (obs (car obs/onset)) | ||
| 1428 | (onset (cadr obs/onset)) | ||
| 1429 | ;; make sure we get the same result with an absolute time: | ||
| 1430 | (ts (encode-time dt)) | ||
| 1431 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1432 | (should (eq 'ical:standard (ical:ast-node-type obs))) | ||
| 1433 | (should (equal start onset)) | ||
| 1434 | (should (equal obs/onset ts-obs/onset))) | ||
| 1435 | |||
| 1436 | (let* ((start (ical:make-date-time :year 2007 :month 11 :day 4 | ||
| 1437 | :hour 2 :minute 0 :second 0 | ||
| 1438 | :zone ict:edt :dst t)) | ||
| 1439 | (dt (ical:make-date-time :year 2008 :month 2 :day 1 | ||
| 1440 | :hour 12 :minute 30 :second 0 | ||
| 1441 | :zone ict:est :dst nil)) | ||
| 1442 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern)) | ||
| 1443 | (obs (car obs/onset)) | ||
| 1444 | (onset (cadr obs/onset)) | ||
| 1445 | ;; make sure we get the same result with an absolute time: | ||
| 1446 | (ts (encode-time dt)) | ||
| 1447 | (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) | ||
| 1448 | (should (eq 'ical:standard (ical:ast-node-type obs))) | ||
| 1449 | (should (equal start onset)) | ||
| 1450 | (should (equal obs/onset ts-obs/onset))) | ||
| 1451 | |||
| 1452 | |||
| 1453 | ;; A date in the middle of the STANDARD observance which is ongoing; | ||
| 1454 | ;; test that the update flag correctly sets the zone information: | ||
| 1455 | (let* ((start (ical:make-date-time :year 2025 :month 11 :day 2 | ||
| 1456 | :hour 2 :minute 0 :second 0 | ||
| 1457 | :zone ict:edt :dst t)) | ||
| 1458 | (dt (ical:make-date-time :year 2026 :month 1 :day 28 | ||
| 1459 | :hour 12 :minute 30 :second 0 | ||
| 1460 | ;; no zone information | ||
| 1461 | )) | ||
| 1462 | (obs/onset (icr:tz-observance-on dt ict:tz-eastern t)) | ||
| 1463 | (obs (car obs/onset)) | ||
| 1464 | (onset (cadr obs/onset))) | ||
| 1465 | (should (eq 'ical:standard (ical:ast-node-type obs))) | ||
| 1466 | (should (equal start onset)))) | ||
| 1467 | |||
| 1468 | |||
| 1469 | ;; Tests for recurrence rule interpretation: | ||
| 1470 | (cl-defmacro ict:rrule-test (recur-string doc | ||
| 1471 | &key dtstart | ||
| 1472 | (low dtstart) | ||
| 1473 | high | ||
| 1474 | tz | ||
| 1475 | rdates | ||
| 1476 | exdates | ||
| 1477 | members | ||
| 1478 | nonmembers | ||
| 1479 | size | ||
| 1480 | (tags nil) | ||
| 1481 | source) | ||
| 1482 | |||
| 1483 | "Create a test which parses RECUR-STRING to an `icalendar-recur', | ||
| 1484 | creates an event with a recurrence set from this value, and checks | ||
| 1485 | various properties of the recurrence set. | ||
| 1486 | |||
| 1487 | DTSTART should be an `icalendar-date' or `icalendar-date-time' | ||
| 1488 | value appropriate to the RECUR-STRING. The value will be | ||
| 1489 | bound to the symbol `dtstart'; this symbol can thus be used inside | ||
| 1490 | the expressions for MEMBERS and NONMEMBERS. | ||
| 1491 | LOW and HIGH should be the bounds of the window in which to compute | ||
| 1492 | recurrences. LOW defaults to DTSTART. | ||
| 1493 | TZ, if present, should be an `icalendar-vtimezone'. | ||
| 1494 | Date-times in the recurrence set will be calculated relative to this | ||
| 1495 | time zone. | ||
| 1496 | RDATES, if present, should be a list of additional | ||
| 1497 | `icalendar-date' or `icalendar-date-time' values to be added to | ||
| 1498 | the recurrence set *in addition to* those generated by the | ||
| 1499 | recurrence rule (see `icalendar-rdate'). | ||
| 1500 | EXDATES, if present, should be a list of `icalendar-date' or | ||
| 1501 | `icalendar-date-time' values to be excluded from the recurrence | ||
| 1502 | set, *even if* they are in RDATES or generated by the | ||
| 1503 | recurrence rule (see `icalendar-exdate'). | ||
| 1504 | MEMBERS, if present, should be a list of values that are expected | ||
| 1505 | to be present in the recurrence set. | ||
| 1506 | NONMEMBERS, if present, should be a list of values that are expected | ||
| 1507 | to be excluded from the recurrence set. | ||
| 1508 | SIZE, if present, should be a positive integer representing the | ||
| 1509 | expected size of the recurrence set. Defaults to the value of the | ||
| 1510 | COUNT clause in the recurrence rule, if any. | ||
| 1511 | TAGS is passed on to `ert-deftest'. | ||
| 1512 | SOURCE should be a symbol; it is used to name the test." | ||
| 1513 | `(ert-deftest ,(intern (concat "ict:rrule-test-" (symbol-name source))) () | ||
| 1514 | ,(format "Parse and evaluate recur-value example from `%s':\n%s" | ||
| 1515 | source doc) | ||
| 1516 | :tags ,tags | ||
| 1517 | (let* ((parsed (ical:parse-from-string 'ical:recur ,recur-string)) | ||
| 1518 | (recvalue (ical:ast-node-value parsed)) | ||
| 1519 | (until (ical:recur-until recvalue)) | ||
| 1520 | (count (ical:recur-count recvalue)) | ||
| 1521 | (dtstart ,dtstart) | ||
| 1522 | (tzid | ||
| 1523 | (when (cl-typep dtstart 'ical:date-time) | ||
| 1524 | "America/New_York")) | ||
| 1525 | (recset-size (or ,size count)) | ||
| 1526 | (vevent | ||
| 1527 | (ical:make-vevent | ||
| 1528 | (ical:uid (concat "uid-test-" ,(symbol-name source))) | ||
| 1529 | (ical:dtstart dtstart (ical:tzidparam tzid)) | ||
| 1530 | (ical:rrule parsed) | ||
| 1531 | (ical:rdate ,rdates) | ||
| 1532 | (ical:exdate ,exdates))) | ||
| 1533 | ;; default for HIGH: UNTIL or DTSTART+3*INTERVAL | ||
| 1534 | (win-high | ||
| 1535 | (or ,high | ||
| 1536 | until | ||
| 1537 | (cadr | ||
| 1538 | (icr:nth-interval 2 ,dtstart recvalue)))) | ||
| 1539 | (recs | ||
| 1540 | (if count | ||
| 1541 | (icr:recurrences-to-count vevent ,tz) | ||
| 1542 | (icr:recurrences-in-window ,low win-high vevent ,tz)))) | ||
| 1543 | (should (ical:ast-node-valid-p parsed)) | ||
| 1544 | (when ,members | ||
| 1545 | (dolist (dt ,members) | ||
| 1546 | (should (member dt recs)))) | ||
| 1547 | (when ,nonmembers | ||
| 1548 | (dolist (dt ,nonmembers) | ||
| 1549 | (should-not (member dt recs)))) | ||
| 1550 | (when recset-size | ||
| 1551 | (should (length= recs recset-size)))))) | ||
| 1552 | |||
| 1553 | (ict:rrule-test | ||
| 1554 | "FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1" | ||
| 1555 | "Last non-weekend day of the month" | ||
| 1556 | :dtstart '(3 31 2025) | ||
| 1557 | :high '(6 1 2025) | ||
| 1558 | :members '((3 31 2025) (4 30 2025) (5 30 2025)) | ||
| 1559 | :nonmembers '((5 31 2025)) ;; 5/31/2025 is a Saturday | ||
| 1560 | :source rfc5545-sec3.3.10/1) | ||
| 1561 | |||
| 1562 | (ict:rrule-test | ||
| 1563 | "FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30" | ||
| 1564 | "Every Sunday in January at 8:30AM and 9:30AM, every other year" | ||
| 1565 | :dtstart (ical:read-date-time "20250105T083000") | ||
| 1566 | :high (ical:read-date-time "20271231T000000") | ||
| 1567 | :members | ||
| 1568 | (let ((jan3-27 (ical:make-date-time :year 2027 :month 1 :day 3 | ||
| 1569 | :hour 8 :minute 30 :second 0))) | ||
| 1570 | (list dtstart | ||
| 1571 | ;; 2025: Jan 5, 12, 19, 26 | ||
| 1572 | (ical:date-time-variant dtstart :hour 9) | ||
| 1573 | (ical:date-time-variant dtstart :day 12) | ||
| 1574 | (ical:date-time-variant dtstart :day 12 :hour 9) | ||
| 1575 | (ical:date-time-variant dtstart :day 19) | ||
| 1576 | (ical:date-time-variant dtstart :day 19 :hour 9) | ||
| 1577 | (ical:date-time-variant dtstart :day 19) | ||
| 1578 | (ical:date-time-variant dtstart :day 19 :hour 9) | ||
| 1579 | (ical:date-time-variant dtstart :day 26) | ||
| 1580 | (ical:date-time-variant dtstart :day 26 :hour 9) | ||
| 1581 | ;; 2027: Jan 3, 10, 17, 24, 31 | ||
| 1582 | (ical:date-time-variant jan3-27 :hour 9) | ||
| 1583 | (ical:date-time-variant jan3-27 :day 10) | ||
| 1584 | (ical:date-time-variant jan3-27 :day 10 :hour 9) | ||
| 1585 | (ical:date-time-variant jan3-27 :day 17) | ||
| 1586 | (ical:date-time-variant jan3-27 :day 17 :hour 9) | ||
| 1587 | (ical:date-time-variant jan3-27 :day 24) | ||
| 1588 | (ical:date-time-variant jan3-27 :day 24 :hour 9) | ||
| 1589 | (ical:date-time-variant jan3-27 :day 31) | ||
| 1590 | (ical:date-time-variant jan3-27 :day 31 :hour 9))) | ||
| 1591 | :nonmembers | ||
| 1592 | (list | ||
| 1593 | (ical:make-date-time :year 2026 :month 1 :day 4 | ||
| 1594 | :hour 8 :minute 30 :second 0) | ||
| 1595 | (ical:make-date-time :year 2026 :month 1 :day 4 | ||
| 1596 | :hour 9 :minute 30 :second 0)) | ||
| 1597 | :source rfc5545-sec3.3.10/2) | ||
| 1598 | |||
| 1599 | (ict:rrule-test | ||
| 1600 | "FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=-1" | ||
| 1601 | "Every year on the last day in February" | ||
| 1602 | :dtstart '(2 29 2024) | ||
| 1603 | :high '(3 1 2028) | ||
| 1604 | :members '((2 28 2025) (2 28 2026) (2 28 2027) (2 29 2028)) | ||
| 1605 | :nonmembers '((2 28 2028)) | ||
| 1606 | :source leap-day/1) | ||
| 1607 | |||
| 1608 | (ict:rrule-test | ||
| 1609 | "FREQ=YEARLY;INTERVAL=4;BYMONTH=2;BYMONTHDAY=29" | ||
| 1610 | "Every four years on February 29" | ||
| 1611 | :dtstart '(2 29 2024) | ||
| 1612 | :high '(3 1 2028) | ||
| 1613 | :members '((2 29 2028)) | ||
| 1614 | :nonmembers '((2 28 2028)) | ||
| 1615 | :source leap-day/2) | ||
| 1616 | |||
| 1617 | (ict:rrule-test | ||
| 1618 | "FREQ=DAILY;COUNT=10" | ||
| 1619 | "Daily for 10 occurrences" | ||
| 1620 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 1621 | :hour 9 :minute 0 :second 0) | ||
| 1622 | :members | ||
| 1623 | ;; (1997 9:00 AM EDT) September 2-11 | ||
| 1624 | (mapcar | ||
| 1625 | (lambda (day) (ical:date-time-variant dtstart :day day)) | ||
| 1626 | (number-sequence 2 11)) | ||
| 1627 | :source rfc5545-sec3.3.10/3) | ||
| 1628 | |||
| 1629 | (ict:rrule-test | ||
| 1630 | "RRULE:FREQ=YEARLY" | ||
| 1631 | "Every year on a specific date, e.g. an anniversary" | ||
| 1632 | :dtstart '(11 11 2024) | ||
| 1633 | :high '(10 1 2030) | ||
| 1634 | :members '((11 11 2024) | ||
| 1635 | (11 11 2025) | ||
| 1636 | (11 11 2026) | ||
| 1637 | (11 11 2027) | ||
| 1638 | (11 11 2028) | ||
| 1639 | (11 11 2029)) | ||
| 1640 | :nonmembers '((11 11 2030)) | ||
| 1641 | :source rfc5545-sec3.6.1/3) | ||
| 1642 | |||
| 1643 | ;; Time zone tests | ||
| 1644 | |||
| 1645 | (ict:rrule-test | ||
| 1646 | "RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19730429T070000Z" | ||
| 1647 | "Every year on the last Sunday of April (through 1973-04-29) at 2AM. | ||
| 1648 | (Onset of US Eastern Daylight Time.)" | ||
| 1649 | :tz ict:tz-eastern | ||
| 1650 | ;; DTSTART and all the times below are at *3*AM EDT, because 2AM EST | ||
| 1651 | ;; (the onset of the observance) does not exist as a local time: | ||
| 1652 | :dtstart (ical:make-date-time :year 1967 :month 4 :day 30 | ||
| 1653 | :hour 3 :minute 0 :second 0 | ||
| 1654 | :zone ict:edt :dst t) | ||
| 1655 | :high (ical:date-time-variant dtstart :year 1973 :month 4 :day 30 | ||
| 1656 | :zone ict:edt :dst t) | ||
| 1657 | :members | ||
| 1658 | (list | ||
| 1659 | (ical:date-time-variant dtstart :year 1968 :day 28 :tz 'preserve) | ||
| 1660 | (ical:date-time-variant dtstart :year 1969 :day 27 :tz 'preserve) | ||
| 1661 | (ical:date-time-variant dtstart :year 1970 :day 26 :tz 'preserve) | ||
| 1662 | (ical:date-time-variant dtstart :year 1971 :day 25 :tz 'preserve) | ||
| 1663 | (ical:date-time-variant dtstart :year 1972 :day 30 :tz 'preserve) | ||
| 1664 | (ical:date-time-variant dtstart :year 1973 :day 29 :tz 'preserve)) | ||
| 1665 | :source rfc5545-sec3.6.5/1) | ||
| 1666 | |||
| 1667 | (ict:rrule-test | ||
| 1668 | "RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU" | ||
| 1669 | "Every year on the first Sunday of November at 2AM. | ||
| 1670 | (Onset of Eastern Standard Time)." | ||
| 1671 | :tz ict:tz-eastern | ||
| 1672 | :dtstart (ical:make-date-time :year 2007 :month 11 :day 4 | ||
| 1673 | :hour 2 :minute 0 :second 0 | ||
| 1674 | :zone ict:edt :dst t) | ||
| 1675 | :high (ical:date-time-variant dtstart :year 2010 :month 11 :day 8 | ||
| 1676 | :zone ict:est :dst nil) | ||
| 1677 | :members | ||
| 1678 | ;; all the times below are at *1*AM EST, because 2AM EDT (the onset of | ||
| 1679 | ;; the observance) is when clocks get set back: | ||
| 1680 | (list (ical:date-time-variant dtstart | ||
| 1681 | :year 2008 :month 11 :day 2 | ||
| 1682 | :zone ict:est :dst nil) | ||
| 1683 | (ical:date-time-variant dtstart | ||
| 1684 | :year 2009 :month 11 :day 1 | ||
| 1685 | :zone ict:est :dst nil) | ||
| 1686 | (ical:date-time-variant dtstart | ||
| 1687 | :year 2010 :month 11 :day 7 | ||
| 1688 | :zone ict:est :dst nil)) | ||
| 1689 | :source rfc5545-sec3.6.5/3.1) | ||
| 1690 | |||
| 1691 | (ict:rrule-test | ||
| 1692 | "RRULE:FREQ=MONTHLY;INTERVAL=3;BYDAY=1SU" | ||
| 1693 | "Every three months on the first Sunday of the month." | ||
| 1694 | :dtstart '(1 5 2025) | ||
| 1695 | :high '(1 1 2026) | ||
| 1696 | :members (list '(4 6 2025) | ||
| 1697 | '(7 6 2025) | ||
| 1698 | '(10 5 2025)) | ||
| 1699 | :nonmembers (list '(1 12 2025) ;; second Sun. | ||
| 1700 | '(2 2 2025) ;; first Sun. in Feb. | ||
| 1701 | '(4 5 2025)) ;; Sat. | ||
| 1702 | :source monthly/interval) | ||
| 1703 | |||
| 1704 | (ict:rrule-test | ||
| 1705 | "RRULE:FREQ=DAILY;COUNT=10\n" | ||
| 1706 | "Daily for 10 occurrences" | ||
| 1707 | :dtstart (ical:read-date-time "19970902T090000") | ||
| 1708 | :members | ||
| 1709 | (mapcar | ||
| 1710 | (lambda (day) (ical:date-time-variant dtstart :day day)) | ||
| 1711 | (number-sequence 2 11)) | ||
| 1712 | :nonmembers (list (ical:date-time-variant dtstart :day 12)) | ||
| 1713 | :high (ical:read-date-time "19970912T090000") | ||
| 1714 | :source rfc5545-sec3.8.5.3/1) | ||
| 1715 | |||
| 1716 | (ict:rrule-test | ||
| 1717 | "RRULE:FREQ=DAILY;UNTIL=19971224T000000Z\n" | ||
| 1718 | "Daily at 9AM until December 24, 1997" | ||
| 1719 | :tags '(:expensive-test) | ||
| 1720 | :tz ict:tz-eastern | ||
| 1721 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 1722 | :hour 9 :minute 0 :second 0 | ||
| 1723 | :zone ict:edt :dst t) | ||
| 1724 | :members | ||
| 1725 | (append | ||
| 1726 | ;; EDT: | ||
| 1727 | (mapcar | ||
| 1728 | (lambda (day) (ical:date-time-variant dtstart :day day :tz 'preserve)) | ||
| 1729 | (number-sequence 2 30)) ;; Sept. 2--30 | ||
| 1730 | (mapcar | ||
| 1731 | (lambda (day) (ical:date-time-variant dtstart :month 10 :day day | ||
| 1732 | :tz 'preserve)) | ||
| 1733 | (number-sequence 1 25)) ;; Oct. 1--25 | ||
| 1734 | ;; EST: | ||
| 1735 | (mapcar | ||
| 1736 | (lambda (day) | ||
| 1737 | (ical:date-time-variant dtstart :month 10 :day day :zone ict:est :dst nil)) | ||
| 1738 | (number-sequence 26 31))) ;; Oct. 26--31 | ||
| 1739 | :source rfc5545-sec3.8.5.3/2) | ||
| 1740 | |||
| 1741 | (ict:rrule-test | ||
| 1742 | "RRULE:FREQ=DAILY;INTERVAL=2\n" | ||
| 1743 | "Every other day - forever" | ||
| 1744 | :tz ict:tz-eastern | ||
| 1745 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 1746 | :hour 9 :minute 0 :second 0 | ||
| 1747 | :zone ict:edt :dst t) | ||
| 1748 | :high (ical:make-date-time :year 1997 :month 12 :day 4 | ||
| 1749 | :hour 0 :minute 0 :second 0 | ||
| 1750 | :zone ict:est :dst nil) | ||
| 1751 | :members | ||
| 1752 | (append | ||
| 1753 | ;; (1997 9:00 AM EDT) September 2,4,6,8...24,26,28,30; | ||
| 1754 | ;; October 2,4,6...20,22,24 | ||
| 1755 | (mapcar | ||
| 1756 | (lambda (n) | ||
| 1757 | (ical:date-time-variant dtstart :day (* 2 n) :tz 'preserve)) | ||
| 1758 | (number-sequence 1 15)) | ||
| 1759 | (mapcar | ||
| 1760 | (lambda (n) | ||
| 1761 | (ical:date-time-variant dtstart :month 10 :day (* 2 n) :tz 'preserve)) | ||
| 1762 | (number-sequence 1 12)) | ||
| 1763 | ;; (1997 9:00 AM EST) October 26,28,30; | ||
| 1764 | ;; November 1,3,5,7...25,27,29; | ||
| 1765 | ;; December 1,3,... | ||
| 1766 | (mapcar | ||
| 1767 | (lambda (n) | ||
| 1768 | (ical:date-time-variant dtstart :month 10 :day (* 2 n) | ||
| 1769 | :zone ict:est :dst nil)) | ||
| 1770 | (number-sequence 13 15)) | ||
| 1771 | (mapcar | ||
| 1772 | (lambda (n) | ||
| 1773 | (ical:date-time-variant dtstart :month 11 :day (1- (* 2 n)) | ||
| 1774 | :zone ict:est :dst nil)) | ||
| 1775 | (number-sequence 1 15)) | ||
| 1776 | (mapcar | ||
| 1777 | (lambda (n) | ||
| 1778 | (ical:date-time-variant dtstart :month 12 :day (1- (* 2 n)) | ||
| 1779 | :zone ict:est :dst nil)) | ||
| 1780 | (number-sequence 1 2))) | ||
| 1781 | |||
| 1782 | :nonmembers | ||
| 1783 | (list | ||
| 1784 | ;; e.g. | ||
| 1785 | (ical:make-date-time :year 1997 :month 10 :day 27 | ||
| 1786 | :hour 9 :minute 0 :second 0 | ||
| 1787 | :zone ict:est :dst nil)) | ||
| 1788 | :source rfc5545-sec3.8.5.3/3) | ||
| 1789 | |||
| 1790 | (ict:rrule-test | ||
| 1791 | "RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5\n" | ||
| 1792 | "Every ten days for five recurrences" | ||
| 1793 | :tz ict:tz-eastern | ||
| 1794 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 1795 | :hour 9 :minute 0 :second 0 | ||
| 1796 | :zone ict:edt :dst t) | ||
| 1797 | |||
| 1798 | :members ;; (1997 9:00 AM EDT) September 2,12,22; October 2,12 | ||
| 1799 | (list | ||
| 1800 | dtstart | ||
| 1801 | (ical:make-date-time :year 1997 :month 9 :day 12 | ||
| 1802 | :hour 9 :minute 0 :second 0 | ||
| 1803 | :zone ict:edt :dst t) | ||
| 1804 | (ical:make-date-time :year 1997 :month 9 :day 22 | ||
| 1805 | :hour 9 :minute 0 :second 0 | ||
| 1806 | :zone ict:edt :dst t) | ||
| 1807 | (ical:make-date-time :year 1997 :month 10 :day 2 | ||
| 1808 | :hour 9 :minute 0 :second 0 | ||
| 1809 | :zone ict:edt :dst t) | ||
| 1810 | (ical:make-date-time :year 1997 :month 10 :day 12 | ||
| 1811 | :hour 9 :minute 0 :second 0 | ||
| 1812 | :zone ict:edt :dst t)) | ||
| 1813 | :source rfc5545-sec3.8.5.3/4) | ||
| 1814 | |||
| 1815 | (ict:rrule-test | ||
| 1816 | "RRULE:FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA\n" | ||
| 1817 | "Every day in January, for three years (weekdays explicit)" | ||
| 1818 | :tags '(:expensive-test) | ||
| 1819 | :tz ict:tz-eastern | ||
| 1820 | :dtstart (ical:make-date-time :year 1998 :month 1 :day 1 | ||
| 1821 | :hour 9 :minute 0 :second 0 | ||
| 1822 | :zone ict:est :dst nil) | ||
| 1823 | :high (ical:make-date-time :year 2000 :month 2 :day 1 | ||
| 1824 | :hour 9 :minute 0 :second 0 | ||
| 1825 | :zone ict:est :dst nil) | ||
| 1826 | :members | ||
| 1827 | ;; (1998 9:00 AM EST)January 1-31 | ||
| 1828 | ;; (1999 9:00 AM EST)January 1-31 | ||
| 1829 | ;; (2000 9:00 AM EST)January 1-31 | ||
| 1830 | (append | ||
| 1831 | (mapcar | ||
| 1832 | (lambda (day) (ical:date-time-variant dtstart :day day :tz 'preserve)) | ||
| 1833 | (number-sequence 1 31)) | ||
| 1834 | (mapcar | ||
| 1835 | (lambda (day) | ||
| 1836 | (ical:date-time-variant dtstart :year 1999 :day day :tz 'preserve)) | ||
| 1837 | (number-sequence 1 31)) | ||
| 1838 | (mapcar | ||
| 1839 | (lambda (day) | ||
| 1840 | (ical:date-time-variant dtstart :year 2000 :day day :tz 'preserve)) | ||
| 1841 | (number-sequence 1 31))) | ||
| 1842 | :source rfc5545-sec3.8.5.3/5) | ||
| 1843 | |||
| 1844 | (ict:rrule-test | ||
| 1845 | "RRULE:FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1\n" | ||
| 1846 | "Every day in January, for three years (weekdays implicit)" | ||
| 1847 | :tags '(:expensive-test) | ||
| 1848 | ;; TODO: as things are currently implemented, this way of expressing | ||
| 1849 | ;; the rule is quite expensive, since we end up computing intervals and | ||
| 1850 | ;; recurrences for every day of the year, even though the only relevant | ||
| 1851 | ;; days are in January and there are no recurrences on the other days. | ||
| 1852 | ;; We could try to optimize e.g. icr:refine-from-clauses to deal with such | ||
| 1853 | ;; cases. | ||
| 1854 | :tz ict:tz-eastern | ||
| 1855 | :dtstart (ical:make-date-time :year 1998 :month 1 :day 1 | ||
| 1856 | :hour 9 :minute 0 :second 0 | ||
| 1857 | :zone ict:est :dst nil) | ||
| 1858 | :high (ical:make-date-time :year 2000 :month 2 :day 1 | ||
| 1859 | :hour 9 :minute 0 :second 0 | ||
| 1860 | :zone ict:est :dst nil) | ||
| 1861 | :members | ||
| 1862 | ;; (1998 9:00 AM EST)January 1-31 | ||
| 1863 | ;; (1999 9:00 AM EST)January 1-31 | ||
| 1864 | ;; (2000 9:00 AM EST)January 1-31 | ||
| 1865 | (append | ||
| 1866 | (mapcar | ||
| 1867 | (lambda (day) (ical:date-time-variant dtstart :day day :tz 'preserve)) | ||
| 1868 | (number-sequence 1 31)) | ||
| 1869 | (mapcar | ||
| 1870 | (lambda (day) | ||
| 1871 | (ical:date-time-variant dtstart :year 1999 :day day :tz 'preserve)) | ||
| 1872 | (number-sequence 1 31)) | ||
| 1873 | (mapcar | ||
| 1874 | (lambda (day) | ||
| 1875 | (ical:date-time-variant dtstart :year 2000 :day day :tz 'preserve)) | ||
| 1876 | (number-sequence 1 31))) | ||
| 1877 | :source rfc5545-sec3.8.5.3/6) | ||
| 1878 | |||
| 1879 | (ict:rrule-test | ||
| 1880 | "RRULE:FREQ=WEEKLY;COUNT=10\n" | ||
| 1881 | "Weekly for ten occurrences" | ||
| 1882 | :tz ict:tz-eastern | ||
| 1883 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 1884 | :hour 9 :minute 0 :second 0 | ||
| 1885 | :zone ict:edt :dst t) | ||
| 1886 | :members | ||
| 1887 | (append | ||
| 1888 | ;; (1997 9:00 AM EDT) September 2,9,16,23,30;October 7,14,21 | ||
| 1889 | (mapcar | ||
| 1890 | (lambda (day) | ||
| 1891 | (ical:date-time-variant dtstart :day day :tz 'preserve)) | ||
| 1892 | (list 2 9 16 23 30)) | ||
| 1893 | (mapcar | ||
| 1894 | (lambda (day) | ||
| 1895 | (ical:date-time-variant dtstart :month 10 :day day :tz 'preserve)) | ||
| 1896 | (list 7 14 21)) | ||
| 1897 | ;; (1997 9:00 AM EST) October 28;November 4 | ||
| 1898 | (list | ||
| 1899 | (ical:make-date-time :year 1997 :month 10 :day 28 | ||
| 1900 | :hour 9 :minute 0 :second 0 | ||
| 1901 | :zone ict:est :dst nil) | ||
| 1902 | (ical:make-date-time :year 1997 :month 11 :day 4 | ||
| 1903 | :hour 9 :minute 0 :second 0 | ||
| 1904 | :zone ict:est :dst nil))) | ||
| 1905 | :source rfc5545-sec3.8.5.3/7) | ||
| 1906 | |||
| 1907 | (ict:rrule-test | ||
| 1908 | "RRULE:FREQ=WEEKLY;UNTIL=19971224T000000Z\n" | ||
| 1909 | "Every week until December 24, 1997" | ||
| 1910 | :tz ict:tz-eastern | ||
| 1911 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 1912 | :hour 9 :minute 0 :second 0 | ||
| 1913 | :zone ict:edt :dst t) | ||
| 1914 | :members | ||
| 1915 | (let ((oct97 (ical:date-time-variant dtstart :month 10 | ||
| 1916 | :zone ict:edt :dst t)) | ||
| 1917 | (nov97 (ical:date-time-variant dtstart :month 11 | ||
| 1918 | :zone ict:est :dst nil)) | ||
| 1919 | (dec97 (ical:date-time-variant dtstart :month 12 | ||
| 1920 | :zone ict:est :dst nil))) | ||
| 1921 | (append | ||
| 1922 | ;; (1997 9:00 AM EDT) September 2,9,16,23,30; | ||
| 1923 | ;; October 7,14,21 | ||
| 1924 | (mapcar | ||
| 1925 | (lambda (day) | ||
| 1926 | (ical:date-time-variant dtstart :day day :tz 'preserve)) | ||
| 1927 | (list 2 9 16 23 30)) | ||
| 1928 | (mapcar | ||
| 1929 | (lambda (day) | ||
| 1930 | (ical:date-time-variant oct97 :day day :tz 'preserve)) | ||
| 1931 | (list 7 14 21)) | ||
| 1932 | ;; (1997 9:00 AM EST) October 28; | ||
| 1933 | ;; November 4,11,18,25; | ||
| 1934 | ;; December 2,9,16,23 | ||
| 1935 | (list (ical:date-time-variant oct97 :day 28 :zone ict:est :dst nil)) | ||
| 1936 | (mapcar | ||
| 1937 | (lambda (day) | ||
| 1938 | (ical:date-time-variant nov97 :day day :tz 'preserve)) | ||
| 1939 | (list 4 11 18 25)) | ||
| 1940 | (mapcar | ||
| 1941 | (lambda (day) | ||
| 1942 | (ical:date-time-variant dec97 :day day :tz 'preserve)) | ||
| 1943 | (list 2 9 16 23)))) | ||
| 1944 | :source rfc5545-sec3.8.5.3/8) | ||
| 1945 | |||
| 1946 | (ict:rrule-test | ||
| 1947 | "RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU\n" | ||
| 1948 | "Every other week - forever; Weekstart on Sunday" | ||
| 1949 | :tz ict:tz-eastern | ||
| 1950 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 1951 | :hour 9 :minute 0 :second 0 | ||
| 1952 | :zone ict:edt :dst t) | ||
| 1953 | :high (ical:make-date-time :year 1998 :month 3 :day 1 | ||
| 1954 | :hour 9 :minute 0 :second 0 | ||
| 1955 | :zone ict:est :dst nil) | ||
| 1956 | :members | ||
| 1957 | (list | ||
| 1958 | ;; ==> (1997 9:00 AM EDT) September 2,16,30; | ||
| 1959 | ;; October 14 | ||
| 1960 | dtstart | ||
| 1961 | (ical:date-time-variant dtstart :day 16 :tz 'preserve) | ||
| 1962 | (ical:date-time-variant dtstart :day 30 :tz 'preserve) | ||
| 1963 | (ical:date-time-variant dtstart :month 10 :day 14 :tz 'preserve) | ||
| 1964 | ;; (1997 9:00 AM EST) October 28; | ||
| 1965 | ;; November 11,25; | ||
| 1966 | ;; December 9,23 | ||
| 1967 | (ical:date-time-variant dtstart :month 10 :day 28 :zone ict:est :dst nil) | ||
| 1968 | (ical:date-time-variant dtstart :month 11 :day 11 :zone ict:est :dst nil) | ||
| 1969 | (ical:date-time-variant dtstart :month 11 :day 25 :zone ict:est :dst nil) | ||
| 1970 | (ical:date-time-variant dtstart :month 12 :day 23 :zone ict:est :dst nil) | ||
| 1971 | ;; (1998 9:00 AM EST) January 6,20; | ||
| 1972 | ;; February 3, 17 | ||
| 1973 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 6 | ||
| 1974 | :zone ict:est :dst nil) | ||
| 1975 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 20 | ||
| 1976 | :zone ict:est :dst nil) | ||
| 1977 | (ical:date-time-variant dtstart :year 1998 :month 2 :day 3 | ||
| 1978 | :zone ict:est :dst nil) | ||
| 1979 | (ical:date-time-variant dtstart :year 1998 :month 2 :day 17 | ||
| 1980 | :zone ict:est :dst nil)) | ||
| 1981 | :source rfc5545-sec3.8.5.3/9) | ||
| 1982 | |||
| 1983 | (ict:rrule-test | ||
| 1984 | "RRULE:FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH\n" | ||
| 1985 | "Weekly on Tuesday and Thursday for five weeks, using UNTIL" | ||
| 1986 | :tz ict:tz-eastern | ||
| 1987 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 1988 | :hour 9 :minute 0 :second 0 | ||
| 1989 | :zone ict:edt :dst t) | ||
| 1990 | :high (ical:make-date-time :year 1997 :month 10 :day 8 | ||
| 1991 | :hour 0 :minute 0 :second 0 :zone 0) | ||
| 1992 | :members | ||
| 1993 | (list | ||
| 1994 | ;; ==> (1997 9:00 AM EDT) September 2,4,9,11,16,18,23,25,30; | ||
| 1995 | ;; October 2 | ||
| 1996 | dtstart | ||
| 1997 | (ical:date-time-variant dtstart :day 4 :tz 'preserve) | ||
| 1998 | (ical:date-time-variant dtstart :day 9 :tz 'preserve) | ||
| 1999 | (ical:date-time-variant dtstart :day 11 :tz 'preserve) | ||
| 2000 | (ical:date-time-variant dtstart :day 16 :tz 'preserve) | ||
| 2001 | (ical:date-time-variant dtstart :day 18 :tz 'preserve) | ||
| 2002 | (ical:date-time-variant dtstart :day 23 :tz 'preserve) | ||
| 2003 | (ical:date-time-variant dtstart :day 25 :tz 'preserve) | ||
| 2004 | (ical:date-time-variant dtstart :day 30 :tz 'preserve) | ||
| 2005 | (ical:date-time-variant dtstart :month 10 :day 2 :tz 'preserve)) | ||
| 2006 | :source rfc5545-sec3.8.5.3/10) | ||
| 2007 | |||
| 2008 | (ict:rrule-test | ||
| 2009 | "RRULE:FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH\n" | ||
| 2010 | "Weekly on Tuesday and Thursday for five weeks, using COUNT" | ||
| 2011 | :tz ict:tz-eastern | ||
| 2012 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 2013 | :hour 9 :minute 0 :second 0 | ||
| 2014 | :zone ict:edt :dst t) | ||
| 2015 | :high (ical:make-date-time :year 1997 :month 10 :day 8 | ||
| 2016 | :hour 0 :minute 0 :second 0 :zone 0) | ||
| 2017 | :members | ||
| 2018 | (list | ||
| 2019 | ;; ==> (1997 9:00 AM EDT) September 2,4,9,11,16,18,23,25,30; | ||
| 2020 | ;; October 2 | ||
| 2021 | dtstart | ||
| 2022 | (ical:date-time-variant dtstart :day 4 :tz 'preserve) | ||
| 2023 | (ical:date-time-variant dtstart :day 9 :tz 'preserve) | ||
| 2024 | (ical:date-time-variant dtstart :day 11 :tz 'preserve) | ||
| 2025 | (ical:date-time-variant dtstart :day 16 :tz 'preserve) | ||
| 2026 | (ical:date-time-variant dtstart :day 18 :tz 'preserve) | ||
| 2027 | (ical:date-time-variant dtstart :day 23 :tz 'preserve) | ||
| 2028 | (ical:date-time-variant dtstart :day 25 :tz 'preserve) | ||
| 2029 | (ical:date-time-variant dtstart :day 30 :tz 'preserve) | ||
| 2030 | (ical:date-time-variant dtstart :month 10 :day 2 :tz 'preserve)) | ||
| 2031 | :source rfc5545-sec3.8.5.3/11) | ||
| 2032 | |||
| 2033 | (ict:rrule-test | ||
| 2034 | "RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR\n" | ||
| 2035 | "Every other week on Monday, Wednesday, and Friday until December 24, | ||
| 2036 | 1997, starting on Monday, September 1, 1997" | ||
| 2037 | :tz ict:tz-eastern | ||
| 2038 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 1 | ||
| 2039 | :hour 9 :minute 0 :second 0 | ||
| 2040 | :zone ict:edt :dst t) | ||
| 2041 | :members | ||
| 2042 | (list | ||
| 2043 | dtstart | ||
| 2044 | ;; ==> (1997 9:00 AM EDT) September 1,3,5,15,17,19,29; | ||
| 2045 | ;; October 1,3,13,15,17 | ||
| 2046 | (ical:date-time-variant dtstart :day 3 :tz 'preserve) | ||
| 2047 | (ical:date-time-variant dtstart :day 5 :tz 'preserve) | ||
| 2048 | (ical:date-time-variant dtstart :day 15 :tz 'preserve) | ||
| 2049 | (ical:date-time-variant dtstart :day 17 :tz 'preserve) | ||
| 2050 | (ical:date-time-variant dtstart :day 19 :tz 'preserve) | ||
| 2051 | (ical:date-time-variant dtstart :day 29 :tz 'preserve) | ||
| 2052 | (ical:date-time-variant dtstart :month 10 :day 1 :tz 'preserve) | ||
| 2053 | (ical:date-time-variant dtstart :month 10 :day 3 :tz 'preserve) | ||
| 2054 | (ical:date-time-variant dtstart :month 10 :day 13 :tz 'preserve) | ||
| 2055 | (ical:date-time-variant dtstart :month 10 :day 15 :tz 'preserve) | ||
| 2056 | (ical:date-time-variant dtstart :month 10 :day 17 :tz 'preserve) | ||
| 2057 | ;; (1997 9:00 AM EST) October 27,29,31; | ||
| 2058 | ;; November 10,12,14,24,26,28; | ||
| 2059 | ;; December 8,10,12,22 | ||
| 2060 | (ical:date-time-variant dtstart :month 10 :day 27 :zone ict:est :dst nil) | ||
| 2061 | (ical:date-time-variant dtstart :month 10 :day 29 :zone ict:est :dst nil) | ||
| 2062 | (ical:date-time-variant dtstart :month 10 :day 31 :zone ict:est :dst nil) | ||
| 2063 | (ical:date-time-variant dtstart :month 11 :day 10 :zone ict:est :dst nil) | ||
| 2064 | (ical:date-time-variant dtstart :month 11 :day 12 :zone ict:est :dst nil) | ||
| 2065 | (ical:date-time-variant dtstart :month 11 :day 14 :zone ict:est :dst nil) | ||
| 2066 | (ical:date-time-variant dtstart :month 11 :day 24 :zone ict:est :dst nil) | ||
| 2067 | (ical:date-time-variant dtstart :month 11 :day 26 :zone ict:est :dst nil) | ||
| 2068 | (ical:date-time-variant dtstart :month 11 :day 28 :zone ict:est :dst nil) | ||
| 2069 | (ical:date-time-variant dtstart :month 12 :day 8 :zone ict:est :dst nil) | ||
| 2070 | (ical:date-time-variant dtstart :month 12 :day 10 :zone ict:est :dst nil) | ||
| 2071 | (ical:date-time-variant dtstart :month 12 :day 12 :zone ict:est :dst nil) | ||
| 2072 | (ical:date-time-variant dtstart :month 12 :day 22 :zone ict:est :dst nil)) | ||
| 2073 | :nonmembers | ||
| 2074 | (list | ||
| 2075 | ;; These match the rule, but are just past the UNTIL date: | ||
| 2076 | (ical:date-time-variant dtstart :month 12 :day 24 :zone ict:est :dst nil) | ||
| 2077 | (ical:date-time-variant dtstart :month 12 :day 26 :zone ict:est :dst nil)) | ||
| 2078 | :source rfc5545-sec3.8.5.3/12) | ||
| 2079 | |||
| 2080 | (ict:rrule-test | ||
| 2081 | "RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH\n" | ||
| 2082 | "Every other week on Tuesday and Thursday, for 8 occurrences" | ||
| 2083 | :tz ict:tz-eastern | ||
| 2084 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 2085 | :hour 9 :minute 0 :second 0 | ||
| 2086 | :zone ict:edt :dst t) | ||
| 2087 | :members | ||
| 2088 | ;; ==> (1997 9:00 AM EDT) September 2,4,16,18,30; | ||
| 2089 | ;; October 2,14,16 | ||
| 2090 | (list | ||
| 2091 | dtstart | ||
| 2092 | (ical:date-time-variant dtstart :day 4 :tz 'preserve) | ||
| 2093 | (ical:date-time-variant dtstart :day 16 :tz 'preserve) | ||
| 2094 | (ical:date-time-variant dtstart :day 18 :tz 'preserve) | ||
| 2095 | (ical:date-time-variant dtstart :day 30 :tz 'preserve) | ||
| 2096 | (ical:date-time-variant dtstart :month 10 :day 2 :tz 'preserve) | ||
| 2097 | (ical:date-time-variant dtstart :month 10 :day 14 :tz 'preserve) | ||
| 2098 | (ical:date-time-variant dtstart :month 10 :day 16 :tz 'preserve)) | ||
| 2099 | :source rfc5545-sec3.8.5.3/13) | ||
| 2100 | |||
| 2101 | (ict:rrule-test | ||
| 2102 | "RRULE:FREQ=MONTHLY;COUNT=10;BYDAY=1FR\n" | ||
| 2103 | "Monthly on the first Friday for 10 occurrences" | ||
| 2104 | :tz ict:tz-eastern | ||
| 2105 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 5 | ||
| 2106 | :hour 9 :minute 0 :second 0 | ||
| 2107 | :zone ict:edt :dst t) | ||
| 2108 | :members | ||
| 2109 | (list | ||
| 2110 | ;; ==> (1997 9:00 AM EDT) September 5;October 3 | ||
| 2111 | dtstart | ||
| 2112 | (ical:date-time-variant dtstart :month 10 :day 3 :tz 'preserve) | ||
| 2113 | ;; (1997 9:00 AM EST) November 7;December 5 | ||
| 2114 | (ical:date-time-variant dtstart :month 11 :day 7 :zone ict:est :dst nil) | ||
| 2115 | (ical:date-time-variant dtstart :month 12 :day 5 :zone ict:est :dst nil) | ||
| 2116 | ;; (1998 9:00 AM EST) January 2;February 6;March 6;April 3 | ||
| 2117 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 2 | ||
| 2118 | :zone ict:est :dst nil) | ||
| 2119 | (ical:date-time-variant dtstart :year 1998 :month 2 :day 6 | ||
| 2120 | :zone ict:est :dst nil) | ||
| 2121 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 6 | ||
| 2122 | :zone ict:est :dst nil) | ||
| 2123 | (ical:date-time-variant dtstart :year 1998 :month 4 :day 3 | ||
| 2124 | :zone ict:est :dst nil) | ||
| 2125 | ;; (1998 9:00 AM EDT) May 1;June 5 | ||
| 2126 | (ical:date-time-variant dtstart :year 1998 :month 5 :day 1 :tz 'preserve) | ||
| 2127 | (ical:date-time-variant dtstart :year 1998 :month 6 :day 5 :tz 'preserve)) | ||
| 2128 | :source rfc5545-sec3.8.5.3/14) | ||
| 2129 | |||
| 2130 | (ict:rrule-test | ||
| 2131 | "RRULE:FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR\n" | ||
| 2132 | "Monthly on the first Friday until December 24, 1997" | ||
| 2133 | :tz ict:tz-eastern | ||
| 2134 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 5 | ||
| 2135 | :hour 9 :minute 0 :second 0 | ||
| 2136 | :zone ict:edt :dst t) | ||
| 2137 | :members | ||
| 2138 | (list | ||
| 2139 | ;; ==> (1997 9:00 AM EDT) September 5; October 3 | ||
| 2140 | dtstart | ||
| 2141 | (ical:date-time-variant dtstart :month 10 :day 3 :tz 'preserve) | ||
| 2142 | ;; (1997 9:00 AM EST) November 7;December 5 | ||
| 2143 | (ical:date-time-variant dtstart :month 11 :day 7 :zone ict:est :dst nil) | ||
| 2144 | (ical:date-time-variant dtstart :month 12 :day 5 :zone ict:est :dst nil)) | ||
| 2145 | :source rfc5545-sec3.8.5.3/15) | ||
| 2146 | |||
| 2147 | (ict:rrule-test | ||
| 2148 | "RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU\n" | ||
| 2149 | "Every other month on the first and last Sunday of the month for 10 occurrences" | ||
| 2150 | :tz ict:tz-eastern | ||
| 2151 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 7 | ||
| 2152 | :hour 9 :minute 0 :second 0 | ||
| 2153 | :zone ict:edt :dst t) | ||
| 2154 | :members | ||
| 2155 | (list | ||
| 2156 | ;; ==> (1997 9:00 AM EDT) September 7,28 | ||
| 2157 | dtstart | ||
| 2158 | (ical:date-time-variant dtstart :day 28 :tz 'preserve) | ||
| 2159 | ;; (1997 9:00 AM EST) November 2,30 | ||
| 2160 | (ical:date-time-variant dtstart :month 11 :day 2 :zone ict:est :dst nil) | ||
| 2161 | (ical:date-time-variant dtstart :month 11 :day 30 :zone ict:est :dst nil) | ||
| 2162 | ;; (1998 9:00 AM EST) January 4,25;March 1,29 | ||
| 2163 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 4 | ||
| 2164 | :zone ict:est :dst nil) | ||
| 2165 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 25 | ||
| 2166 | :zone ict:est :dst nil) | ||
| 2167 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 1 | ||
| 2168 | :zone ict:est :dst nil) | ||
| 2169 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 29 | ||
| 2170 | :zone ict:est :dst nil) | ||
| 2171 | ;; (1998 9:00 AM EDT) May 3,31 | ||
| 2172 | (ical:date-time-variant dtstart :year 1998 :month 5 :day 3 :tz 'preserve) | ||
| 2173 | (ical:date-time-variant dtstart :year 1998 :month 5 :day 31 :tz 'preserve)) | ||
| 2174 | :source rfc5545-sec3.8.5.3/16) | ||
| 2175 | |||
| 2176 | (ict:rrule-test | ||
| 2177 | "RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO\n" | ||
| 2178 | "Monthly on the second-to-last Monday of the month for 6 months" | ||
| 2179 | :tz ict:tz-eastern | ||
| 2180 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 22 | ||
| 2181 | :hour 9 :minute 0 :second 0 | ||
| 2182 | :zone ict:edt :dst t) | ||
| 2183 | :members | ||
| 2184 | (list | ||
| 2185 | ;; ==> (1997 9:00 AM EDT) September 22;October 20 | ||
| 2186 | dtstart | ||
| 2187 | (ical:date-time-variant dtstart :month 10 :day 20 :tz 'preserve) | ||
| 2188 | ;; (1997 9:00 AM EST) November 17;December 22 | ||
| 2189 | (ical:date-time-variant dtstart :month 11 :day 17 | ||
| 2190 | :zone ict:est :dst nil) | ||
| 2191 | (ical:date-time-variant dtstart :month 12 :day 22 | ||
| 2192 | :zone ict:est :dst nil) | ||
| 2193 | ;; (1998 9:00 AM EST) January 19;February 16 | ||
| 2194 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 19 | ||
| 2195 | :zone ict:est :dst nil) | ||
| 2196 | (ical:date-time-variant dtstart :year 1998 :month 2 :day 16 | ||
| 2197 | :zone ict:est :dst nil)) | ||
| 2198 | :source rfc5545-sec3.8.5.3/17) | ||
| 2199 | |||
| 2200 | (ict:rrule-test | ||
| 2201 | "RRULE:FREQ=MONTHLY;BYMONTHDAY=-3\n" | ||
| 2202 | "Monthly on the third-to-the-last day of the month, forever" | ||
| 2203 | :tz ict:tz-eastern | ||
| 2204 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 28 | ||
| 2205 | :hour 9 :minute 0 :second 0 | ||
| 2206 | :zone ict:edt :dst t) | ||
| 2207 | :high (ical:make-date-time :year 1998 :month 3 :day 1 | ||
| 2208 | :hour 0 :minute 0 :second 0 | ||
| 2209 | :zone ict:est :dst nil) | ||
| 2210 | :members | ||
| 2211 | (list | ||
| 2212 | ;; ==> (1997 9:00 AM EDT) September 28 | ||
| 2213 | dtstart | ||
| 2214 | ;; (1997 9:00 AM EST) October 29;November 28;December 29 | ||
| 2215 | (ical:date-time-variant dtstart :month 10 :day 29 | ||
| 2216 | :zone ict:est :dst nil) | ||
| 2217 | (ical:date-time-variant dtstart :month 11 :day 28 | ||
| 2218 | :zone ict:est :dst nil) | ||
| 2219 | (ical:date-time-variant dtstart :month 12 :day 29 | ||
| 2220 | :zone ict:est :dst nil) | ||
| 2221 | ;; (1998 9:00 AM EST) January 29;February 26 | ||
| 2222 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 29 | ||
| 2223 | :zone ict:est :dst nil) | ||
| 2224 | (ical:date-time-variant dtstart :year 1998 :month 2 :day 26 | ||
| 2225 | :zone ict:est :dst nil)) | ||
| 2226 | :source rfc5545-sec3.8.5.3/18) | ||
| 2227 | |||
| 2228 | (ict:rrule-test | ||
| 2229 | "RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15\n" | ||
| 2230 | "Monthly on the 2nd and 15th of the month for 10 occurrences" | ||
| 2231 | :tz ict:tz-eastern | ||
| 2232 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 2233 | :hour 9 :minute 0 :second 0 | ||
| 2234 | :zone ict:edt :dst t) | ||
| 2235 | :members | ||
| 2236 | (list | ||
| 2237 | ;; ==> (1997 9:00 AM EDT) September 2,15;October 2,15 | ||
| 2238 | dtstart | ||
| 2239 | (ical:date-time-variant dtstart :day 15 :tz 'preserve) | ||
| 2240 | (ical:date-time-variant dtstart :month 10 :day 2 :tz 'preserve) | ||
| 2241 | (ical:date-time-variant dtstart :month 10 :day 15 :tz 'preserve) | ||
| 2242 | ;; (1997 9:00 AM EST) November 2,15;December 2,15 | ||
| 2243 | (ical:date-time-variant dtstart :month 11 :day 2 | ||
| 2244 | :zone ict:est :dst nil) | ||
| 2245 | (ical:date-time-variant dtstart :month 11 :day 15 | ||
| 2246 | :zone ict:est :dst nil) | ||
| 2247 | (ical:date-time-variant dtstart :month 12 :day 2 | ||
| 2248 | :zone ict:est :dst nil) | ||
| 2249 | (ical:date-time-variant dtstart :month 12 :day 15 | ||
| 2250 | :zone ict:est :dst nil) | ||
| 2251 | ;; (1998 9:00 AM EST) January 2,15 | ||
| 2252 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 2 | ||
| 2253 | :zone ict:est :dst nil) | ||
| 2254 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 15 | ||
| 2255 | :zone ict:est :dst nil)) | ||
| 2256 | :source rfc5545-sec3.8.5.3/19) | ||
| 2257 | |||
| 2258 | (ict:rrule-test | ||
| 2259 | "RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1\n" | ||
| 2260 | "Monthly on the first and last day of the month for 10 occurrences" | ||
| 2261 | :tz ict:tz-eastern | ||
| 2262 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 30 | ||
| 2263 | :hour 9 :minute 0 :second 0 | ||
| 2264 | :zone ict:edt :dst t) | ||
| 2265 | :members | ||
| 2266 | (list | ||
| 2267 | ;; ==> (1997 9:00 AM EDT) September 30;October 1 | ||
| 2268 | dtstart | ||
| 2269 | (ical:date-time-variant dtstart :month 10 :day 1 :tz 'preserve) | ||
| 2270 | ;; (1997 9:00 AM EST) October 31;November 1,30;December 1,31 | ||
| 2271 | (ical:date-time-variant dtstart :month 10 :day 31 | ||
| 2272 | :zone ict:est :dst nil) | ||
| 2273 | (ical:date-time-variant dtstart :month 11 :day 1 | ||
| 2274 | :zone ict:est :dst nil) | ||
| 2275 | (ical:date-time-variant dtstart :month 11 :day 30 | ||
| 2276 | :zone ict:est :dst nil) | ||
| 2277 | (ical:date-time-variant dtstart :month 12 :day 1 | ||
| 2278 | :zone ict:est :dst nil) | ||
| 2279 | (ical:date-time-variant dtstart :month 12 :day 31 | ||
| 2280 | :zone ict:est :dst nil) | ||
| 2281 | ;; (1998 9:00 AM EST) January 1,31;February 1 | ||
| 2282 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 1 | ||
| 2283 | :zone ict:est :dst nil) | ||
| 2284 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 31 | ||
| 2285 | :zone ict:est :dst nil) | ||
| 2286 | (ical:date-time-variant dtstart :year 1998 :month 2 :day 1 | ||
| 2287 | :zone ict:est :dst nil)) | ||
| 2288 | :source rfc5545-sec3.8.5.3/20) | ||
| 2289 | |||
| 2290 | (ict:rrule-test | ||
| 2291 | "RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15\n" | ||
| 2292 | "Every 18 months on the 10th thru 15th of the month for 10 occurrences" | ||
| 2293 | :tz ict:tz-eastern | ||
| 2294 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 10 | ||
| 2295 | :hour 9 :minute 0 :second 0 | ||
| 2296 | :zone ict:edt :dst t) | ||
| 2297 | :members | ||
| 2298 | (append | ||
| 2299 | (list | ||
| 2300 | ;; ==> (1997 9:00 AM EDT) September 10,11,12,13,14,15 | ||
| 2301 | dtstart | ||
| 2302 | (ical:date-time-variant dtstart :day 11 :tz 'preserve) | ||
| 2303 | (ical:date-time-variant dtstart :day 12 :tz 'preserve) | ||
| 2304 | (ical:date-time-variant dtstart :day 13 :tz 'preserve) | ||
| 2305 | (ical:date-time-variant dtstart :day 14 :tz 'preserve) | ||
| 2306 | (ical:date-time-variant dtstart :day 15 :tz 'preserve)) | ||
| 2307 | |||
| 2308 | ;; (1999 9:00 AM EST) March 10,11,12,13 | ||
| 2309 | (let ((mar99 (ical:make-date-time :year 1999 :month 3 :day 10 | ||
| 2310 | :hour 9 :minute 0 :second 0 | ||
| 2311 | :zone ict:est :dst nil))) | ||
| 2312 | (list | ||
| 2313 | mar99 | ||
| 2314 | (ical:date-time-variant mar99 :day 11 :tz 'preserve) | ||
| 2315 | (ical:date-time-variant mar99 :day 12 :tz 'preserve) | ||
| 2316 | (ical:date-time-variant mar99 :day 13 :tz 'preserve)))) | ||
| 2317 | :nonmembers | ||
| 2318 | (list | ||
| 2319 | ;; These match the rule but are excluded by the COUNT clause: | ||
| 2320 | (ical:make-date-time :year 1999 :month 3 :day 14 | ||
| 2321 | :hour 9 :minute 0 :second 0 | ||
| 2322 | :zone ict:est :dst nil) | ||
| 2323 | (ical:make-date-time :year 1999 :month 3 :day 15 | ||
| 2324 | :hour 9 :minute 0 :second 0 | ||
| 2325 | :zone ict:est :dst nil)) | ||
| 2326 | :source rfc5545-sec3.8.5.3/21) | ||
| 2327 | |||
| 2328 | (ict:rrule-test | ||
| 2329 | "RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU\n" | ||
| 2330 | "Every Tuesday, every other month" | ||
| 2331 | :tz ict:tz-eastern | ||
| 2332 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 2333 | :hour 9 :minute 0 :second 0 | ||
| 2334 | :zone ict:edt :dst t) | ||
| 2335 | :high (ical:make-date-time :year 1998 :month 4 :day 1 | ||
| 2336 | :hour 0 :minute 0 :second 0 | ||
| 2337 | :zone ict:est :dst nil) | ||
| 2338 | :members | ||
| 2339 | (list | ||
| 2340 | ;; ==> (1997 9:00 AM EDT) September 2,9,16,23,30 | ||
| 2341 | dtstart | ||
| 2342 | (ical:date-time-variant dtstart :day 9 :tz 'preserve) | ||
| 2343 | (ical:date-time-variant dtstart :day 16 :tz 'preserve) | ||
| 2344 | (ical:date-time-variant dtstart :day 23 :tz 'preserve) | ||
| 2345 | (ical:date-time-variant dtstart :day 30 :tz 'preserve) | ||
| 2346 | ;; (1997 9:00 AM EST) November 4,11,18,25 | ||
| 2347 | (ical:date-time-variant dtstart :month 11 :day 4 | ||
| 2348 | :zone ict:est :dst nil) | ||
| 2349 | (ical:date-time-variant dtstart :month 11 :day 11 | ||
| 2350 | :zone ict:est :dst nil) | ||
| 2351 | (ical:date-time-variant dtstart :month 11 :day 11 | ||
| 2352 | :zone ict:est :dst nil) | ||
| 2353 | (ical:date-time-variant dtstart :month 11 :day 25 | ||
| 2354 | :zone ict:est :dst nil) | ||
| 2355 | ;; (1998 9:00 AM EST) January 6,13,20,27;March 3,10,17,24,31 | ||
| 2356 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 6 | ||
| 2357 | :zone ict:est :dst nil) | ||
| 2358 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 13 | ||
| 2359 | :zone ict:est :dst nil) | ||
| 2360 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 20 | ||
| 2361 | :zone ict:est :dst nil) | ||
| 2362 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 27 | ||
| 2363 | :zone ict:est :dst nil) | ||
| 2364 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 3 | ||
| 2365 | :zone ict:est :dst nil) | ||
| 2366 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 10 | ||
| 2367 | :zone ict:est :dst nil) | ||
| 2368 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 17 | ||
| 2369 | :zone ict:est :dst nil) | ||
| 2370 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 24 | ||
| 2371 | :zone ict:est :dst nil) | ||
| 2372 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 31 | ||
| 2373 | :zone ict:est :dst nil)) | ||
| 2374 | :nonmembers | ||
| 2375 | ;; e.g. Tuesdays in December 1997: | ||
| 2376 | (list | ||
| 2377 | (ical:date-time-variant dtstart :month 12 :day 2 :zone ict:est :dst nil) | ||
| 2378 | (ical:date-time-variant dtstart :month 12 :day 9 :zone ict:est :dst nil) | ||
| 2379 | (ical:date-time-variant dtstart :month 12 :day 16 :zone ict:est :dst nil) | ||
| 2380 | (ical:date-time-variant dtstart :month 12 :day 23 :zone ict:est :dst nil) | ||
| 2381 | (ical:date-time-variant dtstart :month 12 :day 30 :zone ict:est :dst nil)) | ||
| 2382 | :source rfc5545-sec3.8.5.3/22) | ||
| 2383 | |||
| 2384 | (ict:rrule-test | ||
| 2385 | "RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7\n" | ||
| 2386 | "Yearly in June and July for 10 occurrences" | ||
| 2387 | :tz ict:tz-eastern | ||
| 2388 | :dtstart (ical:make-date-time :year 1997 :month 6 :day 10 | ||
| 2389 | :hour 9 :minute 0 :second 0 | ||
| 2390 | :zone ict:edt :dst t) | ||
| 2391 | ;; Note: Since none of the BYDAY, BYMONTHDAY, or BYYEARDAY | ||
| 2392 | ;; clauses are specified, the month day is gotten from "DTSTART" | ||
| 2393 | :members | ||
| 2394 | ;; ==> (1997 9:00 AM EDT) June 10;July 10 | ||
| 2395 | ;; (1998 9:00 AM EDT) June 10;July 10 | ||
| 2396 | ;; (1999 9:00 AM EDT) June 10;July 10 | ||
| 2397 | ;; (2000 9:00 AM EDT) June 10;July 10 | ||
| 2398 | ;; (2001 9:00 AM EDT) June 10;July 10 | ||
| 2399 | (mapcan | ||
| 2400 | (lambda (y) | ||
| 2401 | (list | ||
| 2402 | (ical:date-time-variant dtstart :year y :month 6 :tz 'preserve) | ||
| 2403 | (ical:date-time-variant dtstart :year y :month 7 :tz 'preserve))) | ||
| 2404 | (number-sequence 1997 2001)) | ||
| 2405 | :source rfc5545-sec3.8.5.3/23) | ||
| 2406 | |||
| 2407 | (ict:rrule-test | ||
| 2408 | "RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3\n" | ||
| 2409 | "Every other year on January, February, and March for 10 occurrences" | ||
| 2410 | :tz ict:tz-eastern | ||
| 2411 | :dtstart (ical:make-date-time :year 1997 :month 3 :day 10 | ||
| 2412 | :hour 9 :minute 0 :second 0 | ||
| 2413 | :zone ict:est :dst nil) | ||
| 2414 | :members | ||
| 2415 | ;; ==> (1997 9:00 AM EST) March 10 | ||
| 2416 | ;; (1999 9:00 AM EST) January 10;February 10;March 10 | ||
| 2417 | ;; (2001 9:00 AM EST) January 10;February 10;March 10 | ||
| 2418 | ;; (2003 9:00 AM EST) January 10;February 10;March 10 | ||
| 2419 | (cons | ||
| 2420 | dtstart | ||
| 2421 | ;; FIXME: this mapcan appears to produce a spurious warning: | ||
| 2422 | (with-suppressed-warnings ((ignored-return-value mapcan)) | ||
| 2423 | (mapcan | ||
| 2424 | (lambda (y) | ||
| 2425 | (list | ||
| 2426 | (ical:date-time-variant dtstart :year y :month 1 :tz 'preserve) | ||
| 2427 | (ical:date-time-variant dtstart :year y :month 2 :tz 'preserve) | ||
| 2428 | (ical:date-time-variant dtstart :year y :month 3 :tz 'preserve))) | ||
| 2429 | (list 1999 2001 2003)))) | ||
| 2430 | :source rfc5545-sec3.8.5.3/24) | ||
| 2431 | |||
| 2432 | (ict:rrule-test | ||
| 2433 | "RRULE:FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200\n" | ||
| 2434 | "Every third year on the 1st, 100th, and 200th day for 10 occurrences" | ||
| 2435 | :tz ict:tz-eastern | ||
| 2436 | :dtstart (ical:make-date-time :year 1997 :month 1 :day 1 | ||
| 2437 | :hour 9 :minute 0 :second 0 | ||
| 2438 | :zone ict:est :dst nil) | ||
| 2439 | |||
| 2440 | :members | ||
| 2441 | (list | ||
| 2442 | ;; ==> (1997 9:00 AM EST) January 1 | ||
| 2443 | dtstart | ||
| 2444 | ;; (1997 9:00 AM EDT) April 10;July 19 | ||
| 2445 | (ical:date-time-variant dtstart :month 4 :day 10 :zone ict:edt :dst t) | ||
| 2446 | (ical:date-time-variant dtstart :month 7 :day 19 :zone ict:edt :dst t) | ||
| 2447 | ;; (2000 9:00 AM EST) January 1 | ||
| 2448 | (ical:date-time-variant dtstart :year 2000 :tz 'preserve) | ||
| 2449 | ;; (2000 9:00 AM EDT) April 9;July 18 | ||
| 2450 | (ical:date-time-variant dtstart :year 2000 :month 4 :day 9 :zone ict:edt :dst t) | ||
| 2451 | (ical:date-time-variant dtstart :year 2000 :month 7 :day 18 :zone ict:edt :dst t) | ||
| 2452 | ;; (2003 9:00 AM EST) January 1 | ||
| 2453 | (ical:date-time-variant dtstart :year 2003 :tz 'preserve) | ||
| 2454 | ;; (2003 9:00 AM EDT) April 10;July 19 | ||
| 2455 | (ical:date-time-variant dtstart :year 2003 :month 4 :day 10 :zone ict:edt :dst t) | ||
| 2456 | (ical:date-time-variant dtstart :year 2003 :month 7 :day 19 :zone ict:edt :dst t) | ||
| 2457 | ;; (2006 9:00 AM EST) January 1 | ||
| 2458 | (ical:date-time-variant dtstart :year 2006 :tz 'preserve)) | ||
| 2459 | :source rfc5545-sec3.8.5.3/25) | ||
| 2460 | |||
| 2461 | (ict:rrule-test | ||
| 2462 | "RRULE:FREQ=YEARLY;BYDAY=20MO\n" | ||
| 2463 | "Every 20th Monday of the year, forever" | ||
| 2464 | :tz ict:tz-eastern | ||
| 2465 | :dtstart (ical:make-date-time :year 1997 :month 5 :day 19 | ||
| 2466 | :hour 9 :minute 0 :second 0 | ||
| 2467 | :zone ict:edt :dst t) | ||
| 2468 | :members | ||
| 2469 | (list | ||
| 2470 | ;; ==> (1997 9:00 AM EDT) May 19 | ||
| 2471 | ;; (1998 9:00 AM EDT) May 18 | ||
| 2472 | ;; (1999 9:00 AM EDT) May 17 | ||
| 2473 | ;; ... | ||
| 2474 | dtstart | ||
| 2475 | (ical:date-time-variant dtstart :year 1998 :day 18 :tz 'preserve) | ||
| 2476 | (ical:date-time-variant dtstart :year 1999 :day 17 :tz 'preserve)) | ||
| 2477 | :source rfc5545-sec3.8.5.3/26) | ||
| 2478 | |||
| 2479 | (ict:rrule-test | ||
| 2480 | "RRULE:FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO\n" | ||
| 2481 | "Every year on Monday in Week 20 (where the week starts Monday), forever" | ||
| 2482 | :tz ict:tz-eastern | ||
| 2483 | :dtstart | ||
| 2484 | (ical:make-date-time :year 1997 :month 5 :day 12 | ||
| 2485 | :hour 9 :minute 0 :second 0 | ||
| 2486 | :zone ict:edt :dst t) | ||
| 2487 | :members | ||
| 2488 | (list | ||
| 2489 | (ical:date-time-variant dtstart :year 1998 :day 11 :tz 'preserve) | ||
| 2490 | (ical:date-time-variant dtstart :year 1999 :day 17 :tz 'preserve)) | ||
| 2491 | :nonmembers | ||
| 2492 | (list | ||
| 2493 | (ical:date-time-variant dtstart :year 1998 :day 12 :tz 'preserve) ; a Tuesday | ||
| 2494 | (ical:date-time-variant dtstart :year 1998 :day 18 :tz 'preserve)) ; wrong weekno | ||
| 2495 | :source rfc5545-sec3.8.5.3/27) | ||
| 2496 | |||
| 2497 | (ict:rrule-test | ||
| 2498 | "RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH\n" | ||
| 2499 | "Every Thursday in March, forever" | ||
| 2500 | :tz ict:tz-eastern | ||
| 2501 | :dtstart (ical:make-date-time :year 1997 :month 3 :day 13 | ||
| 2502 | :hour 9 :minute 0 :second 0 | ||
| 2503 | :zone ict:est :dst nil) | ||
| 2504 | :members | ||
| 2505 | (append | ||
| 2506 | ;; ==> (1997 9:00 AM EST) March 13,20,27 | ||
| 2507 | (mapcar | ||
| 2508 | (lambda (d) | ||
| 2509 | (ical:date-time-variant dtstart :day d :tz 'preserve)) | ||
| 2510 | (list 13 20 27)) | ||
| 2511 | ;; (1998 9:00 AM EST) March 5,12,19,26 | ||
| 2512 | (mapcar | ||
| 2513 | (lambda (d) | ||
| 2514 | (ical:date-time-variant dtstart :year 1998 :day d :tz 'preserve)) | ||
| 2515 | (list 5 12 19 26)) | ||
| 2516 | ;; (1999 9:00 AM EST) March 4,11,18,25 | ||
| 2517 | (mapcar | ||
| 2518 | (lambda (d) | ||
| 2519 | (ical:date-time-variant dtstart :year 1999 :day d :tz 'preserve)) | ||
| 2520 | (list 4 11 18 25))) | ||
| 2521 | :source rfc5545-sec3.8.5.3/28) | ||
| 2522 | |||
| 2523 | (ict:rrule-test | ||
| 2524 | "RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8\n" | ||
| 2525 | "Every Thursday, but only during June, July, and August, forever" | ||
| 2526 | :tz ict:tz-eastern | ||
| 2527 | :dtstart (ical:make-date-time :year 1997 :month 6 :day 5 | ||
| 2528 | :hour 9 :minute 0 :second 0 | ||
| 2529 | :zone ict:edt :dst t) | ||
| 2530 | :members | ||
| 2531 | (append | ||
| 2532 | ;; ==> (1997 9:00 AM EDT) June 5,12,19,26;July 3,10,17,24,31; | ||
| 2533 | ;; August 7,14,21,28 | ||
| 2534 | (mapcar | ||
| 2535 | (lambda (d) | ||
| 2536 | (ical:date-time-variant dtstart :day d :tz 'preserve)) | ||
| 2537 | (list 5 12 19 26)) | ||
| 2538 | (mapcar | ||
| 2539 | (lambda (d) | ||
| 2540 | (ical:date-time-variant dtstart :month 7 :day d :tz 'preserve)) | ||
| 2541 | (list 3 10 17 24 31)) | ||
| 2542 | (mapcar | ||
| 2543 | (lambda (d) | ||
| 2544 | (ical:date-time-variant dtstart :month 8 :day d :tz 'preserve)) | ||
| 2545 | (list 7 14 21 28)) | ||
| 2546 | ;; (1998 9:00 AM EDT) June 4,11,18,25;July 2,9,16,23,30; | ||
| 2547 | ;; August 6,13,20,27 | ||
| 2548 | (mapcar | ||
| 2549 | (lambda (d) | ||
| 2550 | (ical:date-time-variant dtstart :year 1998 :day d :tz 'preserve)) | ||
| 2551 | (list 4 11 18 25)) | ||
| 2552 | (mapcar | ||
| 2553 | (lambda (d) | ||
| 2554 | (ical:date-time-variant dtstart :year 1998 :month 7 :day d :tz 'preserve)) | ||
| 2555 | (list 2 9 16 23 30)) | ||
| 2556 | (mapcar | ||
| 2557 | (lambda (d) | ||
| 2558 | (ical:date-time-variant dtstart :year 1998 :month 8 :day d :tz 'preserve)) | ||
| 2559 | (list 6 13 20 27)) | ||
| 2560 | ;; (1999 9:00 AM EDT) June 3,10,17,24;July 1,8,15,22,29; | ||
| 2561 | ;; August 5,12,19,26 | ||
| 2562 | (mapcar | ||
| 2563 | (lambda (d) | ||
| 2564 | (ical:date-time-variant dtstart :year 1999 :day d :tz 'preserve)) | ||
| 2565 | (list 3 10 17 24)) | ||
| 2566 | (mapcar | ||
| 2567 | (lambda (d) | ||
| 2568 | (ical:date-time-variant dtstart :year 1999 :month 7 :day d :tz 'preserve)) | ||
| 2569 | (list 1 8 15 22 29)) | ||
| 2570 | (mapcar | ||
| 2571 | (lambda (d) | ||
| 2572 | (ical:date-time-variant dtstart :year 1999 :month 8 :day d :tz 'preserve)) | ||
| 2573 | (list 5 12 19 26))) | ||
| 2574 | :source rfc5545-sec3.8.5.3/29) | ||
| 2575 | |||
| 2576 | (ict:rrule-test | ||
| 2577 | "RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13\n" | ||
| 2578 | "Every Friday the 13th, forever, *excluding* DTSTART " | ||
| 2579 | :tz ict:tz-eastern | ||
| 2580 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 2581 | :hour 9 :minute 0 :second 0 | ||
| 2582 | :zone ict:edt :dst t) | ||
| 2583 | :high (ical:make-date-time :year 2000 :month 10 :day 14 | ||
| 2584 | :hour 0 :minute 0 :second 0 | ||
| 2585 | :zone ict:edt :dst t) | ||
| 2586 | :exdates (list dtstart) | ||
| 2587 | :members | ||
| 2588 | (list | ||
| 2589 | ;; ==> (1998 9:00 AM EST) February 13;March 13;November 13 | ||
| 2590 | ;; (1999 9:00 AM EDT) August 13 | ||
| 2591 | ;; (2000 9:00 AM EDT) October 13 | ||
| 2592 | ;; ... | ||
| 2593 | (ical:date-time-variant dtstart :year 1998 :month 2 :day 13 | ||
| 2594 | :zone ict:est :dst nil) | ||
| 2595 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 13 | ||
| 2596 | :zone ict:est :dst nil) | ||
| 2597 | (ical:date-time-variant dtstart :year 1998 :month 11 :day 13 | ||
| 2598 | :zone ict:est :dst nil) | ||
| 2599 | (ical:date-time-variant dtstart :year 1999 :month 8 :day 13 :tz 'preserve) | ||
| 2600 | (ical:date-time-variant dtstart :year 2000 :month 10 :day 13 :tz 'preserve)) | ||
| 2601 | :source rfc5545-sec3.8.5.3/30) | ||
| 2602 | |||
| 2603 | (ict:rrule-test | ||
| 2604 | "RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13\n" | ||
| 2605 | "The first Saturday that follows the first Sunday of the month, forever" | ||
| 2606 | :tz ict:tz-eastern | ||
| 2607 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 13 | ||
| 2608 | :hour 9 :minute 0 :second 0 | ||
| 2609 | :zone ict:edt :dst t) | ||
| 2610 | :high (ical:make-date-time :year 1998 :month 6 :day 14 | ||
| 2611 | :hour 0 :minute 0 :second 0 | ||
| 2612 | :zone ict:edt :dst t) | ||
| 2613 | :members | ||
| 2614 | (list | ||
| 2615 | ;; ==> (1997 9:00 AM EDT) September 13;October 11 | ||
| 2616 | dtstart | ||
| 2617 | (ical:date-time-variant dtstart :month 10 :day 11 :tz 'preserve) | ||
| 2618 | ;; (1997 9:00 AM EST) November 8;December 13 | ||
| 2619 | (ical:date-time-variant dtstart :month 11 :day 8 :zone ict:est :dst nil) | ||
| 2620 | (ical:date-time-variant dtstart :month 12 :day 13 :zone ict:est :dst nil) | ||
| 2621 | ;; (1998 9:00 AM EST) January 10;February 7;March 7 | ||
| 2622 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 10 | ||
| 2623 | :zone ict:est :dst nil) | ||
| 2624 | (ical:date-time-variant dtstart :year 1998 :month 2 :day 7 | ||
| 2625 | :zone ict:est :dst nil) | ||
| 2626 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 7 | ||
| 2627 | :zone ict:est :dst nil) | ||
| 2628 | ;; (1998 9:00 AM EDT) April 11;May 9;June 13... | ||
| 2629 | (ical:date-time-variant dtstart :year 1998 :month 4 :day 11 :tz 'preserve) | ||
| 2630 | (ical:date-time-variant dtstart :year 1998 :month 5 :day 9 :tz 'preserve) | ||
| 2631 | (ical:date-time-variant dtstart :year 1998 :month 6 :day 13 :tz 'preserve)) | ||
| 2632 | :source rfc5545-sec3.8.5.3/31) | ||
| 2633 | |||
| 2634 | (ict:rrule-test | ||
| 2635 | "RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8\n" | ||
| 2636 | "Every 4 years, the first Tuesday after a Monday in November, forever | ||
| 2637 | (U.S. Presidential Election day)" | ||
| 2638 | :tz ict:tz-eastern | ||
| 2639 | :dtstart (ical:make-date-time :year 1996 :month 11 :day 5 | ||
| 2640 | :hour 9 :minute 0 :second 0 | ||
| 2641 | :zone ict:est :dst nil) | ||
| 2642 | |||
| 2643 | :members | ||
| 2644 | (list | ||
| 2645 | ;; ==> (1996 9:00 AM EST) November 5 | ||
| 2646 | dtstart | ||
| 2647 | ;; (2000 9:00 AM EST) November 7 | ||
| 2648 | (ical:date-time-variant dtstart :year 2000 :day 7 :tz 'preserve) | ||
| 2649 | ;; (2004 9:00 AM EST) November 2 | ||
| 2650 | (ical:date-time-variant dtstart :year 2004 :day 2 :tz 'preserve)) | ||
| 2651 | :source rfc5545-sec3.8.5.3/32) | ||
| 2652 | |||
| 2653 | (ict:rrule-test | ||
| 2654 | "RRULE:FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3\n" | ||
| 2655 | "The third instance into the month of one of Tuesday, Wednesday, or | ||
| 2656 | Thursday, for the next 3 months" | ||
| 2657 | ;; TODO: Yikes, why is this so slow?? | ||
| 2658 | :tz ict:tz-eastern | ||
| 2659 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 4 | ||
| 2660 | :hour 9 :minute 0 :second 0 | ||
| 2661 | :zone ict:edt :dst t) | ||
| 2662 | |||
| 2663 | :members | ||
| 2664 | (list | ||
| 2665 | ;; ==> (1997 9:00 AM EDT) September 4;October 7 | ||
| 2666 | ;; (1997 9:00 AM EST) November 6 | ||
| 2667 | dtstart | ||
| 2668 | (ical:date-time-variant dtstart :month 10 :day 7 :tz 'preserve) | ||
| 2669 | (ical:date-time-variant dtstart :month 11 :day 6 :zone ict:est :dst nil)) | ||
| 2670 | :source rfc5545-sec3.8.5.3/33) | ||
| 2671 | |||
| 2672 | (ict:rrule-test | ||
| 2673 | "RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2\n" | ||
| 2674 | "The second-to-last weekday of the month" | ||
| 2675 | :tz ict:tz-eastern | ||
| 2676 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 29 | ||
| 2677 | :hour 9 :minute 0 :second 0 | ||
| 2678 | :zone ict:edt :dst t) | ||
| 2679 | :high (ical:make-date-time :year 1998 :month 4 :day 1 | ||
| 2680 | :hour 0 :minute 0 :second 0 | ||
| 2681 | :zone ict:est :dst nil) | ||
| 2682 | :members | ||
| 2683 | (list | ||
| 2684 | ;; ==> (1997 9:00 AM EDT) September 29 | ||
| 2685 | dtstart | ||
| 2686 | ;; (1997 9:00 AM EST) October 30;November 27;December 30 | ||
| 2687 | (ical:date-time-variant dtstart :month 10 :day 30 :zone ict:est :dst nil) | ||
| 2688 | (ical:date-time-variant dtstart :month 11 :day 27 :zone ict:est :dst nil) | ||
| 2689 | (ical:date-time-variant dtstart :month 12 :day 30 :zone ict:est :dst nil) | ||
| 2690 | ;; (1998 9:00 AM EST) January 29;February 26;March 30 | ||
| 2691 | (ical:date-time-variant dtstart :year 1998 :month 1 :day 29 | ||
| 2692 | :zone ict:est :dst nil) | ||
| 2693 | (ical:date-time-variant dtstart :year 1998 :month 2 :day 26 | ||
| 2694 | :zone ict:est :dst nil) | ||
| 2695 | (ical:date-time-variant dtstart :year 1998 :month 3 :day 30 | ||
| 2696 | :zone ict:est :dst nil)) | ||
| 2697 | :source rfc5545-sec3.8.5.3/34) | ||
| 2698 | |||
| 2699 | (ict:rrule-test | ||
| 2700 | ;; corrected, see Errata ID 3883: https://www.rfc-editor.org/errata/eid3883 | ||
| 2701 | "RRULE:FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T210000Z\n" | ||
| 2702 | "Every 3 hours from 9:00 AM to 5:00 PM on a specific day" | ||
| 2703 | :tz ict:tz-eastern | ||
| 2704 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 2705 | :hour 9 :minute 0 :second 0 | ||
| 2706 | :zone ict:edt :dst t) | ||
| 2707 | |||
| 2708 | :members | ||
| 2709 | (list | ||
| 2710 | ;; ==> (September 2, 1997 EDT) 09:00,12:00,15:00 | ||
| 2711 | dtstart | ||
| 2712 | (ical:date-time-variant dtstart :hour 12 :tz 'preserve) | ||
| 2713 | (ical:date-time-variant dtstart :hour 15 :tz 'preserve)) | ||
| 2714 | :source rfc5545-sec3.8.5.3/35) | ||
| 2715 | |||
| 2716 | (ict:rrule-test | ||
| 2717 | "RRULE:FREQ=MINUTELY;INTERVAL=15;COUNT=6\n" | ||
| 2718 | "Every 15 minutes for 6 occurrences" | ||
| 2719 | :tz ict:tz-eastern | ||
| 2720 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 2721 | :hour 9 :minute 0 :second 0 | ||
| 2722 | :zone ict:edt :dst t) | ||
| 2723 | |||
| 2724 | :members | ||
| 2725 | (list | ||
| 2726 | ;; ==> (September 2, 1997 EDT) 09:00,09:15,09:30,09:45,10:00,10:15 | ||
| 2727 | dtstart | ||
| 2728 | (ical:date-time-variant dtstart :minute 15 :tz 'preserve) | ||
| 2729 | (ical:date-time-variant dtstart :minute 30 :tz 'preserve) | ||
| 2730 | (ical:date-time-variant dtstart :minute 45 :tz 'preserve) | ||
| 2731 | (ical:date-time-variant dtstart :hour 10 :minute 0 :tz 'preserve) | ||
| 2732 | (ical:date-time-variant dtstart :hour 10 :minute 15 :tz 'preserve)) | ||
| 2733 | :source rfc5545-sec3.8.5.3/36) | ||
| 2734 | |||
| 2735 | (ict:rrule-test | ||
| 2736 | "RRULE:FREQ=MINUTELY;INTERVAL=90;COUNT=4\n" | ||
| 2737 | "Every hour and a half for 4 occurrences" | ||
| 2738 | :tz ict:tz-eastern | ||
| 2739 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 2740 | :hour 9 :minute 0 :second 0 | ||
| 2741 | :zone ict:edt :dst t) | ||
| 2742 | :members | ||
| 2743 | (list | ||
| 2744 | ;; ==> (September 2, 1997 EDT) 09:00,10:30;12:00;13:30 | ||
| 2745 | dtstart | ||
| 2746 | (ical:date-time-variant dtstart :hour 10 :minute 30 :tz 'preserve) | ||
| 2747 | (ical:date-time-variant dtstart :hour 12 :minute 0 :tz 'preserve) | ||
| 2748 | (ical:date-time-variant dtstart :hour 13 :minute 30 :tz 'preserve)) | ||
| 2749 | :source rfc5545-sec3.8.5.3/37) | ||
| 2750 | |||
| 2751 | (ict:rrule-test | ||
| 2752 | "RRULE:FREQ=DAILY;BYHOUR=9,10,11,12,13,14,15,16;BYMINUTE=0,20,40\n" | ||
| 2753 | "Every 20 minutes from 9:00 AM to 4:40 PM every day" | ||
| 2754 | :tz ict:tz-eastern | ||
| 2755 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 2756 | :hour 9 :minute 0 :second 0 | ||
| 2757 | :zone ict:edt :dst t) | ||
| 2758 | :high (ical:make-date-time :year 1997 :month 9 :day 4 | ||
| 2759 | :hour 0 :minute 0 :second 0 | ||
| 2760 | :zone ict:edt :dst t) | ||
| 2761 | :members | ||
| 2762 | (append | ||
| 2763 | ;; ==> (September 2, 1997 EDT) 9:00,9:20,9:40,10:00,10:20, | ||
| 2764 | ;; ... 16:00,16:20,16:40 | ||
| 2765 | (mapcan | ||
| 2766 | (lambda (h) | ||
| 2767 | (list | ||
| 2768 | (ical:date-time-variant dtstart :hour h :minute 0 :tz 'preserve) | ||
| 2769 | (ical:date-time-variant dtstart :hour h :minute 20 :tz 'preserve) | ||
| 2770 | (ical:date-time-variant dtstart :hour h :minute 40 :tz 'preserve))) | ||
| 2771 | (number-sequence 9 16)) | ||
| 2772 | ;; (September 3, 1997 EDT) 9:00,9:20,9:40,10:00,10:20, | ||
| 2773 | ;; ...16:00,16:20,16:40 | ||
| 2774 | (mapcan | ||
| 2775 | (lambda (h) | ||
| 2776 | (list | ||
| 2777 | (ical:date-time-variant dtstart :hour h :day 3 :minute 0 :tz 'preserve) | ||
| 2778 | (ical:date-time-variant dtstart :hour h :day 3 :minute 20 :tz 'preserve) | ||
| 2779 | (ical:date-time-variant dtstart :hour h :day 3 :minute 40 :tz 'preserve))) | ||
| 2780 | (number-sequence 9 16))) | ||
| 2781 | :source rfc5545-sec3.8.5.3/38) | ||
| 2782 | |||
| 2783 | (ict:rrule-test | ||
| 2784 | "RRULE:FREQ=MINUTELY;INTERVAL=20;BYHOUR=9,10,11,12,13,14,15,16\n" | ||
| 2785 | "Every 20 minutes from 9:00 AM to 4:40 PM every day | ||
| 2786 | (Alternative rule for the previous example)" | ||
| 2787 | :tags '(:expensive-test) | ||
| 2788 | :tz ict:tz-eastern | ||
| 2789 | :dtstart (ical:make-date-time :year 1997 :month 9 :day 2 | ||
| 2790 | :hour 9 :minute 0 :second 0 | ||
| 2791 | :zone ict:edt :dst t) | ||
| 2792 | :high (ical:make-date-time :year 1997 :month 9 :day 4 | ||
| 2793 | :hour 0 :minute 0 :second 0 | ||
| 2794 | :zone ict:edt :dst t) | ||
| 2795 | :members | ||
| 2796 | (append | ||
| 2797 | ;; ==> (September 2, 1997 EDT) 9:00,9:20,9:40,10:00,10:20, | ||
| 2798 | ;; ... 16:00,16:20,16:40 | ||
| 2799 | (mapcan | ||
| 2800 | (lambda (h) | ||
| 2801 | (list | ||
| 2802 | (ical:date-time-variant dtstart :hour h :minute 0 :tz 'preserve) | ||
| 2803 | (ical:date-time-variant dtstart :hour h :minute 20 :tz 'preserve) | ||
| 2804 | (ical:date-time-variant dtstart :hour h :minute 40 :tz 'preserve))) | ||
| 2805 | (number-sequence 9 16)) | ||
| 2806 | ;; (September 3, 1997 EDT) 9:00,9:20,9:40,10:00,10:20, | ||
| 2807 | ;; ...16:00,16:20,16:40 | ||
| 2808 | (mapcan | ||
| 2809 | (lambda (h) | ||
| 2810 | (list | ||
| 2811 | (ical:date-time-variant dtstart :hour h :day 3 :minute 0 :tz 'preserve) | ||
| 2812 | (ical:date-time-variant dtstart :hour h :day 3 :minute 20 :tz 'preserve) | ||
| 2813 | (ical:date-time-variant dtstart :hour h :day 3 :minute 40 :tz 'preserve))) | ||
| 2814 | (number-sequence 9 16))) | ||
| 2815 | :source rfc5545-sec3.8.5.3/39) | ||
| 2816 | |||
| 2817 | (ict:rrule-test | ||
| 2818 | "RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO\n" | ||
| 2819 | "An example where the days generated makes a difference because of WKST: | ||
| 2820 | every other week on Tuesday and Sunday, week start Monday, for four recurrences" | ||
| 2821 | :tz ict:tz-eastern | ||
| 2822 | :dtstart (ical:make-date-time :year 1997 :month 8 :day 5 | ||
| 2823 | :hour 9 :minute 0 :second 0 | ||
| 2824 | :zone ict:edt :dst t) | ||
| 2825 | :members | ||
| 2826 | (list | ||
| 2827 | ;; ==> (1997 EDT) August 5,10,19,24 | ||
| 2828 | dtstart | ||
| 2829 | (ical:date-time-variant dtstart :day 10 :tz 'preserve) | ||
| 2830 | (ical:date-time-variant dtstart :day 19 :tz 'preserve) | ||
| 2831 | (ical:date-time-variant dtstart :day 24 :tz 'preserve)) | ||
| 2832 | :source rfc5545-sec3.8.5.3/40) | ||
| 2833 | |||
| 2834 | (ict:rrule-test | ||
| 2835 | "RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU\n" | ||
| 2836 | "An example where the days generated makes a difference because of WKST: | ||
| 2837 | every other week on Tuesday and Sunday, week start Sunday, for four recurrences" | ||
| 2838 | :tz ict:tz-eastern | ||
| 2839 | :dtstart (ical:make-date-time :year 1997 :month 8 :day 5 | ||
| 2840 | :hour 9 :minute 0 :second 0 | ||
| 2841 | :zone ict:edt :dst t) | ||
| 2842 | :members | ||
| 2843 | (list | ||
| 2844 | ;; ==> (1997 EDT) August 5,17,19,31 | ||
| 2845 | dtstart | ||
| 2846 | (ical:date-time-variant dtstart :day 17 :tz 'preserve) | ||
| 2847 | (ical:date-time-variant dtstart :day 19 :tz 'preserve) | ||
| 2848 | (ical:date-time-variant dtstart :day 31 :tz 'preserve)) | ||
| 2849 | :source rfc5545-sec3.8.5.3/41) | ||
| 2850 | |||
| 2851 | (ict:rrule-test | ||
| 2852 | "RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5\n" | ||
| 2853 | "An example where an invalid date (i.e., February 30) is ignored." | ||
| 2854 | :tz ict:tz-eastern | ||
| 2855 | :dtstart (ical:make-date-time :year 2007 :month 1 :day 15 | ||
| 2856 | :hour 9 :minute 0 :second 0 | ||
| 2857 | :zone ict:est :dst nil) | ||
| 2858 | :high (ical:make-date-time :year 2007 :month 4 :day 1 | ||
| 2859 | :hour 0 :minute 0 :second 0 | ||
| 2860 | :zone ict:edt :dst t) | ||
| 2861 | :members | ||
| 2862 | (list | ||
| 2863 | ;; ==> (2007 EST) January 15,30 | ||
| 2864 | ;; (2007 EST) February 15 | ||
| 2865 | ;; (2007 EDT) March 15,30 | ||
| 2866 | dtstart | ||
| 2867 | (ical:date-time-variant dtstart :day 30 :tz 'preserve) | ||
| 2868 | (ical:date-time-variant dtstart :month 2 :day 15 :tz 'preserve) | ||
| 2869 | (ical:date-time-variant dtstart :month 3 :day 15 :zone ict:edt :dst t) | ||
| 2870 | (ical:date-time-variant dtstart :month 3 :day 30 :zone ict:edt :dst t)) | ||
| 2871 | :nonmembers | ||
| 2872 | (list | ||
| 2873 | (ical:date-time-variant dtstart :month 2 :day 28 :tz 'preserve) | ||
| 2874 | (ical:date-time-variant dtstart :month 2 :day 30 :tz 'preserve)) | ||
| 2875 | :source rfc5545-sec3.8.5.3/42) | ||
| 2876 | |||
| 2877 | ;; Local Variables: | ||
| 2878 | ;; read-symbol-shorthands: (("ict:" . "icalendar-test-") ("icr:" . "icalendar-recur-") ("ical:" . "icalendar-")) | ||
| 2879 | ;; End: | ||
| 2880 | ;;; icalendar-recur-tests.el ends here | ||
diff --git a/test/lisp/calendar/icalendar-resources/import-legacy-function.ics b/test/lisp/calendar/icalendar-resources/import-legacy-function.ics new file mode 100644 index 00000000000..760131b8192 --- /dev/null +++ b/test/lisp/calendar/icalendar-resources/import-legacy-function.ics | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | BEGIN:VCALENDAR | ||
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | ||
| 3 | VERSION:2.0 | ||
| 4 | BEGIN:VEVENT | ||
| 5 | SUMMARY:Testing legacy `icalendar-import-format' function | ||
| 6 | DESCRIPTION:described | ||
| 7 | CLASS:private | ||
| 8 | LOCATION:somewhere | ||
| 9 | ORGANIZER;CN="Baz Foo":mailto:baz@example.com | ||
| 10 | STATUS:CONFIRMED | ||
| 11 | URL:http://example.com/foo/baz | ||
| 12 | UID:some-unique-id-here | ||
| 13 | DTSTART;VALUE=DATE-TIME:20250919T090000 | ||
| 14 | DTEND;VALUE=DATE-TIME:20250919T113000 | ||
| 15 | END:VEVENT | ||
| 16 | END:VCALENDAR | ||
diff --git a/test/lisp/calendar/icalendar-resources/import-legacy-vars.ics b/test/lisp/calendar/icalendar-resources/import-legacy-vars.ics new file mode 100644 index 00000000000..8aa80277b09 --- /dev/null +++ b/test/lisp/calendar/icalendar-resources/import-legacy-vars.ics | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | BEGIN:VCALENDAR | ||
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | ||
| 3 | VERSION:2.0 | ||
| 4 | BEGIN:VEVENT | ||
| 5 | SUMMARY:Testing legacy `icalendar-import-format*' vars | ||
| 6 | DESCRIPTION:described | ||
| 7 | CLASS:private | ||
| 8 | LOCATION:somewhere | ||
| 9 | ORGANIZER;CN="Baz Foo":mailto:baz@example.com | ||
| 10 | STATUS:CONFIRMED | ||
| 11 | URL:http://example.com/foo/baz | ||
| 12 | UID:some-unique-id-here | ||
| 13 | DTSTART;VALUE=DATE-TIME:20250919T090000 | ||
| 14 | DTEND;VALUE=DATE-TIME:20250919T113000 | ||
| 15 | END:VEVENT | ||
| 16 | END:VCALENDAR | ||
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics index 4efa8ffa133..53380b9734d 100644 --- a/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics +++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics | |||
| @@ -1,9 +1,8 @@ | |||
| 1 | BEGIN:VCALENDAR | 1 | BEGIN:VCALENDAR |
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN |
| 3 | VERSION:2.0 | 3 | VERSION:2.0 |
| 4 | BEGIN:VEVENT | 4 | BEGIN:VEVENT |
| 5 | SUMMARY:non-recurring allday | 5 | SUMMARY:non-recurring allday |
| 6 | DTSTART;VALUE=DATE-TIME:20030919 | 6 | DTSTART;VALUE=DATE:20030919 |
| 7 | END:VEVENT | 7 | END:VEVENT |
| 8 | END:VCALENDAR | 8 | END:VCALENDAR |
| 9 | |||
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics index 2996f494167..de402a29d26 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics +++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics | |||
| @@ -1,11 +1,10 @@ | |||
| 1 | BEGIN:VCALENDAR | 1 | BEGIN:VCALENDAR |
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN |
| 3 | VERSION:2.0 | 3 | VERSION:2.0 |
| 4 | BEGIN:VEVENT | 4 | BEGIN:VEVENT |
| 5 | DTSTART;VALUE=DATE:20040815 | 5 | DTSTART;VALUE=DATE:20040815 |
| 6 | DTEND;VALUE=DATE:20040816 | 6 | SUMMARY:Maria Himmelfahrt |
| 7 | SUMMARY:Maria Himmelfahrt | 7 | RRULE:FREQ=YEARLY |
| 8 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8 | 8 | END:VEVENT |
| 9 | END:VEVENT | 9 | END:VCALENDAR |
| 10 | END:VCALENDAR | 10 | |
| 11 | |||
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics index 5284bf42d8b..350e1aa0f24 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics +++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics | |||
| @@ -1,12 +1,11 @@ | |||
| 1 | BEGIN:VCALENDAR | 1 | BEGIN:VCALENDAR |
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN |
| 3 | VERSION:2.0 | 3 | VERSION:2.0 |
| 4 | BEGIN:VEVENT | 4 | BEGIN:VEVENT |
| 5 | SUMMARY:rrule daily with exceptions | 5 | SUMMARY:rrule daily with exceptions |
| 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 | 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 |
| 7 | DTEND;VALUE=DATE-TIME:20030919T113000 | 7 | DTEND;VALUE=DATE-TIME:20030919T113000 |
| 8 | RRULE:FREQ=DAILY;INTERVAL=2 | 8 | RRULE:FREQ=DAILY;INTERVAL=2 |
| 9 | EXDATE:20030921,20030925 | 9 | EXDATE;VALUE=DATE:20030921,20030925 |
| 10 | END:VEVENT | 10 | END:VEVENT |
| 11 | END:VCALENDAR | 11 | END:VCALENDAR |
| 12 | |||
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily.ics b/test/lisp/calendar/icalendar-resources/import-rrule-daily.ics index 6d013b0b4f6..93ed08065bc 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-daily.ics +++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily.ics | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | BEGIN:VCALENDAR | 1 | BEGIN:VCALENDAR |
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN |
| 3 | VERSION:2.0 | 3 | VERSION:2.0 |
| 4 | BEGIN:VEVENT | 4 | BEGIN:VEVENT |
| 5 | SUMMARY:rrule daily | 5 | SUMMARY:rrule daily |
| 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 | 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 |
| 7 | DTEND;VALUE=DATE-TIME:20030919T113000 | 7 | DTEND;VALUE=DATE-TIME:20030919T113000 |
| 8 | RRULE:FREQ=DAILY; | 8 | RRULE:FREQ=DAILY |
| 9 | END:VEVENT | 9 | END:VEVENT |
| 10 | END:VCALENDAR | 10 | END:VCALENDAR |
| 11 | 11 | ||
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics index b871658600a..9448ca058f8 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics +++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | BEGIN:VCALENDAR | 1 | BEGIN:VCALENDAR |
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN |
| 3 | VERSION:2.0 | 3 | VERSION:2.0 |
| 4 | BEGIN:VEVENT | 4 | BEGIN:VEVENT |
| 5 | SUMMARY:rrule monthly no end | 5 | SUMMARY:rrule monthly no end |
| 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 | 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 |
| 7 | DTEND;VALUE=DATE-TIME:20030919T113000 | 7 | DTEND;VALUE=DATE-TIME:20030919T113000 |
| 8 | RRULE:FREQ=MONTHLY; | 8 | RRULE:FREQ=MONTHLY |
| 9 | END:VEVENT | 9 | END:VEVENT |
| 10 | END:VCALENDAR | 10 | END:VCALENDAR |
| 11 | 11 | ||
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics index d8a1fe2e5af..0434765d613 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics +++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics | |||
| @@ -1,11 +1,10 @@ | |||
| 1 | BEGIN:VCALENDAR | 1 | BEGIN:VCALENDAR |
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN |
| 3 | VERSION:2.0 | 3 | VERSION:2.0 |
| 4 | BEGIN:VEVENT | 4 | BEGIN:VEVENT |
| 5 | SUMMARY:rrule monthly with end | 5 | SUMMARY:rrule monthly with end |
| 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 | 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 |
| 7 | DTEND;VALUE=DATE-TIME:20030919T113000 | 7 | DTEND;VALUE=DATE-TIME:20030919T113000 |
| 8 | RRULE:FREQ=MONTHLY;UNTIL=20050819; | 8 | RRULE:FREQ=MONTHLY;UNTIL=20050819 |
| 9 | END:VEVENT | 9 | END:VEVENT |
| 10 | END:VCALENDAR | 10 | END:VCALENDAR |
| 11 | |||
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics index c3f0b8ae933..44b6f44e2e0 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics +++ b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | BEGIN:VCALENDAR | 1 | BEGIN:VCALENDAR |
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN |
| 3 | VERSION:2.0 | 3 | VERSION:2.0 |
| 4 | BEGIN:VEVENT | 4 | BEGIN:VEVENT |
| 5 | SUMMARY:rrule weekly | 5 | SUMMARY:rrule weekly |
| 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 | 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 |
| 7 | DTEND;VALUE=DATE-TIME:20030919T113000 | 7 | DTEND;VALUE=DATE-TIME:20030919T113000 |
| 8 | RRULE:FREQ=WEEKLY; | 8 | RRULE:FREQ=WEEKLY |
| 9 | END:VEVENT | 9 | END:VEVENT |
| 10 | END:VCALENDAR | 10 | END:VCALENDAR |
| 11 | 11 | ||
diff --git a/test/lisp/calendar/icalendar-resources/import-time-format-12hr-blank.ics b/test/lisp/calendar/icalendar-resources/import-time-format-12hr-blank.ics new file mode 100644 index 00000000000..7f436df5391 --- /dev/null +++ b/test/lisp/calendar/icalendar-resources/import-time-format-12hr-blank.ics | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | BEGIN:VCALENDAR | ||
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | ||
| 3 | VERSION:2.0 | ||
| 4 | BEGIN:VEVENT | ||
| 5 | SUMMARY:12hr blank-padded | ||
| 6 | DTSTART;VALUE=DATE-TIME:20030919T090000 | ||
| 7 | DTEND;VALUE=DATE-TIME:20030919T113000 | ||
| 8 | END:VEVENT | ||
| 9 | END:VCALENDAR | ||
diff --git a/test/lisp/calendar/icalendar-resources/import-with-attachment.ics b/test/lisp/calendar/icalendar-resources/import-with-attachment.ics new file mode 100644 index 00000000000..0b1201714ef --- /dev/null +++ b/test/lisp/calendar/icalendar-resources/import-with-attachment.ics | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | BEGIN:VCALENDAR | ||
| 2 | PRODID:-//Emacs//NONSGML icalendar.el//EN | ||
| 3 | VERSION:2.0 | ||
| 4 | BEGIN:VEVENT | ||
| 5 | UID:f9fee9a0-1231-4984-9078-f1357db352db | ||
| 6 | SUMMARY:Has an attachment | ||
| 7 | ATTACH;VALUE=BINARY;FMTTYPE=text/plain;ENCODING=BASE64:R3JlZXRpbmdzISBJIGFt | ||
| 8 | IGEgYmFzZTY0LWVuY29kZWQgZmlsZQ== | ||
| 9 | DTSTART;VALUE=DATE-TIME:20030919T090000 | ||
| 10 | END:VEVENT | ||
| 11 | END:VCALENDAR | ||
diff --git a/test/lisp/calendar/icalendar-resources/import-with-timezone.ics b/test/lisp/calendar/icalendar-resources/import-with-timezone.ics index 110a9835e41..0db619e4f0a 100644 --- a/test/lisp/calendar/icalendar-resources/import-with-timezone.ics +++ b/test/lisp/calendar/icalendar-resources/import-with-timezone.ics | |||
| @@ -1,27 +1,27 @@ | |||
| 1 | BEGIN:VCALENDAR | 1 | BEGIN:VCALENDAR |
| 2 | BEGIN:VTIMEZONE | 2 | BEGIN:VTIMEZONE |
| 3 | TZID:fictional, nonexistent, arbitrary | 3 | TZID:fictional |
| 4 | BEGIN:STANDARD | 4 | BEGIN:STANDARD |
| 5 | DTSTART:20100101T000000 | 5 | DTSTART:20100101T000000 |
| 6 | TZOFFSETFROM:+0200 | 6 | TZOFFSETFROM:+0200 |
| 7 | TZOFFSETTO:-0200 | 7 | TZOFFSETTO:-0200 |
| 8 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=01 | 8 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=01 |
| 9 | END:STANDARD | 9 | END:STANDARD |
| 10 | BEGIN:DAYLIGHT | 10 | BEGIN:DAYLIGHT |
| 11 | DTSTART:20101201T000000 | 11 | DTSTART:20101201T000000 |
| 12 | TZOFFSETFROM:-0200 | 12 | TZOFFSETFROM:-0200 |
| 13 | TZOFFSETTO:+0200 | 13 | TZOFFSETTO:+0200 |
| 14 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 | 14 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 |
| 15 | END:DAYLIGHT | 15 | END:DAYLIGHT |
| 16 | END:VTIMEZONE | 16 | END:VTIMEZONE |
| 17 | BEGIN:VEVENT | 17 | BEGIN:VEVENT |
| 18 | SUMMARY:standardtime | 18 | SUMMARY:standardtime |
| 19 | DTSTART;TZID="fictional, nonexistent, arbitrary":20120115T120000 | 19 | DTSTART;TZID=fictional:20120115T120000 |
| 20 | DTEND;TZID="fictional, nonexistent, arbitrary":20120115T123000 | 20 | DTEND;TZID=fictional:20120115T123000 |
| 21 | END:VEVENT | 21 | END:VEVENT |
| 22 | BEGIN:VEVENT | 22 | BEGIN:VEVENT |
| 23 | SUMMARY:daylightsavingtime | 23 | SUMMARY:daylightsavingtime |
| 24 | DTSTART;TZID="fictional, nonexistent, arbitrary":20121215T120000 | 24 | DTSTART;TZID=fictional:20121215T120000 |
| 25 | DTEND;TZID="fictional, nonexistent, arbitrary":20121215T123000 | 25 | DTEND;TZID=fictional:20121215T123000 |
| 26 | END:VEVENT | 26 | END:VEVENT |
| 27 | END:VCALENDAR | 27 | END:VCALENDAR |
diff --git a/test/lisp/calendar/icalendar-tests.el b/test/lisp/calendar/icalendar-tests.el index fa1d1169ed6..bd2097b2fb8 100644 --- a/test/lisp/calendar/icalendar-tests.el +++ b/test/lisp/calendar/icalendar-tests.el | |||
| @@ -30,11 +30,34 @@ | |||
| 30 | ;; Note: Watch the trailing blank that is added on import. | 30 | ;; Note: Watch the trailing blank that is added on import. |
| 31 | 31 | ||
| 32 | ;;; Code: | 32 | ;;; Code: |
| 33 | |||
| 34 | (require 'ert) | 33 | (require 'ert) |
| 35 | (require 'ert-x) | 34 | (require 'ert-x) |
| 36 | (require 'icalendar) | 35 | (require 'icalendar) |
| 37 | 36 | ||
| 37 | ;; Some variables in the icalendar-* namespace have now been aliased to | ||
| 38 | ;; diary-icalendar-*: | ||
| 39 | (require 'diary-icalendar) | ||
| 40 | |||
| 41 | (defmacro ical:deftest-obsolete (name _ &rest args-and-body) | ||
| 42 | "Define NAME as an obsolete icalendar.el test." | ||
| 43 | (let (args body) | ||
| 44 | (while (not body) | ||
| 45 | (cond ((stringp (car args-and-body)) | ||
| 46 | (push (pop args-and-body) args)) ; docstring | ||
| 47 | ((keywordp (car args-and-body)) | ||
| 48 | (push (pop args-and-body) args) ; keyword | ||
| 49 | (push (pop args-and-body) args)) ; value | ||
| 50 | (t | ||
| 51 | (setq body args-and-body) | ||
| 52 | (setq args (nreverse args))))) | ||
| 53 | `(ert-deftest ,name () ,@args | ||
| 54 | ;; These values were used by icalendar.el when tests were written: | ||
| 55 | (let ((icalendar-recurring-start-year 2005) | ||
| 56 | (icalendar-vcalendar-prodid "-//Emacs//NONSGML icalendar.el//EN") | ||
| 57 | (icalendar-uid-format "emacs%t%c") | ||
| 58 | (icalendar-export-hidden-diary-entries t)) | ||
| 59 | ,@body)))) | ||
| 60 | |||
| 38 | ;; ====================================================================== | 61 | ;; ====================================================================== |
| 39 | ;; Helpers | 62 | ;; Helpers |
| 40 | ;; ====================================================================== | 63 | ;; ====================================================================== |
| @@ -75,7 +98,7 @@ | |||
| 75 | ;; Tests of functions | 98 | ;; Tests of functions |
| 76 | ;; ====================================================================== | 99 | ;; ====================================================================== |
| 77 | 100 | ||
| 78 | (ert-deftest icalendar--create-uid () | 101 | (ical:deftest-obsolete icalendar--create-uid () |
| 79 | "Test for `icalendar--create-uid'." | 102 | "Test for `icalendar--create-uid'." |
| 80 | (let* ((icalendar-uid-format "xxx-%c-%h-%u-%s") | 103 | (let* ((icalendar-uid-format "xxx-%c-%h-%u-%s") |
| 81 | (icalendar--uid-count 77) | 104 | (icalendar--uid-count 77) |
| @@ -92,7 +115,7 @@ | |||
| 92 | (should (string= (concat "yyyDTSTARTyyy") | 115 | (should (string= (concat "yyyDTSTARTyyy") |
| 93 | (icalendar--create-uid entry-full contents))))) | 116 | (icalendar--create-uid entry-full contents))))) |
| 94 | 117 | ||
| 95 | (ert-deftest icalendar-convert-anniversary-to-ical () | 118 | (ical:deftest-obsolete icalendar-convert-anniversary-to-ical () |
| 96 | "Test method for `icalendar--convert-anniversary-to-ical'." | 119 | "Test method for `icalendar--convert-anniversary-to-ical'." |
| 97 | (let* ((calendar-date-style 'iso) | 120 | (let* ((calendar-date-style 'iso) |
| 98 | result) | 121 | result) |
| @@ -106,7 +129,7 @@ | |||
| 106 | (car result))) | 129 | (car result))) |
| 107 | (should (string= "g" (cdr result))))) | 130 | (should (string= "g" (cdr result))))) |
| 108 | 131 | ||
| 109 | (ert-deftest icalendar--convert-cyclic-to-ical () | 132 | (ical:deftest-obsolete icalendar--convert-cyclic-to-ical () |
| 110 | "Test method for `icalendar--convert-cyclic-to-ical'." | 133 | "Test method for `icalendar--convert-cyclic-to-ical'." |
| 111 | (let* ((calendar-date-style 'iso) | 134 | (let* ((calendar-date-style 'iso) |
| 112 | result) | 135 | result) |
| @@ -119,7 +142,7 @@ | |||
| 119 | (car result))) | 142 | (car result))) |
| 120 | (should (string= "Sommerferien" (cdr result))))) | 143 | (should (string= "Sommerferien" (cdr result))))) |
| 121 | 144 | ||
| 122 | (ert-deftest icalendar--convert-block-to-ical () | 145 | (ical:deftest-obsolete icalendar--convert-block-to-ical () |
| 123 | "Test method for `icalendar--convert-block-to-ical'." | 146 | "Test method for `icalendar--convert-block-to-ical'." |
| 124 | (let* ((calendar-date-style 'iso) | 147 | (let* ((calendar-date-style 'iso) |
| 125 | result) | 148 | result) |
| @@ -132,7 +155,7 @@ | |||
| 132 | (car result))) | 155 | (car result))) |
| 133 | (should (string= "Sommerferien" (cdr result))))) | 156 | (should (string= "Sommerferien" (cdr result))))) |
| 134 | 157 | ||
| 135 | (ert-deftest icalendar--convert-float-to-ical () | 158 | (ical:deftest-obsolete icalendar--convert-float-to-ical () |
| 136 | "Test method for `icalendar--convert-float-to-ical'." | 159 | "Test method for `icalendar--convert-float-to-ical'." |
| 137 | ;; See Bug#78085 | 160 | ;; See Bug#78085 |
| 138 | (let* ((calendar-date-style 'iso) | 161 | (let* ((calendar-date-style 'iso) |
| @@ -148,7 +171,7 @@ | |||
| 148 | (car result))) | 171 | (car result))) |
| 149 | (should (string= "1st Sat/month" (cdr result))))) | 172 | (should (string= "1st Sat/month" (cdr result))))) |
| 150 | 173 | ||
| 151 | (ert-deftest icalendar--convert-yearly-to-ical () | 174 | (ical:deftest-obsolete icalendar--convert-yearly-to-ical () |
| 152 | "Test method for `icalendar--convert-yearly-to-ical'." | 175 | "Test method for `icalendar--convert-yearly-to-ical'." |
| 153 | (let* ((calendar-date-style 'iso) | 176 | (let* ((calendar-date-style 'iso) |
| 154 | result | 177 | result |
| @@ -164,7 +187,7 @@ | |||
| 164 | (car result))) | 187 | (car result))) |
| 165 | (should (string= "Tag der Arbeit" (cdr result))))) | 188 | (should (string= "Tag der Arbeit" (cdr result))))) |
| 166 | 189 | ||
| 167 | (ert-deftest icalendar--convert-weekly-to-ical () | 190 | (ical:deftest-obsolete icalendar--convert-weekly-to-ical () |
| 168 | "Test method for `icalendar--convert-weekly-to-ical'." | 191 | "Test method for `icalendar--convert-weekly-to-ical'." |
| 169 | (let* ((calendar-date-style 'iso) | 192 | (let* ((calendar-date-style 'iso) |
| 170 | result | 193 | result |
| @@ -179,7 +202,7 @@ | |||
| 179 | (car result))) | 202 | (car result))) |
| 180 | (should (string= "subject" (cdr result))))) | 203 | (should (string= "subject" (cdr result))))) |
| 181 | 204 | ||
| 182 | (ert-deftest icalendar--convert-sexp-to-ical () | 205 | (ical:deftest-obsolete icalendar--convert-sexp-to-ical () |
| 183 | "Test method for `icalendar--convert-sexp-to-ical'." | 206 | "Test method for `icalendar--convert-sexp-to-ical'." |
| 184 | (let* (result | 207 | (let* (result |
| 185 | (icalendar-export-sexp-enumeration-days 3)) | 208 | (icalendar-export-sexp-enumeration-days 3)) |
| @@ -192,7 +215,7 @@ | |||
| 192 | (should (string-match "Hebrew date (until sunset): .*" (cdr i)))) | 215 | (should (string-match "Hebrew date (until sunset): .*" (cdr i)))) |
| 193 | result))) | 216 | result))) |
| 194 | 217 | ||
| 195 | (ert-deftest icalendar--convert-to-ical () | 218 | (ical:deftest-obsolete icalendar--convert-to-ical () |
| 196 | "Test method for `icalendar--convert-to-ical'." | 219 | "Test method for `icalendar--convert-to-ical'." |
| 197 | (let* (result | 220 | (let* (result |
| 198 | (icalendar-export-sexp-enumerate-all t) | 221 | (icalendar-export-sexp-enumerate-all t) |
| @@ -216,7 +239,7 @@ | |||
| 216 | (car (car result)))) | 239 | (car (car result)))) |
| 217 | (should (string-match "Newton's birthday" (cdr (car result)))))) | 240 | (should (string-match "Newton's birthday" (cdr (car result)))))) |
| 218 | 241 | ||
| 219 | (ert-deftest icalendar--parse-vtimezone () | 242 | (ical:deftest-obsolete icalendar--parse-vtimezone () |
| 220 | "Test method for `icalendar--parse-vtimezone'." | 243 | "Test method for `icalendar--parse-vtimezone'." |
| 221 | (let (vtimezone result) | 244 | (let (vtimezone result) |
| 222 | ;; testcase: valid timezone with rrule | 245 | ;; testcase: valid timezone with rrule |
| @@ -290,7 +313,7 @@ END:VTIMEZONE | |||
| 290 | ;; FIXME: add testcase that covers changes for fix of bug#34315 | 313 | ;; FIXME: add testcase that covers changes for fix of bug#34315 |
| 291 | )) | 314 | )) |
| 292 | 315 | ||
| 293 | (ert-deftest icalendar--convert-ordinary-to-ical () | 316 | (ical:deftest-obsolete icalendar--convert-ordinary-to-ical () |
| 294 | "Test method for `icalendar--convert-ordinary-to-ical'." | 317 | "Test method for `icalendar--convert-ordinary-to-ical'." |
| 295 | (let* ((calendar-date-style 'iso) | 318 | (let* ((calendar-date-style 'iso) |
| 296 | result) | 319 | result) |
| @@ -328,7 +351,7 @@ END:VTIMEZONE | |||
| 328 | (car result))) | 351 | (car result))) |
| 329 | (should (string= "s" (cdr result))))) | 352 | (should (string= "s" (cdr result))))) |
| 330 | 353 | ||
| 331 | (ert-deftest icalendar--diarytime-to-isotime () | 354 | (ical:deftest-obsolete icalendar--diarytime-to-isotime () |
| 332 | "Test method for `icalendar--diarytime-to-isotime'." | 355 | "Test method for `icalendar--diarytime-to-isotime'." |
| 333 | (should (string= "T011500" | 356 | (should (string= "T011500" |
| 334 | (icalendar--diarytime-to-isotime "01:15" ""))) | 357 | (icalendar--diarytime-to-isotime "01:15" ""))) |
| @@ -361,7 +384,7 @@ END:VTIMEZONE | |||
| 361 | (should (string= "T150000" | 384 | (should (string= "T150000" |
| 362 | (icalendar--diarytime-to-isotime "3" "pm")))) | 385 | (icalendar--diarytime-to-isotime "3" "pm")))) |
| 363 | 386 | ||
| 364 | (ert-deftest icalendar--datetime-to-diary-date () | 387 | (ical:deftest-obsolete icalendar--datetime-to-diary-date () |
| 365 | "Test method for `icalendar--datetime-to-diary-date'." | 388 | "Test method for `icalendar--datetime-to-diary-date'." |
| 366 | (let* ((datetime '(59 59 23 31 12 2008)) | 389 | (let* ((datetime '(59 59 23 31 12 2008)) |
| 367 | (calendar-date-style 'iso)) | 390 | (calendar-date-style 'iso)) |
| @@ -374,7 +397,7 @@ END:VTIMEZONE | |||
| 374 | (should (string= "12 31 2008" | 397 | (should (string= "12 31 2008" |
| 375 | (icalendar--datetime-to-diary-date datetime))))) | 398 | (icalendar--datetime-to-diary-date datetime))))) |
| 376 | 399 | ||
| 377 | (ert-deftest icalendar--datestring-to-isodate () | 400 | (ical:deftest-obsolete icalendar--datestring-to-isodate () |
| 378 | "Test method for `icalendar--datestring-to-isodate'." | 401 | "Test method for `icalendar--datestring-to-isodate'." |
| 379 | (let ((calendar-date-style 'iso)) | 402 | (let ((calendar-date-style 'iso)) |
| 380 | ;; numeric iso | 403 | ;; numeric iso |
| @@ -427,7 +450,7 @@ END:VTIMEZONE | |||
| 427 | (icalendar--datestring-to-isodate "2021 Feb 11" nil 80))) | 450 | (icalendar--datestring-to-isodate "2021 Feb 11" nil 80))) |
| 428 | )) | 451 | )) |
| 429 | 452 | ||
| 430 | (ert-deftest icalendar--first-weekday-of-year () | 453 | (ical:deftest-obsolete icalendar--first-weekday-of-year () |
| 431 | "Test method for `icalendar-first-weekday-of-year'." | 454 | "Test method for `icalendar-first-weekday-of-year'." |
| 432 | (should (eq 1 (icalendar-first-weekday-of-year "TU" 2008))) | 455 | (should (eq 1 (icalendar-first-weekday-of-year "TU" 2008))) |
| 433 | (should (eq 3 (icalendar-first-weekday-of-year "WE" 2007))) | 456 | (should (eq 3 (icalendar-first-weekday-of-year "WE" 2007))) |
| @@ -439,7 +462,7 @@ END:VTIMEZONE | |||
| 439 | (should (eq 3 (icalendar-first-weekday-of-year "MO" 2000))) | 462 | (should (eq 3 (icalendar-first-weekday-of-year "MO" 2000))) |
| 440 | (should (eq 1 (icalendar-first-weekday-of-year "TH" 1970)))) | 463 | (should (eq 1 (icalendar-first-weekday-of-year "TH" 1970)))) |
| 441 | 464 | ||
| 442 | (ert-deftest icalendar--import-format-sample () | 465 | (ical:deftest-obsolete icalendar--import-format-sample () |
| 443 | "Test method for `icalendar-import-format-sample'." | 466 | "Test method for `icalendar-import-format-sample'." |
| 444 | (should (string= (concat "SUMMARY='a' DESCRIPTION='b' LOCATION='c' " | 467 | (should (string= (concat "SUMMARY='a' DESCRIPTION='b' LOCATION='c' " |
| 445 | "ORGANIZER='d' STATUS='' URL='' CLASS=''") | 468 | "ORGANIZER='d' STATUS='' URL='' CLASS=''") |
| @@ -455,7 +478,7 @@ DESCRIPTION:b | |||
| 455 | END:VEVENT | 478 | END:VEVENT |
| 456 | "))))) | 479 | "))))) |
| 457 | 480 | ||
| 458 | (ert-deftest icalendar--format-ical-event () | 481 | (ical:deftest-obsolete icalendar--format-ical-event () |
| 459 | "Test `icalendar--format-ical-event'." | 482 | "Test `icalendar--format-ical-event'." |
| 460 | (let ((icalendar-import-format "%s%d%l%o%t%u%c") | 483 | (let ((icalendar-import-format "%s%d%l%o%t%u%c") |
| 461 | (icalendar-import-format-summary "SUM %s") | 484 | (icalendar-import-format-summary "SUM %s") |
| @@ -493,7 +516,7 @@ END:VEVENT | |||
| 493 | (should (string= "-sum-des-loc-org-nil-nil-nil-" | 516 | (should (string= "-sum-des-loc-org-nil-nil-nil-" |
| 494 | (icalendar--format-ical-event event))))) | 517 | (icalendar--format-ical-event event))))) |
| 495 | 518 | ||
| 496 | (ert-deftest icalendar--parse-summary-and-rest () | 519 | (ical:deftest-obsolete icalendar--parse-summary-and-rest () |
| 497 | "Test `icalendar--parse-summary-and-rest'." | 520 | "Test `icalendar--parse-summary-and-rest'." |
| 498 | (let ((icalendar-import-format "%s%d%l%o%t%u%c") | 521 | (let ((icalendar-import-format "%s%d%l%o%t%u%c") |
| 499 | (icalendar-import-format-summary "SUM %s") | 522 | (icalendar-import-format-summary "SUM %s") |
| @@ -521,7 +544,7 @@ END:VEVENT | |||
| 521 | (should (not result)) | 544 | (should (not result)) |
| 522 | )) | 545 | )) |
| 523 | 546 | ||
| 524 | (ert-deftest icalendar--decode-isodatetime () | 547 | (ical:deftest-obsolete icalendar--decode-isodatetime () |
| 525 | "Test `icalendar--decode-isodatetime'." | 548 | "Test `icalendar--decode-isodatetime'." |
| 526 | (let ((tz (getenv "TZ"))) | 549 | (let ((tz (getenv "TZ"))) |
| 527 | (unwind-protect | 550 | (unwind-protect |
| @@ -571,7 +594,7 @@ END:VEVENT | |||
| 571 | ;; restore time-zone even if something went terribly wrong | 594 | ;; restore time-zone even if something went terribly wrong |
| 572 | (setenv "TZ" tz)))) | 595 | (setenv "TZ" tz)))) |
| 573 | 596 | ||
| 574 | (ert-deftest icalendar--convert-tz-offset () | 597 | (ical:deftest-obsolete icalendar--convert-tz-offset () |
| 575 | "Test `icalendar--convert-tz-offset'." | 598 | "Test `icalendar--convert-tz-offset'." |
| 576 | (let ((tz (getenv "TZ"))) | 599 | (let ((tz (getenv "TZ"))) |
| 577 | (unwind-protect | 600 | (unwind-protect |
| @@ -634,7 +657,7 @@ END:VEVENT | |||
| 634 | ;; restore time-zone even if something went terribly wrong | 657 | ;; restore time-zone even if something went terribly wrong |
| 635 | (setenv "TZ" tz)))) | 658 | (setenv "TZ" tz)))) |
| 636 | 659 | ||
| 637 | (ert-deftest icalendar--decode-isoduration () | 660 | (ical:deftest-obsolete icalendar--decode-isoduration () |
| 638 | "Test `icalendar--decode-isoduration'." | 661 | "Test `icalendar--decode-isoduration'." |
| 639 | 662 | ||
| 640 | ;; testcase: 7 days | 663 | ;; testcase: 7 days |
| @@ -764,7 +787,7 @@ END:VCALENDAR | |||
| 764 | ;; cleanup!! | 787 | ;; cleanup!! |
| 765 | (kill-buffer (find-buffer-visiting temp-file))))) | 788 | (kill-buffer (find-buffer-visiting temp-file))))) |
| 766 | 789 | ||
| 767 | (ert-deftest icalendar-export-ordinary-no-time () | 790 | (ical:deftest-obsolete icalendar-export-ordinary-no-time () |
| 768 | "Perform export test." | 791 | "Perform export test." |
| 769 | 792 | ||
| 770 | (let ((icalendar-export-hidden-diary-entries nil)) | 793 | (let ((icalendar-export-hidden-diary-entries nil)) |
| @@ -783,7 +806,7 @@ DTEND;VALUE=DATE:20001004 | |||
| 783 | SUMMARY:ordinary no time | 806 | SUMMARY:ordinary no time |
| 784 | ")) | 807 | ")) |
| 785 | 808 | ||
| 786 | (ert-deftest icalendar-export-ordinary () | 809 | (ical:deftest-obsolete icalendar-export-ordinary () |
| 787 | "Perform export test." | 810 | "Perform export test." |
| 788 | 811 | ||
| 789 | (icalendar-tests--test-export | 812 | (icalendar-tests--test-export |
| @@ -812,7 +835,7 @@ DTEND;VALUE=DATE-TIME:20001003T173000 | |||
| 812 | SUMMARY:ordinary with time 3 | 835 | SUMMARY:ordinary with time 3 |
| 813 | ")) | 836 | ")) |
| 814 | 837 | ||
| 815 | (ert-deftest icalendar-export-multiline () | 838 | (ical:deftest-obsolete icalendar-export-multiline () |
| 816 | "Perform export test." | 839 | "Perform export test." |
| 817 | 840 | ||
| 818 | ;; multiline -- FIXME!!! | 841 | ;; multiline -- FIXME!!! |
| @@ -830,7 +853,7 @@ DESCRIPTION: | |||
| 830 | 17:30 multiline continued FIXME | 853 | 17:30 multiline continued FIXME |
| 831 | ")) | 854 | ")) |
| 832 | 855 | ||
| 833 | (ert-deftest icalendar-export-weekly-by-day () | 856 | (ical:deftest-obsolete icalendar-export-weekly-by-day () |
| 834 | "Perform export test." | 857 | "Perform export test." |
| 835 | 858 | ||
| 836 | ;; weekly by day | 859 | ;; weekly by day |
| @@ -854,7 +877,7 @@ RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=MO | |||
| 854 | SUMMARY:weekly by day with start and end time | 877 | SUMMARY:weekly by day with start and end time |
| 855 | ")) | 878 | ")) |
| 856 | 879 | ||
| 857 | (ert-deftest icalendar-export-yearly () | 880 | (ical:deftest-obsolete icalendar-export-yearly () |
| 858 | "Perform export test." | 881 | "Perform export test." |
| 859 | ;; yearly | 882 | ;; yearly |
| 860 | (icalendar-tests--test-export | 883 | (icalendar-tests--test-export |
| @@ -867,7 +890,7 @@ RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYMONTHDAY=1 | |||
| 867 | SUMMARY:yearly no time | 890 | SUMMARY:yearly no time |
| 868 | ")) | 891 | ")) |
| 869 | 892 | ||
| 870 | (ert-deftest icalendar-export-anniversary () | 893 | (ical:deftest-obsolete icalendar-export-anniversary () |
| 871 | "Perform export test." | 894 | "Perform export test." |
| 872 | ;; anniversaries | 895 | ;; anniversaries |
| 873 | (icalendar-tests--test-export | 896 | (icalendar-tests--test-export |
| @@ -889,7 +912,7 @@ RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYMONTHDAY=03 | |||
| 889 | SUMMARY:anniversary with time | 912 | SUMMARY:anniversary with time |
| 890 | ")) | 913 | ")) |
| 891 | 914 | ||
| 892 | (ert-deftest icalendar-export-block () | 915 | (ical:deftest-obsolete icalendar-export-block () |
| 893 | "Perform export test." | 916 | "Perform export test." |
| 894 | ;; block | 917 | ;; block |
| 895 | (icalendar-tests--test-export | 918 | (icalendar-tests--test-export |
| @@ -919,7 +942,7 @@ RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20010706 | |||
| 919 | SUMMARY:block no end time | 942 | SUMMARY:block no end time |
| 920 | ")) | 943 | ")) |
| 921 | 944 | ||
| 922 | (ert-deftest icalendar-export-alarms () | 945 | (ical:deftest-obsolete icalendar-export-alarms () |
| 923 | "Perform export test with different settings for exporting alarms." | 946 | "Perform export test with different settings for exporting alarms." |
| 924 | ;; no alarm | 947 | ;; no alarm |
| 925 | (icalendar-tests--test-export | 948 | (icalendar-tests--test-export |
| @@ -1016,7 +1039,7 @@ END:VALARM | |||
| 1016 | (defun icalendar-tests--diary-float (&rest args) | 1039 | (defun icalendar-tests--diary-float (&rest args) |
| 1017 | (apply #'diary-float args)) | 1040 | (apply #'diary-float args)) |
| 1018 | 1041 | ||
| 1019 | (ert-deftest icalendar-export-bug-56241-dotted-pair () | 1042 | (ical:deftest-obsolete icalendar-export-bug-56241-dotted-pair () |
| 1020 | "See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=56241#5" | 1043 | "See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=56241#5" |
| 1021 | ;; This test started failing early July 2023 without any apparent change | 1044 | ;; This test started failing early July 2023 without any apparent change |
| 1022 | ;; to the underlying code, so is probably sensitive to the current date. | 1045 | ;; to the underlying code, so is probably sensitive to the current date. |
| @@ -1029,7 +1052,7 @@ END:VALARM | |||
| 1029 | "%%(icalendar-tests--diary-float 7 0 1) First Sunday in July 2")))) | 1052 | "%%(icalendar-tests--diary-float 7 0 1) First Sunday in July 2")))) |
| 1030 | 1053 | ||
| 1031 | 1054 | ||
| 1032 | ;; (ert-deftest icalendar-export-bug-56241-sexp-does-not-match () | 1055 | ;; (ical:deftest-obsolete icalendar-export-bug-56241-sexp-does-not-match () |
| 1033 | ;; "Reported in #bug56241 -- needs to be fixed!" | 1056 | ;; "Reported in #bug56241 -- needs to be fixed!" |
| 1034 | ;; (let ((icalendar-export-sexp-enumeration-days 0)) | 1057 | ;; (let ((icalendar-export-sexp-enumeration-days 0)) |
| 1035 | ;; (mapc (lambda (diary-string) | 1058 | ;; (mapc (lambda (diary-string) |
| @@ -1038,7 +1061,7 @@ END:VALARM | |||
| 1038 | ;; '("%%(diary-float 7 0 1) First Sunday in July 1" | 1061 | ;; '("%%(diary-float 7 0 1) First Sunday in July 1" |
| 1039 | ;; "%%(icalendar-tests--diary-float 7 0 1) First Sunday in July 2")))) | 1062 | ;; "%%(icalendar-tests--diary-float 7 0 1) First Sunday in July 2")))) |
| 1040 | 1063 | ||
| 1041 | (ert-deftest icalendar-export-bug-56241-nested-sexps () | 1064 | (ical:deftest-obsolete icalendar-export-bug-56241-nested-sexps () |
| 1042 | "Reported in #bug56241 -- needs to be fixed!" | 1065 | "Reported in #bug56241 -- needs to be fixed!" |
| 1043 | (let ((icalendar-export-sexp-enumeration-days 366)) | 1066 | (let ((icalendar-export-sexp-enumeration-days 366)) |
| 1044 | (mapc (lambda (diary-string) | 1067 | (mapc (lambda (diary-string) |
| @@ -1130,7 +1153,7 @@ Argument EXPECTED-OUTPUT file containing expected diary string." | |||
| 1130 | (should (string= expected-output result))) | 1153 | (should (string= expected-output result))) |
| 1131 | (kill-buffer (find-buffer-visiting temp-file))))) | 1154 | (kill-buffer (find-buffer-visiting temp-file))))) |
| 1132 | 1155 | ||
| 1133 | (ert-deftest icalendar-import-non-recurring () | 1156 | (ical:deftest-obsolete icalendar-import-non-recurring () |
| 1134 | "Perform standard import tests." | 1157 | "Perform standard import tests." |
| 1135 | (icalendar-tests--test-import "import-non-recurring-1.ics" | 1158 | (icalendar-tests--test-import "import-non-recurring-1.ics" |
| 1136 | "import-non-recurring-1.diary-iso" | 1159 | "import-non-recurring-1.diary-iso" |
| @@ -1158,7 +1181,7 @@ Argument EXPECTED-OUTPUT file containing expected diary string." | |||
| 1158 | "import-non-recurring-another-example.diary-american")) | 1181 | "import-non-recurring-another-example.diary-american")) |
| 1159 | 1182 | ||
| 1160 | 1183 | ||
| 1161 | (ert-deftest icalendar-import-rrule () | 1184 | (ical:deftest-obsolete icalendar-import-rrule () |
| 1162 | (icalendar-tests--test-import "import-rrule-daily.ics" | 1185 | (icalendar-tests--test-import "import-rrule-daily.ics" |
| 1163 | "import-rrule-daily.diary-iso" | 1186 | "import-rrule-daily.diary-iso" |
| 1164 | "import-rrule-daily.diary-european" | 1187 | "import-rrule-daily.diary-european" |
| @@ -1217,7 +1240,7 @@ Argument EXPECTED-OUTPUT file containing expected diary string." | |||
| 1217 | "import-rrule-count-every-second-year.diary-american") | 1240 | "import-rrule-count-every-second-year.diary-american") |
| 1218 | ) | 1241 | ) |
| 1219 | 1242 | ||
| 1220 | (ert-deftest icalendar-import-duration () | 1243 | (ical:deftest-obsolete icalendar-import-duration () |
| 1221 | (icalendar-tests--test-import "import-duration.ics" | 1244 | (icalendar-tests--test-import "import-duration.ics" |
| 1222 | "import-duration.diary-iso" | 1245 | "import-duration.diary-iso" |
| 1223 | "import-duration.diary-european" | 1246 | "import-duration.diary-european" |
| @@ -1228,41 +1251,41 @@ Argument EXPECTED-OUTPUT file containing expected diary string." | |||
| 1228 | "import-duration-2.diary-european" | 1251 | "import-duration-2.diary-european" |
| 1229 | "import-duration-2.diary-american")) | 1252 | "import-duration-2.diary-american")) |
| 1230 | 1253 | ||
| 1231 | (ert-deftest icalendar-import-bug-6766 () | 1254 | (ical:deftest-obsolete icalendar-import-bug-6766 () |
| 1232 | ;;bug#6766 -- multiple byday values in a weekly rrule | 1255 | ;;bug#6766 -- multiple byday values in a weekly rrule |
| 1233 | (icalendar-tests--test-import "import-bug-6766.ics" | 1256 | (icalendar-tests--test-import "import-bug-6766.ics" |
| 1234 | "import-bug-6766.diary-iso" | 1257 | "import-bug-6766.diary-iso" |
| 1235 | "import-bug-6766.diary-european" | 1258 | "import-bug-6766.diary-european" |
| 1236 | "import-bug-6766.diary-american")) | 1259 | "import-bug-6766.diary-american")) |
| 1237 | 1260 | ||
| 1238 | (ert-deftest icalendar-import-bug-24199 () | 1261 | (ical:deftest-obsolete icalendar-import-bug-24199 () |
| 1239 | ;;bug#24199 -- monthly rule with byday-clause | 1262 | ;;bug#24199 -- monthly rule with byday-clause |
| 1240 | (icalendar-tests--test-import "import-bug-24199.ics" | 1263 | (icalendar-tests--test-import "import-bug-24199.ics" |
| 1241 | "import-bug-24199.diary-iso" | 1264 | "import-bug-24199.diary-iso" |
| 1242 | "import-bug-24199.diary-european" | 1265 | "import-bug-24199.diary-european" |
| 1243 | "import-bug-24199.diary-american")) | 1266 | "import-bug-24199.diary-american")) |
| 1244 | 1267 | ||
| 1245 | (ert-deftest icalendar-import-bug-33277 () | 1268 | (ical:deftest-obsolete icalendar-import-bug-33277 () |
| 1246 | ;;bug#33277 -- start time equals end time | 1269 | ;;bug#33277 -- start time equals end time |
| 1247 | (icalendar-tests--test-import "import-bug-33277.ics" | 1270 | (icalendar-tests--test-import "import-bug-33277.ics" |
| 1248 | "import-bug-33277.diary-iso" | 1271 | "import-bug-33277.diary-iso" |
| 1249 | "import-bug-33277.diary-european" | 1272 | "import-bug-33277.diary-european" |
| 1250 | "import-bug-33277.diary-american")) | 1273 | "import-bug-33277.diary-american")) |
| 1251 | 1274 | ||
| 1252 | (ert-deftest icalendar-import-multiple-vcalendars () | 1275 | (ical:deftest-obsolete icalendar-import-multiple-vcalendars () |
| 1253 | (icalendar-tests--test-import "import-multiple-vcalendars.ics" | 1276 | (icalendar-tests--test-import "import-multiple-vcalendars.ics" |
| 1254 | "import-multiple-vcalendars.diary-iso" | 1277 | "import-multiple-vcalendars.diary-iso" |
| 1255 | "import-multiple-vcalendars.diary-european" | 1278 | "import-multiple-vcalendars.diary-european" |
| 1256 | "import-multiple-vcalendars.diary-american")) | 1279 | "import-multiple-vcalendars.diary-american")) |
| 1257 | 1280 | ||
| 1258 | (ert-deftest icalendar-import-with-uid () | 1281 | (ical:deftest-obsolete icalendar-import-with-uid () |
| 1259 | "Perform import test with uid." | 1282 | "Perform import test with uid." |
| 1260 | (icalendar-tests--test-import "import-with-uid.ics" | 1283 | (icalendar-tests--test-import "import-with-uid.ics" |
| 1261 | "import-with-uid.diary-iso" | 1284 | "import-with-uid.diary-iso" |
| 1262 | "import-with-uid.diary-european" | 1285 | "import-with-uid.diary-european" |
| 1263 | "import-with-uid.diary-american")) | 1286 | "import-with-uid.diary-american")) |
| 1264 | 1287 | ||
| 1265 | (ert-deftest icalendar-import-with-timezone () | 1288 | (ical:deftest-obsolete icalendar-import-with-timezone () |
| 1266 | ;; This is known to fail on MS-Windows, because the test assumes | 1289 | ;; This is known to fail on MS-Windows, because the test assumes |
| 1267 | ;; Posix features of specifying DST rules. | 1290 | ;; Posix features of specifying DST rules. |
| 1268 | :expected-result (if (memq system-type '(windows-nt ms-dos)) | 1291 | :expected-result (if (memq system-type '(windows-nt ms-dos)) |
| @@ -1334,7 +1357,7 @@ Argument INPUT icalendar event string." | |||
| 1334 | (set-buffer-modified-p nil) | 1357 | (set-buffer-modified-p nil) |
| 1335 | (kill-buffer (current-buffer)))))))) | 1358 | (kill-buffer (current-buffer)))))))) |
| 1336 | 1359 | ||
| 1337 | (ert-deftest icalendar-cycle () | 1360 | (ical:deftest-obsolete icalendar-cycle () |
| 1338 | "Perform cycling tests. | 1361 | "Perform cycling tests. |
| 1339 | Take care to avoid auto-generated UIDs here." | 1362 | Take care to avoid auto-generated UIDs here." |
| 1340 | (icalendar-tests--test-cycle | 1363 | (icalendar-tests--test-cycle |
| @@ -1363,7 +1386,7 @@ SUMMARY:and diary-anniversary | |||
| 1363 | ;; ====================================================================== | 1386 | ;; ====================================================================== |
| 1364 | ;; Real world | 1387 | ;; Real world |
| 1365 | ;; ====================================================================== | 1388 | ;; ====================================================================== |
| 1366 | (ert-deftest icalendar-real-world () | 1389 | (ical:deftest-obsolete icalendar-real-world () |
| 1367 | "Perform real-world tests, as gathered from problem reports." | 1390 | "Perform real-world tests, as gathered from problem reports." |
| 1368 | ;; This is known to fail on MS-Windows, since it doesn't support DST | 1391 | ;; This is known to fail on MS-Windows, since it doesn't support DST |
| 1369 | ;; specification with month and day. | 1392 | ;; specification with month and day. |
| @@ -1506,7 +1529,7 @@ RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=09;BYMONTHDAY=21 | |||
| 1506 | SUMMARY:ff birthday (%d years old)") | 1529 | SUMMARY:ff birthday (%d years old)") |
| 1507 | 1530 | ||
| 1508 | ;; FIXME: this testcase verifies that icalendar-export fails to | 1531 | ;; FIXME: this testcase verifies that icalendar-export fails to |
| 1509 | ;; export the nested sexp. After repairing bug56241 icalendar-export | 1532 | ;; export the nested sexp. After repairing bug56241 icalendar-export |
| 1510 | ;; works correctly for this sexp but now the testcase fails. | 1533 | ;; works correctly for this sexp but now the testcase fails. |
| 1511 | ;; Therefore this testcase is disabled for the time being. | 1534 | ;; Therefore this testcase is disabled for the time being. |
| 1512 | ;; (icalendar-tests--test-export | 1535 | ;; (icalendar-tests--test-export |
| @@ -1702,7 +1725,7 @@ SUMMARY:NNN Wwwwwwww Wwwww - Aaaaaa Pppppppp rrrrrr ddd oo Nnnnnnnn 30 | |||
| 1702 | (let ((time (icalendar--decode-isodatetime string day zone))) | 1725 | (let ((time (icalendar--decode-isodatetime string day zone))) |
| 1703 | (format-time-string "%FT%T%z" (encode-time time) 0))) | 1726 | (format-time-string "%FT%T%z" (encode-time time) 0))) |
| 1704 | 1727 | ||
| 1705 | (ert-deftest icalendar-tests--decode-isodatetime () | 1728 | (ical:deftest-obsolete icalendar-tests--decode-isodatetime () |
| 1706 | "Test `icalendar--decode-isodatetime'." | 1729 | "Test `icalendar--decode-isodatetime'." |
| 1707 | (should (equal (icalendar-test--format "20040917T050910-02:00") | 1730 | (should (equal (icalendar-test--format "20040917T050910-02:00") |
| 1708 | "2004-09-17T03:09:10+0000")) | 1731 | "2004-09-17T03:09:10+0000")) |
| @@ -1728,4 +1751,8 @@ SUMMARY:NNN Wwwwwwww Wwwww - Aaaaaa Pppppppp rrrrrr ddd oo Nnnnnnnn 30 | |||
| 1728 | "2004-09-17T06:09:10+0000"))) | 1751 | "2004-09-17T06:09:10+0000"))) |
| 1729 | 1752 | ||
| 1730 | (provide 'icalendar-tests) | 1753 | (provide 'icalendar-tests) |
| 1754 | ;; Local Variables: | ||
| 1755 | ;; read-symbol-shorthands: (("ical:" . "icalendar-")) | ||
| 1756 | ;; byte-compile-warnings: (not obsolete) | ||
| 1757 | ;; End: | ||
| 1731 | ;;; icalendar-tests.el ends here | 1758 | ;;; icalendar-tests.el ends here |
diff --git a/test/lisp/misc-tests.el b/test/lisp/misc-tests.el index b6f5f01ad2a..81ebe1a5869 100644 --- a/test/lisp/misc-tests.el +++ b/test/lisp/misc-tests.el | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | (require 'ert) | 26 | (require 'ert) |
| 27 | (require 'misc) | 27 | (require 'misc) |
| 28 | (require 'mule-util) | ||
| 28 | 29 | ||
| 29 | (defmacro with-misc-test (original result &rest body) | 30 | (defmacro with-misc-test (original result &rest body) |
| 30 | (declare (indent 2)) | 31 | (declare (indent 2)) |
| @@ -243,5 +244,94 @@ | |||
| 243 | (setq-default display-line-numbers dln)) | 244 | (setq-default display-line-numbers dln)) |
| 244 | (should (= w0 w1)))) | 245 | (should (= w0 w1)))) |
| 245 | 246 | ||
| 247 | ;; Exercise `truncate-string-pixelwise' with strings of the same | ||
| 248 | ;; characters of differing widths, with and without ellipses, in varying | ||
| 249 | ;; faces, and varying face heights and compare results to each | ||
| 250 | ;; character's measured width. | ||
| 251 | (ert-deftest misc-test-truncate-string-pixelwise () | ||
| 252 | ;; Test empty string without an explicit buffer. | ||
| 253 | (should (equal (truncate-string-pixelwise "" 123) "")) | ||
| 254 | ;; Test fast path without an explicit buffer. | ||
| 255 | (should (equal (truncate-string-pixelwise "123" 123) "123")) | ||
| 256 | (with-temp-buffer | ||
| 257 | ;; Test empty string with an explicit buffer. | ||
| 258 | (should (equal (truncate-string-pixelwise "" 123 (current-buffer)) "")) | ||
| 259 | ;; Test fast path with an explicit buffer. | ||
| 260 | (should (equal (truncate-string-pixelwise "123" 123 (current-buffer)) "123"))) | ||
| 261 | |||
| 262 | (dolist (c '(?W ?X ?y ?1)) | ||
| 263 | (dolist (ellipsis `(nil "..." ,(truncate-string-ellipsis))) | ||
| 264 | (dolist (face '(fixed-pitch variable-pitch)) | ||
| 265 | (dolist (height '(1.0 0.5 1.5)) | ||
| 266 | (with-temp-buffer | ||
| 267 | (setq-local face-remapping-alist `((,face . default))) | ||
| 268 | (face-remap-add-relative 'default :height height) | ||
| 269 | (let ((char-pixels (string-pixel-width | ||
| 270 | (make-string 1 c) (current-buffer)))) | ||
| 271 | (dotimes (i 20) | ||
| 272 | (setq i (1+ i)) | ||
| 273 | (should (eq i (length | ||
| 274 | (truncate-string-pixelwise | ||
| 275 | (make-string (* i 2) c) | ||
| 276 | (* i char-pixels) | ||
| 277 | (current-buffer) | ||
| 278 | ellipsis)))))))))))) | ||
| 279 | |||
| 280 | ;; Exercise `truncate-string-pixelwise' with varying unicode strings, in | ||
| 281 | ;; varying faces, and varying face heights and compare results to a | ||
| 282 | ;; naive `string-pixel-width' based string truncate function. | ||
| 283 | (ert-deftest misc-test-truncate-string-pixelwise-unicode () | ||
| 284 | :tags '(:expensive-test) | ||
| 285 | (skip-when noninteractive) | ||
| 286 | (let ((max-pixels 500) | ||
| 287 | (truncate-string-naive (lambda (string pixels buffer) | ||
| 288 | (while (and (length> string 0) | ||
| 289 | (> (string-pixel-width string buffer) pixels)) | ||
| 290 | (setq string (substring string 0 (1- (length string))))) | ||
| 291 | string)) | ||
| 292 | (strings (list | ||
| 293 | "foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz" | ||
| 294 | (concat "話說天下大勢,分久必合,合久必分:周末七國分爭,并入於秦。" | ||
| 295 | "及秦滅之後,楚、漢分爭,又并入於漢。漢朝自高祖斬白蛇而起義," | ||
| 296 | "一統天下。後來光武中興,傳至獻帝,遂分為三國。推其致亂之由," | ||
| 297 | "殆始於桓、靈二帝。桓帝禁錮善類,崇信宦官。及桓帝崩,靈帝即位," | ||
| 298 | "大將軍竇武、太傅陳蕃,共相輔佐。時有宦官曹節等弄權,竇武、陳蕃謀誅之," | ||
| 299 | "作事不密,反為所害。中涓自此愈橫") | ||
| 300 | (concat "короче теперь если по русски написать все четко или все равно" | ||
| 301 | " короче теперь если по русски написать все четко или все равно" | ||
| 302 | " короче теперь если по русски написать все четко или все равно" | ||
| 303 | " короче теперь если по русски написать все четко или все равно") | ||
| 304 | "будет разрыв строки непонятно где🏁🚩🎌🏴🏳️ 🏳️ <200d>🌈🏳️ <200d>⚧️🏴<200d>☠️" | ||
| 305 | (apply #'concat (make-list 200 "\u0065\u0301 ")) ; composed é \u00E9 | ||
| 306 | (let ((woman-loves-man ; 👩❤️👨 | ||
| 307 | (concat "\N{WOMAN}" | ||
| 308 | "\N{ZERO WIDTH JOINER}" | ||
| 309 | "\N{HEAVY BLACK HEART}" | ||
| 310 | "\N{VARIATION SELECTOR-16}" | ||
| 311 | "\N{ZERO WIDTH JOINER}" | ||
| 312 | "\N{MAN}" | ||
| 313 | " "))) | ||
| 314 | (apply #'concat (make-list 200 woman-loves-man))) | ||
| 315 | (propertize (let ((varying-height-string | ||
| 316 | (mapconcat | ||
| 317 | #'identity | ||
| 318 | (list "AWi!" | ||
| 319 | (propertize "foo" 'face '(:height 2.5)) | ||
| 320 | (propertize "bar" 'face '(:height 0.5)) | ||
| 321 | (propertize "baz" 'face '(:height 1.0))) | ||
| 322 | " "))) | ||
| 323 | (apply #'concat (make-list 100 varying-height-string))) | ||
| 324 | 'face 'variable-pitch)))) | ||
| 325 | (dolist (face '(fixed-pitch variable-pitch)) | ||
| 326 | (dolist (height '(1.0 0.5 1.5)) | ||
| 327 | (with-temp-buffer | ||
| 328 | (setq-local face-remapping-alist `((,face . default))) | ||
| 329 | (face-remap-add-relative 'default :height height) | ||
| 330 | (dolist (string strings) | ||
| 331 | (should (eq (length (funcall truncate-string-naive | ||
| 332 | string max-pixels (current-buffer))) | ||
| 333 | (length (truncate-string-pixelwise | ||
| 334 | string max-pixels (current-buffer))))))))))) | ||
| 335 | |||
| 246 | (provide 'misc-tests) | 336 | (provide 'misc-tests) |
| 247 | ;;; misc-tests.el ends here | 337 | ;;; misc-tests.el ends here |
diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 53ce1929cad..3d0ab522d3f 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el | |||
| @@ -28,10 +28,9 @@ | |||
| 28 | (defvar dbus-debug) | 28 | (defvar dbus-debug) |
| 29 | (defvar dbus-message-type-signal) | 29 | (defvar dbus-message-type-signal) |
| 30 | (declare-function dbus-get-unique-name "dbusbind.c" (bus)) | 30 | (declare-function dbus-get-unique-name "dbusbind.c" (bus)) |
| 31 | (declare-function dbus-close-inhibitor-lock "dbusbind.c" (lock)) | 31 | (declare-function dbus--fd-open "dbusbind.c" (filename)) |
| 32 | (declare-function dbus-registered-inhibitor-locks "dbusbind.c" ()) | 32 | (declare-function dbus--fd-close "dbusbind.c" (fd)) |
| 33 | (declare-function dbus-make-inhibitor-lock "dbusbind.c" | 33 | (declare-function dbus--registered-fds "dbusbind.c" ()) |
| 34 | (what why &optional block)) | ||
| 35 | 34 | ||
| 36 | (defconst dbus--test-enabled-session-bus | 35 | (defconst dbus--test-enabled-session-bus |
| 37 | (and (featurep 'dbusbind) | 36 | (and (featurep 'dbusbind) |
| @@ -2308,89 +2307,156 @@ The argument EXPECTED-ARGS is a list of expected arguments for the method." | |||
| 2308 | ;; Cleanup. | 2307 | ;; Cleanup. |
| 2309 | (dbus-unregister-service :session dbus--test-service))) | 2308 | (dbus-unregister-service :session dbus--test-service))) |
| 2310 | 2309 | ||
| 2311 | (ert-deftest dbus-test10-inhibitor-locks () | 2310 | (ert-deftest dbus-test10-keep-fd () |
| 2312 | "Check `dbus-*-inhibitor-locks'." | 2311 | "Check D-Bus `:keep-fd' argument." |
| 2313 | :tags '(:expensive-test) | 2312 | :tags '(:expensive-test) |
| 2314 | (skip-unless dbus--test-enabled-system-bus) | 2313 | (skip-unless dbus--test-enabled-system-bus) |
| 2315 | (skip-unless (dbus-ping :system dbus--test-systemd-service 1000)) | 2314 | (skip-unless (dbus-ping :system dbus--test-systemd-service 1000)) |
| 2316 | 2315 | ||
| 2317 | (let (lock1 lock2) | 2316 | (let ((what "sleep") |
| 2317 | (who "Emacs test user") | ||
| 2318 | (why "Test delay") | ||
| 2319 | (mode "delay") | ||
| 2320 | (fd-directory (format "/proc/%d/fd" (emacs-pid))) | ||
| 2321 | lock1 lock2) | ||
| 2318 | ;; Create inhibitor lock. | 2322 | ;; Create inhibitor lock. |
| 2319 | (setq lock1 (dbus-make-inhibitor-lock "sleep" "Test delay")) | 2323 | (setq lock1 |
| 2324 | (dbus-call-method | ||
| 2325 | :system dbus--test-systemd-service dbus--test-systemd-path | ||
| 2326 | dbus--test-systemd-manager-interface "Inhibit" | ||
| 2327 | what who why mode)) | ||
| 2320 | (should (natnump lock1)) | 2328 | (should (natnump lock1)) |
| 2321 | ;; The lock is reported by systemd. | 2329 | ;; The lock is reported by systemd. |
| 2322 | (should | 2330 | (should |
| 2323 | (member | 2331 | (member |
| 2324 | (list "sleep" "Emacs" "Test delay" "delay" (user-uid) (emacs-pid)) | 2332 | (list what who why mode (user-uid) (emacs-pid)) |
| 2325 | (dbus-call-method | 2333 | (dbus-call-method |
| 2326 | :system dbus--test-systemd-service dbus--test-systemd-path | 2334 | :system dbus--test-systemd-service dbus--test-systemd-path |
| 2327 | dbus--test-systemd-manager-interface "ListInhibitors"))) | 2335 | dbus--test-systemd-manager-interface "ListInhibitors"))) |
| 2328 | ;; The lock is registered internally. | 2336 | ;; The lock is not registered internally. |
| 2329 | (should | 2337 | (should-not (assoc lock1 (dbus--registered-fds))) |
| 2330 | (member | ||
| 2331 | (list lock1 "sleep" "Test delay" nil) | ||
| 2332 | (dbus-registered-inhibitor-locks))) | ||
| 2333 | ;; There exist a file descriptor. | 2338 | ;; There exist a file descriptor. |
| 2334 | (when (file-directory-p (format "/proc/%d/fd" (emacs-pid))) | 2339 | (when (file-directory-p fd-directory) |
| 2335 | (should (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock1)))) | 2340 | (should |
| 2336 | 2341 | (file-symlink-p | |
| 2337 | ;; It is not possible to modify registered inhibitor locks on Lisp level. | 2342 | (expand-file-name (number-to-string lock1) fd-directory)))) |
| 2338 | (setcar (assoc lock1 (dbus-registered-inhibitor-locks)) 'malicious) | ||
| 2339 | (should (assoc lock1 (dbus-registered-inhibitor-locks))) | ||
| 2340 | (should-not (assoc 'malicious (dbus-registered-inhibitor-locks))) | ||
| 2341 | |||
| 2342 | ;; Creating it again returns the same inhibitor lock. | ||
| 2343 | (should (= lock1 (dbus-make-inhibitor-lock "sleep" "Test delay"))) | ||
| 2344 | 2343 | ||
| 2345 | ;; Create another inhibitor lock. | 2344 | ;; Create another inhibitor lock. Keep the file descriptor. |
| 2346 | (setq lock2 (dbus-make-inhibitor-lock "sleep" "Test block" 'block)) | 2345 | (setq lock2 |
| 2346 | (dbus-call-method | ||
| 2347 | :system dbus--test-systemd-service dbus--test-systemd-path | ||
| 2348 | dbus--test-systemd-manager-interface "Inhibit" :keep-fd | ||
| 2349 | what who why mode)) | ||
| 2347 | (should (natnump lock2)) | 2350 | (should (natnump lock2)) |
| 2348 | (should-not (= lock1 lock2)) | 2351 | (should-not (= lock1 lock2)) |
| 2349 | ;; The lock is reported by systemd. | 2352 | ;; The lock is reported by systemd. |
| 2350 | (should | 2353 | (should |
| 2351 | (member | 2354 | (member |
| 2352 | (list "sleep" "Emacs" "Test block" "block" (user-uid) (emacs-pid)) | 2355 | (list what who why mode (user-uid) (emacs-pid)) |
| 2353 | (dbus-call-method | 2356 | (dbus-call-method |
| 2354 | :system dbus--test-systemd-service dbus--test-systemd-path | 2357 | :system dbus--test-systemd-service dbus--test-systemd-path |
| 2355 | dbus--test-systemd-manager-interface "ListInhibitors"))) | 2358 | dbus--test-systemd-manager-interface "ListInhibitors"))) |
| 2356 | ;; The lock is registered internally. | 2359 | ;; The lock is registered internally. |
| 2357 | (should | 2360 | (should |
| 2358 | (member | 2361 | (member |
| 2359 | (list lock2 "sleep" "Test block" t) | 2362 | (cons lock2 dbus--test-systemd-path) |
| 2360 | (dbus-registered-inhibitor-locks))) | 2363 | (dbus--registered-fds))) |
| 2361 | ;; There exist a file descriptor. | 2364 | ;; There exist a file descriptor. |
| 2362 | (when (file-directory-p (format "/proc/%d/fd" (emacs-pid))) | 2365 | (when (file-directory-p fd-directory) |
| 2363 | (should (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock2)))) | 2366 | (should |
| 2364 | 2367 | (file-symlink-p | |
| 2365 | ;; Close the first inhibitor lock. | 2368 | (expand-file-name (number-to-string lock2) fd-directory)))) |
| 2366 | (should (dbus-close-inhibitor-lock lock1)) | 2369 | |
| 2367 | ;; The internal registration has gone. | 2370 | ;; Create another inhibitor lock via |
| 2368 | (should-not | 2371 | ;; `dbus-call-method-asynchronously'. Keep the file descriptor. |
| 2369 | (member | 2372 | (setq lock1 nil) |
| 2370 | (list lock1 "sleep" "Test delay" nil) | 2373 | (dbus-call-method-asynchronously |
| 2371 | (dbus-registered-inhibitor-locks))) | 2374 | :system dbus--test-systemd-service dbus--test-systemd-path |
| 2372 | ;; The file descriptor has been deleted. | 2375 | dbus--test-systemd-manager-interface "Inhibit" |
| 2373 | (when (file-directory-p (format "/proc/%d/fd" (emacs-pid))) | 2376 | (lambda (lock) (setq lock1 lock)) :keep-fd |
| 2374 | (should-not (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock1)))) | 2377 | what who why mode) |
| 2375 | 2378 | (with-timeout (1 (dbus--test-timeout-handler)) | |
| 2376 | ;; Closing it again is a noop. | 2379 | (while (null lock1) (read-event nil nil 0.1))) |
| 2377 | (should-not (dbus-close-inhibitor-lock lock1)) | ||
| 2378 | |||
| 2379 | ;; Creating it again returns (another?) inhibitor lock. | ||
| 2380 | (setq lock1 (dbus-make-inhibitor-lock "sleep" "Test delay")) | ||
| 2381 | (should (natnump lock1)) | 2380 | (should (natnump lock1)) |
| 2381 | (should-not (= lock1 lock2)) | ||
| 2382 | ;; The lock is registered internally. | 2382 | ;; The lock is registered internally. |
| 2383 | (should | 2383 | (should |
| 2384 | (member | 2384 | (member |
| 2385 | (list lock1 "sleep" "Test delay" nil) | 2385 | (cons lock1 dbus--test-systemd-path) |
| 2386 | (dbus-registered-inhibitor-locks))) | 2386 | (dbus--registered-fds))) |
| 2387 | ;; There exist a file descriptor. | 2387 | ;; There exist a file descriptor. |
| 2388 | (when (file-directory-p (format "/proc/%d/fd" (emacs-pid))) | 2388 | (when (file-directory-p fd-directory) |
| 2389 | (should (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock1)))) | 2389 | (should |
| 2390 | (file-symlink-p | ||
| 2391 | (expand-file-name (number-to-string lock1) fd-directory)))) | ||
| 2392 | |||
| 2393 | ;; It is not possible to modify registered inhibitor locks on Lisp level. | ||
| 2394 | (setcar (assoc lock1 (dbus--registered-fds)) 'malicious) | ||
| 2395 | (should (assoc lock1 (dbus--registered-fds))) | ||
| 2396 | (should-not (assoc 'malicious (dbus--registered-fds))) | ||
| 2390 | 2397 | ||
| 2391 | ;; Close the inhibitor locks. | 2398 | ;; Close the inhibitor locks. |
| 2392 | (should (dbus-close-inhibitor-lock lock1)) | 2399 | (should (dbus--fd-close lock1)) |
| 2393 | (should (dbus-close-inhibitor-lock lock2)))) | 2400 | (should (dbus--fd-close lock2)) |
| 2401 | ;; The internal registration has gone. | ||
| 2402 | (should-not | ||
| 2403 | (member | ||
| 2404 | (cons lock1 dbus--test-systemd-path) | ||
| 2405 | (dbus--registered-fds))) | ||
| 2406 | (should-not | ||
| 2407 | (member | ||
| 2408 | (cons lock2 dbus--test-systemd-path) | ||
| 2409 | (dbus--registered-fds))) | ||
| 2410 | ;; The file descriptors have been deleted. | ||
| 2411 | (when (file-directory-p fd-directory) | ||
| 2412 | (should-not | ||
| 2413 | (file-exists-p (expand-file-name (number-to-string lock1) fd-directory))) | ||
| 2414 | (should-not | ||
| 2415 | (file-exists-p (expand-file-name (number-to-string lock2) fd-directory)))) | ||
| 2416 | |||
| 2417 | ;; Closing them again is a noop. | ||
| 2418 | (should-not (dbus--fd-close lock1)) | ||
| 2419 | (should-not (dbus--fd-close lock2)))) | ||
| 2420 | |||
| 2421 | (ert-deftest dbus-test10-open-close-fd () | ||
| 2422 | "Check D-Bus open/close a file descriptor." | ||
| 2423 | :tags '(:expensive-test) | ||
| 2424 | (skip-unless dbus--test-enabled-system-bus) | ||
| 2425 | (skip-unless (dbus-ping :system dbus--test-systemd-service 1000)) | ||
| 2426 | |||
| 2427 | (ert-with-temp-file tmpfile | ||
| 2428 | (let ((fd-directory (format "/proc/%d/fd" (emacs-pid))) | ||
| 2429 | fd) | ||
| 2430 | ;; Create file descriptor. | ||
| 2431 | (setq fd (dbus--fd-open tmpfile)) | ||
| 2432 | (should (natnump fd)) | ||
| 2433 | ;; The file descriptor is registered internally. | ||
| 2434 | (should (member (cons fd tmpfile) (dbus--registered-fds))) | ||
| 2435 | ;; There exist a file descriptor file. | ||
| 2436 | (when (file-directory-p fd-directory) | ||
| 2437 | (should | ||
| 2438 | (file-symlink-p (expand-file-name (number-to-string fd) fd-directory))) | ||
| 2439 | (should | ||
| 2440 | (string-equal | ||
| 2441 | (file-truename (expand-file-name (number-to-string fd) fd-directory)) | ||
| 2442 | tmpfile))) | ||
| 2443 | |||
| 2444 | ;; It is not possible to modify registered file descriptors on Lisp level. | ||
| 2445 | (setcar (assoc fd (dbus--registered-fds)) 'malicious) | ||
| 2446 | (should (assoc fd (dbus--registered-fds))) | ||
| 2447 | (should-not (assoc 'malicious (dbus--registered-fds))) | ||
| 2448 | |||
| 2449 | ;; Close the file descriptor. | ||
| 2450 | (should (dbus--fd-close fd)) | ||
| 2451 | ;; The internal registration has gone. | ||
| 2452 | (should-not (member (cons fd tmpfile) (dbus--registered-fds))) | ||
| 2453 | ;; The file descriptor file has been deleted. | ||
| 2454 | (when (file-directory-p fd-directory) | ||
| 2455 | (should-not | ||
| 2456 | (file-exists-p (expand-file-name (number-to-string fd) fd-directory)))) | ||
| 2457 | |||
| 2458 | ;; Closing it again is a noop. | ||
| 2459 | (should-not (dbus--fd-close fd))))) | ||
| 2394 | 2460 | ||
| 2395 | (defun dbus-test-all (&optional interactive) | 2461 | (defun dbus-test-all (&optional interactive) |
| 2396 | "Run all tests for \\[dbus]." | 2462 | "Run all tests for \\[dbus]." |
diff --git a/test/lisp/net/tramp-archive-tests.el b/test/lisp/net/tramp-archive-tests.el index f3bfaac005c..79fbe38b299 100644 --- a/test/lisp/net/tramp-archive-tests.el +++ b/test/lisp/net/tramp-archive-tests.el | |||
| @@ -757,7 +757,7 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'." | |||
| 757 | ;; `set-file-modes' is not implemented. | 757 | ;; `set-file-modes' is not implemented. |
| 758 | (should-error | 758 | (should-error |
| 759 | (set-file-modes tmp-name1 #o777) | 759 | (set-file-modes tmp-name1 #o777) |
| 760 | :type 'file-error) | 760 | :type 'remote-file-error) |
| 761 | (should (= (file-modes tmp-name1) #o400)) | 761 | (should (= (file-modes tmp-name1) #o400)) |
| 762 | (should-not (file-executable-p tmp-name1)) | 762 | (should-not (file-executable-p tmp-name1)) |
| 763 | (should-not (file-writable-p tmp-name1)) | 763 | (should-not (file-writable-p tmp-name1)) |
| @@ -766,7 +766,7 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'." | |||
| 766 | ;; `set-file-modes' is not implemented. | 766 | ;; `set-file-modes' is not implemented. |
| 767 | (should-error | 767 | (should-error |
| 768 | (set-file-modes tmp-name2 #o777) | 768 | (set-file-modes tmp-name2 #o777) |
| 769 | :type 'file-error) | 769 | :type 'remote-file-error) |
| 770 | (should (= (file-modes tmp-name2) #o500)) | 770 | (should (= (file-modes tmp-name2) #o500)) |
| 771 | (should (file-executable-p tmp-name2)) | 771 | (should (file-executable-p tmp-name2)) |
| 772 | (should-not (file-writable-p tmp-name2))) | 772 | (should-not (file-writable-p tmp-name2))) |
| @@ -796,7 +796,7 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'." | |||
| 796 | ;; `make-symbolic-link' is not implemented. | 796 | ;; `make-symbolic-link' is not implemented. |
| 797 | (should-error | 797 | (should-error |
| 798 | (make-symbolic-link tmp-name1 tmp-name2) | 798 | (make-symbolic-link tmp-name1 tmp-name2) |
| 799 | :type 'file-error) | 799 | :type 'remote-file-error) |
| 800 | (should (file-symlink-p tmp-name2)) | 800 | (should (file-symlink-p tmp-name2)) |
| 801 | (should (file-regular-p tmp-name2)) | 801 | (should (file-regular-p tmp-name2)) |
| 802 | (should | 802 | (should |
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index bbfe15d2f59..28d773ca616 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el | |||
| @@ -71,6 +71,7 @@ | |||
| 71 | (declare-function edebug-mode "edebug") | 71 | (declare-function edebug-mode "edebug") |
| 72 | (declare-function project-mode-line-format "project") | 72 | (declare-function project-mode-line-format "project") |
| 73 | (declare-function tramp-check-remote-uname "tramp-sh") | 73 | (declare-function tramp-check-remote-uname "tramp-sh") |
| 74 | (declare-function tramp-file-name-with-sudo "tramp-cmds") | ||
| 74 | (declare-function tramp-find-executable "tramp-sh") | 75 | (declare-function tramp-find-executable "tramp-sh") |
| 75 | (declare-function tramp-get-remote-chmod-h "tramp-sh") | 76 | (declare-function tramp-get-remote-chmod-h "tramp-sh") |
| 76 | (declare-function tramp-get-remote-path "tramp-sh") | 77 | (declare-function tramp-get-remote-path "tramp-sh") |
| @@ -185,7 +186,7 @@ The temporary file is not created." | |||
| 185 | (declare (indent defun) (debug (body))) | 186 | (declare (indent defun) (debug (body))) |
| 186 | `(condition-case err | 187 | `(condition-case err |
| 187 | (progn ,@body) | 188 | (progn ,@body) |
| 188 | (file-error | 189 | (remote-file-error |
| 189 | (unless (string-match-p | 190 | (unless (string-match-p |
| 190 | (rx bol (| "make-symbolic-link not supported" | 191 | (rx bol (| "make-symbolic-link not supported" |
| 191 | (: "Making symbolic link" | 192 | (: "Making symbolic link" |
| @@ -2203,19 +2204,31 @@ being the result.") | |||
| 2203 | m)) | 2204 | m)) |
| 2204 | :type 'user-error))))) | 2205 | :type 'user-error))))) |
| 2205 | 2206 | ||
| 2206 | (ert-deftest tramp-test03-file-name-method-rules () | 2207 | (ert-deftest tramp-test03-file-error () |
| 2207 | "Check file name rules for some methods." | 2208 | "Check that Tramp signals an error in case of connection problems." |
| 2208 | (skip-unless (eq tramp-syntax 'default)) | 2209 | ;; Connect to a non-existing host. |
| 2209 | (skip-unless (tramp--test-enabled)) | 2210 | (let ((vec (copy-tramp-file-name tramp-test-vec)) |
| 2210 | 2211 | ;; Don't poison it. | |
| 2211 | ;; Multi hops are allowed for inline methods only. | 2212 | (tramp-default-proxies-alist tramp-default-proxies-alist) |
| 2212 | (let (non-essential) | 2213 | (tramp-show-ad-hoc-proxies t)) |
| 2213 | (should-error | 2214 | (cl-letf* (((symbol-function #'read-string) #'ignore) ; Suppress password. |
| 2214 | (expand-file-name "/ssh:user1@host1|method:user2@host2:/path/to/file") | 2215 | ((tramp-file-name-host vec) "example.com.invalid")) |
| 2215 | :type 'user-error) | 2216 | (should-error |
| 2216 | (should-error | 2217 | (file-exists-p (tramp-make-tramp-file-name vec)) |
| 2217 | (expand-file-name "/method:user1@host1|ssh:user2@host2:/path/to/file") | 2218 | ;; `user-error' is raised if the host shall be local. |
| 2218 | :type 'user-error))) | 2219 | ;; `remote-file-error' is raised if the host cannot be connected. |
| 2220 | :type (if (tramp--test-ange-ftp-p) | ||
| 2221 | 'ftp-error '(user-error remote-file-error))) | ||
| 2222 | (should-error | ||
| 2223 | (file-exists-p (tramp-make-tramp-file-name vec)) | ||
| 2224 | ;; `ftp-error' and `remote-file-error' are subcategories of | ||
| 2225 | ;; `file-error'. Let's check this as well. | ||
| 2226 | :type '(user-error file-error)) | ||
| 2227 | ;; Check multi-hop. | ||
| 2228 | (should-error | ||
| 2229 | (file-exists-p | ||
| 2230 | (tramp-file-name-with-sudo (tramp-make-tramp-file-name vec))) | ||
| 2231 | :type '(user-error file-error))))) | ||
| 2219 | 2232 | ||
| 2220 | (ert-deftest tramp-test04-substitute-in-file-name () | 2233 | (ert-deftest tramp-test04-substitute-in-file-name () |
| 2221 | "Check `substitute-in-file-name'." | 2234 | "Check `substitute-in-file-name'." |
| @@ -7637,11 +7650,12 @@ This requires restrictions of file name syntax." | |||
| 7637 | (unless (tramp--test-crypt-p) | 7650 | (unless (tramp--test-crypt-p) |
| 7638 | (or (tramp--test-adb-p) (tramp--test-sh-p) (tramp--test-sshfs-p) | 7651 | (or (tramp--test-adb-p) (tramp--test-sh-p) (tramp--test-sshfs-p) |
| 7639 | (and (tramp--test-smb-p) | 7652 | (and (tramp--test-smb-p) |
| 7640 | (file-writable-p | 7653 | (ignore-errors |
| 7641 | (file-name-concat | 7654 | (file-writable-p |
| 7642 | (file-remote-p ert-remote-temporary-file-directory) | 7655 | (file-name-concat |
| 7643 | ;; We check a directory on the "ADMIN$" share. | 7656 | (file-remote-p ert-remote-temporary-file-directory) |
| 7644 | "ADMIN$" "Boot")))))) | 7657 | ;; We check a directory on the "ADMIN$" share. |
| 7658 | "ADMIN$" "Boot"))))))) | ||
| 7645 | 7659 | ||
| 7646 | (defun tramp--test-supports-set-file-modes-p () | 7660 | (defun tramp--test-supports-set-file-modes-p () |
| 7647 | "Return whether the method under test supports setting file modes." | 7661 | "Return whether the method under test supports setting file modes." |
diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el index 7267754dc7d..ffc097fee74 100644 --- a/test/lisp/progmodes/eglot-tests.el +++ b/test/lisp/progmodes/eglot-tests.el | |||
| @@ -1017,7 +1017,8 @@ int main() { | |||
| 1017 | "fn main() -> i32 { return 42.2;}") | 1017 | "fn main() -> i32 { return 42.2;}") |
| 1018 | ("other-file.rs" . | 1018 | ("other-file.rs" . |
| 1019 | "fn foo() -> () { let hi=3; }")))) | 1019 | "fn foo() -> () { let hi=3; }")))) |
| 1020 | (let ((eglot-server-programs '((rust-mode . ("rust-analyzer"))))) | 1020 | (let ((eglot-server-programs '((rust-mode . ("rust-analyzer")))) |
| 1021 | (project-vc-non-essential-cache-timeout 0)) | ||
| 1021 | ;; Open other-file.rs, and see diagnostics arrive for main.rs, | 1022 | ;; Open other-file.rs, and see diagnostics arrive for main.rs, |
| 1022 | ;; which we didn't open. | 1023 | ;; which we didn't open. |
| 1023 | (with-current-buffer (eglot--find-file-noselect "project/other-file.rs") | 1024 | (with-current-buffer (eglot--find-file-noselect "project/other-file.rs") |
diff --git a/test/lisp/vc/ediff-mult-tests.el b/test/lisp/vc/ediff-mult-tests.el index e3514f77d2f..7887ae086fe 100644 --- a/test/lisp/vc/ediff-mult-tests.el +++ b/test/lisp/vc/ediff-mult-tests.el | |||
| @@ -20,13 +20,12 @@ | |||
| 20 | ;;; Code: | 20 | ;;; Code: |
| 21 | 21 | ||
| 22 | (require 'ert) | 22 | (require 'ert) |
| 23 | (require 'ert-x) | ||
| 23 | (require 'ediff-mult) | 24 | (require 'ediff-mult) |
| 24 | 25 | ||
| 25 | (ert-deftest ediff-test-bug3348 () | 26 | (ert-deftest ediff-test-bug3348 () |
| 26 | "After saving `ediff-meta-diff-buffer' to a file, we should not reuse it." | 27 | "After saving `ediff-meta-diff-buffer' to a file, we should not reuse it." |
| 27 | (let ((test-dir | 28 | (ert-with-temp-directory test-dir |
| 28 | (expand-file-name "bug-3348-testdir" temporary-file-directory))) | ||
| 29 | (make-directory test-dir t) | ||
| 30 | (cd test-dir) | 29 | (cd test-dir) |
| 31 | 30 | ||
| 32 | (make-directory "dir-a" t) | 31 | (make-directory "dir-a" t) |
diff --git a/test/lisp/vc/vc-git-tests.el b/test/lisp/vc/vc-git-tests.el index fe55cc75d6f..9721cc4d4ff 100644 --- a/test/lisp/vc/vc-git-tests.el +++ b/test/lisp/vc/vc-git-tests.el | |||
| @@ -194,4 +194,39 @@ is absent." | |||
| 194 | ("Tracking" . ,main-branch) | 194 | ("Tracking" . ,main-branch) |
| 195 | ("Remote" . "none (tracking local branch)"))))))))) | 195 | ("Remote" . "none (tracking local branch)"))))))))) |
| 196 | 196 | ||
| 197 | (ert-deftest vc-git-test-branch-remotes () | ||
| 198 | "Test behavior of `vc-git--branch-remotes'." | ||
| 199 | (skip-unless (executable-find vc-git-program)) | ||
| 200 | (vc-git-test--with-repo repo | ||
| 201 | (let ((main-branch (vc-git-test--start-branch))) | ||
| 202 | (should (null (vc-git--branch-remotes))) | ||
| 203 | (vc-git--out-ok "config" | ||
| 204 | (format "branch.%s.remote" main-branch) | ||
| 205 | "origin") | ||
| 206 | (should (null (vc-git--branch-remotes))) | ||
| 207 | (vc-git--out-ok "config" | ||
| 208 | (format "branch.%s.merge" main-branch) | ||
| 209 | main-branch) | ||
| 210 | (let ((alist (vc-git--branch-remotes))) | ||
| 211 | (should (assq 'upstream alist)) | ||
| 212 | (should (null (assq 'push alist)))) | ||
| 213 | (vc-git--out-ok "config" | ||
| 214 | (format "branch.%s.pushRemote" main-branch) | ||
| 215 | "fork") | ||
| 216 | (let ((alist (vc-git--branch-remotes))) | ||
| 217 | (should (assq 'upstream alist)) | ||
| 218 | (should (equal (cdr (assq 'push alist)) | ||
| 219 | (concat "fork/" main-branch)))) | ||
| 220 | (vc-git--out-ok "config" "--unset" | ||
| 221 | (format "branch.%s.pushRemote" main-branch)) | ||
| 222 | (vc-git--out-ok "config" "remote.pushDefault" "fork") | ||
| 223 | (let ((alist (vc-git--branch-remotes))) | ||
| 224 | (should (assq 'upstream alist)) | ||
| 225 | (should (equal (cdr (assq 'push alist)) | ||
| 226 | (concat "fork/" main-branch)))) | ||
| 227 | (vc-git--out-ok "config" "remote.pushDefault" "origin") | ||
| 228 | (let ((alist (vc-git--branch-remotes))) | ||
| 229 | (should (assq 'upstream alist)) | ||
| 230 | (should (null (assq 'push alist))))))) | ||
| 231 | |||
| 197 | ;;; vc-git-tests.el ends here | 232 | ;;; vc-git-tests.el ends here |