]> code.delx.au - gnu-emacs/blobdiff - test/automated/icalendar-tests.el
Merge from emacs-24; up to 2014-07-27T09:41:59Z!ttn@gnu.org
[gnu-emacs] / test / automated / icalendar-tests.el
index 503ea22d2b82bccf2c7c2daf323ceae7a9b623c0..a6a5da2ff576d36b9904a0ffab46847a26c0805f 100644 (file)
@@ -1,6 +1,6 @@
 ;; icalendar-tests.el --- Test suite for icalendar.el
 
-;; Copyright (C) 2005, 2008-201 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2008-2014 Free Software Foundation, Inc.
 
 ;; Author:         Ulf Jasper <ulf.jasper@web.de>
 ;; Created:        March 2005
     (should (string=  (concat "yyyDTSTARTyyy")
                       (icalendar--create-uid entry-full contents)))))
 
-(ert-deftest icalendar--calendar-style ()
-  "Test for `icalendar--date-style'."
-  (dolist (calendar-date-style '(iso american european))
-    (should (eq (icalendar--date-style) calendar-date-style)))
-  (let ((cds calendar-date-style)
-        (european-calendar-style t))
-    (makunbound 'calendar-date-style)
-    (should (eq (icalendar--date-style) 'european))
-    (with-no-warnings (setq european-calendar-style nil)) ;still get warning!?! FIXME
-    (should (eq (icalendar--date-style) 'american))
-    (setq calendar-date-style cds)))
-
 (ert-deftest icalendar-convert-anniversary-to-ical ()
   "Test method for `icalendar--convert-anniversary-to-ical'."
   (let* ((calendar-date-style 'iso)
          result)
     (setq result (icalendar--convert-anniversary-to-ical
                   "" "%%(diary-anniversary 1964 6 30) g"))
-    (should (= 2 (length result)))
+    (should (consp result))
     (should (string= (concat
                       "\nDTSTART;VALUE=DATE:19640630"
                       "\nDTEND;VALUE=DATE:19640701"
                       "\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=06;BYMONTHDAY=30")
                      (car result)))
-    (should (string= "g" (cadr result)))))
+    (should (string= "g" (cdr result)))))
 
 (ert-deftest icalendar--convert-cyclic-to-ical ()
   "Test method for `icalendar--convert-cyclic-to-ical'."
          result)
     (setq result (icalendar--convert-block-to-ical
                   "" "%%(diary-block 2004 7 19 2004 8 27) Sommerferien"))
-    (should (= 2 (length result)))
+    (should (consp result))
     (should (string= (concat
                       "\nDTSTART;VALUE=DATE:20040719"
                       "\nDTEND;VALUE=DATE:20040828")
                      (car result)))
-    (should (string= "Sommerferien" (cadr result)))))
+    (should (string= "Sommerferien" (cdr result)))))
 
 (ert-deftest icalendar--convert-block-to-ical ()
   "Test method for `icalendar--convert-block-to-ical'."
          result)
     (setq result (icalendar--convert-block-to-ical
                   "" "%%(diary-block 2004 7 19 2004 8 27) Sommerferien"))
-    (should (= 2 (length result)))
+    (should (consp result))
     (should (string= (concat
                       "\nDTSTART;VALUE=DATE:20040719"
                       "\nDTEND;VALUE=DATE:20040828")
                      (car result)))
-    (should (string= "Sommerferien" (cadr result)))))
+    (should (string= "Sommerferien" (cdr result)))))
 
 (ert-deftest icalendar--convert-yearly-to-ical ()
   "Test method for `icalendar--convert-yearly-to-ical'."
           ["January" "February" "March" "April" "May" "June" "July" "August"
            "September" "October" "November" "December"]))
     (setq result (icalendar--convert-yearly-to-ical "" "May 1 Tag der Arbeit"))
-    (should (= 2 (length result)))
+    (should (consp result))
     (should (string= (concat
                       "\nDTSTART;VALUE=DATE:19000501"
                       "\nDTEND;VALUE=DATE:19000502"
                       "\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYMONTHDAY=1")
                      (car result)))
