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