]> code.delx.au - gnu-emacs/blob - test/automated/file-notify-tests.el
Update copyright year to 2016
[gnu-emacs] / test / automated / file-notify-tests.el
1 ;;; file-notify-tests.el --- Tests of file notifications -*- lexical-binding: t; -*-
2
3 ;; Copyright (C) 2013-2016 Free Software Foundation, Inc.
4
5 ;; Author: Michael Albinus <michael.albinus@gmx.de>
6
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.
11 ;;
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.
16 ;;
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/'.
19
20 ;;; Commentary:
21
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.
27
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.
33
34 ;; A whole test run can be performed calling the command `file-notify-test-all'.
35
36 ;;; Code:
37
38 (require 'ert)
39 (require 'filenotify)
40 (require 'tramp)
41
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.")
57
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)
65
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))
69
70 (defun file-notify--test-cleanup ()
71 "Cleanup after a test."
72 (file-notify-rm-watch file-notify--test-desc)
73
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))
87
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")))
96
97 (setq password-cache-expiry nil
98 tramp-verbose 0
99 tramp-message-show-message nil)
100
101 ;; This shall happen on hydra only.
102 (when (getenv "NIX_STORE")
103 (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
104
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)))
112
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.")
117
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))
135
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)))))
148
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)))
162
163 ;; Cleanup.
164 (file-notify--test-cleanup))
165
166 (file-notify--deftest-remote file-notify-test00-availability
167 "Test availability of `file-notify' for remote files.")
168
169 (ert-deftest file-notify-test01-add-watch ()
170 "Check `file-notify-add-watch'."
171 (skip-unless (file-notify--test-local-enabled))
172
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))))
176
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)
198
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)))
221
222 ;; Cleanup.
223 (file-notify--test-cleanup))
224
225 (file-notify--deftest-remote file-notify-test01-add-watch
226 "Check `file-notify-add-watch' for remote files.")
227
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))))
248
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))))))
265
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))
270
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))))
277
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))))
294
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)))
300
301 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
302 file-notify--test-tmpfile1 (file-notify--test-make-temp-name))
303
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))
318
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)))
339
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))
364
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))
380
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)))
406
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))))))
416
417 ;; Cleanup.
418 (file-notify--test-cleanup)))
419
420 (file-notify--deftest-remote file-notify-test02-events
421 "Check file creation/change/removal notifications for remote files.")
422
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)
427
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))
438
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)
449
450 ;; `auto-revert-buffers' runs every 5".
451 (with-timeout (timeout (ignore))
452 (while (null auto-revert-notify-watch-descriptor)
453 (sleep-for 1)))
454
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)
459
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)
467
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)))
476
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)
483
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)
491
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)))))
500
501 ;; Cleanup.
502 (with-current-buffer "*Messages*" (widen))
503 (ignore-errors (kill-buffer buf))
504 (file-notify--test-cleanup))))
505
506 (file-notify--deftest-remote file-notify-test03-autorevert
507 "Check autorevert via file notification for remote files.")
508
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)))
514
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)))
533
534 ;; Cleanup.
535 (file-notify--test-cleanup))
536
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))))
557
558 ;; Cleanup.
559 (file-notify--test-cleanup)))
560
561 (file-notify--deftest-remote file-notify-test04-file-validity
562 "Check `file-notify-valid-p' via file notification for remote files.")
563
564 (ert-deftest file-notify-test05-dir-validity ()
565 "Check `file-notify-valid-p' for directories."
566 (skip-unless (file-notify--test-local-enabled))
567
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)))
585
586 ;; Cleanup.
587 (file-notify--test-cleanup))
588
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)))
608
609 ;; Cleanup.
610 (file-notify--test-cleanup)))
611
612 (file-notify--deftest-remote file-notify-test05-dir-validity
613 "Check `file-notify-valid-p' via file notification for remote directories.")
614
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-")))
621
622 ;; TODO:
623
624 ;; * For w32notify, no stopped events arrive when a directory is removed.
625 ;; * Try to handle arriving events under cygwin reliably.
626
627 (provide 'file-notify-tests)
628 ;;; file-notify-tests.el ends here