-    (should (string= "Tag der Arbeit" (cadr result)))))
+    (should (string= "Tag der Arbeit" (cdr result)))))
 
 (ert-deftest icalendar--convert-weekly-to-ical ()
   "Test method for `icalendar--convert-weekly-to-ical'."
           ["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday"
            "Saturday"]))
     (setq result (icalendar--convert-weekly-to-ical "" "Monday 8:30 subject"))
-    (should (= 2 (length result)))
+    (should (consp result))
     (should (string= (concat "\nDTSTART;VALUE=DATE-TIME:20050103T083000"
                              "\nDTEND;VALUE=DATE-TIME:20050103T093000"
                              "\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=MO")
                      (car result)))
-    (should (string= "subject" (cadr result)))))
+    (should (string= "subject" (cdr result)))))
+
+(ert-deftest icalendar--convert-sexp-to-ical ()
+  "Test method for `icalendar--convert-sexp-to-ical'."
+  (let* (result
+         (icalendar-export-sexp-enumeration-days 3))
+    ;; test case %%(diary-hebrew-date)
+    (setq result (icalendar--convert-sexp-to-ical "" "%%(diary-hebrew-date)"))
+    (should (consp result))
+    (should (eq icalendar-export-sexp-enumeration-days (length result)))
+    (mapc (lambda (i)
+            (should (consp i))
+            (should (string-match "Hebrew date (until sunset): .*" (cdr i))))
+          result)))
+
+(ert-deftest icalendar--convert-to-ical ()
+  "Test method for `icalendar--convert-to-ical'."
+  (let* (result
+         (icalendar-export-sexp-enumerate-all t)
+         (icalendar-export-sexp-enumeration-days 3)
+         (calendar-date-style 'iso))
+    ;; test case: %%(diary-anniversary 1642 12 25) Newton
+    ;; forced enumeration not matching the actual day --> empty
+    (setq result (icalendar--convert-sexp-to-ical
+                  "" "%%(diary-anniversary 1642 12 25) Newton's birthday"
+                  (encode-time 1 1 1 6 12 2014)))
+    (should (null result))
+    ;; test case: %%(diary-anniversary 1642 12 25) Newton
+    ;; enumeration does match the actual day -->
+    (setq result (icalendar--convert-sexp-to-ical
+                  "" "%%(diary-anniversary 1642 12 25) Newton's birthday"
+                  (encode-time 1 1 1 24 12 2014)))
+    (should (= 1 (length result)))
+    (should (consp (car result)))
+    (should (string-match
+             "\nDTSTART;VALUE=DATE:20141225\nDTEND;VALUE=DATE:20141226"
+             (car (car result))))
+    (should (string-match "Newton's birthday" (cdr (car result))))))
 
 (ert-deftest icalendar--parse-vtimezone ()
   "Test method for `icalendar--parse-vtimezone'."
@@ -188,7 +213,7 @@ END:VTIMEZONE
     (should (string= "STD-02:00DST-03:00,M3.5.0/03:00:00,M10.5.0/04:00:00"
                      (cdr result)))
     (setq vtimezone (icalendar-tests--get-ical-event "BEGIN:VTIMEZONE
-TZID:anothername
+TZID:anothername\, with a comma
 BEGIN:STANDARD
 DTSTART:16010101T040000
 TZOFFSETFROM:+0300
@@ -204,7 +229,7 @@ END:DAYLIGHT
 END:VTIMEZONE
 "))
     (setq result (icalendar--parse-vtimezone vtimezone))
-    (should (string= "anothername" (car result)))
+    (should (string= "anothername, with a comma" (car result)))
     (message (cdr result))
     (should (string= "STD-02:00DST-03:00,M3.2.1/03:00:00,M10.2.1/04:00:00"
                      (cdr result)))))
@@ -215,28 +240,37 @@ END:VTIMEZONE
          result)
     ;; without time
     (setq result (icalendar--convert-ordinary-to-ical "&?" "2010 2 15 subject"))
-    (should (= 2 (length result)))
+    (should (consp result))
     (should (string=  "\nDTSTART;VALUE=DATE:20100215\nDTEND;VALUE=DATE:20100216"
                       (car result)))
-    (should (string= "subject" (cadr result)))
+    (should (string= "subject" (cdr result)))
+
+    ;; with start time
+    (setq result (icalendar--convert-ordinary-to-ical
+                  "&?" "&2010 2 15 12:34 s"))
+    (should (consp result))
+    (should (string=  (concat "\nDTSTART;VALUE=DATE-TIME:20100215T123400"
+                              "\nDTEND;VALUE=DATE-TIME:20100215T133400")
+                      (car result)))
+    (should (string= "s" (cdr result)))
 
     ;; with time
     (setq result (icalendar--convert-ordinary-to-ical
                   "&?" "&2010 2 15 12:34-23:45 s"))
-    (should (= 2 (length result)))
+    (should (consp result))
     (should (string=  (concat "\nDTSTART;VALUE=DATE-TIME:20100215T123400"
                               "\nDTEND;VALUE=DATE-TIME:20100215T234500")
                       (car result)))
-    (should (string= "s" (cadr result)))
+    (should (string= "s" (cdr result)))
 
     ;; with time, again -- test bug#5549
     (setq result (icalendar--convert-ordinary-to-ical
                   "x?" "x2010 2 15 0:34-1:45 s"))
-    (should (= 2 (length result)))
+    (should (consp result))
     (should (string=  (concat "\nDTSTART;VALUE=DATE-TIME:20100215T003400"
                               "\nDTEND;VALUE=DATE-TIME:20100215T014500")
                       (car result)))
-    (should (string= "s" (cadr result)))))
+    (should (string= "s" (cdr result)))))
 
 (ert-deftest icalendar--diarytime-to-isotime ()
   "Test method for `icalendar--diarytime-to-isotime'."
@@ -267,7 +301,9 @@ END:VTIMEZONE
   (should (string= "T120100"
                   (icalendar--diarytime-to-isotime "1201" "pm")))
   (should (string= "T125900"
-                  (icalendar--diarytime-to-isotime "1259" "pm"))))
+                  (icalendar--diarytime-to-isotime "1259" "pm")))
+  (should (string= "T150000"
+                  (icalendar--diarytime-to-isotime "3" "pm"))))
 
 (ert-deftest icalendar--datetime-to-diary-date ()
   "Test method for `icalendar--datetime-to-diary-date'."
@@ -414,6 +450,38 @@ END:VEVENT
     (should (not result))
     ))
 
