]> git.eshelyaron.com Git - emacs.git/commitdiff
Some final fixes in file notification before merging with master
authorMichael Albinus <michael.albinus@gmx.de>
Wed, 25 Nov 2015 14:00:06 +0000 (15:00 +0100)
committerMichael Albinus <michael.albinus@gmx.de>
Wed, 25 Nov 2015 14:07:12 +0000 (15:07 +0100)
* lisp/filenotify.el (file-notify--rm-descriptor): Remove WHAT arg.
(file-notify-callback): Improve check for `stopped' event.  Call
`file-notify-rm-watch' rather than `file-notify--rm-descriptor'.
(file-notify-add-watch): In case FILE is not a directory, call the
file monitor for the kqueue backend.  Otherwise, call the
directory monitor for the upper directory.

* src/inotify.c (inotifyevent_to_event): Extract file name from
watch_object if the event doesn't provide it.
(Finotify_add_watch): Add file name to watch_object.

* test/automated/file-notify-tests.el (file-notify--test-timeout):
Use different timeouts for different libraries.
(file-notify--test-with-events): Suppress lock files.  Flush
outstanding events before running the body.
(file-notify-test02-events, file-notify-test04-file-validity): Do
not skip cygwin tests.  Add additional test for file creation.
Adapt expected result for different backends.
(file-notify-test03-autorevert): Some of the tests don't work for
w32notify.
(file-notify-test06-many-events): Rename into both directions.

lisp/filenotify.el
src/inotify.c
test/automated/file-notify-tests.el

index 0d7a2b914c6e0bfeb5a592c05c9837ec9af7e8b2..b6c1f686fe15b4457da4fa1f71d76c0af41f9d6c 100644 (file)
@@ -49,17 +49,16 @@ handler.  The value in the hash table is a list
 Several values for a given DIR happen only for `inotify', when
 different files from the same directory are watched.")
 
-(defun file-notify--rm-descriptor (descriptor &optional what)
+(defun file-notify--rm-descriptor (descriptor)
   "Remove DESCRIPTOR from `file-notify-descriptors'.
 DESCRIPTOR should be an object returned by `file-notify-add-watch'.
-If it is registered in `file-notify-descriptors', a stopped event is sent.
-WHAT is a file or directory name to be removed, needed just for `inotify'."
+If it is registered in `file-notify-descriptors', a stopped event is sent."
   (let* ((desc (if (consp descriptor) (car descriptor) descriptor))
         (file (if (consp descriptor) (cdr descriptor)))
          (registered (gethash desc file-notify-descriptors))
         (dir (car registered)))
 
-    (when (and (consp registered) (or (null what) (string-equal dir what)))
+    (when (consp registered)
       ;; Send `stopped' event.
       (dolist (entry (cdr registered))
        (funcall (cdr entry)
@@ -236,7 +235,6 @@ EVENT is the cadr of the event in `file-notify-handle-event'
           (setq pending-event nil))
 
         ;; Check for stopped.
-       ;;(message "file-notify-callback %S %S %S" file file1 registered)
         (setq
          stopped
          (or
@@ -244,10 +242,13 @@ EVENT is the cadr of the event in `file-notify-handle-event'
           (and
            (memq action '(deleted renamed))
            (= (length (cdr registered)) 1)
-           (string-equal
-            (file-name-nondirectory file)
-           (or (file-name-nondirectory (car registered))
-               (car (cadr registered)))))))
+           (or
+            (string-equal
+             (file-name-nondirectory file)
+            (file-name-nondirectory (car registered)))
+            (string-equal
+             (file-name-nondirectory file)
+             (car (cadr registered)))))))
 
        ;; Apply callback.
        (when (and action
@@ -266,6 +267,9 @@ EVENT is the cadr of the event in `file-notify-handle-event'
                    (and (stringp file1)
                         (string-equal
                          (nth 0 entry) (file-name-nondirectory file1)))))
+          ;;(message
+           ;;"file-notify-callback %S %S %S %S %S"
+           ;;(file-notify--descriptor desc file) action file file1 registered)
          (if file1
              (funcall
               callback
@@ -276,8 +280,7 @@ EVENT is the cadr of the event in `file-notify-handle-event'
 
       ;; Modify `file-notify-descriptors'.
       (when stopped
-        (file-notify--rm-descriptor
-         (file-notify--descriptor desc file) file)))))
+        (file-notify-rm-watch (file-notify--descriptor desc file))))))
 
 ;; `kqueue', `gfilenotify' and `w32notify' return a unique descriptor
 ;; for every `file-notify-add-watch', while `inotify' returns a unique
