; * admin/release-process: Minor copyedits and additions.
[emacs.git] / test / automated / file-notify-tests.el
blob67e929a647728d2f3fbb73633131662d31846182
1 ;;; file-notify-tests.el --- Tests of file notifications -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2013-2015 Free Software Foundation, Inc.
5 ;; Author: Michael Albinus <michael.albinus@gmx.de>
7 ;; This program is free software: you can redistribute it and/or
8 ;; modify it under the terms of the GNU General Public License as
9 ;; published by the Free Software Foundation, either version 3 of the
10 ;; License, or (at your option) any later version.
12 ;; This program is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with this program. If not, see `http://www.gnu.org/licenses/'.
20 ;;; Commentary:
22 ;; Some of the tests require access to a remote host files. Since
23 ;; this could be problematic, a mock-up connection method "mock" is
24 ;; used. Emulating a remote connection, it simply calls "sh -i".
25 ;; Tramp's file name handlers still run, so this test is sufficient
26 ;; except for connection establishing.
28 ;; If you want to test a real Tramp connection, set
29 ;; $REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to
30 ;; overwrite the default value. If you want to skip tests accessing a
31 ;; remote host, set this environment variable to "/dev/null" or
32 ;; whatever is appropriate on your system.
34 ;; A whole test run can be performed calling the command `file-notify-test-all'.
36 ;;; Code:
38 (require 'ert)
39 (require 'filenotify)
40 (require 'tramp)
42 ;; There is no default value on w32 systems, which could work out of the box.
43 (defconst file-notify-test-remote-temporary-file-directory
44 (cond
45 ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
46 ((eq system-type 'windows-nt) null-device)
47 (t (add-to-list
48 'tramp-methods
49 '("mock"
50 (tramp-login-program "sh")
51 (tramp-login-args (("-i")))
52 (tramp-remote-shell "/bin/sh")
53 (tramp-remote-shell-args ("-c"))
54 (tramp-connection-timeout 10)))
55 (format "/mock::%s" temporary-file-directory)))
56 "Temporary directory for Tramp tests.")
58 (defvar file-notify--test-tmpfile nil)
59 (defvar file-notify--test-tmpfile1 nil)
60 (defvar file-notify--test-desc nil)
61 (defvar file-notify--test-results nil)
62 (defvar file-notify--test-event nil)
63 (defvar file-notify--test-events nil)
64 (defvar file-notify--test-expected-events nil)
66 (defun file-notify--test-timeout ()
67 "Timeout to wait for arriving events, in seconds."
68 (if (file-remote-p temporary-file-directory) 6 3))
70 (defun file-notify--test-cleanup ()
71 "Cleanup after a test."
72 (file-notify-rm-watch file-notify--test-desc)
74 (when (and file-notify--test-tmpfile
75 (file-exists-p file-notify--test-tmpfile))
76 (if (file-directory-p file-notify--test-tmpfile)
77 (delete-directory file-notify--test-tmpfile 'recursive)
78 (delete-file file-notify--test-tmpfile)))
79 (when (and file-notify--test-tmpfile1
80 (file-exists-p file-notify--test-tmpfile1))
81 (if (file-directory-p file-notify--test-tmpfile1)
82 (delete-directory file-notify--test-tmpfile1 'recursive)
83 (delete-file file-notify--test-tmpfile1)))
84 (when (file-remote-p temporary-file-directory)
85 (tramp-cleanup-connection
86 (tramp-dissect-file-name temporary-file-directory) nil 'keep-password))
88 (setq file-notify--test-tmpfile nil
89 file-notify--test-tmpfile1 nil
90 file-notify--test-desc nil
91 file-notify--test-results nil
92 file-notify--test-events nil
93 file-notify--test-expected-events nil)
94 (when file-notify--test-event
95 (error "file-notify--test-event should not be set but bound dynamically")))
97 (setq password-cache-expiry nil
98 tramp-verbose 0
99 tramp-message-show-message nil)
101 ;; This shall happen on hydra only.
102 (when (getenv "NIX_STORE")
103 (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
105 ;; We do not want to try and fail `file-notify-add-watch'.
106 (defun file-notify--test-local-enabled ()
107 "Whether local file notification is enabled.
108 This is needed for local `temporary-file-directory' only, in the
109 remote case we return always t."
110 (or file-notify--library
111 (file-remote-p temporary-file-directory)))
113 (defvar file-notify--test-remote-enabled-checked nil
114 "Cached result of `file-notify--test-remote-enabled'.
115 If the function did run, the value is a cons cell, the `cdr'
116 being the result.")
118 (defun file-notify--test-remote-enabled ()
119 "Whether remote file notification is enabled."
120 (unless (consp file-notify--test-remote-enabled-checked)
121 (let (desc)
122 (ignore-errors
123 (and
124 (file-remote-p file-notify-test-remote-temporary-file-directory)
125 (file-directory-p file-notify-test-remote-temporary-file-directory)
126 (file-writable-p file-notify-test-remote-temporary-file-directory)
127 (setq desc
128 (file-notify-add-watch
129 file-notify-test-remote-temporary-file-directory
130 '(change) 'ignore))))
131 (setq file-notify--test-remote-enabled-checked (cons t desc))
132 (when desc (file-notify-rm-watch desc))))
133 ;; Return result.
134 (cdr file-notify--test-remote-enabled-checked))
136 (defmacro file-notify--deftest-remote (test docstring)
137 "Define ert `TEST-remote' for remote files."
138 (declare (indent 1))
139 `(ert-deftest ,(intern (concat (symbol-name test) "-remote")) ()
140 ,docstring
141 (let* ((temporary-file-directory
142 file-notify-test-remote-temporary-file-directory)
143 (ert-test (ert-get-test ',test)))
144 (skip-unless (file-notify--test-remote-enabled))
145 (tramp-cleanup-connection
146 (tramp-dissect-file-name temporary-file-directory) nil 'keep-password)
147 (funcall (ert-test-body ert-test)))))
149 (ert-deftest file-notify-test00-availability ()
150 "Test availability of `file-notify'."
151 (skip-unless (file-notify--test-local-enabled))
152 ;; Report the native library which has been used.
153 (if (null (file-remote-p temporary-file-directory))
154 (message "Local library: `%s'" file-notify--library)
155 (message "Remote command: `%s'"
156 (replace-regexp-in-string
157 "<[[:digit:]]+>\\'" ""
158 (process-name (cdr file-notify--test-remote-enabled-checked)))))
159 (should
160 (setq file-notify--test-desc
161 (file-notify-add-watch temporary-file-directory '(change) 'ignore)))
163 ;; Cleanup.
164 (file-notify--test-cleanup))
166 (file-notify--deftest-remote file-notify-test00-availability
167 "Test availability of `file-notify' for remote files.")
169 (ert-deftest file-notify-test01-add-watch ()
170 "Check `file-notify-add-watch'."
171 (skip-unless (file-notify--test-local-enabled))
173 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
174 file-notify--test-tmpfile1
175 (format "%s/%s" file-notify--test-tmpfile (md5 (current-time-string))))
177 ;; Check, that different valid parameters are accepted.
178 (should
179 (setq file-notify--test-desc
180 (file-notify-add-watch temporary-file-directory '(change) 'ignore)))
181 (file-notify-rm-watch file-notify--test-desc)
182 (should
183 (setq file-notify--test-desc
184 (file-notify-add-watch
185 temporary-file-directory '(attribute-change) 'ignore)))
186 (file-notify-rm-watch file-notify--test-desc)
187 (should
188 (setq file-notify--test-desc
189 (file-notify-add-watch
190 temporary-file-directory '(change attribute-change) 'ignore)))
191 (file-notify-rm-watch file-notify--test-desc)
192 ;; The file does not need to exist, just the upper directory.
193 (should
194 (setq file-notify--test-desc
195 (file-notify-add-watch
196 file-notify--test-tmpfile '(change attribute-change) 'ignore)))
197 (file-notify-rm-watch file-notify--test-desc)
199 ;; Check error handling.
200 (should-error (file-notify-add-watch 1 2 3 4)
201 :type 'wrong-number-of-arguments)
202 (should
203 (equal (should-error
204 (file-notify-add-watch 1 2 3))
205 '(wrong-type-argument 1)))
206 (should
207 (equal (should-error
208 (file-notify-add-watch temporary-file-directory 2 3))
209 '(wrong-type-argument 2)))
210 (should
211 (equal (should-error
212 (file-notify-add-watch temporary-file-directory '(change) 3))
213 '(wrong-type-argument 3)))
214 ;; The upper directory of a file must exist.
215 (should
216 (equal (should-error
217 (file-notify-add-watch
218 file-notify--test-tmpfile1 '(change attribute-change) 'ignore))
219 `(file-notify-error
220 "Directory does not exist" ,file-notify--test-tmpfile)))
222 ;; Cleanup.
223 (file-notify--test-cleanup))
225 (file-notify--deftest-remote file-notify-test01-add-watch
226 "Check `file-notify-add-watch' for remote files.")
228 (defun file-notify--test-event-test ()
229 "Ert test function to be called by `file-notify--test-event-handler'.
230 We cannot pass arguments, so we assume that `file-notify--test-event'
231 is bound somewhere."
232 ;; Check the descriptor.
233 (should (equal (car file-notify--test-event) file-notify--test-desc))
234 ;; Check the file name.
235 (should
236 (or (string-equal (file-notify--event-file-name file-notify--test-event)
237 file-notify--test-tmpfile)
238 (string-equal (directory-file-name
239 (file-name-directory
240 (file-notify--event-file-name file-notify--test-event)))
241 file-notify--test-tmpfile)))
242 ;; Check the second file name if exists.
243 (when (eq (nth 1 file-notify--test-event) 'renamed)
244 (should
245 (string-equal
246 (file-notify--event-file1-name file-notify--test-event)
247 file-notify--test-tmpfile1))))
249 (defun file-notify--test-event-handler (event)
250 "Run a test over FILE-NOTIFY--TEST-EVENT.
251 For later analysis, append the test result to `file-notify--test-results'
252 and the event to `file-notify--test-events'."
253 (let* ((file-notify--test-event event)
254 (result
255 (ert-run-test (make-ert-test :body 'file-notify--test-event-test))))
256 ;; Do not add temporary files, this would confuse the checks.
257 (unless (string-match
258 (regexp-quote ".#")
259 (file-notify--event-file-name file-notify--test-event))
260 ;;(message "file-notify--test-event-handler %S" file-notify--test-event)
261 (setq file-notify--test-events
262 (append file-notify--test-events `(,file-notify--test-event))
263 file-notify--test-results
264 (append file-notify--test-results `(,result))))))
266 (defun file-notify--test-make-temp-name ()
267 "Create a temporary file name for test."
268 (expand-file-name
269 (make-temp-name "file-notify-test") temporary-file-directory))
271 (defmacro file-notify--wait-for-events (timeout until)
272 "Wait for and return file notification events until form UNTIL is true.
273 TIMEOUT is the maximum time to wait for, in seconds."
274 `(with-timeout (,timeout (ignore))
275 (while (null ,until)
276 (read-event nil nil 0.1))))
278 (defmacro file-notify--test-with-events (events &rest body)
279 "Run BODY collecting events and then compare with EVENTS.
280 Don't wait longer than timeout seconds for the events to be delivered."
281 (declare (indent 1))
282 (let ((outer (make-symbol "outer")))
283 `(let ((,outer file-notify--test-events))
284 (setq file-notify--test-expected-events
285 (append file-notify--test-expected-events ,events))
286 (let (file-notify--test-events)
287 ,@body
288 (file-notify--wait-for-events
289 (file-notify--test-timeout)
290 (= (length ,events) (length file-notify--test-events)))
291 (should (equal ,events (mapcar #'cadr file-notify--test-events)))
292 (setq ,outer (append ,outer file-notify--test-events)))
293 (setq file-notify--test-events ,outer))))
295 (ert-deftest file-notify-test02-events ()
296 "Check file creation/change/removal notifications."
297 (skip-unless (file-notify--test-local-enabled))
298 ;; Under cygwin there are so bad timings that it doesn't make sense to test.
299 (skip-unless (not (eq system-type 'cygwin)))
301 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
302 file-notify--test-tmpfile1 (file-notify--test-make-temp-name))
304 (unwind-protect
305 (progn
306 ;; Check creation, change and deletion.
307 (setq file-notify--test-desc
308 (file-notify-add-watch
309 file-notify--test-tmpfile
310 '(change) 'file-notify--test-event-handler))
311 (file-notify--test-with-events '(created changed deleted)
312 (write-region
313 "any text" nil file-notify--test-tmpfile nil 'no-message)
314 (delete-file file-notify--test-tmpfile))
315 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
316 (let (file-notify--test-events)
317 (file-notify-rm-watch file-notify--test-desc))
319 ;; Check creation, change and deletion. There must be a
320 ;; `stopped' event when deleting the directory. It doesn't
321 ;; work for w32notify.
322 (unless (eq file-notify--library 'w32notify)
323 (make-directory file-notify--test-tmpfile)
324 (setq file-notify--test-desc
325 (file-notify-add-watch
326 file-notify--test-tmpfile
327 '(change) 'file-notify--test-event-handler))
328 (file-notify--test-with-events
329 ;; There are two `deleted' events, for the file and for
330 ;; the directory.
331 '(created changed deleted deleted stopped)
332 (write-region
333 "any text" nil (expand-file-name "foo" file-notify--test-tmpfile)
334 nil 'no-message)
335 (delete-directory file-notify--test-tmpfile 'recursive))
336 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
337 (let (file-notify--test-events)
338 (file-notify-rm-watch file-notify--test-desc)))
340 ;; Check copy.
341 (setq file-notify--test-desc
342 (file-notify-add-watch
343 file-notify--test-tmpfile
344 '(change) 'file-notify--test-event-handler))
345 (should file-notify--test-desc)
346 (file-notify--test-with-events
347 ;; w32notify does not distinguish between `changed' and
348 ;; `attribute-changed'.
349 (if (eq file-notify--library 'w32notify)
350 '(created changed changed deleted)
351 '(created changed deleted))
352 (write-region
353 "any text" nil file-notify--test-tmpfile nil 'no-message)
354 (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1)
355 ;; The next two events shall not be visible.
356 (set-file-modes file-notify--test-tmpfile 000)
357 (read-event nil nil 0.1) ; In order to distinguish the events.
358 (set-file-times file-notify--test-tmpfile '(0 0))
359 (delete-file file-notify--test-tmpfile)
360 (delete-file file-notify--test-tmpfile1))
361 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
362 (let (file-notify--test-events)
363 (file-notify-rm-watch file-notify--test-desc))
365 ;; Check rename.
366 (setq file-notify--test-desc
367 (file-notify-add-watch
368 file-notify--test-tmpfile
369 '(change) 'file-notify--test-event-handler))
370 (should file-notify--test-desc)
371 (file-notify--test-with-events '(created changed renamed)
372 (write-region
373 "any text" nil file-notify--test-tmpfile nil 'no-message)
374 (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1)
375 ;; After the rename, we won't get events anymore.
376 (delete-file file-notify--test-tmpfile1))
377 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
378 (let (file-notify--test-events)
379 (file-notify-rm-watch file-notify--test-desc))
381 ;; Check attribute change. It doesn't work for w32notify.
382 (unless (eq file-notify--library 'w32notify)
383 (setq file-notify--test-desc
384 (file-notify-add-watch
385 file-notify--test-tmpfile
386 '(attribute-change) 'file-notify--test-event-handler))
387 (file-notify--test-with-events
388 (if (file-remote-p temporary-file-directory)
389 ;; In the remote case, `write-region' raises also an
390 ;; `attribute-changed' event.
391 '(attribute-changed attribute-changed attribute-changed)
392 '(attribute-changed attribute-changed))
393 ;; We must use short delays between the operations.
394 ;; Otherwise, not all events arrive us in the remote case.
395 (write-region
396 "any text" nil file-notify--test-tmpfile nil 'no-message)
397 (read-event nil nil 0.1)
398 (set-file-modes file-notify--test-tmpfile 000)
399 (read-event nil nil 0.1)
400 (set-file-times file-notify--test-tmpfile '(0 0))
401 (read-event nil nil 0.1)
402 (delete-file file-notify--test-tmpfile))
403 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
404 (let (file-notify--test-events)
405 (file-notify-rm-watch file-notify--test-desc)))
407 ;; Check the global sequence again just to make sure that
408 ;; `file-notify--test-events' has been set correctly.
409 (should (equal (mapcar #'cadr file-notify--test-events)
410 file-notify--test-expected-events))
411 (should file-notify--test-results)
412 (dolist (result file-notify--test-results)
413 (when (ert-test-failed-p result)
414 (ert-fail
415 (cadr (ert-test-result-with-condition-condition result))))))
417 ;; Cleanup.
418 (file-notify--test-cleanup)))
420 (file-notify--deftest-remote file-notify-test02-events
421 "Check file creation/change/removal notifications for remote files.")
423 (require 'autorevert)
424 (setq auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded"
425 auto-revert-remote-files t
426 auto-revert-stop-on-user-input nil)
428 (ert-deftest file-notify-test03-autorevert ()
429 "Check autorevert via file notification."
430 (skip-unless (file-notify--test-local-enabled))
431 ;; `auto-revert-buffers' runs every 5". And we must wait, until the
432 ;; file has been reverted.
433 (let ((timeout (if (file-remote-p temporary-file-directory) 60 10))
434 buf)
435 (unwind-protect
436 (progn
437 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
439 (write-region
440 "any text" nil file-notify--test-tmpfile nil 'no-message)
441 (setq buf (find-file-noselect file-notify--test-tmpfile))
442 (with-current-buffer buf
443 (should (string-equal (buffer-string) "any text"))
444 ;; `buffer-stale--default-function' checks for
445 ;; `verify-visited-file-modtime'. We must ensure that it
446 ;; returns nil.
447 (sleep-for 1)
448 (auto-revert-mode 1)
450 ;; `auto-revert-buffers' runs every 5".
451 (with-timeout (timeout (ignore))
452 (while (null auto-revert-notify-watch-descriptor)
453 (sleep-for 1)))
455 ;; Check, that file notification has been used.
456 (should auto-revert-mode)
457 (should auto-revert-use-notify)
458 (should auto-revert-notify-watch-descriptor)
460 ;; Modify file. We wait for a second, in order to have
461 ;; another timestamp.
462 (with-current-buffer (get-buffer-create "*Messages*")
463 (narrow-to-region (point-max) (point-max)))
464 (sleep-for 1)
465 (write-region
466 "another text" nil file-notify--test-tmpfile nil 'no-message)
468 ;; Check, that the buffer has been reverted.
469 (with-current-buffer (get-buffer-create "*Messages*")
470 (file-notify--wait-for-events
471 timeout
472 (string-match
473 (format-message "Reverting buffer `%s'." (buffer-name buf))
474 (buffer-string))))
475 (should (string-match "another text" (buffer-string)))
477 ;; Stop file notification. Autorevert shall still work via polling.
478 (file-notify-rm-watch auto-revert-notify-watch-descriptor)
479 (file-notify--wait-for-events
480 timeout (null auto-revert-use-notify))
481 (should-not auto-revert-use-notify)
482 (should-not auto-revert-notify-watch-descriptor)
484 ;; Modify file. We wait for two seconds, in order to have
485 ;; another timestamp. One second seems to be too short.
486 (with-current-buffer (get-buffer-create "*Messages*")
487 (narrow-to-region (point-max) (point-max)))
488 (sleep-for 2)
489 (write-region
490 "foo bla" nil file-notify--test-tmpfile nil 'no-message)
492 ;; Check, that the buffer has been reverted.
493 (with-current-buffer (get-buffer-create "*Messages*")
494 (file-notify--wait-for-events
495 timeout
496 (string-match
497 (format-message "Reverting buffer `%s'." (buffer-name buf))
498 (buffer-string))))
499 (should (string-match "foo bla" (buffer-string)))))
501 ;; Cleanup.
502 (with-current-buffer "*Messages*" (widen))
503 (ignore-errors (kill-buffer buf))
504 (file-notify--test-cleanup))))
506 (file-notify--deftest-remote file-notify-test03-autorevert
507 "Check autorevert via file notification for remote files.")
509 (ert-deftest file-notify-test04-file-validity ()
510 "Check `file-notify-valid-p' for files."
511 (skip-unless (file-notify--test-local-enabled))
512 ;; Under cygwin there are so bad timings that it doesn't make sense to test.
513 (skip-unless (not (eq system-type 'cygwin)))
515 (unwind-protect
516 (progn
517 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
518 file-notify--test-desc
519 (file-notify-add-watch
520 file-notify--test-tmpfile
521 '(change) #'file-notify--test-event-handler))
522 (file-notify--test-with-events '(created changed deleted)
523 (should (file-notify-valid-p file-notify--test-desc))
524 (write-region
525 "any text" nil file-notify--test-tmpfile nil 'no-message)
526 (delete-file file-notify--test-tmpfile))
527 ;; After deleting the file, the descriptor is still valid.
528 (should (file-notify-valid-p file-notify--test-desc))
529 ;; After removing the watch, the descriptor must not be valid
530 ;; anymore.
531 (file-notify-rm-watch file-notify--test-desc)
532 (should-not (file-notify-valid-p file-notify--test-desc)))
534 ;; Cleanup.
535 (file-notify--test-cleanup))
537 (unwind-protect
538 ;; The batch-mode operation of w32notify is fragile (there's no
539 ;; input threads to send the message to).
540 ;(unless (and noninteractive (eq file-notify--library 'w32notify))
541 (unless (eq file-notify--library 'w32notify)
542 (let ((temporary-file-directory
543 (make-temp-file "file-notify-test-parent" t)))
544 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
545 file-notify--test-desc
546 (file-notify-add-watch
547 file-notify--test-tmpfile
548 '(change) #'file-notify--test-event-handler))
549 (file-notify--test-with-events '(created changed deleted stopped)
550 (should (file-notify-valid-p file-notify--test-desc))
551 (write-region
552 "any text" nil file-notify--test-tmpfile nil 'no-message)
553 (delete-directory temporary-file-directory t))
554 ;; After deleting the parent directory, the descriptor must
555 ;; not be valid anymore.
556 (should-not (file-notify-valid-p file-notify--test-desc))))
558 ;; Cleanup.
559 (file-notify--test-cleanup)))
561 (file-notify--deftest-remote file-notify-test04-file-validity
562 "Check `file-notify-valid-p' via file notification for remote files.")
564 (ert-deftest file-notify-test05-dir-validity ()
565 "Check `file-notify-valid-p' for directories."
566 (skip-unless (file-notify--test-local-enabled))
568 (unwind-protect
569 (progn
570 (setq file-notify--test-tmpfile
571 (file-name-as-directory (file-notify--test-make-temp-name)))
572 (make-directory file-notify--test-tmpfile)
573 (setq file-notify--test-desc
574 (file-notify-add-watch
575 file-notify--test-tmpfile
576 '(change) #'file-notify--test-event-handler))
577 (should (file-notify-valid-p file-notify--test-desc))
578 ;; After removing the watch, the descriptor must not be valid
579 ;; anymore.
580 (file-notify-rm-watch file-notify--test-desc)
581 (file-notify--wait-for-events
582 (file-notify--test-timeout)
583 (not (file-notify-valid-p file-notify--test-desc)))
584 (should-not (file-notify-valid-p file-notify--test-desc)))
586 ;; Cleanup.
587 (file-notify--test-cleanup))
589 (unwind-protect
590 ;; The batch-mode operation of w32notify is fragile (there's no
591 ;; input threads to send the message to).
592 (unless (and noninteractive (eq file-notify--library 'w32notify))
593 (setq file-notify--test-tmpfile
594 (file-name-as-directory (file-notify--test-make-temp-name)))
595 (make-directory file-notify--test-tmpfile)
596 (setq file-notify--test-desc
597 (file-notify-add-watch
598 file-notify--test-tmpfile
599 '(change) #'file-notify--test-event-handler))
600 (should (file-notify-valid-p file-notify--test-desc))
601 ;; After deleting the directory, the descriptor must not be
602 ;; valid anymore.
603 (delete-directory file-notify--test-tmpfile t)
604 (file-notify--wait-for-events
605 (file-notify--test-timeout)
606 (not (file-notify-valid-p file-notify--test-desc)))
607 (should-not (file-notify-valid-p file-notify--test-desc)))
609 ;; Cleanup.
610 (file-notify--test-cleanup)))
612 (file-notify--deftest-remote file-notify-test05-dir-validity
613 "Check `file-notify-valid-p' via file notification for remote directories.")
615 (defun file-notify-test-all (&optional interactive)
616 "Run all tests for \\[file-notify]."
617 (interactive "p")
618 (if interactive
619 (ert-run-tests-interactively "^file-notify-")
620 (ert-run-tests-batch "^file-notify-")))
622 ;; TODO:
624 ;; * For w32notify, no stopped events arrive when a directory is removed.
625 ;; * Try to handle arriving events under cygwin reliably.
627 (provide 'file-notify-tests)
628 ;;; file-notify-tests.el ends here