+(ert-deftest icalendar--decode-isodatetime ()
+  "Test `icalendar--decode-isodatetime'."
+  (let ((tz (getenv "TZ"))
+       result)
+    (unwind-protect
+       (progn
+         ;; Use Eastern European Time (UTC+2, UTC+3 daylight saving)
+         (setenv "TZ" "EET-2EEST,M3.5.0/3,M10.5.0/4")
+
+          (message "%s" (current-time-zone (encode-time 0 0 10 1 1 2013 0)))
+          (message "%s" (current-time-zone (encode-time 0 0 10 1 8 2013 0)))
+
+          ;; testcase: no time zone in input -> keep time as is
+          ;; 1 Jan 2013 10:00
+          (should (equal '(0 0 10 1 1 2013 2 nil 7200)
+                         (icalendar--decode-isodatetime "20130101T100000")))
+          ;; 1 Aug 2013 10:00 (DST)
+          (should (equal '(0 0 10 1 8 2013 4 t 10800)
+                         (icalendar--decode-isodatetime "20130801T100000")))
+
+          ;; testcase: UTC time zone specifier in input -> convert to local time
+          ;; 31 Dec 2013 23:00 UTC -> 1 Jan 2013 01:00 EET
+          (should (equal '(0 0 1 1 1 2014 3 nil 7200)
+                         (icalendar--decode-isodatetime "20131231T230000Z")))
+          ;; 1 Aug 2013 10:00 UTC -> 1 Aug 2013 13:00 EEST
+          (should (equal '(0 0 13 1 8 2013 4 t 10800)
+                         (icalendar--decode-isodatetime "20130801T100000Z")))
+
+          )
+      ;; restore time-zone even if something went terribly wrong
+      (setenv "TZ" tz)))  )
+
 ;; ======================================================================
 ;; Export tests
 ;; ======================================================================
@@ -428,12 +496,16 @@ Argument EXPECTED-OUTPUT expected iCalendar result string.
 
 European style input data must use german month names.  American
 and ISO style input data must use english month names."