@@ -342,7 +345,12 @@ FILE is the name of the file whose event is being reported."
        ;; A file name handler could exist even if there is no local
        ;; file notification support.
        (setq desc (funcall
-                   handler 'file-notify-add-watch file flags callback))
+                   handler 'file-notify-add-watch
+                    ;; kqueue does not report file changes in
+                    ;; directory monitor.  So we must watch the file
+                    ;; itself.
+                    (if (eq file-notify--library 'kqueue) file dir)
+                    flags callback))
 
       ;; Check, whether Emacs has been compiled with file notification
       ;; support.
@@ -379,7 +387,9 @@ FILE is the name of the file whose event is being reported."
                 l-flags)))
 
       ;; Call low-level function.
-      (setq desc (funcall func file l-flags 'file-notify-callback)))
+      (setq desc (funcall
+                  func (if (eq file-notify--library 'kqueue) file dir)
+                  l-flags 'file-notify-callback)))
 
     ;; Modify `file-notify-descriptors'.
     (setq file (unless (file-directory-p file) (file-name-nondirectory file))
index d1a80bbad1bd60d297dbfc7e01c63fddb4f5b223..6577ee28cd135029fe904dc4bd5462e7888daf73 100644 (file)
@@ -46,8 +46,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 static int inotifyfd = -1;
 
 /* Assoc list of files being watched.
-   Format:
-   (watch-descriptor . callback)
+   Format: (watch-descriptor name callback)
  */
 static Lisp_Object watch_list;
 
@@ -106,12 +105,14 @@ inotifyevent_to_event (Lisp_Object watch_object, struct inotify_event const *ev)
       name = make_unibyte_string (ev->name, min (len, ev->len));
       name = DECODE_FILE (name);
     }
+  else
+    name = XCAR (XCDR (watch_object));
 
   return list2 (list4 (make_watch_descriptor (ev->wd),
                        mask_to_aspects (ev->mask),
                        name,
                        make_number (ev->cookie)),
-                XCDR (watch_object));
+               Fnth (make_number (2), watch_object));
 }
 
 /* This callback is called when the FD is available for read.  The inotify
@@ -325,7 +326,7 @@ is managed internally and there is no corresponding inotify_init.  Use
       watch_list = Fdelete (watch_object, watch_list);
 
   /* Store watch object in watch list.  */
-  watch_object = Fcons (watch_descriptor, callback);
+  watch_object = list3 (watch_descriptor, encoded_file_name, callback);
   watch_list = Fcons (watch_object, watch_list);
 
   return watch_descriptor;
index 7bacddd8855bd1a4742daee5b25f4c8ad6e9cdb0..b665dddb6315a610c11c81e8d601871c085ac441 100644 (file)
 
 (defun file-notify--test-timeout ()
   "Timeout to wait for arriving events, in seconds."
-  (if (file-remote-p temporary-file-directory) 6 3))
+  (cond
+   ((file-remote-p temporary-file-directory) 6)
+   ((string-equal (file-notify--test-library) "w32notify") 20)
+   ((eq system-type 'cygwin) 10)
+   (t 3)))
 
 (defun file-notify--test-cleanup ()
   "Cleanup after a test."
@@ -262,7 +266,7 @@ and the event to `file-notify--test-events'."
   (let* ((file-notify--test-event event)
          (result
           (ert-run-test (make-ert-test :body 'file-notify--test-event-test))))
-    ;; Do not add temporary files, this would confuse the checks.
+    ;; Do not add lock files, this would confuse the checks.
     (unless (string-match
             (regexp-quote ".#")
             (file-notify--event-file-name file-notify--test-event))
@@ -289,9 +293,14 @@ TIMEOUT is the maximum time to wait for, in seconds."
 Don't wait longer than timeout seconds for the events to be delivered."
   (declare (indent 1))
   (let ((outer (make-symbol "outer")))
-    `(let ((,outer file-notify--test-events))
+    `(let ((,outer file-notify--test-events)
+           create-lockfiles)
        (setq file-notify--test-expected-events
             (append file-notify--test-expected-events ,events))
+       ;; Flush pending events.
+       (file-notify--wait-for-events
+        (file-notify--test-timeout)
+        (input-pending-p))
        (let (file-notify--test-events)
          ,@body
          (file-notify--wait-for-events
@@ -305,11 +314,34 @@ Don't wait longer than timeout seconds for the events to be delivered."
 (ert-deftest file-notify-test02-events ()
   "Check file creation/change/removal notifications."
   (skip-unless (file-notify--test-local-enabled))
-  ;; Under cygwin there are so bad timings that it doesn't make sense to test.
-  (skip-unless (not (eq system-type 'cygwin)))
 
   (unwind-protect
       (progn
+        ;; Check file creation, change and deletion.  It doesn't work
+        ;; for cygwin and kqueue, because we don't use an implicit
+        ;; directory monitor (kqueue), or the timings are too bad (cygwin).
+        (unless (or (eq system-type 'cygwin)
+                   (string-equal (file-notify--test-library) "kqueue"))
+          (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
+          (should
+           (setq file-notify--test-desc
+                 (file-notify-add-watch
+                  file-notify--test-tmpfile
+                  '(change) 'file-notify--test-event-handler)))
+          (file-notify--test-with-events
+              (cond
+               ;; cygwin recognizes only `deleted' and `stopped' events.
+               ((eq system-type 'cygwin)
+                '(deleted stopped))
+               (t '(created changed deleted stopped)))
+            (write-region
+             "another text" nil file-notify--test-tmpfile nil 'no-message)
+            (read-event nil nil 0.1)
+            (delete-file file-notify--test-tmpfile))
+          ;; `file-notify-rm-watch' fires the `stopped' event.  Suppress it.
+          (let (file-notify--test-events)
+            (file-notify-rm-watch file-notify--test-desc)))
+
         ;; Check file change and deletion.
        (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
         (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
@@ -318,9 +350,23 @@ Don't wait longer than timeout seconds for the events to be delivered."
               (file-notify-add-watch
                file-notify--test-tmpfile
                '(change) 'file-notify--test-event-handler)))
-        (file-notify--test-with-events '(changed deleted)
+        (file-notify--test-with-events
+           (cond
+            ;; cygwin recognizes only `deleted' and `stopped' events.
+            ((eq system-type 'cygwin)
+             '(deleted stopped))
+             ;; inotify, kqueueg and gfilenotify raise just one
+             ;; `changed' event, the other backends show us two of
+             ;; them.
+             ((or (string-equal "inotify" (file-notify--test-library))
+                  (string-equal "kqueue" (file-notify--test-library))
+                  (string-equal "gfilenotify" (file-notify--test-library)))
+             '(changed deleted stopped))
+            (t '(changed changed deleted stopped)))
+          (read-event nil nil 0.1)
           (write-region
            "another text" nil file-notify--test-tmpfile nil 'no-message)
+          (read-event nil nil 0.1)
           (delete-file file-notify--test-tmpfile))
        ;; `file-notify-rm-watch' fires the `stopped' event.  Suppress it.
        (let (file-notify--test-events)
@@ -328,29 +374,37 @@ Don't wait longer than timeout seconds for the events to be delivered."
 
         ;; Check file creation, change and deletion when watching a
         ;; directory.  There must be a `stopped' event when deleting
-        ;; the directory.  It doesn't work for w32notify.
-       (unless (string-equal (file-notify--test-library) "w32notify")
-         (let ((temporary-file-directory
-                (make-temp-file "file-notify-test-parent" t)))
-           (should
-            (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
-                  file-notify--test-desc
-                  (file-notify-add-watch
-                   temporary-file-directory
-                   '(change) 'file-notify--test-event-handler)))
-           (file-notify--test-with-events
-               ;; There are two `deleted' events, for the file and
-               ;; for the directory.  Except for kqueue.
-               (if (string-equal (file-notify--test-library) "kqueue")
-                   '(created changed deleted stopped)
-                 '(created changed deleted deleted stopped))
-             (write-region
-              "any text" nil file-notify--test-tmpfile nil 'no-message)
-             (read-event nil nil 0.1)
-             (delete-directory temporary-file-directory 'recursive))
-           ;; `file-notify-rm-watch' fires the `stopped' event.  Suppress it.
-           (let (file-notify--test-events)
-             (file-notify-rm-watch file-notify--test-desc))))
+        ;; the directory.
+       (let ((temporary-file-directory
+              (make-temp-file "file-notify-test-parent" t)))
+         (should
+          (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+                file-notify--test-desc
+                (file-notify-add-watch
+                 temporary-file-directory
+                 '(change) 'file-notify--test-event-handler)))
+         (file-notify--test-with-events
+             (cond
+              ;; w32notify does raise a `stopped' event when a
+              ;; watched directory is deleted.
+              ((string-equal (file-notify--test-library) "w32notify")
+               '(created changed deleted))
+              ;; cygwin recognizes only `deleted' and `stopped' events.
+              ((eq system-type 'cygwin)
+               '(deleted stopped))
+              ;; There are two `deleted' events, for the file and for
+              ;; the directory.  Except for kqueue.
+              ((string-equal (file-notify--test-library) "kqueue")
+               '(created changed deleted stopped))
+              (t '(created changed deleted deleted stopped)))
+           (read-event nil nil 0.1)
+           (write-region
+            "any text" nil file-notify--test-tmpfile nil 'no-message)
+           (read-event nil nil 0.1)
+           (delete-directory temporary-file-directory 'recursive))
+         ;; `file-notify-rm-watch' fires the `stopped' event.  Suppress it.
+         (let (file-notify--test-events)
+           (file-notify-rm-watch file-notify--test-desc)))
 
         ;; Check copy of files inside a directory.
        (let ((temporary-file-directory
@@ -363,11 +417,22 @@ Don't wait longer than timeout seconds for the events to be delivered."
                  temporary-file-directory
                  '(change) 'file-notify--test-event-handler)))
          (file-notify--test-with-events
-             ;; w32notify does not distinguish between `changed' and
-             ;; `attribute-changed'.
-             (if (string-equal (file-notify--test-library) "w32notify")
-                 '(created changed changed deleted)
+             (cond
+              ;; w32notify does not distinguish between `changed' and
+              ;; `attribute-changed'.
+              ((string-equal (file-notify--test-library) "w32notify")
+               '(created changed created changed changed changed changed
+                 deleted deleted))
+              ;; cygwin recognizes only `deleted' and `stopped' events.
+              ((eq system-type 'cygwin)
+               '(deleted stopped))
+              ;; There are three `deleted' events, for two files and
+              ;; for the directory.  Except for kqueue.
+              ((string-equal (file-notify--test-library) "kqueue")
                '(created changed created changed deleted stopped))
+              (t '(created changed created changed
+                   deleted deleted deleted stopped)))
+           (read-event nil nil 0.1)
            (write-region
             "any text" nil file-notify--test-tmpfile nil 'no-message)
            (read-event nil nil 0.1)
@@ -393,7 +458,21 @@ Don't wait longer than timeout seconds for the events to be delivered."
                 (file-notify-add-watch
                  temporary-file-directory
                  '(change) 'file-notify--test-event-handler)))
-         (file-notify--test-with-events '(created changed renamed)
+         (file-notify--test-with-events
+             (cond
+              ;; w32notify does not distinguish between `changed' and
+              ;; `attribute-changed'.
+              ((string-equal (file-notify--test-library) "w32notify")
+               '(created changed renamed deleted))
+              ;; cygwin recognizes only `deleted' and `stopped' events.
+              ((eq system-type 'cygwin)
+               '(deleted stopped))
+              ;; There are two `deleted' events, for the file and for
+              ;; the directory.  Except for kqueue.
+              ((string-equal (file-notify--test-library) "kqueue")
+               '(created changed renamed deleted stopped))
+              (t '(created changed renamed deleted deleted stopped)))
+           (read-event nil nil 0.1)
            (write-region
             "any text" nil file-notify--test-tmpfile nil 'no-message)
            (read-event nil nil 0.1)
@@ -405,30 +484,37 @@ Don't wait longer than timeout seconds for the events to be delivered."
          (let (file-notify--test-events)
            (file-notify-rm-watch file-notify--test-desc)))
 
-        ;; Check attribute change.  It doesn't work for kqueue and w32notify.
-       (unless (or (string-equal (file-notify--test-library) "kqueue")
-                   (string-equal (file-notify--test-library) "w32notify"))
+        ;; Check attribute change.  Does not work for cygwin.
+       (unless (eq system-type 'cygwin)
+         (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
+         (write-region
+          "any text" nil file-notify--test-tmpfile nil 'no-message)
          (should
           (setq file-notify--test-desc
                 (file-notify-add-watch
                  file-notify--test-tmpfile
                  '(attribute-change) 'file-notify--test-event-handler)))
-          (file-notify--test-with-events
-              (if (file-remote-p temporary-file-directory)
-                  ;; In the remote case, `write-region' raises also an
-                  ;; `attribute-changed' event.
-                  '(attribute-changed attribute-changed attribute-changed)
-                '(attribute-changed attribute-changed))
-            ;; We must use short delays between the operations.
-            ;; Otherwise, not all events arrive us in the remote case.
-            (write-region
-             "any text" nil file-notify--test-tmpfile nil 'no-message)
-            (read-event nil nil 0.1)
-            (set-file-modes file-notify--test-tmpfile 000)
-            (read-event nil nil 0.1)
-            (set-file-times file-notify--test-tmpfile '(0 0))
-            (read-event nil nil 0.1)
-            (delete-file file-notify--test-tmpfile))
+         (file-notify--test-with-events
+             (cond
+              ;; w32notify does not distinguish between `changed' and
+              ;; `attribute-changed'.
+              ((string-equal (file-notify--test-library) "w32notify")
+               '(changed changed changed changed))
+              ;; For kqueue and in the remote case, `write-region'
+              ;; raises also an `attribute-changed' event.
+              ((or (string-equal (file-notify--test-library) "kqueue")
+                   (file-remote-p temporary-file-directory))
+               '(attribute-changed attribute-changed attribute-changed))
+              (t '(attribute-changed attribute-changed)))
+           (read-event nil nil 0.1)
+           (write-region
+            "any text" nil file-notify--test-tmpfile nil 'no-message)
+           (read-event nil nil 0.1)
+           (set-file-modes file-notify--test-tmpfile 000)
+           (read-event nil nil 0.1)
+           (set-file-times file-notify--test-tmpfile '(0 0))
+           (read-event nil nil 0.1)
+           (delete-file file-notify--test-tmpfile))
          ;; `file-notify-rm-watch' fires the `stopped' event.  Suppress it.
          (let (file-notify--test-events)
            (file-notify-rm-watch file-notify--test-desc)))
@@ -504,28 +590,31 @@ Don't wait longer than timeout seconds for the events to be delivered."
            (should (string-match "another text" (buffer-string)))
 
             ;; Stop file notification.  Autorevert shall still work via polling.
-           (file-notify-rm-watch auto-revert-notify-watch-descriptor)
-            (file-notify--wait-for-events
-             timeout (null auto-revert-use-notify))
-           (should-not auto-revert-use-notify)
-           (should-not auto-revert-notify-watch-descriptor)
-
-           ;; Modify file.  We wait for two seconds, in order to have
-           ;; another timestamp.  One second seems to be too short.
-            (with-current-buffer (get-buffer-create "*Messages*")
-              (narrow-to-region (point-max) (point-max)))
-           (sleep-for 2)
-            (write-region
-             "foo bla" nil file-notify--test-tmpfile nil 'no-message)
-
-           ;; Check, that the buffer has been reverted.
-           (with-current-buffer (get-buffer-create "*Messages*")
+           ;; It doesn't work for `w32notify'.
+           (unless (string-equal (file-notify--test-library) "w32notify")
+             (file-notify-rm-watch auto-revert-notify-watch-descriptor)
              (file-notify--wait-for-events
-              timeout
-              (string-match
-                (format-message "Reverting buffer `%s'." (buffer-name buf))
-                (buffer-string))))
-           (should (string-match "foo bla" (buffer-string)))))
+              timeout (null auto-revert-use-notify))
+             (should-not auto-revert-use-notify)
+             (should-not auto-revert-notify-watch-descriptor)
+
+             ;; Modify file.  We wait for two seconds, in order to
+             ;; have another timestamp.  One second seems to be too
+             ;; short.
+             (with-current-buffer (get-buffer-create "*Messages*")
+               (narrow-to-region (point-max) (point-max)))
+             (sleep-for 2)
+             (write-region
+              "foo bla" nil file-notify--test-tmpfile nil 'no-message)
+
+             ;; Check, that the buffer has been reverted.
+             (with-current-buffer (get-buffer-create "*Messages*")
+               (file-notify--wait-for-events
+                timeout
+                (string-match
+                 (format-message "Reverting buffer `%s'." (buffer-name buf))
+                 (buffer-string))))
+             (should (string-match "foo bla" (buffer-string))))))
 
       ;; Cleanup.
       (with-current-buffer "*Messages*" (widen))
@@ -538,8 +627,6 @@ Don't wait longer than timeout seconds for the events to be delivered."
 (ert-deftest file-notify-test04-file-validity ()
   "Check `file-notify-valid-p' for files."
   (skip-unless (file-notify--test-local-enabled))
-  ;; Under cygwin there are so bad timings that it doesn't make sense to test.
-  (skip-unless (not (eq system-type 'cygwin)))
 
   (unwind-protect
       (progn
@@ -569,7 +656,20 @@ Don't wait longer than timeout seconds for the events to be delivered."
               (file-notify-add-watch
                file-notify--test-tmpfile
                '(change) #'file-notify--test-event-handler)))
-        (file-notify--test-with-events '(changed deleted)
+        (file-notify--test-with-events
+            (cond
+             ;; cygwin recognizes only `deleted' and `stopped' events.
+            ((eq system-type 'cygwin)
+             '(deleted stopped))
+             ;; inotify, kqueueg and gfilenotify raise just one
+             ;; `changed' event, the other backends show us two of
+             ;; them.
+             ((or (string-equal "inotify" (file-notify--test-library))
+                  (string-equal "kqueue" (file-notify--test-library))
+                  (string-equal "gfilenotify" (file-notify--test-library)))
+             '(changed deleted stopped))
+            (t '(changed changed deleted stopped)))
+         (read-event nil nil 0.1)
           (should (file-notify-valid-p file-notify--test-desc))
           (write-region
            "another text" nil file-notify--test-tmpfile nil 'no-message)
@@ -583,10 +683,10 @@ Don't wait longer than timeout seconds for the events to be delivered."
     (file-notify--test-cleanup))
 
   (unwind-protect
-      ;; The batch-mode operation of w32notify is fragile (there's no
-      ;; input threads to send the message to).
+      ;; w32notify does not send a `stopped' event when deleting a
+      ;; directory.  The test does not work, therefore.
       (unless (string-equal (file-notify--test-library) "w32notify")
-        (let ((temporary-file-directory
+       (let ((temporary-file-directory
               (make-temp-file "file-notify-test-parent" t)))
          (should
           (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
@@ -594,20 +694,25 @@ Don't wait longer than timeout seconds for the events to be delivered."
                 (file-notify-add-watch
                  temporary-file-directory
                  '(change) #'file-notify--test-event-handler)))
-          (file-notify--test-with-events
-             ;; There are two `deleted' events, for the file and for
-             ;; the directory.  Except for kqueue.
-             (if (string-equal (file-notify--test-library) "kqueue")
-                 '(created changed deleted stopped)
-               '(created changed deleted deleted stopped))
-            (should (file-notify-valid-p file-notify--test-desc))
-            (write-region
-             "any text" nil file-notify--test-tmpfile nil 'no-message)
-            (read-event nil nil 0.1)
+         (file-notify--test-with-events
+             (cond
+              ;; cygwin recognizes only `deleted' and `stopped' events.
+              ((eq system-type 'cygwin)
+               '(deleted stopped))
+              ;; There are two `deleted' events, for the file and for
+              ;; the directory.  Except for kqueue.
+              ((string-equal (file-notify--test-library) "kqueue")
+               '(created changed deleted stopped))
+              (t '(created changed deleted deleted stopped)))
+           (should (file-notify-valid-p file-notify--test-desc))
+           (read-event nil nil 0.1)
+           (write-region
+            "any text" nil file-notify--test-tmpfile nil 'no-message)
+           (read-event nil nil 0.1)
            (delete-directory temporary-file-directory t))
-          ;; After deleting the parent directory, the descriptor must
-          ;; not be valid anymore.
-          (should-not (file-notify-valid-p file-notify--test-desc))))
+         ;; After deleting the parent directory, the descriptor must
+         ;; not be valid anymore.
+         (should-not (file-notify-valid-p file-notify--test-desc))))
 
     ;; Cleanup.
     (file-notify--test-cleanup)))
@@ -659,7 +764,7 @@ Don't wait longer than timeout seconds for the events to be delivered."
         ;; valid anymore.
         (delete-directory file-notify--test-tmpfile t)
         (file-notify--wait-for-events
-         (file-notify--test-timeout)
+        (file-notify--test-timeout)
         (not (file-notify-valid-p file-notify--test-desc)))
         (should-not (file-notify-valid-p file-notify--test-desc)))
 
@@ -672,8 +777,9 @@ Don't wait longer than timeout seconds for the events to be delivered."
 (ert-deftest file-notify-test06-many-events ()
   "Check that events are not dropped."
   (skip-unless (file-notify--test-local-enabled))
-  ;; Under cygwin there are so bad timings that it doesn't make sense to test.
+  ;; Under cygwin events arrive in random order.  Impossible to define a test.
   (skip-unless (not (eq system-type 'cygwin)))
+
   (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
   (make-directory file-notify--test-tmpfile)
   (should
@@ -699,10 +805,18 @@ Don't wait longer than timeout seconds for the events to be delivered."
           (let ((source-file-list source-file-list)
                 (target-file-list target-file-list))
             (while (and source-file-list target-file-list)
+              (read-event nil nil 0.1)
               (write-region "" nil (pop source-file-list) nil 'no-message)
               (read-event nil nil 0.1)
               (write-region "" nil (pop target-file-list) nil 'no-message))))
-        (file-notify--test-with-events (make-list n 'renamed)
+        (file-notify--test-with-events
+           (cond
+            ;; w32notify fires both `deleted' and `renamed' events.
+            ((string-equal (file-notify--test-library) "w32notify")
+             (let (r)
+               (dotimes (i n r)
+                 (setq r (append '(deleted renamed) r)))))
+            (t (make-list n 'renamed)))
           (let ((source-file-list source-file-list)
                 (target-file-list target-file-list))
             (while (and source-file-list target-file-list)
@@ -725,7 +839,7 @@ Don't wait longer than timeout seconds for the events to be delivered."
 ;; TODO:
 
 ;; * For w32notify, no stopped events arrive when a directory is removed.
-;; * Try to handle arriving events under cygwin reliably.
+;; * Check, why cygwin recognizes only `deleted' and `stopped' events.
 
 (provide 'file-notify-tests)
 ;;; file-notify-tests.el ends here