aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorMichael Albinus2016-01-22 19:56:09 +0100
committerMichael Albinus2016-01-22 19:56:09 +0100
commit7bf54d01159eb09bae3c9cd86f2af0812d9afdf6 (patch)
treef00e00ba1ed5a492ec94faf8d07a6ca2f857a9c5 /test
parentf7dc6d8b5bb318e02a4016d93f8b34de0716f4dc (diff)
downloademacs-7bf54d01159eb09bae3c9cd86f2af0812d9afdf6.tar.gz
emacs-7bf54d01159eb09bae3c9cd86f2af0812d9afdf6.zip
Backport kqueue integration from master
* configure.ac (--with-file-notification): Add kqueue. (top): Remove special test for "${HAVE_NS}" and ${with_file_notification}, this is handled inside gfilenotify tests. Add kqueue tests. Use NOTIFY_CFLAGS and NOTIFY_LIBS instead of library specific variables. Add error message for gfile on Nextstep. * doc/lispref/os.texi (File Notifications): Add kqueue as backend. Fix some glitches in the example. * etc/NEWS: Mention kqueue. * lisp/filenotify.el (file-notify--library) (file-notify-descriptors, file-notify-callback) (file-notify-add-watch, file-notify-rm-watch) (file-notify-valid-p): Add kqueue support. (file-notify--rm-descriptor): Remove WHAT arg. * src/Makefile.in: Use NOTIFY_CFLAGS and NOTIFY_LIBS. * src/emacs.c (main): Call globals_of_kqueue and syms_of_kqueue. * src/inotify.c (inotifyevent_to_event): Extract file name from watch_object if the event doesn't provide it. (Finotify_add_watch): Add file name to watch_object. * src/keyboard.c (make_lispy_event): Check also for HAVE_KQUEUE. * src/kqueue.c: New file. * src/lisp.h: Declare extern globals_of_kqueue and syms_of_kqueue. * test/automated/file-notify-tests.el (file-notify--test-expected-events): Remove. (file-notify--test-cleanup): Do not set that variable. (file-notify--test-timeout) Use different timeouts for different libraries. (file-notify--test-library): New defun. (file-notify--test-event-test): Make stronger checks. (file-notify--test-with-events): EVENTS can also be a list of lists. Flush outstanding events before running the body. Make timeout heuristically depend on the number of events. (file-notify-test01-add-watch, file-notify-test02-events) (file-notify-test04-file-validity, file-notify-test05-dir-validity): Rewrite in order to call file monitors but directory monitors. (file-notify-test02-events, file-notify-test04-file-validity): Do not skip cygwin tests. Add additional test for file creation. Adapt expected result for different backends. (file-notify-test03-autorevert): Some of the tests don't work for w32notify. (file-notify-test06-many-events): New test.
Diffstat (limited to 'test')
-rw-r--r--test/automated/file-notify-tests.el585
1 files changed, 405 insertions, 180 deletions
diff --git a/test/automated/file-notify-tests.el b/test/automated/file-notify-tests.el
index 7bf7b0b3d15..de64f5086d2 100644
--- a/test/automated/file-notify-tests.el
+++ b/test/automated/file-notify-tests.el
@@ -61,11 +61,14 @@
61(defvar file-notify--test-results nil) 61(defvar file-notify--test-results nil)
62(defvar file-notify--test-event nil) 62(defvar file-notify--test-event nil)
63(defvar file-notify--test-events nil) 63(defvar file-notify--test-events nil)
64(defvar file-notify--test-expected-events nil)
65 64
66(defun file-notify--test-timeout () 65(defun file-notify--test-timeout ()
67 "Timeout to wait for arriving events, in seconds." 66 "Timeout to wait for arriving events, in seconds."
68 (if (file-remote-p temporary-file-directory) 6 3)) 67 (cond
68 ((file-remote-p temporary-file-directory) 6)
69 ((string-equal (file-notify--test-library) "w32notify") 20)
70 ((eq system-type 'cygwin) 10)
71 (t 3)))
69 72
70(defun file-notify--test-cleanup () 73(defun file-notify--test-cleanup ()
71 "Cleanup after a test." 74 "Cleanup after a test."
@@ -89,8 +92,7 @@
89 file-notify--test-tmpfile1 nil 92 file-notify--test-tmpfile1 nil
90 file-notify--test-desc nil 93 file-notify--test-desc nil
91 file-notify--test-results nil 94 file-notify--test-results nil
92 file-notify--test-events nil 95 file-notify--test-events nil)
93 file-notify--test-expected-events nil)
94 (when file-notify--test-event 96 (when file-notify--test-event
95 (error "file-notify--test-event should not be set but bound dynamically"))) 97 (error "file-notify--test-event should not be set but bound dynamically")))
96 98
@@ -133,6 +135,18 @@ being the result.")
133 ;; Return result. 135 ;; Return result.
134 (cdr file-notify--test-remote-enabled-checked)) 136 (cdr file-notify--test-remote-enabled-checked))
135 137
138(defun file-notify--test-library ()
139 "The used library for the test, as a string.
140In the remote case, it is the process name which runs on the
141remote host, or nil."
142 (if (null (file-remote-p temporary-file-directory))
143 (symbol-name file-notify--library)
144 (and (consp file-notify--test-remote-enabled-checked)
145 (processp (cdr file-notify--test-remote-enabled-checked))
146 (replace-regexp-in-string
147 "<[[:digit:]]+>\\'" ""
148 (process-name (cdr file-notify--test-remote-enabled-checked))))))
149
136(defmacro file-notify--deftest-remote (test docstring) 150(defmacro file-notify--deftest-remote (test docstring)
137 "Define ert `TEST-remote' for remote files." 151 "Define ert `TEST-remote' for remote files."
138 (declare (indent 1)) 152 (declare (indent 1))
@@ -151,12 +165,7 @@ being the result.")
151 "Test availability of `file-notify'." 165 "Test availability of `file-notify'."
152 (skip-unless (file-notify--test-local-enabled)) 166 (skip-unless (file-notify--test-local-enabled))
153 ;; Report the native library which has been used. 167 ;; Report the native library which has been used.
154 (if (null (file-remote-p temporary-file-directory)) 168 (message "Library: `%s'" (file-notify--test-library))
155 (message "Local library: `%s'" file-notify--library)
156 (message "Remote command: `%s'"
157 (replace-regexp-in-string
158 "<[[:digit:]]+>\\'" ""
159 (process-name (cdr file-notify--test-remote-enabled-checked)))))
160 (should 169 (should
161 (setq file-notify--test-desc 170 (setq file-notify--test-desc
162 (file-notify-add-watch temporary-file-directory '(change) 'ignore))) 171 (file-notify-add-watch temporary-file-directory '(change) 'ignore)))
@@ -190,12 +199,13 @@ being the result.")
190 (file-notify-add-watch 199 (file-notify-add-watch
191 temporary-file-directory '(change attribute-change) 'ignore))) 200 temporary-file-directory '(change attribute-change) 'ignore)))
192 (file-notify-rm-watch file-notify--test-desc) 201 (file-notify-rm-watch file-notify--test-desc)
193 ;; The file does not need to exist, just the upper directory. 202 (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
194 (should 203 (should
195 (setq file-notify--test-desc 204 (setq file-notify--test-desc
196 (file-notify-add-watch 205 (file-notify-add-watch
197 file-notify--test-tmpfile '(change attribute-change) 'ignore))) 206 file-notify--test-tmpfile '(change attribute-change) 'ignore)))
198 (file-notify-rm-watch file-notify--test-desc) 207 (file-notify-rm-watch file-notify--test-desc)
208 (delete-file file-notify--test-tmpfile)
199 209
200 ;; Check error handling. 210 ;; Check error handling.
201 (should-error (file-notify-add-watch 1 2 3 4) 211 (should-error (file-notify-add-watch 1 2 3 4)
@@ -236,16 +246,17 @@ is bound somewhere."
236 (should 246 (should
237 (or (string-equal (file-notify--event-file-name file-notify--test-event) 247 (or (string-equal (file-notify--event-file-name file-notify--test-event)
238 file-notify--test-tmpfile) 248 file-notify--test-tmpfile)
239 (string-equal (directory-file-name 249 (string-equal (file-notify--event-file-name file-notify--test-event)
240 (file-name-directory 250 file-notify--test-tmpfile1)
241 (file-notify--event-file-name file-notify--test-event))) 251 (string-equal (file-notify--event-file-name file-notify--test-event)
242 file-notify--test-tmpfile))) 252 temporary-file-directory)))
243 ;; Check the second file name if exists. 253 ;; Check the second file name if exists.
244 (when (eq (nth 1 file-notify--test-event) 'renamed) 254 (when (eq (nth 1 file-notify--test-event) 'renamed)
245 (should 255 (should
246 (string-equal 256 (or (string-equal (file-notify--event-file1-name file-notify--test-event)
247 (file-notify--event-file1-name file-notify--test-event) 257 file-notify--test-tmpfile1)
248 file-notify--test-tmpfile1)))) 258 (string-equal (file-notify--event-file1-name file-notify--test-event)
259 temporary-file-directory)))))
249 260
250(defun file-notify--test-event-handler (event) 261(defun file-notify--test-event-handler (event)
251 "Run a test over FILE-NOTIFY--TEST-EVENT. 262 "Run a test over FILE-NOTIFY--TEST-EVENT.
@@ -254,7 +265,7 @@ and the event to `file-notify--test-events'."
254 (let* ((file-notify--test-event event) 265 (let* ((file-notify--test-event event)
255 (result 266 (result
256 (ert-run-test (make-ert-test :body 'file-notify--test-event-test)))) 267 (ert-run-test (make-ert-test :body 'file-notify--test-event-test))))
257 ;; Do not add temporary files, this would confuse the checks. 268 ;; Do not add lock files, this would confuse the checks.
258 (unless (string-match 269 (unless (string-match
259 (regexp-quote ".#") 270 (regexp-quote ".#")
260 (file-notify--event-file-name file-notify--test-event)) 271 (file-notify--event-file-name file-notify--test-event))
@@ -278,137 +289,246 @@ TIMEOUT is the maximum time to wait for, in seconds."
278 289
279(defmacro file-notify--test-with-events (events &rest body) 290(defmacro file-notify--test-with-events (events &rest body)
280 "Run BODY collecting events and then compare with EVENTS. 291 "Run BODY collecting events and then compare with EVENTS.
281Don't wait longer than timeout seconds for the events to be delivered." 292EVENTS is either a simple list of events, or a list of lists of
293events, which represent different possible results. Don't wait
294longer than timeout seconds for the events to be delivered."
282 (declare (indent 1)) 295 (declare (indent 1))
283 (let ((outer (make-symbol "outer"))) 296 (let ((outer (make-symbol "outer")))
284 `(let ((,outer file-notify--test-events)) 297 `(let* ((,outer file-notify--test-events)
285 (setq file-notify--test-expected-events 298 (events (if (consp (car ,events)) ,events (list ,events)))
286 (append file-notify--test-expected-events ,events)) 299 (max-length (apply 'max (mapcar 'length events)))
300 create-lockfiles result)
301 ;; Flush pending events.
302 (file-notify--wait-for-events
303 (file-notify--test-timeout)
304 (input-pending-p))
287 (let (file-notify--test-events) 305 (let (file-notify--test-events)
288 ,@body 306 ,@body
289 (file-notify--wait-for-events 307 (file-notify--wait-for-events
290 (file-notify--test-timeout) 308 ;; More events need more time. Use some fudge factor.
291 (= (length ,events) (length file-notify--test-events))) 309 (* (ceiling max-length 100) (file-notify--test-timeout))
292 (should (equal ,events (mapcar #'cadr file-notify--test-events))) 310 (= max-length (length file-notify--test-events)))
311 ;; One of the possible results shall match.
312 (should
313 (dolist (elt events result)
314 (setq result
315 (or result
316 (equal elt (mapcar #'cadr file-notify--test-events))))))
293 (setq ,outer (append ,outer file-notify--test-events))) 317 (setq ,outer (append ,outer file-notify--test-events)))
294 (setq file-notify--test-events ,outer)))) 318 (setq file-notify--test-events ,outer))))
295 319
296(ert-deftest file-notify-test02-events () 320(ert-deftest file-notify-test02-events ()
297 "Check file creation/change/removal notifications." 321 "Check file creation/change/removal notifications."
298 (skip-unless (file-notify--test-local-enabled)) 322 (skip-unless (file-notify--test-local-enabled))
299 ;; Under cygwin there are so bad timings that it doesn't make sense to test.
300 (skip-unless (not (eq system-type 'cygwin)))
301
302 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
303 file-notify--test-tmpfile1 (file-notify--test-make-temp-name))
304 323
305 (unwind-protect 324 (unwind-protect
306 (progn 325 (progn
307 ;; Check creation, change and deletion. 326 ;; Check file creation, change and deletion. It doesn't work
308 (setq file-notify--test-desc 327 ;; for cygwin and kqueue, because we don't use an implicit
309 (file-notify-add-watch 328 ;; directory monitor (kqueue), or the timings are too bad (cygwin).
310 file-notify--test-tmpfile 329 (unless (or (eq system-type 'cygwin)
311 '(change) 'file-notify--test-event-handler)) 330 (string-equal (file-notify--test-library) "kqueue"))
312 (file-notify--test-with-events '(created changed deleted) 331 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
332 (should
333 (setq file-notify--test-desc
334 (file-notify-add-watch
335 file-notify--test-tmpfile
336 '(change) 'file-notify--test-event-handler)))
337 (file-notify--test-with-events
338 (cond
339 ;; cygwin recognizes only `deleted' and `stopped' events.
340 ((eq system-type 'cygwin)
341 '(deleted stopped))
342 (t '(created changed deleted stopped)))
343 (write-region
344 "another text" nil file-notify--test-tmpfile nil 'no-message)
345 (read-event nil nil 0.1)
346 (delete-file file-notify--test-tmpfile))
347 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
348 (let (file-notify--test-events)
349 (file-notify-rm-watch file-notify--test-desc)))
350
351 ;; Check file change and deletion.
352 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
353 (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
354 (should
355 (setq file-notify--test-desc
356 (file-notify-add-watch
357 file-notify--test-tmpfile
358 '(change) 'file-notify--test-event-handler)))
359 (file-notify--test-with-events
360 (cond
361 ;; cygwin recognizes only `deleted' and `stopped' events.
362 ((eq system-type 'cygwin)
363 '(deleted stopped))
364 ;; inotify and kqueue raise just one `changed' event.
365 ((or (string-equal "inotify" (file-notify--test-library))
366 (string-equal "kqueue" (file-notify--test-library)))
367 '(changed deleted stopped))
368 ;; gfilenotify raises one or two `changed' events
369 ;; randomly, no chance to test. So we accept both cases.
370 ((string-equal "gfilenotify" (file-notify--test-library))
371 '((changed deleted stopped)
372 (changed changed deleted stopped)))
373 (t '(changed changed deleted stopped)))
374 (read-event nil nil 0.1)
313 (write-region 375 (write-region
314 "any text" nil file-notify--test-tmpfile nil 'no-message) 376 "another text" nil file-notify--test-tmpfile nil 'no-message)
377 (read-event nil nil 0.1)
315 (delete-file file-notify--test-tmpfile)) 378 (delete-file file-notify--test-tmpfile))
316 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. 379 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
317 (let (file-notify--test-events) 380 (let (file-notify--test-events)
318 (file-notify-rm-watch file-notify--test-desc)) 381 (file-notify-rm-watch file-notify--test-desc))
319 382
320 ;; Check creation, change and deletion. There must be a 383 ;; Check file creation, change and deletion when watching a
321 ;; `stopped' event when deleting the directory. It doesn't 384 ;; directory. There must be a `stopped' event when deleting
322 ;; work for w32notify. 385 ;; the directory.
323 (unless (eq file-notify--library 'w32notify) 386 (let ((temporary-file-directory
324 (make-directory file-notify--test-tmpfile) 387 (make-temp-file "file-notify-test-parent" t)))
325 (setq file-notify--test-desc 388 (should
326 (file-notify-add-watch 389 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
327 file-notify--test-tmpfile 390 file-notify--test-desc
328 '(change) 'file-notify--test-event-handler)) 391 (file-notify-add-watch
392 temporary-file-directory
393 '(change) 'file-notify--test-event-handler)))
329 (file-notify--test-with-events 394 (file-notify--test-with-events
330 ;; There are two `deleted' events, for the file and for 395 (cond
331 ;; the directory. 396 ;; w32notify does raise a `stopped' event when a
332 '(created changed deleted deleted stopped) 397 ;; watched directory is deleted.
398 ((string-equal (file-notify--test-library) "w32notify")
399 '(created changed deleted))
400 ;; cygwin recognizes only `deleted' and `stopped' events.
401 ((eq system-type 'cygwin)
402 '(deleted stopped))
403 ;; There are two `deleted' events, for the file and for
404 ;; the directory. Except for kqueue.
405 ((string-equal (file-notify--test-library) "kqueue")
406 '(created changed deleted stopped))
407 (t '(created changed deleted deleted stopped)))
408 (read-event nil nil 0.1)
333 (write-region 409 (write-region
334 "any text" nil (expand-file-name "foo" file-notify--test-tmpfile) 410 "any text" nil file-notify--test-tmpfile nil 'no-message)
335 nil 'no-message) 411 (read-event nil nil 0.1)
336 (delete-directory file-notify--test-tmpfile 'recursive)) 412 (delete-directory temporary-file-directory 'recursive))
337 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. 413 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
338 (let (file-notify--test-events) 414 (let (file-notify--test-events)
339 (file-notify-rm-watch file-notify--test-desc))) 415 (file-notify-rm-watch file-notify--test-desc)))
340 416
341 ;; Check copy. 417 ;; Check copy of files inside a directory.
342 (setq file-notify--test-desc 418 (let ((temporary-file-directory
343 (file-notify-add-watch 419 (make-temp-file "file-notify-test-parent" t)))
344 file-notify--test-tmpfile 420 (should
345 '(change) 'file-notify--test-event-handler)) 421 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
346 (should file-notify--test-desc) 422 file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
347 (file-notify--test-with-events 423 file-notify--test-desc
348 ;; w32notify does not distinguish between `changed' and 424 (file-notify-add-watch
349 ;; `attribute-changed'. 425 temporary-file-directory
350 (if (eq file-notify--library 'w32notify) 426 '(change) 'file-notify--test-event-handler)))
351 '(created changed changed deleted) 427 (file-notify--test-with-events
352 '(created changed deleted)) 428 (cond
353 (write-region 429 ;; w32notify does not distinguish between `changed' and
354 "any text" nil file-notify--test-tmpfile nil 'no-message) 430 ;; `attribute-changed'.
355 (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) 431 ((string-equal (file-notify--test-library) "w32notify")
356 ;; The next two events shall not be visible. 432 '(created changed created changed changed changed changed
357 (set-file-modes file-notify--test-tmpfile 000) 433 deleted deleted))
358 (read-event nil nil 0.1) ; In order to distinguish the events. 434 ;; cygwin recognizes only `deleted' and `stopped' events.
359 (set-file-times file-notify--test-tmpfile '(0 0)) 435 ((eq system-type 'cygwin)
360 (delete-file file-notify--test-tmpfile) 436 '(deleted stopped))
361 (delete-file file-notify--test-tmpfile1)) 437 ;; There are three `deleted' events, for two files and
362 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. 438 ;; for the directory. Except for kqueue.
363 (let (file-notify--test-events) 439 ((string-equal (file-notify--test-library) "kqueue")
364 (file-notify-rm-watch file-notify--test-desc)) 440 '(created changed created changed deleted stopped))
441 (t '(created changed created changed
442 deleted deleted deleted stopped)))
443 (read-event nil nil 0.1)
444 (write-region
445 "any text" nil file-notify--test-tmpfile nil 'no-message)
446 (read-event nil nil 0.1)
447 (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1)
448 ;; The next two events shall not be visible.
449 (read-event nil nil 0.1)
450 (set-file-modes file-notify--test-tmpfile 000)
451 (read-event nil nil 0.1)
452 (set-file-times file-notify--test-tmpfile '(0 0))
453 (read-event nil nil 0.1)
454 (delete-directory temporary-file-directory 'recursive))
455 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
456 (let (file-notify--test-events)
457 (file-notify-rm-watch file-notify--test-desc)))
365 458
366 ;; Check rename. 459 ;; Check rename of files inside a directory.
367 (setq file-notify--test-desc 460 (let ((temporary-file-directory
368 (file-notify-add-watch 461 (make-temp-file "file-notify-test-parent" t)))
369 file-notify--test-tmpfile 462 (should
370 '(change) 'file-notify--test-event-handler)) 463 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
371 (should file-notify--test-desc) 464 file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
372 (file-notify--test-with-events '(created changed renamed) 465 file-notify--test-desc
373 (write-region 466 (file-notify-add-watch
374 "any text" nil file-notify--test-tmpfile nil 'no-message) 467 temporary-file-directory
375 (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) 468 '(change) 'file-notify--test-event-handler)))
376 ;; After the rename, we won't get events anymore. 469 (file-notify--test-with-events
377 (delete-file file-notify--test-tmpfile1)) 470 (cond
378 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. 471 ;; w32notify does not distinguish between `changed' and
379 (let (file-notify--test-events) 472 ;; `attribute-changed'.
380 (file-notify-rm-watch file-notify--test-desc)) 473 ((string-equal (file-notify--test-library) "w32notify")
474 '(created changed renamed deleted))
475 ;; cygwin recognizes only `deleted' and `stopped' events.
476 ((eq system-type 'cygwin)
477 '(deleted stopped))
478 ;; There are two `deleted' events, for the file and for
479 ;; the directory. Except for kqueue.
480 ((string-equal (file-notify--test-library) "kqueue")
481 '(created changed renamed deleted stopped))
482 (t '(created changed renamed deleted deleted stopped)))
483 (read-event nil nil 0.1)
484 (write-region
485 "any text" nil file-notify--test-tmpfile nil 'no-message)
486 (read-event nil nil 0.1)
487 (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1)
488 ;; After the rename, we won't get events anymore.
489 (read-event nil nil 0.1)
490 (delete-directory temporary-file-directory 'recursive))
491 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
492 (let (file-notify--test-events)
493 (file-notify-rm-watch file-notify--test-desc)))
381 494
382 ;; Check attribute change. It doesn't work for w32notify. 495 ;; Check attribute change. Does not work for cygwin.
383 (unless (eq file-notify--library 'w32notify) 496 (unless (eq system-type 'cygwin)
384 (setq file-notify--test-desc 497 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
385 (file-notify-add-watch 498 (write-region
386 file-notify--test-tmpfile 499 "any text" nil file-notify--test-tmpfile nil 'no-message)
387 '(attribute-change) 'file-notify--test-event-handler)) 500 (should
388 (file-notify--test-with-events 501 (setq file-notify--test-desc
389 (if (file-remote-p temporary-file-directory) 502 (file-notify-add-watch
390 ;; In the remote case, `write-region' raises also an 503 file-notify--test-tmpfile
391 ;; `attribute-changed' event. 504 '(attribute-change) 'file-notify--test-event-handler)))
392 '(attribute-changed attribute-changed attribute-changed) 505 (file-notify--test-with-events
393 '(attribute-changed attribute-changed)) 506 (cond
394 ;; We must use short delays between the operations. 507 ;; w32notify does not distinguish between `changed' and
395 ;; Otherwise, not all events arrive us in the remote case. 508 ;; `attribute-changed'.
396 (write-region 509 ((string-equal (file-notify--test-library) "w32notify")
397 "any text" nil file-notify--test-tmpfile nil 'no-message) 510 '(changed changed changed changed))
398 (read-event nil nil 0.1) 511 ;; For kqueue and in the remote case, `write-region'
399 (set-file-modes file-notify--test-tmpfile 000) 512 ;; raises also an `attribute-changed' event.
400 (read-event nil nil 0.1) 513 ((or (string-equal (file-notify--test-library) "kqueue")
401 (set-file-times file-notify--test-tmpfile '(0 0)) 514 (file-remote-p temporary-file-directory))
402 (read-event nil nil 0.1) 515 '(attribute-changed attribute-changed attribute-changed))
403 (delete-file file-notify--test-tmpfile)) 516 (t '(attribute-changed attribute-changed)))
517 (read-event nil nil 0.1)
518 (write-region
519 "any text" nil file-notify--test-tmpfile nil 'no-message)
520 (read-event nil nil 0.1)
521 (set-file-modes file-notify--test-tmpfile 000)
522 (read-event nil nil 0.1)
523 (set-file-times file-notify--test-tmpfile '(0 0))
524 (read-event nil nil 0.1)
525 (delete-file file-notify--test-tmpfile))
404 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. 526 ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
405 (let (file-notify--test-events) 527 (let (file-notify--test-events)
406 (file-notify-rm-watch file-notify--test-desc))) 528 (file-notify-rm-watch file-notify--test-desc)))
407 529
408 ;; Check the global sequence again just to make sure that 530 ;; Check the global sequence again just to make sure that
409 ;; `file-notify--test-events' has been set correctly. 531 ;; `file-notify--test-events' has been set correctly.
410 (should (equal (mapcar #'cadr file-notify--test-events)
411 file-notify--test-expected-events))
412 (should file-notify--test-results) 532 (should file-notify--test-results)
413 (dolist (result file-notify--test-results) 533 (dolist (result file-notify--test-results)
414 (when (ert-test-failed-p result) 534 (when (ert-test-failed-p result)
@@ -476,28 +596,31 @@ Don't wait longer than timeout seconds for the events to be delivered."
476 (should (string-match "another text" (buffer-string))) 596 (should (string-match "another text" (buffer-string)))
477 597
478 ;; Stop file notification. Autorevert shall still work via polling. 598 ;; Stop file notification. Autorevert shall still work via polling.
479 (file-notify-rm-watch auto-revert-notify-watch-descriptor) 599 ;; It doesn't work for `w32notify'.
480 (file-notify--wait-for-events 600 (unless (string-equal (file-notify--test-library) "w32notify")
481 timeout (null auto-revert-use-notify)) 601 (file-notify-rm-watch auto-revert-notify-watch-descriptor)
482 (should-not auto-revert-use-notify)
483 (should-not auto-revert-notify-watch-descriptor)
484
485 ;; Modify file. We wait for two seconds, in order to have
486 ;; another timestamp. One second seems to be too short.
487 (with-current-buffer (get-buffer-create "*Messages*")
488 (narrow-to-region (point-max) (point-max)))
489 (sleep-for 2)
490 (write-region
491 "foo bla" nil file-notify--test-tmpfile nil 'no-message)
492
493 ;; Check, that the buffer has been reverted.
494 (with-current-buffer (get-buffer-create "*Messages*")
495 (file-notify--wait-for-events 602 (file-notify--wait-for-events
496 timeout 603 timeout (null auto-revert-use-notify))
497 (string-match 604 (should-not auto-revert-use-notify)
498 (format-message "Reverting buffer `%s'." (buffer-name buf)) 605 (should-not auto-revert-notify-watch-descriptor)
499 (buffer-string)))) 606
500 (should (string-match "foo bla" (buffer-string))))) 607 ;; Modify file. We wait for two seconds, in order to
608 ;; have another timestamp. One second seems to be too
609 ;; short.
610 (with-current-buffer (get-buffer-create "*Messages*")
611 (narrow-to-region (point-max) (point-max)))
612 (sleep-for 2)
613 (write-region
614 "foo bla" nil file-notify--test-tmpfile nil 'no-message)
615
616 ;; Check, that the buffer has been reverted.
617 (with-current-buffer (get-buffer-create "*Messages*")
618 (file-notify--wait-for-events
619 timeout
620 (string-match
621 (format-message "Reverting buffer `%s'." (buffer-name buf))
622 (buffer-string))))
623 (should (string-match "foo bla" (buffer-string))))))
501 624
502 ;; Cleanup. 625 ;; Cleanup.
503 (with-current-buffer "*Messages*" (widen)) 626 (with-current-buffer "*Messages*" (widen))
@@ -510,51 +633,94 @@ Don't wait longer than timeout seconds for the events to be delivered."
510(ert-deftest file-notify-test04-file-validity () 633(ert-deftest file-notify-test04-file-validity ()
511 "Check `file-notify-valid-p' for files." 634 "Check `file-notify-valid-p' for files."
512 (skip-unless (file-notify--test-local-enabled)) 635 (skip-unless (file-notify--test-local-enabled))
513 ;; Under cygwin there are so bad timings that it doesn't make sense to test.
514 (skip-unless (not (eq system-type 'cygwin)))
515 636
516 (unwind-protect 637 (unwind-protect
517 (progn 638 (progn
518 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) 639 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
519 file-notify--test-desc 640 (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
520 (file-notify-add-watch 641 (should
521 file-notify--test-tmpfile 642 (setq file-notify--test-desc
522 '(change) #'file-notify--test-event-handler)) 643 (file-notify-add-watch
523 (file-notify--test-with-events '(created changed deleted) 644 file-notify--test-tmpfile
645 '(change) #'file-notify--test-event-handler)))
646 (should (file-notify-valid-p file-notify--test-desc))
647 ;; After calling `file-notify-rm-watch', the descriptor is not
648 ;; valid anymore.
649 (file-notify-rm-watch file-notify--test-desc)
650 (should-not (file-notify-valid-p file-notify--test-desc))
651 (delete-file file-notify--test-tmpfile))
652
653 ;; Cleanup.
654 (file-notify--test-cleanup))
655
656 (unwind-protect
657 (progn
658 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
659 (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
660 (should
661 (setq file-notify--test-desc
662 (file-notify-add-watch
663 file-notify--test-tmpfile
664 '(change) #'file-notify--test-event-handler)))
665 (file-notify--test-with-events
666 (cond
667 ;; cygwin recognizes only `deleted' and `stopped' events.
668 ((eq system-type 'cygwin)
669 '(deleted stopped))
670 ;; inotify and kqueue raise just one `changed' event.
671 ((or (string-equal "inotify" (file-notify--test-library))
672 (string-equal "kqueue" (file-notify--test-library)))
673 '(changed deleted stopped))
674 ;; gfilenotify raises one or two `changed' events
675 ;; randomly, no chance to test. So we accept both cases.
676 ((string-equal "gfilenotify" (file-notify--test-library))
677 '((changed deleted stopped)
678 (changed changed deleted stopped)))
679 (t '(changed changed deleted stopped)))
524 (should (file-notify-valid-p file-notify--test-desc)) 680 (should (file-notify-valid-p file-notify--test-desc))
681 (read-event nil nil 0.1)
525 (write-region 682 (write-region
526 "any text" nil file-notify--test-tmpfile nil 'no-message) 683 "another text" nil file-notify--test-tmpfile nil 'no-message)
684 (read-event nil nil 0.1)
527 (delete-file file-notify--test-tmpfile)) 685 (delete-file file-notify--test-tmpfile))
528 ;; After deleting the file, the descriptor is still valid. 686 ;; After deleting the file, the descriptor is not valid anymore.
529 (should (file-notify-valid-p file-notify--test-desc)) 687 (should-not (file-notify-valid-p file-notify--test-desc))
530 ;; After removing the watch, the descriptor must not be valid 688 (file-notify-rm-watch file-notify--test-desc))
531 ;; anymore.
532 (file-notify-rm-watch file-notify--test-desc)
533 (should-not (file-notify-valid-p file-notify--test-desc)))
534 689
535 ;; Cleanup. 690 ;; Cleanup.
536 (file-notify--test-cleanup)) 691 (file-notify--test-cleanup))
537 692
538 (unwind-protect 693 (unwind-protect
539 ;; The batch-mode operation of w32notify is fragile (there's no 694 ;; w32notify does not send a `stopped' event when deleting a
540 ;; input threads to send the message to). 695 ;; directory. The test does not work, therefore.
541 ;(unless (and noninteractive (eq file-notify--library 'w32notify)) 696 (unless (string-equal (file-notify--test-library) "w32notify")
542 (unless (eq file-notify--library 'w32notify) 697 (let ((temporary-file-directory
543 (let ((temporary-file-directory
544 (make-temp-file "file-notify-test-parent" t))) 698 (make-temp-file "file-notify-test-parent" t)))
545 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) 699 (should
546 file-notify--test-desc 700 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
547 (file-notify-add-watch 701 file-notify--test-desc
548 file-notify--test-tmpfile 702 (file-notify-add-watch
549 '(change) #'file-notify--test-event-handler)) 703 temporary-file-directory
550 (file-notify--test-with-events '(created changed deleted stopped) 704 '(change) #'file-notify--test-event-handler)))
551 (should (file-notify-valid-p file-notify--test-desc)) 705 (file-notify--test-with-events
552 (write-region 706 (cond
553 "any text" nil file-notify--test-tmpfile nil 'no-message) 707 ;; cygwin recognizes only `deleted' and `stopped' events.
708 ((eq system-type 'cygwin)
709 '(deleted stopped))
710 ;; There are two `deleted' events, for the file and for
711 ;; the directory. Except for kqueue.
712 ((string-equal (file-notify--test-library) "kqueue")
713 '(created changed deleted stopped))
714 (t '(created changed deleted deleted stopped)))
715 (should (file-notify-valid-p file-notify--test-desc))
716 (read-event nil nil 0.1)
717 (write-region
718 "any text" nil file-notify--test-tmpfile nil 'no-message)
719 (read-event nil nil 0.1)
554 (delete-directory temporary-file-directory t)) 720 (delete-directory temporary-file-directory t))
555 ;; After deleting the parent directory, the descriptor must 721 ;; After deleting the parent directory, the descriptor must
556 ;; not be valid anymore. 722 ;; not be valid anymore.
557 (should-not (file-notify-valid-p file-notify--test-desc)))) 723 (should-not (file-notify-valid-p file-notify--test-desc))))
558 724
559 ;; Cleanup. 725 ;; Cleanup.
560 (file-notify--test-cleanup))) 726 (file-notify--test-cleanup)))
@@ -571,10 +737,11 @@ Don't wait longer than timeout seconds for the events to be delivered."
571 (setq file-notify--test-tmpfile 737 (setq file-notify--test-tmpfile
572 (file-name-as-directory (file-notify--test-make-temp-name))) 738 (file-name-as-directory (file-notify--test-make-temp-name)))
573 (make-directory file-notify--test-tmpfile) 739 (make-directory file-notify--test-tmpfile)
574 (setq file-notify--test-desc 740 (should
575 (file-notify-add-watch 741 (setq file-notify--test-desc
576 file-notify--test-tmpfile 742 (file-notify-add-watch
577 '(change) #'file-notify--test-event-handler)) 743 file-notify--test-tmpfile
744 '(change) #'file-notify--test-event-handler)))
578 (should (file-notify-valid-p file-notify--test-desc)) 745 (should (file-notify-valid-p file-notify--test-desc))
579 ;; After removing the watch, the descriptor must not be valid 746 ;; After removing the watch, the descriptor must not be valid
580 ;; anymore. 747 ;; anymore.
@@ -590,20 +757,22 @@ Don't wait longer than timeout seconds for the events to be delivered."
590 (unwind-protect 757 (unwind-protect
591 ;; The batch-mode operation of w32notify is fragile (there's no 758 ;; The batch-mode operation of w32notify is fragile (there's no
592 ;; input threads to send the message to). 759 ;; input threads to send the message to).
593 (unless (and noninteractive (eq file-notify--library 'w32notify)) 760 (unless (and noninteractive
761 (string-equal (file-notify--test-library) "w32notify"))
594 (setq file-notify--test-tmpfile 762 (setq file-notify--test-tmpfile
595 (file-name-as-directory (file-notify--test-make-temp-name))) 763 (file-name-as-directory (file-notify--test-make-temp-name)))
596 (make-directory file-notify--test-tmpfile) 764 (make-directory file-notify--test-tmpfile)
597 (setq file-notify--test-desc 765 (should
598 (file-notify-add-watch 766 (setq file-notify--test-desc
599 file-notify--test-tmpfile 767 (file-notify-add-watch
600 '(change) #'file-notify--test-event-handler)) 768 file-notify--test-tmpfile
769 '(change) #'file-notify--test-event-handler)))
601 (should (file-notify-valid-p file-notify--test-desc)) 770 (should (file-notify-valid-p file-notify--test-desc))
602 ;; After deleting the directory, the descriptor must not be 771 ;; After deleting the directory, the descriptor must not be
603 ;; valid anymore. 772 ;; valid anymore.
604 (delete-directory file-notify--test-tmpfile t) 773 (delete-directory file-notify--test-tmpfile t)
605 (file-notify--wait-for-events 774 (file-notify--wait-for-events
606 (file-notify--test-timeout) 775 (file-notify--test-timeout)
607 (not (file-notify-valid-p file-notify--test-desc))) 776 (not (file-notify-valid-p file-notify--test-desc)))
608 (should-not (file-notify-valid-p file-notify--test-desc))) 777 (should-not (file-notify-valid-p file-notify--test-desc)))
609 778
@@ -613,6 +782,62 @@ Don't wait longer than timeout seconds for the events to be delivered."
613(file-notify--deftest-remote file-notify-test05-dir-validity 782(file-notify--deftest-remote file-notify-test05-dir-validity
614 "Check `file-notify-valid-p' via file notification for remote directories.") 783 "Check `file-notify-valid-p' via file notification for remote directories.")
615 784
785(ert-deftest file-notify-test06-many-events ()
786 "Check that events are not dropped."
787 :tags '(:expensive-test)
788 (skip-unless (file-notify--test-local-enabled))
789 ;; Under cygwin events arrive in random order. Impossible to define a test.
790 (skip-unless (not (eq system-type 'cygwin)))
791
792 (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
793 (make-directory file-notify--test-tmpfile)
794 (should
795 (setq file-notify--test-desc
796 (file-notify-add-watch
797 file-notify--test-tmpfile
798 '(change) 'file-notify--test-event-handler)))
799 (unwind-protect
800 (let ((n 1000)
801 source-file-list target-file-list
802 (default-directory file-notify--test-tmpfile))
803 (dotimes (i n)
804 ;; It matters which direction we rename, at least for
805 ;; kqueue. This backend parses directories in alphabetic
806 ;; order (x%d before y%d). So we rename both directions.
807 (if (zerop (mod i 2))
808 (progn
809 (push (expand-file-name (format "x%d" i)) source-file-list)
810 (push (expand-file-name (format "y%d" i)) target-file-list))
811 (push (expand-file-name (format "y%d" i)) source-file-list)
812 (push (expand-file-name (format "x%d" i)) target-file-list)))
813 (file-notify--test-with-events (make-list (+ n n) 'created)
814 (let ((source-file-list source-file-list)
815 (target-file-list target-file-list))
816 (while (and source-file-list target-file-list)
817 (read-event nil nil 0.1)
818 (write-region "" nil (pop source-file-list) nil 'no-message)
819 (read-event nil nil 0.1)
820 (write-region "" nil (pop target-file-list) nil 'no-message))))
821 (file-notify--test-with-events
822 (cond
823 ;; w32notify fires both `deleted' and `renamed' events.
824 ((string-equal (file-notify--test-library) "w32notify")
825 (let (r)
826 (dotimes (_i n r)
827 (setq r (append '(deleted renamed) r)))))
828 (t (make-list n 'renamed)))
829 (let ((source-file-list source-file-list)
830 (target-file-list target-file-list))
831 (while (and source-file-list target-file-list)
832 (rename-file (pop source-file-list) (pop target-file-list) t))))
833 (file-notify--test-with-events (make-list n 'deleted)
834 (dolist (file target-file-list)
835 (delete-file file))))
836 (file-notify--test-cleanup)))
837
838(file-notify--deftest-remote file-notify-test06-many-events
839 "Check that events are not dropped for remote directories.")
840
616(defun file-notify-test-all (&optional interactive) 841(defun file-notify-test-all (&optional interactive)
617 "Run all tests for \\[file-notify]." 842 "Run all tests for \\[file-notify]."
618 (interactive "p") 843 (interactive "p")
@@ -623,7 +848,7 @@ Don't wait longer than timeout seconds for the events to be delivered."
623;; TODO: 848;; TODO:
624 849
625;; * For w32notify, no stopped events arrive when a directory is removed. 850;; * For w32notify, no stopped events arrive when a directory is removed.
626;; * Try to handle arriving events under cygwin reliably. 851;; * Check, why cygwin recognizes only `deleted' and `stopped' events.
627 852
628(provide 'file-notify-tests) 853(provide 'file-notify-tests)
629;;; file-notify-tests.el ends here 854;;; file-notify-tests.el ends here