-  (let ((tz (cadr (current-time-zone)))
+  (let ((tz (getenv "TZ"))
        (calendar-date-style 'iso)
        (icalendar-recurring-start-year 2000))
     (unwind-protect
        (progn
-         (set-time-zone-rule "CET")
+;;;      (message "Current time zone: %s" (current-time-zone))
+         ;; Use this form so as not to rely on system tz database.
+         ;; Eg hydra.nixos.org.
+         (setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
+;;;      (message "Current time zone: %s" (current-time-zone))
          (when input-iso
            (let ((calendar-month-name-array
                   ["January" "February" "March" "April" "May" "June" "July" "August"
@@ -461,8 +533,8 @@ and ISO style input data must use english month names."
                    "Saturday"]))
              (setq calendar-date-style 'american)
              (icalendar-tests--do-test-export input-american expected-output))))
-      ;; restore time-zone if something went terribly wrong
-      (set-time-zone-rule tz))))
+      ;; restore time-zone even if something went terribly wrong
+      (setenv "TZ" tz))))
 
 (defun icalendar-tests--do-test-export (input expected-output)
   "Actually perform export test.
@@ -671,47 +743,77 @@ Argument INPUT icalendar event string.
 Argument EXPECTED-ISO expected iso style diary string.
 Argument EXPECTED-EUROPEAN expected european style diary string.
 Argument EXPECTED-AMERICAN expected american style diary string."
-  (let ((timezone (cadr (current-time-zone))))
-    (set-time-zone-rule "CET")
-    (with-temp-buffer
-      (if (string-match "^BEGIN:VCALENDAR" input)
-          (insert input)
-        (insert "BEGIN:VCALENDAR\nPRODID:-//Emacs//NONSGML icalendar.el//EN\n")
-        (insert "VERSION:2.0\nBEGIN:VEVENT\n")
-        (insert input)
-        (unless (eq (char-before) ?\n)
-          (insert "\n"))
-        (insert "END:VEVENT\nEND:VCALENDAR\n"))
-      (let ((icalendar-import-format "%s%d%l%o%t%u%c")
-            (icalendar-import-format-summary "%s")
-            (icalendar-import-format-location "\n Location: %s")
-            (icalendar-import-format-description "\n Desc: %s")
-            (icalendar-import-format-organizer "\n Organizer: %s")
-            (icalendar-import-format-status "\n Status: %s")
-            (icalendar-import-format-url "\n URL: %s")
-            (icalendar-import-format-class "\n Class: %s")
-            calendar-date-style)
-        (when expected-iso
-          (setq calendar-date-style 'iso)
-          (icalendar-tests--do-test-import input expected-iso))
-        (when expected-european
-          (setq calendar-date-style 'european)
-          (icalendar-tests--do-test-import input expected-european))
-        (when expected-american
-          (setq calendar-date-style 'american)
-          (icalendar-tests--do-test-import input expected-american))))
-    (set-time-zone-rule timezone)))
+  (let ((timezone (getenv "TZ")))
+    (unwind-protect
+       (progn
+;;;      (message "Current time zone: %s" (current-time-zone))
+         ;; Use this form so as not to rely on system tz database.
+         ;; Eg hydra.nixos.org.
+         (setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
+;;;      (message "Current time zone: %s" (current-time-zone))
+         (with-temp-buffer
+           (if (string-match "^BEGIN:VCALENDAR" input)
+               (insert input)
+             (insert "BEGIN:VCALENDAR\nPRODID:-//Emacs//NONSGML icalendar.el//EN\n")
+             (insert "VERSION:2.0\nBEGIN:VEVENT\n")
+             (insert input)
+             (unless (eq (char-before) ?\n)
+               (insert "\n"))
+             (insert "END:VEVENT\nEND:VCALENDAR\n"))
+           (let ((icalendar-import-format "%s%d%l%o%t%u%c%U")
+                 (icalendar-import-format-summary "%s")
+                 (icalendar-import-format-location "\n Location: %s")
+                 (icalendar-import-format-description "\n Desc: %s")
+                 (icalendar-import-format-organizer "\n Organizer: %s")
+                 (icalendar-import-format-status "\n Status: %s")
+                 (icalendar-import-format-url "\n URL: %s")
+                 (icalendar-import-format-class "\n Class: %s")
+                 (icalendar-import-format-uid "\n UID: %s")
+                 calendar-date-style)
+             (when expected-iso
+               (setq calendar-date-style 'iso)
+               (icalendar-tests--do-test-import input expected-iso))
+             (when expected-european
+               (setq calendar-date-style 'european)
+               (icalendar-tests--do-test-import input expected-european))
+             (when expected-american
+               (setq calendar-date-style 'american)
+               (icalendar-tests--do-test-import input expected-american)))))
+      (setenv "TZ" timezone))))
 
 (defun icalendar-tests--do-test-import (input expected-output)
   "Actually perform import test.
 Argument INPUT input icalendar string.
 Argument EXPECTED-OUTPUT expected diary string."
   (let ((temp-file (make-temp-file "icalendar-test-diary")))
+    ;; Test the Catch-the-mysterious-coding-header logic below.
+    ;; Ruby-mode adds an after-save-hook which inserts the header!
+    ;; (save-excursion
+    ;;   (find-file temp-file)
+    ;;   (ruby-mode))
     (icalendar-import-buffer temp-file t t)
     (save-excursion
       (find-file temp-file)
+      ;; Check for the mysterious "# coding: ..." header, remove it
+      ;; and give a shout
+      (goto-char (point-min))
+      (when (re-search-forward "# coding: .*?\n" nil t)
+        (message (concat "%s\n"
+                         "Found mysterious \"# coding ...\" header!  Removing it.\n"
+                         "Current Modes: %s, %s\n"
+                         "Current test: %s\n"
+                         "%s")
+                 (make-string 70 ?*)
+                 major-mode
+                 minor-mode-list
+                 (ert-running-test)
+                 (make-string 70 ?*))
+        (buffer-disable-undo)
+        (replace-match "")
+        (set-buffer-modified-p nil))
+
       (let ((result (buffer-substring-no-properties (point-min) (point-max))))
-       (should (string= expected-output result)))
+        (should (string= expected-output result)))
       (kill-buffer (find-buffer-visiting temp-file))
       (delete-file temp-file))))
 
@@ -751,14 +853,17 @@ DTSTAMP:20031103T011641Z
    "&%%(and (diary-block 2004 7 19 2004 8 27)) Sommerferien
  Status: TENTATIVE
  Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
 "
    "&%%(and (diary-block 19 7 2004 27 8 2004)) Sommerferien
  Status: TENTATIVE
  Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
 "
    "&%%(and (diary-block 7 19 2004 8 27 2004)) Sommerferien
  Status: TENTATIVE
  Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
 ")
   (icalendar-tests--test-import
    "UID
@@ -782,13 +887,16 @@ LAST-MODIFIED
 "
    "&2004/11/23 14:00-14:30 folded summary
  Status: TENTATIVE
- Class: PRIVATE\n"
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n"
    "&23/11/2004 14:00-14:30 folded summary
  Status: TENTATIVE
- Class: PRIVATE\n"
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n"
    "&11/23/2004 14:00-14:30 folded summary
  Status: TENTATIVE
- Class: PRIVATE\n")
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n")
 
   (icalendar-tests--test-import
    "UID
@@ -810,13 +918,16 @@ DTSTAMP
 "
    "&2004/11/23 14:45-15:45 another example
  Status: TENTATIVE
- Class: PRIVATE\n"
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b\n"
    "&23/11/2004 14:45-15:45 another example
  Status: TENTATIVE
- Class: PRIVATE\n"
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b\n"
    "&11/23/2004 14:45-15:45 another example
  Status: TENTATIVE
- Class: PRIVATE\n"))
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b\n"))
 
 (ert-deftest icalendar-import-rrule ()
   (icalendar-tests--test-import
@@ -879,7 +990,6 @@ RRULE:FREQ=MONTHLY;UNTIL=20050819;
    "DTSTART;VALUE=DATE:20040815
 DTEND;VALUE=DATE:20040816
 SUMMARY:Maria Himmelfahrt
-UID:CC56BEA6-49D2-11D8-8833-00039386D1C2-RID
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8
 "
    "&%%(and (diary-anniversary 2004 8 15))  Maria Himmelfahrt\n"
@@ -982,11 +1092,14 @@ SEQUENCE:1
 CREATED:20041127T183329
 "
    "&%%(and (diary-cyclic 1 2001 12 21) (diary-block 2001 12 21 2001 12 29))  Urlaub
- Class: PUBLIC\n"
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"
    "&%%(and (diary-cyclic 1 21 12 2001) (diary-block 21 12 2001 29 12 2001))  Urlaub
- Class: PUBLIC\n"
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"
    "&%%(and (diary-cyclic 1 12 21 2001) (diary-block 12 21 2001 12 29 2001))  Urlaub
- Class: PUBLIC\n"))
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"))
 
 (ert-deftest icalendar-import-bug-6766 ()
   ;;bug#6766 -- multiple byday values in a weekly rrule
@@ -1016,20 +1129,26 @@ UID:8814e3f9-7482-408f-996c-3bfe486a1263
 "&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 2010 4 21)) 11:30-12:00 Scrum
  Status: CONFIRMED
  Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
 &%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 2010 4 22)) Tues + Thurs thinking
  Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
 "
 "&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 21 4 2010)) 11:30-12:00 Scrum
  Status: CONFIRMED
  Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
 &%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 22 4 2010)) Tues + Thurs thinking
  Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
 "
 "&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 4 21 2010)) 11:30-12:00 Scrum
  Status: CONFIRMED
  Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
 &%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 4 22 2010)) Tues + Thurs thinking
  Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
 "))
 
 (ert-deftest icalendar-import-multiple-vcalendars ()
@@ -1074,6 +1193,55 @@ END:VCALENDAR
    "&23/7/2011 event-1\n&24/7/2011 event-2\n&25/7/2011 event-3a\n&25/7/2011 event-3b\n"
    "&7/23/2011 event-1\n&7/24/2011 event-2\n&7/25/2011 event-3a\n&7/25/2011 event-3b\n"))
 
+(ert-deftest icalendar-import-with-uid ()
+  "Perform import test with uid."
+  (icalendar-tests--test-import
+   "UID:1234567890uid
+SUMMARY:non-recurring
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000"
+   "&2003/9/19 09:00-11:30 non-recurring\n UID: 1234567890uid\n"
+   "&19/9/2003 09:00-11:30 non-recurring\n UID: 1234567890uid\n"
+   "&9/19/2003 09:00-11:30 non-recurring\n UID: 1234567890uid\n"))
+
+(ert-deftest icalendar-import-with-timezone ()
+  ;; bug#11473
+  (icalendar-tests--test-import
+   "BEGIN:VCALENDAR
+BEGIN:VTIMEZONE
+TZID:fictional\, nonexistent\, arbitrary
+BEGIN:STANDARD
+DTSTART:20100101T000000
+TZOFFSETFROM:+0200
+TZOFFSETTO:-0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=01
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20101201T000000
+TZOFFSETFROM:-0200
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+SUMMARY:standardtime
+DTSTART;TZID=\"fictional, nonexistent, arbitrary\":20120115T120000
+DTEND;TZID=\"fictional, nonexistent, arbitrary\":20120115T123000
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY:daylightsavingtime
+DTSTART;TZID=\"fictional, nonexistent, arbitrary\":20121215T120000
+DTEND;TZID=\"fictional, nonexistent, arbitrary\":20121215T123000
+END:VEVENT
+END:VCALENDAR"
+   ;; "standardtime" begins first sunday in january and is 4 hours behind CET
+   ;; "daylightsavingtime" begins first sunday in november and is 1 hour before CET
+   "&2012/1/15 15:00-15:30 standardtime
+&2012/12/15 11:00-11:30 daylightsavingtime
+"
+   nil
+   nil)
+  )
 ;; ======================================================================
 ;; Cycle
 ;; ======================================================================
@@ -1089,14 +1257,15 @@ Argument INPUT icalendar event string."
       (unless (eq (char-before) ?\n)
         (insert "\n"))
       (insert "END:VEVENT\nEND:VCALENDAR\n"))
-    (let ((icalendar-import-format "%s%d%l%o%t%u%c")
+    (let ((icalendar-import-format "%s%d%l%o%t%u%c%U")
           (icalendar-import-format-summary "%s")
           (icalendar-import-format-location "\n Location: %s")
           (icalendar-import-format-description "\n Desc: %s")
           (icalendar-import-format-organizer "\n Organizer: %s")
           (icalendar-import-format-status "\n Status: %s")
           (icalendar-import-format-url "\n URL: %s")
-          (icalendar-import-format-class "\n Class: %s"))
+          (icalendar-import-format-class "\n Class: %s")
+          (icalendar-import-format-class "\n UID: %s"))
       (dolist (calendar-date-style '(iso european american))
         (icalendar-tests--do-test-cycle)))))
 
@@ -1120,28 +1289,30 @@ Argument INPUT icalendar event string."
          (save-excursion
            (find-file temp-ics)
            (goto-char (point-min))
-           (when (re-search-forward "\nUID:.*\n" nil t)
-             (replace-match "\n"))
+           ;;(when (re-search-forward "\nUID:.*\n" nil t)
+             ;;(replace-match "\n"))
            (let ((cycled (buffer-substring-no-properties (point-min) (point-max))))
              (should (string= org-input cycled)))))
       ;; clean up
       (kill-buffer (find-buffer-visiting temp-diary))
-      (save-excursion
-       (set-buffer (find-buffer-visiting temp-ics))
+      (with-current-buffer (find-buffer-visiting temp-ics)
        (set-buffer-modified-p nil)
        (kill-buffer (current-buffer)))
       (delete-file temp-diary)
       (delete-file temp-ics))))
 
 (ert-deftest icalendar-cycle ()
-  "Perform cycling tests."
+  "Perform cycling tests.
+Take care to avoid auto-generated UIDs here."
   (icalendar-tests--test-cycle
-   "DTSTART;VALUE=DATE-TIME:20030919T090000
+   "UID:dummyuid
+DTSTART;VALUE=DATE-TIME:20030919T090000
 DTEND;VALUE=DATE-TIME:20030919T113000
 SUMMARY:Cycletest
 ")
   (icalendar-tests--test-cycle
-   "DTSTART;VALUE=DATE-TIME:20030919T090000
+   "UID:blah
+DTSTART;VALUE=DATE-TIME:20030919T090000
 DTEND;VALUE=DATE-TIME:20030919T113000
 SUMMARY:Cycletest
 DESCRIPTION:beschreibung!
@@ -1149,7 +1320,8 @@ LOCATION:nowhere
 ORGANIZER:ulf
 ")
     (icalendar-tests--test-cycle
-     "DTSTART;VALUE=DATE:19190909
+     "UID:4711
+DTSTART;VALUE=DATE:19190909
 DTEND;VALUE=DATE:19190910
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=09;BYMONTHDAY=09
 SUMMARY:and diary-anniversary
@@ -1222,12 +1394,14 @@ END:VCALENDAR"
  Location: Cccc
  Organizer: MAILTO:aaaaaaa@aaaaaaa.com
  Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
 "
    "&5/9/2003 10:30-15:30 On-Site Interview
  Desc: 10:30am - Blah
  Location: Cccc
  Organizer: MAILTO:aaaaaaa@aaaaaaa.com
  Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
 ")
 
   ;; 2003-06-18 a
@@ -1268,12 +1442,14 @@ END:VALARM"
  Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
  Organizer: MAILTO:xxx@xxxxx.com
  Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
 "
    "&6/23/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
  Desc: 753 Zeichen hier radiert
  Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
  Organizer: MAILTO:xxx@xxxxx.com
  Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
 ")
   ;; 2003-06-18 b -- uses timezone
   (icalendar-tests--test-import
@@ -1338,12 +1514,14 @@ END:VCALENDAR"
  Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
  Organizer: MAILTO:bbb@bbbbb.com
  Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
 "
    "&6/23/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
  Desc: Viele Zeichen standen hier früher
  Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
  Organizer: MAILTO:bbb@bbbbb.com
  Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
 ")
   ;; export 2004-10-28 block entries
   (icalendar-tests--test-export
@@ -1567,8 +1745,6 @@ VERSION
 PRODID
  :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN
 BEGIN:VEVENT
-UID
- :04979712-3902-11d9-93dd-8f9f4afe08da
 SUMMARY
  :Jjjjj & Wwwww
 STATUS
@@ -1587,8 +1763,6 @@ LAST-MODIFIED
  :20041118T013640Z
 END:VEVENT
 BEGIN:VEVENT
-UID
- :6161a312-3902-11d9-b512-f764153bb28b
 SUMMARY
  :BB Aaaaaaaa Bbbbb
 STATUS
@@ -1605,8 +1779,6 @@ DTSTAMP
  :20041118T013641Z
 END:VEVENT
 BEGIN:VEVENT
-UID
- :943a4d7e-3902-11d9-9ce7-c9addeadf928
 SUMMARY
  :Hhhhhhhh
 STATUS
@@ -1623,8 +1795,6 @@ DTSTAMP
  :20041118T013831Z
 END:VEVENT
 BEGIN:VEVENT
-UID
- :fe53615e-3902-11d9-9dd8-9d38a155bf41
 SUMMARY
  :MMM Aaaaaaaaa
 STATUS
@@ -1645,8 +1815,6 @@ DTSTAMP
  :20041118T014117Z
 END:VEVENT
 BEGIN:VEVENT
-UID
- :87c928ee-3901-11d9-b21f-b45042155024
 SUMMARY
  :Rrrr/Cccccc ii Aaaaaaaa
 DESCRIPTION
@@ -1669,8 +1837,6 @@ LAST-MODIFIED
  :20041118T014203Z
 END:VEVENT
 BEGIN:VEVENT
-UID
- :e8f331ae-3902-11d9-9948-dfdcb66a2872
 SUMMARY
  :Wwww aa hhhh
 STATUS
@@ -1790,11 +1956,13 @@ DTSTAMP
  Desc: abcdef
  Status: CONFIRMED
  Class: PRIVATE
+ UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
 "
    "&%%(and (diary-block 2 6 2005 2 6 2005)) Waitangi Day
  Desc: abcdef
  Status: CONFIRMED
  Class: PRIVATE
+ UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
 ")
 
   ;; 2005-03-01 lt
@@ -1805,8 +1973,10 @@ UID:6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
 DTSTAMP:20050118T210335Z
 DURATION:P7D"
    nil
-   "&%%(and (diary-block 17 2 2005 23 2 2005)) Hhhhhh Aaaaa ii Aaaaaaaa\n"
-   "&%%(and (diary-block 2 17 2005 2 23 2005)) Hhhhhh Aaaaa ii Aaaaaaaa\n")
+   "&%%(and (diary-block 17 2 2005 23 2 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
+ UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID\n"
+   "&%%(and (diary-block 2 17 2005 2 23 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
+ UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID\n")
 
   ;; 2005-03-23 lt
   (icalendar-tests--test-export
@@ -1831,7 +2001,72 @@ DTEND;VALUE=DATE:19001102
 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=11;BYMONTHDAY=1
 SUMMARY:NNN Wwwwwwww Wwwww - Aaaaaa Pppppppp rrrrrr ddd oo Nnnnnnnn 30
 ")
-  )
+
+  ;; bug#11473
+  (icalendar-tests--test-import
+   "BEGIN:VCALENDAR
+METHOD:REQUEST
+PRODID:Microsoft Exchange Server 2007
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:(UTC+01:00) Amsterdam\, Berlin\, Bern\, Rome\, Stockholm\, Vienna
+BEGIN:STANDARD
+DTSTART:16010101T030000
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+ORGANIZER;CN=\"A. Luser\":MAILTO:a.luser@foo.com
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Luser, Oth
+ er\":MAILTO:other.luser@foo.com
+DESCRIPTION;LANGUAGE=en-US:\nWhassup?\n\n
+SUMMARY;LANGUAGE=en-US:Query
+DTSTART;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna\"
+ :20120515T150000
+DTEND;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna\":2
+ 0120515T153000
+UID:040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000
+ 010000000575268034ECDB649A15349B1BF240F15
+RECURRENCE-ID;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, V
+ ienna\":20120515T170000
+CLASS:PUBLIC
+PRIORITY:5
+DTSTAMP:20120514T153645Z
+TRANSP:OPAQUE
+STATUS:CONFIRMED
+SEQUENCE:15
+LOCATION;LANGUAGE=en-US:phone
+X-MICROSOFT-CDO-APPT-SEQUENCE:15
+X-MICROSOFT-CDO-OWNERAPPTID:1907632092
+X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-INSTTYPE:3
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT15M
+END:VALARM
+END:VEVENT
+END:VCALENDAR"
+   nil
+   "&15/5/2012 15:00-15:30 Query
+ Location: phone
+ Organizer: MAILTO:a.luser@foo.com
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000010000000575268034ECDB649A15349B1BF240F15
+"     nil)
+)
 
 (provide 'icalendar-tests)
 ;;; icalendar-tests.el ends here