]> code.delx.au - gnu-emacs/blob - test/lisp/filenotify-tests.el
* src/casefiddle.c (Fupcase_region): Add arg ‘region-noncontiguous-p’.
[gnu-emacs] / test / lisp / filenotify-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-desc1 nil)
62 (defvar file-notify--test-desc2 nil)
63 (defvar file-notify--test-results nil)
64 (defvar file-notify--test-event nil)
65 (defvar file-notify--test-events nil)
66
67 (defconst file-notify--test-read-event-timeout 0.01
68 "Timeout for `read-event' calls.
69 It is different for local and remote file notification libraries.")
70
71 (defun file-notify--test-timeout ()
72 "Timeout to wait for arriving events, in seconds."
73 (cond
74 ((file-remote-p temporary-file-directory) 6)
75 ((string-equal (file-notify--test-library) "w32notify") 4)
76 (t 3)))
77
78 (defun file-notify--test-no-descriptors ()
79 "Check that `file-notify-descriptors' is an empty hash table.
80 Return nil when any other file notification watch is still active."
81 ;; Give read events a last chance.
82 (unless (zerop (hash-table-count file-notify-descriptors))
83 (read-event nil nil file-notify--test-read-event-timeout))
84 ;; Now check.
85 (zerop (hash-table-count file-notify-descriptors)))
86
87 (defun file-notify--test-no-descriptors-explainer ()
88 "Explain why `file-notify--test-no-descriptors' fails."
89 (let ((result (list "Watch descriptor(s) existent:")))
90 (maphash
91 (lambda (key value) (push (cons key value) result))
92 file-notify-descriptors)
93 (nreverse result)))
94
95 (put 'file-notify--test-no-descriptors 'ert-explainer
96 'file-notify--test-no-descriptors-explainer)
97
98 (defun file-notify--test-cleanup-p ()
99 "Check, that the test has cleaned up the environment as much as needed."
100 ;; `file-notify--test-event' should not be set but bound
101 ;; dynamically.
102 (should-not file-notify--test-event)
103 ;; The test should have cleaned up this already. Let's check
104 ;; nevertheless.
105 (should (file-notify--test-no-descriptors)))
106
107 (defun file-notify--test-cleanup ()
108 "Cleanup after a test."
109 (file-notify-rm-watch file-notify--test-desc)
110 (file-notify-rm-watch file-notify--test-desc1)
111 (file-notify-rm-watch file-notify--test-desc2)
112
113 (ignore-errors
114 (delete-file (file-newest-backup file-notify--test-tmpfile)))
115 (ignore-errors
116 (if (file-directory-p file-notify--test-tmpfile)
117 (delete-directory file-notify--test-tmpfile 'recursive)
118 (delete-file file-notify--test-tmpfile)))
119 (ignore-errors
120 (if (file-directory-p file-notify--test-tmpfile1)
121 (delete-directory file-notify--test-tmpfile1 'recursive)
122 (delete-file file-notify--test-tmpfile1)))
123 (ignore-errors
124 (when (file-remote-p temporary-file-directory)
125 (tramp-cleanup-connection
126 (tramp-dissect-file-name temporary-file-directory) nil 'keep-password)))
127
128 (setq file-notify--test-tmpfile nil
129 file-notify--test-tmpfile1 nil
130 file-notify--test-desc nil
131 file-notify--test-desc1 nil
132 file-notify--test-desc2 nil
133 file-notify--test-results nil
134 file-notify--test-events nil))
135
136 (setq password-cache-expiry nil
137 tramp-verbose 0
138 tramp-message-show-message nil)
139
140 ;; This shall happen on hydra only.
141 (when (getenv "NIX_STORE")
142 (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
143
144 ;; We do not want to try and fail `file-notify-add-watch'.
145 (defun file-notify--test-local-enabled ()
146 "Whether local file notification is enabled.
147 This is needed for local `temporary-file-directory' only, in the
148 remote case we return always t."
149 (or file-notify--library
150 (file-remote-p temporary-file-directory)))
151
152 (defvar file-notify--test-remote-enabled-checked nil
153 "Cached result of `file-notify--test-remote-enabled'.
154 If the function did run, the value is a cons cell, the `cdr'
155 being the result.")
156
157 (defun file-notify--test-remote-enabled ()
158 "Whether remote file notification is enabled."
159 (unless (consp file-notify--test-remote-enabled-checked)
160 (let (desc)
161 (ignore-errors
162 (and
163 (file-remote-p file-notify-test-remote-temporary-file-directory)
164 (file-directory-p file-notify-test-remote-temporary-file-directory)
165 (file-writable-p file-notify-test-remote-temporary-file-directory)
166 (setq desc
167 (file-notify-add-watch
168 file-notify-test-remote-temporary-file-directory
169 '(change) #'ignore))))
170 (setq file-notify--test-remote-enabled-checked (cons t desc))
171 (when desc (file-notify-rm-watch desc))))
172 ;; Return result.
173 (cdr file-notify--test-remote-enabled-checked))
174
175 (defun file-notify--test-library ()
176 "The used library for the test, as a string.
177 In the remote case, it is the process name which runs on the
178 remote host, or nil."
179 (if (null (file-remote-p temporary-file-directory))
180 (symbol-name file-notify--library)
181 (and (consp file-notify--test-remote-enabled-checked)
182 (processp (cdr file-notify--test-remote-enabled-checked))
183 (replace-regexp-in-string
184 "<[[:digit:]]+>\\'" ""
185 (process-name (cdr file-notify--test-remote-enabled-checked))))))
186
187 (defmacro file-notify--deftest-remote (test docstring)
188 "Define ert `TEST-remote' for remote files."
189 (declare (indent 1))
190 `(ert-deftest ,(intern (concat (symbol-name test) "-remote")) ()
191 ,docstring
192 :tags '(:expensive-test)
193 (let* ((temporary-file-directory
194 file-notify-test-remote-temporary-file-directory)
195 (file-notify--test-read-event-timeout 0.1)
196 (ert-test (ert-get-test ',test)))
197 (skip-unless (file-notify--test-remote-enabled))
198 (tramp-cleanup-connection
199 (tramp-dissect-file-name temporary-file-directory) nil 'keep-password)
200 (funcall (ert-test-body ert-test)))))
201
202 (ert-deftest file-notify-test00-availability ()
203 "Test availability of `file-notify'."
204 (skip-unless (file-notify--test-local-enabled))
205
206 (unwind-protect
207 (progn
208 ;; Report the native library which has been used.
209 (message "Library: `%s'" (file-notify--test-library))
210 (should
211 (setq file-notify--test-desc
212 (file-notify-add-watch
213 temporary-file-directory '(change) #'ignore)))
214 (file-notify-rm-watch file-notify--test-desc)
215
216 ;; The environment shall be cleaned up.
217 (file-notify--test-cleanup-p))
218
219 ;; Cleanup.
220 (file-notify--test-cleanup)))
221
222 (file-notify--deftest-remote file-notify-test00-availability
223 "Test availability of `file-notify' for remote files.")
224
225 (ert-deftest file-notify-test01-add-watch ()
226 "Check `file-notify-add-watch'."
227 (skip-unless (file-notify--test-local-enabled))
228
229 (unwind-protect
230 (progn
231 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
232 file-notify--test-tmpfile1
233 (format
234 "%s/%s" file-notify--test-tmpfile (md5 (current-time-string))))
235
236 ;; Check, that different valid parameters are accepted.
237 (should
238 (setq file-notify--test-desc
239 (file-notify-add-watch
240 temporary-file-directory '(change) #'ignore)))
241 (file-notify-rm-watch file-notify--test-desc)
242 (should
243 (setq file-notify--test-desc
244 (file-notify-add-watch
245 temporary-file-directory '(attribute-change) #'ignore)))
246 (file-notify-rm-watch file-notify--test-desc)
247 (should
248 (setq file-notify--test-desc
249 (file-notify-add-watch
250 temporary-file-directory '(change attribute-change) #'ignore)))
251 (file-notify-rm-watch file-notify--test-desc)
252 (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
253 (should
254 (setq file-notify--test-desc
255 (file-notify-add-watch
256 file-notify--test-tmpfile '(change attribute-change) #'ignore)))
257 (file-notify-rm-watch file-notify--test-desc)
258 (delete-file file-notify--test-tmpfile)
259
260 ;; Check error handling.
261 (should-error (file-notify-add-watch 1 2 3 4)
262 :type 'wrong-number-of-arguments)
263 (should
264 (equal (should-error
265 (file-notify-add-watch 1 2 3))
266 '(wrong-type-argument 1)))
267 (should
268 (equal (should-error
269 (file-notify-add-watch temporary-file-directory 2 3))
270 '(wrong-type-argument 2)))
271 (should
272 (equal (should-error
273 (file-notify-add-watch temporary-file-directory '(change) 3))
274 '(wrong-type-argument 3)))
275 ;; The upper directory of a file must exist.
276 (should
277 (equal (should-error
278 (file-notify-add-watch
279 file-notify--test-tmpfile1
280 '(change attribute-change) #'ignore))
281 `(file-notify-error
282 "Directory does not exist" ,file-notify--test-tmpfile)))
283
284 ;; The environment shall be cleaned up.
285 (file-notify--test-cleanup-p))
286
287 ;; Cleanup.
288 (file-notify--test-cleanup)))
289
290 (file-notify--deftest-remote file-notify-test01-add-watch
291 "Check `file-notify-add-watch' for remote files.")
292
293 (defun file-notify--test-event-test ()
294 "Ert test function to be called by `file-notify--test-event-handler'.
295 We cannot pass arguments, so we assume that `file-notify--test-event'
296 is bound somewhere."
297 ;; Check the descriptor.
298 (should (equal (car file-notify--test-event) file-notify--test-desc))
299 ;; Check the file name.
300 (should
301 (string-prefix-p
302 (file-notify--event-watched-file file-notify--test-event)
303 (file-notify--event-file-name file-notify--test-event)))
304 ;; Check the second file name if exists.
305 (when (eq (nth 1 file-notify--test-event) 'renamed)
306 (should
307 (string-prefix-p
308 (file-notify--event-watched-file file-notify--test-event)
309 (file-notify--event-file1-name file-notify--test-event)))))
310
311 (defun file-notify--test-event-handler (event)
312 "Run a test over FILE-NOTIFY--TEST-EVENT.
313 For later analysis, append the test result to `file-notify--test-results'
314 and the event to `file-notify--test-events'."
315 (let* ((file-notify--test-event event)
316 (result
317 (ert-run-test (make-ert-test :body 'file-notify--test-event-test))))
318 ;; Do not add lock files, this would confuse the checks.
319 (unless (string-match
320 (regexp-quote ".#")
321 (file-notify--event-file-name file-notify--test-event))
322 ;;(message "file-notify--test-event-handler result: %s event: %S"
323 ;;(null (ert-test-failed-p result)) file-notify--test-event)
324 (setq file-notify--test-events
325 (append file-notify--test-events `(,file-notify--test-event))
326 file-notify--test-results
327 (append file-notify--test-results `(,result))))))
328
329 (defun file-notify--test-make-temp-name ()
330 "Create a temporary file name for test."
331 (expand-file-name
332 (make-temp-name "file-notify-test") temporary-file-directory))
333
334 (defmacro file-notify--wait-for-events (timeout until)
335 "Wait for and return file notification events until form UNTIL is true.
336 TIMEOUT is the maximum time to wait for, in seconds."
337 `(with-timeout (,timeout (ignore))
338 (while (null ,until)
339 (read-event nil nil file-notify--test-read-event-timeout))))
340
341 (defun file-notify--test-with-events-check (events)
342 "Check whether received events match one of the EVENTS alternatives."
343 (let (result)
344 (dolist (elt events result)
345 (setq result
346 (or result
347 (if (eq (car elt) 'random)
348 (equal (sort (cdr elt) 'string-lessp)
349 (sort (mapcar #'cadr file-notify--test-events)
350 'string-lessp))
351 (equal elt (mapcar #'cadr file-notify--test-events))))))))
352
353 (defun file-notify--test-with-events-explainer (events)
354 "Explain why `file-notify--test-with-events-check' fails."
355 (if (null (cdr events))
356 (format "Received events do not match expected events\n%s\n%s"
357 (mapcar #'cadr file-notify--test-events) (car events))
358 (format
359 "Received events do not match any sequence of expected events\n%s\n%s"
360 (mapcar #'cadr file-notify--test-events) events)))
361
362 (put 'file-notify--test-with-events-check 'ert-explainer
363 'file-notify--test-with-events-explainer)
364
365 (defmacro file-notify--test-with-events (events &rest body)
366 "Run BODY collecting events and then compare with EVENTS.
367 EVENTS is either a simple list of events, or a list of lists of
368 events, which represent different possible results. The first
369 event of a list could be the pseudo event `random', which is
370 just an indicator for comparison.
371
372 Don't wait longer than timeout seconds for the events to be
373 delivered."
374 (declare (indent 1))
375 `(let* ((events (if (consp (car ,events)) ,events (list ,events)))
376 (max-length
377 (apply
378 'max
379 (mapcar
380 (lambda (x) (length (if (eq (car x) 'random) (cdr x) x)))
381 events)))
382 create-lockfiles)
383 ;; Flush pending events.
384 (file-notify--wait-for-events
385 (file-notify--test-timeout)
386 (input-pending-p))
387 (setq file-notify--test-events nil
388 file-notify--test-results nil)
389 ,@body
390 (file-notify--wait-for-events
391 ;; More events need more time. Use some fudge factor.
392 (* (ceiling max-length 100) (file-notify--test-timeout))
393 (= max-length (length file-notify--test-events)))
394 ;; Check the result sequence just to make sure that all events
395 ;; are as expected.
396 (dolist (result file-notify--test-results)
397 (when (ert-test-failed-p result)
398 (ert-fail
399 (cadr (ert-test-result-with-condition-condition result)))))
400 ;; One of the possible event sequences shall match.
401 (should (file-notify--test-with-events-check events))))
402
403 (ert-deftest file-notify-test02-events ()
404 "Check file creation/change/removal notifications."
405 (skip-unless (file-notify--test-local-enabled))
406
407 (unwind-protect
408 (progn
409 ;; Check file creation, change and deletion. It doesn't work
410 ;; for cygwin and kqueue, because we don't use an implicit
411 ;; directory monitor (kqueue), or the timings are too bad (cygwin).
412 (unless (or (eq system-type 'cygwin)
413 (string-equal (file-notify--test-library) "kqueue"))
414 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
415 (should
416 (setq file-notify--test-desc
417 (file-notify-add-watch
418 file-notify--test-tmpfile
419 '(change) #'file-notify--test-event-handler)))
420 (file-notify--test-with-events
421 (cond
422 ;; cygwin recognizes only `deleted' and `stopped' events.
423 ((eq system-type 'cygwin)
424 '(deleted stopped))
425 (t '(created changed deleted stopped)))
426 (write-region
427 "another text" nil file-notify--test-tmpfile nil 'no-message)
428 (read-event nil nil file-notify--test-read-event-timeout)
429 (delete-file file-notify--test-tmpfile))
430 (file-notify-rm-watch file-notify--test-desc))
431
432 ;; Check file change and deletion.
433 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
434 (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
435 (should
436 (setq file-notify--test-desc
437 (file-notify-add-watch
438 file-notify--test-tmpfile
439 '(change) #'file-notify--test-event-handler)))
440 (file-notify--test-with-events
441 (cond
442 ;; cygwin recognizes only `deleted' and `stopped' events.
443 ((eq system-type 'cygwin)
444 '(deleted stopped))
445 ;; inotify and kqueue raise just one `changed' event.
446 ((or (string-equal "inotify" (file-notify--test-library))
447 (string-equal "kqueue" (file-notify--test-library)))
448 '(changed deleted stopped))
449 ;; gfilenotify raises one or two `changed' events
450 ;; randomly, no chance to test. So we accept both cases.
451 ((string-equal "gfilenotify" (file-notify--test-library))
452 '((changed deleted stopped)
453 (changed changed deleted stopped)))
454 (t '(changed changed deleted stopped)))
455 (write-region
456 "another text" nil file-notify--test-tmpfile nil 'no-message)
457 (read-event nil nil file-notify--test-read-event-timeout)
458 (delete-file file-notify--test-tmpfile))
459 (file-notify-rm-watch file-notify--test-desc)
460
461 ;; Check file creation, change and deletion when watching a
462 ;; directory. There must be a `stopped' event when deleting
463 ;; the directory.
464 (let ((temporary-file-directory
465 (make-temp-file "file-notify-test-parent" t)))
466 (should
467 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
468 file-notify--test-desc
469 (file-notify-add-watch
470 temporary-file-directory
471 '(change) #'file-notify--test-event-handler)))
472 (file-notify--test-with-events
473 (cond
474 ;; w32notify does not raise `deleted' and `stopped'
475 ;; events for the watched directory.
476 ((string-equal (file-notify--test-library) "w32notify")
477 '(created changed deleted))
478 ;; cygwin recognizes only `deleted' and `stopped' events.
479 ((eq system-type 'cygwin)
480 '(deleted stopped))
481 ;; There are two `deleted' events, for the file and for
482 ;; the directory. Except for kqueue.
483 ((string-equal (file-notify--test-library) "kqueue")
484 '(created changed deleted stopped))
485 (t '(created changed deleted deleted stopped)))
486 (write-region
487 "any text" nil file-notify--test-tmpfile nil 'no-message)
488 (read-event nil nil file-notify--test-read-event-timeout)
489 (delete-directory temporary-file-directory 'recursive))
490 (file-notify-rm-watch file-notify--test-desc))
491
492 ;; Check copy of files inside a directory.
493 (let ((temporary-file-directory
494 (make-temp-file "file-notify-test-parent" t)))
495 (should
496 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
497 file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
498 file-notify--test-desc
499 (file-notify-add-watch
500 temporary-file-directory
501 '(change) #'file-notify--test-event-handler)))
502 (file-notify--test-with-events
503 (cond
504 ;; w32notify does not distinguish between `changed' and
505 ;; `attribute-changed'. It does not raise `deleted'
506 ;; and `stopped' events for the watched directory.
507 ((string-equal (file-notify--test-library) "w32notify")
508 '(created changed created changed
509 changed changed changed
510 deleted deleted))
511 ;; cygwin recognizes only `deleted' and `stopped' events.
512 ((eq system-type 'cygwin)
513 '(deleted stopped))
514 ;; There are three `deleted' events, for two files and
515 ;; for the directory. Except for kqueue.
516 ((string-equal (file-notify--test-library) "kqueue")
517 '(created changed created changed deleted stopped))
518 (t '(created changed created changed
519 deleted deleted deleted stopped)))
520 (write-region
521 "any text" nil file-notify--test-tmpfile nil 'no-message)
522 (read-event nil nil file-notify--test-read-event-timeout)
523 (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1)
524 ;; The next two events shall not be visible.
525 (read-event nil nil file-notify--test-read-event-timeout)
526 (set-file-modes file-notify--test-tmpfile 000)
527 (read-event nil nil file-notify--test-read-event-timeout)
528 (set-file-times file-notify--test-tmpfile '(0 0))
529 (read-event nil nil file-notify--test-read-event-timeout)
530 (delete-directory temporary-file-directory 'recursive))
531 (file-notify-rm-watch file-notify--test-desc))
532
533 ;; Check rename of files inside a directory.
534 (let ((temporary-file-directory
535 (make-temp-file "file-notify-test-parent" t)))
536 (should
537 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
538 file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
539 file-notify--test-desc
540 (file-notify-add-watch
541 temporary-file-directory
542 '(change) #'file-notify--test-event-handler)))
543 (file-notify--test-with-events
544 (cond
545 ;; w32notify does not raise `deleted' and `stopped'
546 ;; events for the watched directory.
547 ((string-equal (file-notify--test-library) "w32notify")
548 '(created changed renamed deleted))
549 ;; cygwin recognizes only `deleted' and `stopped' events.
550 ((eq system-type 'cygwin)
551 '(deleted stopped))
552 ;; There are two `deleted' events, for the file and for
553 ;; the directory. Except for kqueue.
554 ((string-equal (file-notify--test-library) "kqueue")
555 '(created changed renamed deleted stopped))
556 (t '(created changed renamed deleted deleted stopped)))
557 (write-region
558 "any text" nil file-notify--test-tmpfile nil 'no-message)
559 (read-event nil nil file-notify--test-read-event-timeout)
560 (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1)
561 ;; After the rename, we won't get events anymore.
562 (read-event nil nil file-notify--test-read-event-timeout)
563 (delete-directory temporary-file-directory 'recursive))
564 (file-notify-rm-watch file-notify--test-desc))
565
566 ;; Check attribute change. Does not work for cygwin.
567 (unless (eq system-type 'cygwin)
568 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
569 (write-region
570 "any text" nil file-notify--test-tmpfile nil 'no-message)
571 (should
572 (setq file-notify--test-desc
573 (file-notify-add-watch
574 file-notify--test-tmpfile
575 '(attribute-change) #'file-notify--test-event-handler)))
576 (file-notify--test-with-events
577 (cond
578 ;; w32notify does not distinguish between `changed' and
579 ;; `attribute-changed'. Under MS Windows 7, we get
580 ;; four `changed' events, and under MS Windows 10 just
581 ;; two. Strange.
582 ((string-equal (file-notify--test-library) "w32notify")
583 '((changed changed)
584 (changed changed changed changed)))
585 ;; For kqueue and in the remote case, `write-region'
586 ;; raises also an `attribute-changed' event.
587 ((or (string-equal (file-notify--test-library) "kqueue")
588 (file-remote-p temporary-file-directory))
589 '(attribute-changed attribute-changed attribute-changed))
590 (t '(attribute-changed attribute-changed)))
591 (write-region
592 "any text" nil file-notify--test-tmpfile nil 'no-message)
593 (read-event nil nil file-notify--test-read-event-timeout)
594 (set-file-modes file-notify--test-tmpfile 000)
595 (read-event nil nil file-notify--test-read-event-timeout)
596 (set-file-times file-notify--test-tmpfile '(0 0))
597 (read-event nil nil file-notify--test-read-event-timeout)
598 (delete-file file-notify--test-tmpfile))
599 (file-notify-rm-watch file-notify--test-desc))
600
601 ;; The environment shall be cleaned up.
602 (file-notify--test-cleanup-p))
603
604 ;; Cleanup.
605 (file-notify--test-cleanup)))
606
607 (file-notify--deftest-remote file-notify-test02-events
608 "Check file creation/change/removal notifications for remote files.")
609
610 (require 'autorevert)
611 (setq auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded"
612 auto-revert-remote-files t
613 auto-revert-stop-on-user-input nil)
614
615 (ert-deftest file-notify-test03-autorevert ()
616 "Check autorevert via file notification."
617 (skip-unless (file-notify--test-local-enabled))
618
619 ;; `auto-revert-buffers' runs every 5". And we must wait, until the
620 ;; file has been reverted.
621 (let ((timeout (if (file-remote-p temporary-file-directory) 60 10))
622 buf)
623 (unwind-protect
624 (progn
625 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
626 (write-region
627 "any text" nil file-notify--test-tmpfile nil 'no-message)
628 (setq buf (find-file-noselect file-notify--test-tmpfile))
629 (with-current-buffer buf
630 (should (string-equal (buffer-string) "any text"))
631 ;; `buffer-stale--default-function' checks for
632 ;; `verify-visited-file-modtime'. We must ensure that it
633 ;; returns nil.
634 (sleep-for 1)
635 (auto-revert-mode 1)
636
637 ;; `auto-revert-buffers' runs every 5".
638 (with-timeout (timeout (ignore))
639 (while (null auto-revert-notify-watch-descriptor)
640 (sleep-for 1)))
641
642 ;; Check, that file notification has been used.
643 (should auto-revert-mode)
644 (should auto-revert-use-notify)
645 (should auto-revert-notify-watch-descriptor)
646
647 ;; Modify file. We wait for a second, in order to have
648 ;; another timestamp.
649 (with-current-buffer (get-buffer-create "*Messages*")
650 (narrow-to-region (point-max) (point-max)))
651 (sleep-for 1)
652 (write-region
653 "another text" nil file-notify--test-tmpfile nil 'no-message)
654
655 ;; Check, that the buffer has been reverted.
656 (with-current-buffer (get-buffer-create "*Messages*")
657 (file-notify--wait-for-events
658 timeout
659 (string-match
660 (format-message "Reverting buffer `%s'." (buffer-name buf))
661 (buffer-string))))
662 (should (string-match "another text" (buffer-string)))
663
664 ;; Stop file notification. Autorevert shall still work via polling.
665 (file-notify-rm-watch auto-revert-notify-watch-descriptor)
666 (file-notify--wait-for-events
667 timeout (null auto-revert-use-notify))
668 (should-not auto-revert-use-notify)
669 (should-not auto-revert-notify-watch-descriptor)
670
671 ;; Modify file. We wait for two seconds, in order to
672 ;; have another timestamp. One second seems to be too
673 ;; short.
674 (with-current-buffer (get-buffer-create "*Messages*")
675 (narrow-to-region (point-max) (point-max)))
676 (sleep-for 2)
677 (write-region
678 "foo bla" nil file-notify--test-tmpfile nil 'no-message)
679
680 ;; Check, that the buffer has been reverted.
681 (with-current-buffer (get-buffer-create "*Messages*")
682 (file-notify--wait-for-events
683 timeout
684 (string-match
685 (format-message "Reverting buffer `%s'." (buffer-name buf))
686 (buffer-string))))
687 (should (string-match "foo bla" (buffer-string))))
688
689 ;; The environment shall be cleaned up.
690 (file-notify--test-cleanup-p))
691
692 ;; Cleanup.
693 (with-current-buffer "*Messages*" (widen))
694 (ignore-errors (kill-buffer buf))
695 (file-notify--test-cleanup))))
696
697 (file-notify--deftest-remote file-notify-test03-autorevert
698 "Check autorevert via file notification for remote files.")
699
700 (ert-deftest file-notify-test04-file-validity ()
701 "Check `file-notify-valid-p' for files."
702 (skip-unless (file-notify--test-local-enabled))
703
704 (unwind-protect
705 (progn
706 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
707 (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
708 (should
709 (setq file-notify--test-desc
710 (file-notify-add-watch
711 file-notify--test-tmpfile '(change) #'ignore)))
712 (should (file-notify-valid-p file-notify--test-desc))
713 ;; After calling `file-notify-rm-watch', the descriptor is not
714 ;; valid anymore.
715 (file-notify-rm-watch file-notify--test-desc)
716 (should-not (file-notify-valid-p file-notify--test-desc))
717 (delete-file file-notify--test-tmpfile)
718
719 ;; The environment shall be cleaned up.
720 (file-notify--test-cleanup-p))
721
722 ;; Cleanup.
723 (file-notify--test-cleanup))
724
725 (unwind-protect
726 (progn
727 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
728 (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
729 (should
730 (setq file-notify--test-desc
731 (file-notify-add-watch
732 file-notify--test-tmpfile
733 '(change) #'file-notify--test-event-handler)))
734 (should (file-notify-valid-p file-notify--test-desc))
735 (file-notify--test-with-events
736 (cond
737 ;; cygwin recognizes only `deleted' and `stopped' events.
738 ((eq system-type 'cygwin)
739 '(deleted stopped))
740 ;; inotify and kqueue raise just one `changed' event.
741 ((or (string-equal "inotify" (file-notify--test-library))
742 (string-equal "kqueue" (file-notify--test-library)))
743 '(changed deleted stopped))
744 ;; gfilenotify raises one or two `changed' events
745 ;; randomly, no chance to test. So we accept both cases.
746 ((string-equal "gfilenotify" (file-notify--test-library))
747 '((changed deleted stopped)
748 (changed changed deleted stopped)))
749 (t '(changed changed deleted stopped)))
750 (write-region
751 "another text" nil file-notify--test-tmpfile nil 'no-message)
752 (read-event nil nil file-notify--test-read-event-timeout)
753 (delete-file file-notify--test-tmpfile))
754 ;; After deleting the file, the descriptor is not valid anymore.
755 (should-not (file-notify-valid-p file-notify--test-desc))
756 (file-notify-rm-watch file-notify--test-desc)
757
758 ;; The environment shall be cleaned up.
759 (file-notify--test-cleanup-p))
760
761 ;; Cleanup.
762 (file-notify--test-cleanup))
763
764 (unwind-protect
765 (let ((temporary-file-directory
766 (make-temp-file "file-notify-test-parent" t)))
767 (should
768 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
769 file-notify--test-desc
770 (file-notify-add-watch
771 temporary-file-directory
772 '(change) #'file-notify--test-event-handler)))
773 (should (file-notify-valid-p file-notify--test-desc))
774 (file-notify--test-with-events
775 (cond
776 ;; w32notify does not raise `deleted' and `stopped' events
777 ;; for the watched directory.
778 ((string-equal (file-notify--test-library) "w32notify")
779 '(created changed deleted))
780 ;; cygwin recognizes only `deleted' and `stopped' events.
781 ((eq system-type 'cygwin)
782 '(deleted stopped))
783 ;; There are two `deleted' events, for the file and for the
784 ;; directory. Except for kqueue.
785 ((string-equal (file-notify--test-library) "kqueue")
786 '(created changed deleted stopped))
787 (t '(created changed deleted deleted stopped)))
788 (write-region
789 "any text" nil file-notify--test-tmpfile nil 'no-message)
790 (read-event nil nil file-notify--test-read-event-timeout)
791 (delete-directory temporary-file-directory t))
792 ;; After deleting the parent directory, the descriptor must
793 ;; not be valid anymore.
794 (should-not (file-notify-valid-p file-notify--test-desc))
795
796 ;; The environment shall be cleaned up.
797 (file-notify--test-cleanup-p))
798
799 ;; Cleanup.
800 (file-notify--test-cleanup)))
801
802 (file-notify--deftest-remote file-notify-test04-file-validity
803 "Check `file-notify-valid-p' via file notification for remote files.")
804
805 (ert-deftest file-notify-test05-dir-validity ()
806 "Check `file-notify-valid-p' for directories."
807 (skip-unless (file-notify--test-local-enabled))
808
809 (unwind-protect
810 (progn
811 (should
812 (setq file-notify--test-tmpfile
813 (make-temp-file "file-notify-test-parent" t)))
814 (should
815 (setq file-notify--test-desc
816 (file-notify-add-watch
817 file-notify--test-tmpfile '(change) #'ignore)))
818 (should (file-notify-valid-p file-notify--test-desc))
819 ;; After removing the watch, the descriptor must not be valid
820 ;; anymore.
821 (file-notify-rm-watch file-notify--test-desc)
822 (file-notify--wait-for-events
823 (file-notify--test-timeout)
824 (not (file-notify-valid-p file-notify--test-desc)))
825 (should-not (file-notify-valid-p file-notify--test-desc))
826 (delete-directory file-notify--test-tmpfile t)
827
828 ;; The environment shall be cleaned up.
829 (file-notify--test-cleanup-p))
830
831 ;; Cleanup.
832 (file-notify--test-cleanup))
833
834 (unwind-protect
835 (progn
836 (should
837 (setq file-notify--test-tmpfile
838 (make-temp-file "file-notify-test-parent" t)))
839 (should
840 (setq file-notify--test-desc
841 (file-notify-add-watch
842 file-notify--test-tmpfile '(change) #'ignore)))
843 (should (file-notify-valid-p file-notify--test-desc))
844 ;; After deleting the directory, the descriptor must not be
845 ;; valid anymore.
846 (delete-directory file-notify--test-tmpfile t)
847 (file-notify--wait-for-events
848 (file-notify--test-timeout)
849 (not (file-notify-valid-p file-notify--test-desc)))
850 (should-not (file-notify-valid-p file-notify--test-desc))
851
852 ;; The environment shall be cleaned up.
853 (file-notify--test-cleanup-p))
854
855 ;; Cleanup.
856 (file-notify--test-cleanup)))
857
858 (file-notify--deftest-remote file-notify-test05-dir-validity
859 "Check `file-notify-valid-p' via file notification for remote directories.")
860
861 (ert-deftest file-notify-test06-many-events ()
862 "Check that events are not dropped."
863 :tags '(:expensive-test)
864 (skip-unless (file-notify--test-local-enabled))
865 ;; Under cygwin events arrive in random order. Impossible to define a test.
866 (skip-unless (not (eq system-type 'cygwin)))
867
868 (should
869 (setq file-notify--test-tmpfile
870 (make-temp-file "file-notify-test-parent" t)))
871 (should
872 (setq file-notify--test-desc
873 (file-notify-add-watch
874 file-notify--test-tmpfile
875 '(change) #'file-notify--test-event-handler)))
876 (unwind-protect
877 (let ((n 1000)
878 source-file-list target-file-list
879 (default-directory file-notify--test-tmpfile))
880 (dotimes (i n)
881 ;; It matters which direction we rename, at least for
882 ;; kqueue. This backend parses directories in alphabetic
883 ;; order (x%d before y%d). So we rename into both directions.
884 (if (zerop (mod i 2))
885 (progn
886 (push (expand-file-name (format "x%d" i)) source-file-list)
887 (push (expand-file-name (format "y%d" i)) target-file-list))
888 (push (expand-file-name (format "y%d" i)) source-file-list)
889 (push (expand-file-name (format "x%d" i)) target-file-list)))
890 (file-notify--test-with-events (make-list (+ n n) 'created)
891 (let ((source-file-list source-file-list)
892 (target-file-list target-file-list))
893 (while (and source-file-list target-file-list)
894 (read-event nil nil file-notify--test-read-event-timeout)
895 (write-region "" nil (pop source-file-list) nil 'no-message)
896 (read-event nil nil file-notify--test-read-event-timeout)
897 (write-region "" nil (pop target-file-list) nil 'no-message))))
898 (file-notify--test-with-events
899 (cond
900 ;; w32notify fires both `deleted' and `renamed' events.
901 ((string-equal (file-notify--test-library) "w32notify")
902 (let (r)
903 (dotimes (_i n r)
904 (setq r (append '(deleted renamed) r)))))
905 (t (make-list n 'renamed)))
906 (let ((source-file-list source-file-list)
907 (target-file-list target-file-list))
908 (while (and source-file-list target-file-list)
909 (read-event nil nil file-notify--test-read-event-timeout)
910 (rename-file (pop source-file-list) (pop target-file-list) t))))
911 (file-notify--test-with-events (make-list n 'deleted)
912 (dolist (file target-file-list)
913 (read-event nil nil file-notify--test-read-event-timeout)
914 (delete-file file) file-notify--test-read-event-timeout))
915 (delete-directory file-notify--test-tmpfile)
916
917 ;; The environment shall be cleaned up.
918 (file-notify--test-cleanup-p))
919
920 ;; Cleanup.
921 (file-notify--test-cleanup)))
922
923 (file-notify--deftest-remote file-notify-test06-many-events
924 "Check that events are not dropped for remote directories.")
925
926 (ert-deftest file-notify-test07-backup ()
927 "Check that backup keeps file notification."
928 (skip-unless (file-notify--test-local-enabled))
929
930 (unwind-protect
931 (progn
932 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
933 (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
934 (should
935 (setq file-notify--test-desc
936 (file-notify-add-watch
937 file-notify--test-tmpfile
938 '(change) #'file-notify--test-event-handler)))
939 (should (file-notify-valid-p file-notify--test-desc))
940 (file-notify--test-with-events
941 (cond
942 ;; On Cygwin there is one `changed' event in both the
943 ;; local and remote cases.
944 ((eq system-type 'cygwin) '(changed))
945 ;; For w32notify and in the remote case, there are two
946 ;; `changed' events.
947 ((or (string-equal (file-notify--test-library) "w32notify")
948 (file-remote-p temporary-file-directory))
949 '(changed changed))
950 ;; gfilenotify raises one or two `changed' events
951 ;; randomly, no chance to test. So we accept both cases.
952 ((string-equal "gfilenotify" (file-notify--test-library))
953 '((changed)
954 (changed changed)))
955 (t '(changed)))
956 ;; There shouldn't be any problem, because the file is kept.
957 (with-temp-buffer
958 (let ((buffer-file-name file-notify--test-tmpfile)
959 (make-backup-files t)
960 (backup-by-copying t)
961 (kept-new-versions 1)
962 (delete-old-versions t))
963 (insert "another text")
964 (save-buffer))))
965 ;; After saving the buffer, the descriptor is still valid.
966 (should (file-notify-valid-p file-notify--test-desc))
967 (delete-file file-notify--test-tmpfile)
968
969 ;; The environment shall be cleaned up.
970 (file-notify--test-cleanup-p))
971
972 ;; Cleanup.
973 (file-notify--test-cleanup))
974
975 (unwind-protect
976 ;; It doesn't work for kqueue, because we don't use an implicit
977 ;; directory monitor.
978 (unless (string-equal (file-notify--test-library) "kqueue")
979 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
980 (write-region
981 "any text" nil file-notify--test-tmpfile nil 'no-message)
982 (should
983 (setq file-notify--test-desc
984 (file-notify-add-watch
985 file-notify--test-tmpfile
986 '(change) #'file-notify--test-event-handler)))
987 (should (file-notify-valid-p file-notify--test-desc))
988 (file-notify--test-with-events
989 (cond
990 ;; On Cygwin we only get the `changed' event.
991 ((eq system-type 'cygwin) '(changed))
992 (t '(renamed created changed)))
993 ;; The file is renamed when creating a backup. It shall
994 ;; still be watched.
995 (with-temp-buffer
996 (let ((buffer-file-name file-notify--test-tmpfile)
997 (make-backup-files t)
998 (backup-by-copying nil)
999 (backup-by-copying-when-mismatch nil)
1000 (kept-new-versions 1)
1001 (delete-old-versions t))
1002 (insert "another text")
1003 (save-buffer))))
1004 ;; After saving the buffer, the descriptor is still valid.
1005 (should (file-notify-valid-p file-notify--test-desc))
1006 (delete-file file-notify--test-tmpfile)
1007
1008 ;; The environment shall be cleaned up.
1009 (file-notify--test-cleanup-p))
1010
1011 ;; Cleanup.
1012 (file-notify--test-cleanup)))
1013
1014 (file-notify--deftest-remote file-notify-test07-backup
1015 "Check that backup keeps file notification for remote files.")
1016
1017 (ert-deftest file-notify-test08-watched-file-in-watched-dir ()
1018 "Watches a directory and a file in that directory separately.
1019 Checks that the callbacks are only called with events with
1020 descriptors that were issued when registering the watches. This
1021 test caters for the situation in bug#22736 where the callback for
1022 the directory received events for the file with the descriptor of
1023 the file watch."
1024 :tags '(:expensive-test)
1025 (skip-unless (file-notify--test-local-enabled))
1026
1027 ;; A directory to be watched.
1028 (should
1029 (setq file-notify--test-tmpfile
1030 (make-temp-file "file-notify-test-parent" t)))
1031 ;; A file to be watched.
1032 (should
1033 (setq file-notify--test-tmpfile1
1034 (let ((temporary-file-directory file-notify--test-tmpfile))
1035 (file-notify--test-make-temp-name))))
1036 (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message)
1037 (unwind-protect
1038 (cl-flet (;; Directory monitor.
1039 (dir-callback (event)
1040 (let ((file-notify--test-desc file-notify--test-desc1))
1041 (file-notify--test-event-handler event)))
1042 ;; File monitor.
1043 (file-callback (event)
1044 (let ((file-notify--test-desc file-notify--test-desc2))
1045 (file-notify--test-event-handler event))))
1046 (should
1047 (setq file-notify--test-desc1
1048 (file-notify-add-watch
1049 file-notify--test-tmpfile
1050 '(change) #'dir-callback)))
1051 (should
1052 (setq file-notify--test-desc2
1053 (file-notify-add-watch
1054 file-notify--test-tmpfile1
1055 '(change) #'file-callback)))
1056 (should (file-notify-valid-p file-notify--test-desc1))
1057 (should (file-notify-valid-p file-notify--test-desc2))
1058 (should-not (equal file-notify--test-desc1 file-notify--test-desc2))
1059 ;; gfilenotify raises one or two `changed' events randomly in
1060 ;; the file monitor, no chance to test.
1061 (unless (string-equal "gfilenotify" (file-notify--test-library))
1062 (let ((n 100) events)
1063 ;; Compute the expected events.
1064 (dotimes (_i (/ n 2))
1065 (setq events
1066 (append
1067 (append
1068 ;; Directory monitor and file monitor.
1069 (cond
1070 ;; In the remote case, there are two `changed'
1071 ;; events.
1072 ((file-remote-p temporary-file-directory)
1073 '(changed changed changed changed))
1074 ;; The directory monitor in kqueue does not
1075 ;; raise any `changed' event. Just the file
1076 ;; monitor event is received.
1077 ((string-equal (file-notify--test-library) "kqueue")
1078 '(changed))
1079 ;; Otherwise, both monitors report the
1080 ;; `changed' event.
1081 (t '(changed changed)))
1082
1083 ;; Just the directory monitor.
1084 (cond
1085 ;; In kqueue, there is an additional `changed'
1086 ;; event. Why?
1087 ((string-equal (file-notify--test-library) "kqueue")
1088 '(changed created changed))
1089 (t '(created changed))))
1090 events)))
1091 ;; gvfs-monitor-dir returns the events in random order.
1092 (when (string-equal "gvfs-monitor-dir" (file-notify--test-library))
1093 (setq events (cons 'random events)))
1094
1095 ;; Run the test.
1096 (file-notify--test-with-events events
1097 (dotimes (i n)
1098 (read-event nil nil file-notify--test-read-event-timeout)
1099 (if (zerop (mod i 2))
1100 (write-region
1101 "any text" nil file-notify--test-tmpfile1 t 'no-message)
1102 (let ((temporary-file-directory file-notify--test-tmpfile))
1103 (write-region
1104 "any text" nil
1105 (file-notify--test-make-temp-name) nil 'no-message)))))))
1106
1107 ;; If we delete the file, the directory monitor shall still be
1108 ;; active. We receive the `deleted' event from both the
1109 ;; directory and the file monitor. The `stopped' event is
1110 ;; from the file monitor. It's undecided in which order the
1111 ;; the directory and the file monitor are triggered.
1112 (file-notify--test-with-events '(random deleted deleted stopped)
1113 (delete-file file-notify--test-tmpfile1))
1114 (should (file-notify-valid-p file-notify--test-desc1))
1115 (should-not (file-notify-valid-p file-notify--test-desc2))
1116
1117 ;; Now we delete the directory.
1118 (file-notify--test-with-events
1119 (cond
1120 ;; In kqueue, just one `deleted' event for the directory
1121 ;; is received.
1122 ((string-equal (file-notify--test-library) "kqueue")
1123 '(deleted stopped))
1124 (t (append
1125 ;; The directory monitor raises a `deleted' event for
1126 ;; every file contained in the directory, we must
1127 ;; count them.
1128 (make-list
1129 (length
1130 (directory-files
1131 file-notify--test-tmpfile nil
1132 directory-files-no-dot-files-regexp 'nosort))
1133 'deleted)
1134 ;; The events of the directory itself.
1135 (cond
1136 ;; w32notify does not raise `deleted' and `stopped'
1137 ;; events for the watched directory.
1138 ((string-equal (file-notify--test-library) "w32notify") '())
1139 (t '(deleted stopped))))))
1140 (delete-directory file-notify--test-tmpfile 'recursive))
1141 (should-not (file-notify-valid-p file-notify--test-desc1))
1142 (should-not (file-notify-valid-p file-notify--test-desc2))
1143
1144 ;; The environment shall be cleaned up.
1145 (file-notify--test-cleanup-p))
1146
1147 ;; Cleanup.
1148 (file-notify--test-cleanup)))
1149
1150 (file-notify--deftest-remote file-notify-test08-watched-file-in-watched-dir
1151 "Check `file-notify-test08-watched-file-in-watched-dir' for remote files.")
1152
1153 (ert-deftest file-notify-test09-sufficient-resources ()
1154 "Check that file notification does not use too many resources."
1155 :tags '(:expensive-test)
1156 (skip-unless (file-notify--test-local-enabled))
1157 ;; This test is intended for kqueue only.
1158 (skip-unless (string-equal (file-notify--test-library) "kqueue"))
1159
1160 (should
1161 (setq file-notify--test-tmpfile
1162 (make-temp-file "file-notify-test-parent" t)))
1163 (unwind-protect
1164 (let ((temporary-file-directory file-notify--test-tmpfile)
1165 descs)
1166 (should-error
1167 (while t
1168 ;; We watch directories, because we want to reach the upper
1169 ;; limit. Watching a file might not be sufficient, because
1170 ;; most of the libraries implement this as watching the
1171 ;; upper directory.
1172 (setq file-notify--test-tmpfile1
1173 (make-temp-file "file-notify-test-parent" t)
1174 descs
1175 (cons
1176 (should
1177 (file-notify-add-watch
1178 file-notify--test-tmpfile1 '(change) #'ignore))
1179 descs)))
1180 :type 'file-notify-error)
1181 ;; Remove watches. If we don't do it prior removing
1182 ;; directories, Emacs crashes in batch mode.
1183 (dolist (desc descs)
1184 (file-notify-rm-watch desc))
1185 ;; Remove directories.
1186 (delete-directory file-notify--test-tmpfile 'recursive)
1187
1188 ;; The environment shall be cleaned up.
1189 (file-notify--test-cleanup-p))
1190
1191 ;; Cleanup.
1192 (file-notify--test-cleanup)))
1193
1194 (file-notify--deftest-remote file-notify-test09-sufficient-resources
1195 "Check `file-notify-test09-sufficient-resources' for remote files.")
1196
1197 (defun file-notify-test-all (&optional interactive)
1198 "Run all tests for \\[file-notify]."
1199 (interactive "p")
1200 (if interactive
1201 (ert-run-tests-interactively "^file-notify-")
1202 (ert-run-tests-batch "^file-notify-")))
1203
1204 ;; TODO:
1205
1206 ;; * kqueue does not send all expected `deleted' events. Maybe due to
1207 ;; the missing directory monitor.
1208 ;; * For w32notify, no `deleted' and `stopped' events arrive when a
1209 ;; directory is removed.
1210 ;; * For w32notify, no `attribute-changed' events arrive. Its sends
1211 ;; `changed' events instead.
1212 ;; * Check, why cygwin recognizes only `deleted' and `stopped' events.
1213
1214 (provide 'file-notify-tests)
1215 ;;; file-notify-tests.el ends here