From f5814df689cf18b672675174414019ac1ebe8981 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sat, 26 Jul 2025 12:45:51 +0200 Subject: [PATCH] Rework filenotify-tests.el * lisp/filenotify.el (file-notify--rm-descriptor): Use `insert-special-event'. * lisp/net/tramp-sh.el (tramp-bundle-read-file-names): Fix docstring. (tramp-sh-gio-monitor-process-filter): Extend error strings. * test/infra/Dockerfile.emba (emacs-base): Install python3. * test/lisp/filenotify-tests.el (auto-revert-buffer-list): Declare. (file-notify--test-rootdir): New defvar. Replace all uses of `temporary-file-directory' by it. (file-notify--test-cleanup): Set `auto-revert-buffer-list' to nil. (file-notify--test-monitor): Check also for `process-live-p'. Skip test, if the monitor cannot be determined. (file-notify--deftest-remote): Do not call `tramp-cleanup-connection', this is done in `file-notify--test-cleanup' already. (with-file-notify-test): New defmacro. Use it in (almost) all tests. (file-notify--test-make-temp-name): Do not create `file-notify--test-tmpdir'. (file-notify--test-event-handler): Use `directory-file-name '. (auto-revert-debug): Set it to nil. (file-notify-test-*): Rewrite, using `with-file-notify-test' and `ert-with-temp-file'. * test/lisp/net/tramp-tests.el (tramp-test46-file-notifications): Tag it :unstable. (cherry picked from commit 76c17ac0f018dd860f0829e78f780bcd884466c6) --- lisp/filenotify.el | 4 +- lisp/net/tramp-sh.el | 10 +- test/infra/Dockerfile.emba | 2 +- test/lisp/filenotify-tests.el | 2433 +++++++++++++++------------------ test/lisp/net/tramp-tests.el | 8 +- 5 files changed, 1152 insertions(+), 1305 deletions(-) diff --git a/lisp/filenotify.el b/lisp/filenotify.el index 300c9babfdb..54b7f046357 100644 --- a/lisp/filenotify.el +++ b/lisp/filenotify.el @@ -78,8 +78,8 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'. If it is registered in `file-notify-descriptors', a `stopped' event is sent." (when-let ((watch (gethash descriptor file-notify-descriptors))) (unwind-protect - ;; Send `stopped' event. - (file-notify-handle-event + ;; Insert `stopped' event. + (insert-special-event (make-file-notify :-event `(,descriptor stopped ,(file-notify--watch-absolute-filename watch)) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 1d1879fb4d2..9dd449023a9 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -3628,8 +3628,9 @@ will be used." (defun tramp-bundle-read-file-names (vec files) "Read file attributes of FILES and with one command fill the cache. -FILES must be the local names only. The cache attributes to be -filled are described in `tramp-bundle-read-file-names'." +FILES must be the local names only. The cache attributes to be filled +are \"file-exists-p\", \"file-readable-p\", \"file-directory-p\" and +\"file-executable-p\"." (when files (tramp-maybe-send-script vec tramp-bundle-read-file-names "tramp_bundle_read_file_names") @@ -3883,7 +3884,10 @@ Fall back to normal file name handler if no Tramp handler exists." (catch 'doesnt-work ;; https://bugs.launchpad.net/bugs/1742946 (when (string-match-p - (rx (| "Monitoring not supported" "No locations given")) string) + (rx (| "Monitoring not supported" + "No locations given" + "Unable to find default local file monitor type")) + string) (delete-process proc) (throw 'doesnt-work nil)) diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba index 64cb40fd399..7301c3ea2e7 100644 --- a/test/infra/Dockerfile.emba +++ b/test/infra/Dockerfile.emba @@ -29,7 +29,7 @@ FROM debian:bookworm as emacs-base RUN apt-get update && \ apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \ libc-dev gcc g++ make autoconf automake libncurses-dev gnutls-dev \ - libxml2-dev libdbus-1-dev libacl1-dev acl git man-db texinfo gdb \ + libxml2-dev libdbus-1-dev libacl1-dev acl git man-db texinfo gdb python3 \ && rm -rf /var/lib/apt/lists/* FROM emacs-base as emacs-inotify diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el index 506d79ecfb3..8b494456014 100644 --- a/test/lisp/filenotify-tests.el +++ b/test/lisp/filenotify-tests.el @@ -56,12 +56,15 @@ (require 'ert-x) (require 'filenotify) +(defvar auto-revert-buffer-list) + ;; Filter suppressed remote file-notify libraries. (when (stringp (getenv "REMOTE_FILE_NOTIFY_LIBRARY")) (dolist (lib '("inotifywait" "gio" "smb-notify")) (unless (string-equal (getenv "REMOTE_FILE_NOTIFY_LIBRARY") lib) (add-to-list 'tramp-connection-properties `(nil ,lib nil))))) +(defvar file-notify--test-rootdir temporary-file-directory) (defvar file-notify--test-tmpdir nil) (defvar file-notify--test-tmpfile nil) (defvar file-notify--test-tmpfile1 nil) @@ -86,14 +89,14 @@ There are different timeouts for local and remote file notification libraries." ;; GFam{File,Directory}Monitor case. So we use a large timeout ;; for any monitor. ((file-notify--test-monitor) 7) - ((file-remote-p temporary-file-directory) 0.1) + ((file-remote-p file-notify--test-rootdir) 0.1) (t 0.01))) nil) (defun file-notify--test-timeout () "Timeout to wait for arriving a bunch of events, in seconds." (cond - ((file-remote-p temporary-file-directory) 20) + ((file-remote-p file-notify--test-rootdir) 20) ((eq system-type 'cygwin) 10) ((getenv "EMACS_EMBA_CI") 10) ((string-equal (file-notify--test-library) "w32notify") 4) @@ -156,14 +159,15 @@ Return nil when any other file notification watch is still active." (ignore-errors (delete-directory file-notify--test-tmpdir 'recursive)) (ignore-errors - (when (file-remote-p temporary-file-directory) + (when (file-remote-p file-notify--test-rootdir) (tramp-cleanup-connection - (tramp-dissect-file-name temporary-file-directory) t 'keep-password))) + (tramp-dissect-file-name file-notify--test-rootdir) t 'keep-password))) (when (hash-table-p file-notify-descriptors) (clrhash file-notify-descriptors)) - (setq file-notify--test-tmpdir nil + (setq auto-revert-buffer-list nil + file-notify--test-tmpdir nil file-notify--test-tmpfile nil file-notify--test-tmpfile1 nil file-notify--test-desc nil @@ -195,10 +199,10 @@ Return nil when any other file notification watch is still active." ;; We do not want to try and fail `file-notify-add-watch'. (defun file-notify--test-local-enabled () "Whether local file notification is enabled. -This is needed for local `temporary-file-directory' only, in the +This is needed for local `file-notify--test-rootdir' only, in the remote case we return always t." (or file-notify--library - (file-remote-p temporary-file-directory))) + (file-remote-p file-notify--test-rootdir))) (defvar file-notify--test-remote-enabled-checked (if (getenv "EMACS_HYDRA_CI") '(t . nil)) @@ -228,7 +232,7 @@ being the result.") "The used library for the test, as a string. In the remote case, it is the process name which runs on the remote host, or nil." - (if (null (file-remote-p temporary-file-directory)) + (if (null (file-remote-p file-notify--test-rootdir)) (symbol-name file-notify--library) (and (consp file-notify--test-remote-enabled-checked) (processp (cdr file-notify--test-remote-enabled-checked)) @@ -258,20 +262,21 @@ must be a valid watch descriptor." (add-to-list 'file-notify--test-monitors (cons file-notify--test-desc - (if (file-remote-p temporary-file-directory) + (if (file-remote-p file-notify--test-rootdir) ;; `file-notify--test-desc' is the connection process. (progn - (while (not (tramp-connection-property-p - file-notify--test-desc "file-monitor")) + (while (and (process-live-p file-notify--test-desc) + (not (tramp-connection-property-p + file-notify--test-desc "file-monitor"))) (accept-process-output file-notify--test-desc 0)) (tramp-get-connection-property - file-notify--test-desc "file-monitor" nil)) + file-notify--test-desc "file-monitor")) (and (functionp 'gfile-monitor-name) (gfile-monitor-name file-notify--test-desc))))) ;; If we don't know the monitor, there are good chances the - ;; test will fail. We let it fail already here, in order to - ;; know the real reason. - (should (alist-get file-notify--test-desc file-notify--test-monitors))) + ;; test will fail. We skip it. + (unless (alist-get file-notify--test-desc file-notify--test-monitors) + (ert-skip "Cannot determine test monitor"))) (alist-get file-notify--test-desc file-notify--test-monitors)))) (defmacro file-notify--deftest-remote (test docstring &optional unstable) @@ -281,122 +286,118 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." `(ert-deftest ,(intern (concat (symbol-name test) "-remote")) () ,docstring :tags (if ,unstable '(:expensive-test :unstable) '(:expensive-test)) - (let* ((temporary-file-directory ert-remote-temporary-file-directory) + (let* ((file-notify--test-rootdir ert-remote-temporary-file-directory) (ert-test (ert-get-test ',test)) vc-handled-backends) (skip-unless (file-notify--test-remote-enabled)) - (tramp-cleanup-connection - (tramp-dissect-file-name temporary-file-directory) t 'keep-password) (file-notify--test-cleanup) (funcall (ert-test-body ert-test))))) +(defmacro with-file-notify-test (&rest body) + "Setup test environment. +It creates `file-notify--test-tmpdir' and `file-notify--test-tmpfile'. +When returning, they are deleted." + (declare (debug t)) + `(ert-with-temp-directory file-notify--test-tmpdir + :prefix + (expand-file-name "file-notify-test-parent" file-notify--test-rootdir) + :suffix "" + (let ((ert-temp-file-prefix + (expand-file-name "file-notify-test" file-notify--test-tmpdir)) + (ert-temp-file-suffix "")) + (ert-with-temp-file file-notify--test-tmpfile + :prefix ert-temp-file-prefix :suffix ert-temp-file-suffix + (unwind-protect + (progn ,@body) + (file-notify--test-cleanup)))))) + (ert-deftest file-notify-test00-availability () "Test availability of `file-notify'." (skip-unless (file-notify--test-local-enabled)) - (unwind-protect - (progn - ;; Report the native library which has been used. - (message "Library: `%s'" (file-notify--test-library)) - (should - (setq file-notify--test-desc - (file-notify-add-watch - temporary-file-directory '(change) #'ignore))) - (when (file-notify--test-monitor) - (message "Monitor: `%s'" (file-notify--test-monitor))) - (file-notify-rm-watch file-notify--test-desc) + (with-file-notify-test + ;; Report the native library which has been used. + (message "Library: `%s'" (file-notify--test-library)) + (should + (setq file-notify--test-desc + (file-notify-add-watch file-notify--test-tmpdir '(change) #'ignore))) + (when (file-notify--test-monitor) + (message "Monitor: `%s'" (file-notify--test-monitor))) + (file-notify-rm-watch file-notify--test-desc) - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) (file-notify--deftest-remote file-notify-test00-availability "Test availability of `file-notify' for remote files.") (defun file-notify--test-make-temp-name () "Create a temporary file name for test." - (unless (stringp file-notify--test-tmpdir) - (setq file-notify--test-tmpdir - (expand-file-name - (make-temp-name "file-notify-test-parent") temporary-file-directory))) - (unless (file-directory-p file-notify--test-tmpdir) - (make-directory file-notify--test-tmpdir)) - (expand-file-name - (make-temp-name "file-notify-test") file-notify--test-tmpdir)) + (make-temp-name + (expand-file-name "file-notify-test" file-notify--test-tmpdir))) (ert-deftest file-notify-test01-add-watch () "Check `file-notify-add-watch'." (skip-unless (file-notify--test-local-enabled)) - (unwind-protect - (progn - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) - file-notify--test-tmpfile1 - (format - "%s/%s" file-notify--test-tmpfile (md5 (current-time-string)))) - - ;; Check, that different valid parameters are accepted. - (should - (setq file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpdir '(change) #'ignore))) - (file-notify-rm-watch file-notify--test-desc) - (should - (setq file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpdir '(attribute-change) #'ignore))) - (file-notify-rm-watch file-notify--test-desc) - (should - (setq file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpdir '(change attribute-change) #'ignore))) - (file-notify-rm-watch file-notify--test-desc) - - ;; File monitors like kqueue insist, that the watched file - ;; exists. Directory monitors are not bound to this - ;; restriction. - (when (string-equal (file-notify--test-library) "kqueue") - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message)) - (should - (setq file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpfile '(change attribute-change) #'ignore))) - (file-notify-rm-watch file-notify--test-desc) - (when (string-equal (file-notify--test-library) "kqueue") - (delete-file file-notify--test-tmpfile)) - - ;; Check error handling. - (should-error (file-notify-add-watch 1 2 3 4) - :type 'wrong-number-of-arguments) - (should - (equal (should-error - (file-notify-add-watch 1 2 3)) - '(wrong-type-argument 1))) - (should - (equal (should-error - (file-notify-add-watch file-notify--test-tmpdir 2 3)) - '(wrong-type-argument 2))) - (should - (equal (should-error - (file-notify-add-watch file-notify--test-tmpdir '(change) 3)) - '(wrong-type-argument 3))) - ;; The upper directory of a file must exist. - (should - (equal (should-error - (file-notify-add-watch - file-notify--test-tmpfile1 - '(change attribute-change) #'ignore)) - `(file-notify-error - "Directory does not exist" ,file-notify--test-tmpfile))) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + (with-file-notify-test + (setq file-notify--test-tmpfile1 + (format "%s/%s" file-notify--test-tmpfile (md5 (current-time-string)))) + (delete-file file-notify--test-tmpfile) + + ;; Check, that different valid parameters are accepted. + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpdir '(change) #'ignore))) + (file-notify-rm-watch file-notify--test-desc) + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpdir '(attribute-change) #'ignore))) + (file-notify-rm-watch file-notify--test-desc) + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpdir '(change attribute-change) #'ignore))) + (file-notify-rm-watch file-notify--test-desc) + + ;; File monitors like kqueue insist, that the watched file exists. + ;; Directory monitors are not bound to this restriction. + (when (string-equal (file-notify--test-library) "kqueue") + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)) + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpfile '(change attribute-change) #'ignore))) + (file-notify-rm-watch file-notify--test-desc) + + ;; Check error handling. + (should-error (file-notify-add-watch 1 2 3 4) + :type 'wrong-number-of-arguments) + (should + (equal (should-error + (file-notify-add-watch 1 2 3)) + '(wrong-type-argument 1))) + (should + (equal (should-error + (file-notify-add-watch file-notify--test-tmpdir 2 3)) + '(wrong-type-argument 2))) + (should + (equal (should-error + (file-notify-add-watch file-notify--test-tmpdir '(change) 3)) + '(wrong-type-argument 3))) + ;; The upper directory of a file must exist. + (should + (equal (should-error + (file-notify-add-watch + file-notify--test-tmpfile1 + '(change attribute-change) #'ignore)) + `(file-notify-error + "Directory does not exist" ,file-notify--test-tmpfile))) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) (file-notify--deftest-remote file-notify-test01-add-watch "Check `file-notify-add-watch' for remote files.") @@ -406,125 +407,104 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." "Check `file-notify-rm-watch' and `file-notify-rm-all-watches'." (skip-unless (file-notify--test-local-enabled)) - (unwind-protect - ;; Check, that `file-notify-rm-watch' works. - (progn - (should - (setq file-notify--test-desc - (file-notify-add-watch - temporary-file-directory '(change) #'ignore))) - (file-notify-rm-watch file-notify--test-desc) - ;; Check, that any parameter is accepted. - (condition-case err - (progn - (file-notify-rm-watch nil) - (file-notify-rm-watch 0) - (file-notify-rm-watch "foo") - (file-notify-rm-watch 'foo)) - (error (ert-fail err))) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - ;; Check, that no error is returned removing a watch descriptor twice. - (progn - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) - file-notify--test-tmpfile1 (file-notify--test-make-temp-name)) - (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) - (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message) - (should - (setq file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpfile '(change) #'ignore))) - (should - (setq file-notify--test-desc1 - (file-notify-add-watch - file-notify--test-tmpfile1 '(change) #'ignore))) - ;; Remove `file-notify--test-desc' twice. - (file-notify-rm-watch file-notify--test-desc) - (file-notify-rm-watch file-notify--test-desc) - (file-notify-rm-watch file-notify--test-desc1) - (delete-file file-notify--test-tmpfile) - (delete-file file-notify--test-tmpfile1) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - ;; Check, that removing watch descriptors out of order do not - ;; harm. This fails on cygwin because of timing issues unless a - ;; long `sit-for' is added before the call to - ;; `file-notify--test-wait-event'. - (unless (eq system-type 'cygwin) - (let (results) - (cl-flet ((first-callback (event) - (when (eq (file-notify--test-event-action event) 'deleted) - (push 1 results))) - (second-callback (event) - (when (eq (file-notify--test-event-action event) 'deleted) - (push 2 results)))) - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message) - (should - (setq file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpfile - '(change) #'first-callback))) - (should - (setq file-notify--test-desc1 - (file-notify-add-watch - file-notify--test-tmpfile - '(change) #'second-callback))) - ;; `file-notify-rm-watch' confuses `file-notify--test-monitor'. - ;; Initialize it in time. - (file-notify--test-monitor) - ;; Remove first watch. - (file-notify-rm-watch file-notify--test-desc) - ;; Only the second callback shall run. - (file-notify--test-wait-event) - (delete-file file-notify--test-tmpfile) - (file-notify--test-wait-for-events - (file-notify--test-timeout) results) - (should (equal results (list 2))) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)))) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - ;; Check `file-notify-rm-all-watches'. - (progn - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) - file-notify--test-tmpfile1 (file-notify--test-make-temp-name)) - (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) - (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message) - (should - (setq file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpfile '(change) #'ignore))) - (should - (setq file-notify--test-desc1 - (file-notify-add-watch - file-notify--test-tmpfile1 '(change) #'ignore))) - (file-notify-rm-all-watches) - (delete-file file-notify--test-tmpfile) - (delete-file file-notify--test-tmpfile1) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + (with-file-notify-test + ;; Check, that `file-notify-rm-watch' works. + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpdir '(change) #'ignore))) + (file-notify-rm-watch file-notify--test-desc) + ;; Check, that any parameter is accepted. + (condition-case err + (progn + (file-notify-rm-watch nil) + (file-notify-rm-watch 0) + (file-notify-rm-watch "foo") + (file-notify-rm-watch 'foo)) + (error (ert-fail err))) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)) + + (with-file-notify-test + (ert-with-temp-file file-notify--test-tmpfile1 + :prefix ert-temp-file-prefix :suffix ert-temp-file-suffix + ;; Check, that no error is returned removing a watch descriptor twice. + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpfile '(change) #'ignore))) + (should + (setq file-notify--test-desc1 + (file-notify-add-watch + file-notify--test-tmpfile1 '(change) #'ignore))) + ;; Remove `file-notify--test-desc' twice. + (file-notify-rm-watch file-notify--test-desc) + (file-notify-rm-watch file-notify--test-desc) + (file-notify-rm-watch file-notify--test-desc1) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) + + (with-file-notify-test + ;; Check, that removing watch descriptors out of order do not harm. + ;; This fails on cygwin because of timing issues unless a long + ;; `sit-for' is added before the call to + ;; `file-notify--test-wait-event'. + (unless (eq system-type 'cygwin) + (let (results) + (cl-flet ((first-callback (event) + (when (eq (file-notify--test-event-action event) 'deleted) + (push 1 results))) + (second-callback (event) + (when (eq (file-notify--test-event-action event) 'deleted) + (push 2 results)))) + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpfile + '(change) #'first-callback))) + (should + (setq file-notify--test-desc1 + (file-notify-add-watch + file-notify--test-tmpfile + '(change) #'second-callback))) + ;; `file-notify-rm-watch' confuses `file-notify--test-monitor'. + ;; Initialize it in time. + (file-notify--test-monitor) + ;; Remove first watch. + (file-notify-rm-watch file-notify--test-desc) + ;; Only the second callback shall run. + (file-notify--test-wait-event) + (delete-file file-notify--test-tmpfile) + (file-notify--test-wait-for-events + (file-notify--test-timeout) results) + (should (equal results (list 2))) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))))) + + (with-file-notify-test + (ert-with-temp-file file-notify--test-tmpfile1 + :prefix ert-temp-file-prefix :suffix ert-temp-file-suffix + ;; Check `file-notify-rm-all-watches'. + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpfile '(change) #'ignore))) + (should + (setq file-notify--test-desc1 + (file-notify-add-watch + file-notify--test-tmpfile1 '(change) #'ignore))) + (file-notify-rm-all-watches) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)))) (file-notify--deftest-remote file-notify-test02-rm-watch "Check `file-notify-rm-watch' for remote files.") @@ -559,7 +539,7 @@ and `file-notify--test-file' are bound somewhere." For later analysis, append the test result to `file-notify--test-results' and the event to `file-notify--test-events'." (let* ((file-notify--test-event event) - (file-notify--test-file file) + (file-notify--test-file (directory-file-name file)) (result (ert-run-test (make-ert-test :body 'file-notify--test-event-test)))) ;; Do not add lock files, this would confuse the checks. @@ -661,305 +641,274 @@ delivered." :tags '(:expensive-test) (skip-unless (file-notify--test-local-enabled)) - (unwind-protect - ;; Check file creation, change and deletion. It doesn't work - ;; for kqueue, because we don't use an implicit directory - ;; monitor. - (unless (string-equal (file-notify--test-library) "kqueue") - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (should - (setq file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpfile - '(change) #'file-notify--test-event-handler))) - (file-notify--test-with-actions - (cond - ;; SMBSamba reports three `changed' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - '(created changed changed changed deleted stopped)) - ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and - ;; GPollFileMonitor do not report the `changed' event. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor - GKqueueFileMonitor GPollFileMonitor)) - '(created deleted stopped)) - (t '(created changed deleted stopped))) - (write-region - "another text" nil file-notify--test-tmpfile nil 'no-message) - (file-notify--test-wait-event) - (delete-file file-notify--test-tmpfile)) - (file-notify-rm-watch file-notify--test-desc) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - (progn - ;; Check file change and deletion. - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) - (should - (setq file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpfile - '(change) #'file-notify--test-event-handler))) - (file-notify--test-with-actions - (cond - ;; SMBSamba reports four `changed' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - '(changed changed changed changed deleted stopped)) - ;; GFam{File,Directory}Monitor and GPollFileMonitor do - ;; not detect the `changed' event reliably. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) - '((deleted stopped) - (changed deleted stopped))) - ;; GKqueueFileMonitor does not report the `changed' event. - ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) - '(deleted stopped)) - ;; There could be one or two `changed' events. - (t '((changed deleted stopped) - (changed changed deleted stopped)))) - (write-region - "another text" nil file-notify--test-tmpfile nil 'no-message) - (file-notify--test-wait-event) - (delete-file file-notify--test-tmpfile)) - (file-notify-rm-watch file-notify--test-desc) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - ;; Check file creation, change and deletion when watching a - ;; directory. There must be a `stopped' event when deleting the - ;; directory. - (let ((file-notify--test-tmpdir - (make-temp-file "file-notify-test-parent" t))) - (should - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) - file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpdir - '(change) #'file-notify--test-event-handler))) - (file-notify--test-with-actions - (cond - ;; w32notify does not raise `deleted' and `stopped' - ;; events for the watched directory. - ((string-equal (file-notify--test-library) "w32notify") - '(created changed deleted)) - ;; SMBSamba reports three `changed' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - '(created changed changed changed deleted deleted stopped)) - ;; There are two `deleted' events, for the file and for - ;; the directory. Except for - ;; GFam{File,Directory}Monitor, GPollFileMonitor and - ;; kqueue. And GFam{File,Directory}Monitor and - ;; GPollFileMonitor do not raise a `changed' event. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) - '(created deleted stopped)) - ((string-equal (file-notify--test-library) "kqueue") - '(created changed deleted stopped)) - ;; GKqueueFileMonitor does not report the `changed' event. - ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) - '(created deleted deleted stopped)) - (t '(created changed deleted deleted stopped))) - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message) - (file-notify--test-wait-event) - (delete-directory file-notify--test-tmpdir 'recursive)) - (file-notify-rm-watch file-notify--test-desc) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - ;; Check copy of files inside a directory. - (let ((file-notify--test-tmpdir - (make-temp-file "file-notify-test-parent" t))) - (should - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) - file-notify--test-tmpfile1 (file-notify--test-make-temp-name) - file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpdir - '(change) #'file-notify--test-event-handler))) - (file-notify--test-with-actions - (cond - ;; w32notify does not distinguish between `changed' and - ;; `attribute-changed'. It does not raise `deleted' and - ;; `stopped' events for the watched directory. - ((string-equal (file-notify--test-library) "w32notify") - '(created changed created changed - changed changed changed - deleted deleted)) - ;; SMBSamba reports three `changed' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - '(created changed changed changed created changed changed changed - deleted deleted deleted stopped)) - ;; There are three `deleted' events, for two files and - ;; for the directory. Except for - ;; GFam{File,Directory}Monitor, GPollFileMonitor and - ;; kqueue. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) - '(created created changed changed deleted stopped)) - ((string-equal (file-notify--test-library) "kqueue") - '(created changed created changed deleted stopped)) - ;; GKqueueFileMonitor does not report the `changed' event. - ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) - '(created created deleted deleted deleted stopped)) - (t '(created changed created changed - deleted deleted deleted stopped))) - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message) - (file-notify--test-wait-event) - (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) - ;; The next two events shall not be visible. - (file-notify--test-wait-event) - (set-file-modes file-notify--test-tmpfile 000 'nofollow) - (file-notify--test-wait-event) - (set-file-times file-notify--test-tmpfile '(0 0) 'nofollow) - (file-notify--test-wait-event) - (delete-directory file-notify--test-tmpdir 'recursive)) - (file-notify-rm-watch file-notify--test-desc) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - ;; Check rename of files inside a directory. - (let ((file-notify--test-tmpdir - (make-temp-file "file-notify-test-parent" t))) - (should - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) - file-notify--test-tmpfile1 (file-notify--test-make-temp-name) - file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpdir - '(change) #'file-notify--test-event-handler))) - (file-notify--test-with-actions - (cond - ;; w32notify does not raise `deleted' and `stopped' - ;; events for the watched directory. - ((string-equal (file-notify--test-library) "w32notify") - '(created changed renamed deleted)) - ;; SMBSamba reports three `changed' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - '(created changed changed changed - renamed changed changed deleted deleted stopped)) - ;; There are two `deleted' events, for the file and for - ;; the directory. Except for - ;; GFam{File,Directory}Monitor, GPollfileMonitor and - ;; kqueue. And GFam{File,Directory}Monitor and - ;; GPollFileMonitor raise `created' and `deleted' events - ;; instead of a `renamed' event. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) - '(created created deleted deleted stopped)) - ((string-equal (file-notify--test-library) "kqueue") - '(created changed renamed deleted stopped)) - ;; GKqueueFileMonitor does not report the `changed' event. - ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) - '(created renamed deleted deleted stopped)) - (t '(created changed renamed deleted deleted stopped))) - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message) - (file-notify--test-wait-event) - (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) - ;; After the rename, we won't get events anymore. - (file-notify--test-wait-event) - (delete-directory file-notify--test-tmpdir 'recursive)) - (file-notify-rm-watch file-notify--test-desc) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - ;; Check attribute change. - (progn - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message) - (should - (setq file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpfile - '(attribute-change) #'file-notify--test-event-handler))) - (file-notify--test-with-actions - (cond - ;; w32notify does not distinguish between `changed' and - ;; `attribute-changed'. Under MS Windows 7, we get four - ;; `changed' events, and under MS Windows 10 just two. - ;; Strange. - ((string-equal (file-notify--test-library) "w32notify") - '((changed changed) - (changed changed changed changed))) - ;; SMBWindows does not distinguish between `changed' and - ;; `attribute-changed'. - ((eq (file-notify--test-monitor) 'SMBWindows) - '(changed changed)) - ;; SMBSamba does not distinguish between `changed' and - ;; `attribute-changed'. - ((eq (file-notify--test-monitor) 'SMBSamba) - '(changed changed changed changed)) - ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and - ;; GPollFileMonitor do not report the `attribute-changed' - ;; event. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor - GKqueueFileMonitor GPollFileMonitor)) - '()) - ;; For GInotifyFileMonitor,`write-region' raises - ;; also an `attribute-changed' event on gio. - ((and (string-equal (file-notify--test-library) "gio") - (eq (file-notify--test-monitor) 'GInotifyFileMonitor)) - '(attribute-changed attribute-changed attribute-changed)) - ;; For kqueue, `write-region' raises also an - ;; `attribute-changed' event. - ((string-equal (file-notify--test-library) "kqueue") - '(attribute-changed attribute-changed attribute-changed)) - ;; For inotifywait, `write-region' raises also an - ;; `attribute-changed' event. - ((string-equal (file-notify--test-library) "inotifywait") - '(attribute-changed attribute-changed attribute-changed)) - (t '(attribute-changed attribute-changed))) - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message) - (file-notify--test-wait-event) - (set-file-modes file-notify--test-tmpfile 000 'nofollow) - (file-notify--test-wait-event) - (set-file-times file-notify--test-tmpfile '(0 0) 'nofollow) - (file-notify--test-wait-event) - (delete-file file-notify--test-tmpfile)) - (file-notify-rm-watch file-notify--test-desc) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + ;; It doesn't work for kqueue, because we don't use an implicit + ;; directory monitor. + (unless (string-equal (file-notify--test-library) "kqueue") + (with-file-notify-test + ;; Check file creation, change and deletion. + (delete-file file-notify--test-tmpfile) + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpfile + '(change) #'file-notify--test-event-handler))) + (file-notify--test-with-actions + (cond + ;; SMBSamba reports three `changed' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + '(created changed changed changed deleted stopped)) + ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and + ;; GPollFileMonitor do not report the `changed' event. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor + GKqueueFileMonitor GPollFileMonitor)) + '(created deleted stopped)) + (t '(created changed deleted stopped))) + (write-region + "another text" nil file-notify--test-tmpfile nil 'no-message) + (file-notify--test-wait-event) + (delete-file file-notify--test-tmpfile)) + (file-notify-rm-watch file-notify--test-desc) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) + + (with-file-notify-test + ;; Check file change and deletion. + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpfile + '(change) #'file-notify--test-event-handler))) + (file-notify--test-with-actions + (cond + ;; SMBSamba reports four `changed' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + '(changed changed changed changed deleted stopped)) + ;; GFam{File,Directory}Monitor and GPollFileMonitor do not + ;; detect the `changed' event reliably. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) + '((deleted stopped) + (changed deleted stopped))) + ;; GKqueueFileMonitor does not report the `changed' event. + ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) + '(deleted stopped)) + ;; There could be one or two `changed' events. + (t '((changed deleted stopped) + (changed changed deleted stopped)))) + (write-region "another text" nil file-notify--test-tmpfile nil 'no-message) + (file-notify--test-wait-event) + (delete-file file-notify--test-tmpfile)) + (file-notify-rm-watch file-notify--test-desc) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)) + + (with-file-notify-test + (delete-file file-notify--test-tmpfile) + ;; Check file creation, change and deletion when watching a + ;; directory. There must be a `stopped' event when deleting the + ;; directory. + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpdir + '(change) #'file-notify--test-event-handler))) + (file-notify--test-with-actions + (cond + ;; w32notify does not raise `deleted' and `stopped' events for + ;; the watched directory. + ((string-equal (file-notify--test-library) "w32notify") + '(created changed deleted)) + ;; SMBSamba reports three `changed' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + '(created changed changed changed deleted deleted stopped)) + ;; There are two `deleted' events, for the file and for the + ;; directory. Except for GFam{File,Directory}Monitor, + ;; GPollFileMonitor and kqueue. And GFam{File,Directory}Monitor + ;; and GPollFileMonitor do not raise a `changed' event. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) + '(created deleted stopped)) + ((string-equal (file-notify--test-library) "kqueue") + '(created changed deleted stopped)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) + '(created deleted deleted stopped)) + (t '(created changed deleted deleted stopped))) + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (file-notify--test-wait-event) + (delete-directory file-notify--test-tmpdir 'recursive)) + (file-notify-rm-watch file-notify--test-desc) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)) + + (with-file-notify-test + (ert-with-temp-file file-notify--test-tmpfile1 + :prefix ert-temp-file-prefix :suffix ert-temp-file-suffix + ;; Check copy of files inside a directory. + (delete-file file-notify--test-tmpfile) + (delete-file file-notify--test-tmpfile1) + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpdir + '(change) #'file-notify--test-event-handler))) + (file-notify--test-with-actions + (cond + ;; w32notify does not distinguish between `changed' and + ;; `attribute-changed'. It does not raise `deleted' and + ;; `stopped' events for the watched directory. + ((string-equal (file-notify--test-library) "w32notify") + '(created changed created changed + changed changed changed + deleted deleted)) + ;; SMBSamba reports three `changed' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + '(created changed changed changed created changed changed changed + deleted deleted deleted stopped)) + ;; There are three `deleted' events, for two files and for the + ;; directory. Except for GFam{File,Directory}Monitor, + ;; GPollFileMonitor and kqueue. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) + '(created created changed changed deleted stopped)) + ((string-equal (file-notify--test-library) "kqueue") + '(created changed created changed deleted stopped)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) + '(created created deleted deleted deleted stopped)) + (t '(created changed created changed + deleted deleted deleted stopped))) + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (file-notify--test-wait-event) + (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) + ;; The next two events shall not be visible. + (file-notify--test-wait-event) + (set-file-modes file-notify--test-tmpfile 000 'nofollow) + (file-notify--test-wait-event) + (set-file-times file-notify--test-tmpfile '(0 0) 'nofollow) + (file-notify--test-wait-event) + (delete-directory file-notify--test-tmpdir 'recursive)) + (file-notify-rm-watch file-notify--test-desc) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) + + (with-file-notify-test + (ert-with-temp-file file-notify--test-tmpfile1 + :prefix ert-temp-file-prefix :suffix ert-temp-file-suffix + ;; Check rename of files inside a directory. + (delete-file file-notify--test-tmpfile) + (delete-file file-notify--test-tmpfile1) + (should + (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) + file-notify--test-tmpfile1 (file-notify--test-make-temp-name) + file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpdir + '(change) #'file-notify--test-event-handler))) + (file-notify--test-with-actions + (cond + ;; w32notify does not raise `deleted' and `stopped' events for + ;; the watched directory. + ((string-equal (file-notify--test-library) "w32notify") + '(created changed renamed deleted)) + ;; SMBSamba reports three `changed' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + '(created changed changed changed + renamed changed changed deleted deleted stopped)) + ;; There are two `deleted' events, for the file and for the + ;; directory. Except for GFam{File,Directory}Monitor, + ;; GPollfileMonitor and kqueue. And + ;; GFam{File,Directory}Monitor and GPollFileMonitor raise + ;; `created' and `deleted' events instead of a `renamed' + ;; event. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) + '(created created deleted deleted stopped)) + ((string-equal (file-notify--test-library) "kqueue") + '(created changed renamed deleted stopped)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) + '(created renamed deleted deleted stopped)) + (t '(created changed renamed deleted deleted stopped))) + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (file-notify--test-wait-event) + (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) + ;; After the rename, we won't get events anymore. + (file-notify--test-wait-event) + (delete-directory file-notify--test-tmpdir 'recursive)) + (file-notify-rm-watch file-notify--test-desc) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) + + (with-file-notify-test + ;; Check attribute change. + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpfile + '(attribute-change) #'file-notify--test-event-handler))) + (file-notify--test-with-actions + (cond + ;; w32notify does not distinguish between `changed' and + ;; `attribute-changed'. Under MS Windows 7, we get four + ;; `changed' events, and under MS Windows 10 just two. Strange. + ((string-equal (file-notify--test-library) "w32notify") + '((changed changed) + (changed changed changed changed))) + ;; SMBWindows does not distinguish between `changed' and + ;; `attribute-changed'. + ((eq (file-notify--test-monitor) 'SMBWindows) + '(changed changed)) + ;; SMBSamba does not distinguish between `changed' and + ;; `attribute-changed'. + ((eq (file-notify--test-monitor) 'SMBSamba) + '(changed changed changed changed)) + ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and + ;; GPollFileMonitor do not report the `attribute-changed' event. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor + GKqueueFileMonitor GPollFileMonitor)) + '()) + ;; For GInotifyFileMonitor,`write-region' raises also an + ;; `attribute-changed' event on gio. + ((and (string-equal (file-notify--test-library) "gio") + (eq (file-notify--test-monitor) 'GInotifyFileMonitor)) + '(attribute-changed attribute-changed attribute-changed)) + ;; For kqueue, `write-region' raises also an `attribute-changed' + ;; event. + ((string-equal (file-notify--test-library) "kqueue") + '(attribute-changed attribute-changed attribute-changed)) + ;; For inotifywait, `write-region' raises also an + ;; `attribute-changed' event. + ((string-equal (file-notify--test-library) "inotifywait") + '(attribute-changed attribute-changed attribute-changed)) + (t '(attribute-changed attribute-changed))) + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (file-notify--test-wait-event) + (set-file-modes file-notify--test-tmpfile 000 'nofollow) + (file-notify--test-wait-event) + (set-file-times file-notify--test-tmpfile '(0 0) 'nofollow) + (file-notify--test-wait-event) + (delete-file file-notify--test-tmpfile)) + (file-notify-rm-watch file-notify--test-desc) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) (file-notify--deftest-remote file-notify-test03-events "Check file creation/change/removal notifications for remote files.") (require 'autorevert) -(setq auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded" +(setq auto-revert-debug nil + auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded" auto-revert-remote-files t auto-revert-stop-on-user-input nil) @@ -970,99 +919,93 @@ delivered." ;; Run with shortened `auto-revert-interval' for a faster test. (let* ((auto-revert-interval 1) - (timeout (if (file-remote-p temporary-file-directory) + (timeout (if (file-remote-p file-notify--test-rootdir) 60 ; FIXME: can this be shortened? (* auto-revert-interval 2.5))) (text-quoting-style 'grave) buf) (auto-revert-set-timer) - (unwind-protect - (progn - ;; In the remote case, `vc-refresh-state' returns undesired - ;; error messages. Let's suppress them. - (advice-add 'vc-refresh-state :around 'ignore) - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message) - (setq buf (find-file-noselect file-notify--test-tmpfile)) - (with-current-buffer buf - (should (string-equal (buffer-string) "any text")) - ;; `buffer-stale--default-function' checks for - ;; `verify-visited-file-modtime'. We must ensure that it - ;; returns nil. - (sleep-for 1) - (auto-revert-mode 1) - - (with-timeout (timeout (ignore)) - (while (null auto-revert-notify-watch-descriptor) - (sleep-for 0.2))) - - ;; `file-notify--test-monitor' needs to know - ;; `file-notify--test-desc' in order to compute proper - ;; timeouts. - (setq file-notify--test-desc auto-revert-notify-watch-descriptor) - - ;; GKqueueFileMonitor does not report the `changed' event. - (skip-when (eq (file-notify--test-monitor) 'GKqueueFileMonitor)) - - ;; Check, that file notification has been used. - (should auto-revert-mode) - (should auto-revert-use-notify) - (should auto-revert-notify-watch-descriptor) - - ;; Modify file. We wait for a second, in order to have - ;; another timestamp. - (ert-with-message-capture captured-messages - (let ((inhibit-message t)) - (sleep-for 1) - (write-region - "another text" nil file-notify--test-tmpfile nil 'no-message) - - ;; Check, that the buffer has been reverted. - (file-notify--test-wait-for-events - timeout - (string-match-p - (rx bol "Reverting buffer `" - (literal (buffer-name buf)) "'" eol) - captured-messages)) - (should (string-match-p "another text" (buffer-string))))) - - ;; Stop file notification. Autorevert shall still work via polling. - (file-notify-rm-watch auto-revert-notify-watch-descriptor) - (file-notify--test-wait-for-events - timeout (null auto-revert-notify-watch-descriptor)) - (should auto-revert-use-notify) - (should-not - (file-notify-valid-p auto-revert-notify-watch-descriptor)) - - ;; Modify file. We wait for two seconds, in order to - ;; have another timestamp. One second seems to be too - ;; short. And cygwin sporadically requires more than two. - (ert-with-message-capture captured-messages - (let ((inhibit-message t)) - (sleep-for (if (eq system-type 'cygwin) 3 2)) - (write-region - "foo bla" nil file-notify--test-tmpfile nil 'no-message) - - ;; Check, that the buffer has been reverted. - (file-notify--test-wait-for-events - timeout - (string-match-p - (rx bol "Reverting buffer `" - (literal (buffer-name buf)) "'" eol) - captured-messages)) - (should (string-match-p "foo bla" (buffer-string))))) - - ;; Stop autorevert, in order to cleanup descriptor. - (auto-revert-mode -1)) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (advice-remove 'vc-refresh-state 'ignore) - (ignore-errors (kill-buffer buf)) - (file-notify--test-cleanup)))) + + (with-file-notify-test + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (setq buf (find-file-noselect file-notify--test-tmpfile)) + (with-current-buffer buf + ;; In the remote case, `vc-refresh-state' returns undesired error + ;; messages. Let's suppress them. + (add-function :around (local #'vc-refresh-state) #'ignore) + (should (string-equal (buffer-string) "any text")) + ;; `buffer-stale--default-function' checks for + ;; `verify-visited-file-modtime'. We must ensure that it returns + ;; nil. + (sleep-for 1) + (auto-revert-mode 1) + + (file-notify--test-wait-for-events + timeout auto-revert-notify-watch-descriptor) + + ;; `file-notify--test-monitor' needs to know + ;; `file-notify--test-desc' in order to compute proper timeouts. + (setq file-notify--test-desc auto-revert-notify-watch-descriptor) + + ;; GKqueueFileMonitor does not report the `changed' event. + (skip-when (eq (file-notify--test-monitor) 'GKqueueFileMonitor)) + + ;; Check, that file notification has been used. + (should auto-revert-mode) + (should auto-revert-use-notify) + (should auto-revert-notify-watch-descriptor) + + ;; Modify file. We wait for a second, in order to have another + ;; timestamp. + (ert-with-message-capture captured-messages + (let ((inhibit-message t)) + (sleep-for 1) + (write-region + "another text" nil file-notify--test-tmpfile nil 'no-message) + + ;; Check, that the buffer has been reverted. + (file-notify--test-wait-for-events + timeout + (string-match-p + (rx bol "Reverting buffer `" + (literal (buffer-name buf)) "'" eol) + captured-messages)) + (should (string-match-p "another text" (buffer-string))))) + + ;; Stop file notification. Autorevert shall still work via polling. + (file-notify-rm-watch auto-revert-notify-watch-descriptor) + (file-notify--test-wait-for-events + timeout + (or (null auto-revert-notify-watch-descriptor) + (not (file-notify-valid-p auto-revert-notify-watch-descriptor)))) + (should auto-revert-use-notify) + + ;; Modify file. We wait for two seconds, in order to have + ;; another timestamp. One second seems to be too short. And + ;; cygwin sporadically requires more than two. + (ert-with-message-capture captured-messages + (let ((inhibit-message t)) + (sleep-for (if (eq system-type 'cygwin) 3 2)) + (write-region "foo bla" nil file-notify--test-tmpfile nil 'no-message) + + ;; Check, that the buffer has been reverted. + (file-notify--test-wait-for-events + timeout + (string-match-p + (rx bol "Reverting buffer `" + (literal (buffer-name buf)) "'" eol) + captured-messages)) + (should (string-match-p "foo bla" (buffer-string))))) + + ;; Stop autorevert, in order to cleanup descriptor. + (auto-revert-mode -1) + (remove-function (local #'vc-refresh-state) #'ignore)) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p) + + ;; Cleanup. + (ignore-errors (kill-buffer buf))))) (file-notify--deftest-remote file-notify-test04-autorevert "Check autorevert via file notification for remote files.") @@ -1072,124 +1015,102 @@ delivered." :tags '(:expensive-test) (skip-unless (file-notify--test-local-enabled)) - (unwind-protect - (progn - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) - (should - (setq file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpfile '(change) #'ignore))) - (should (file-notify-valid-p file-notify--test-desc)) - ;; After calling `file-notify-rm-watch', the descriptor is not - ;; valid anymore. - (file-notify-rm-watch file-notify--test-desc) - (should-not (file-notify-valid-p file-notify--test-desc)) - (delete-file file-notify--test-tmpfile) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - (progn - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) - (should - (setq file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpfile - '(change) #'file-notify--test-event-handler))) - (should (file-notify-valid-p file-notify--test-desc)) - (file-notify--test-with-actions - (cond - ;; SMBSamba reports three `changed' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - '(changed changed changed changed deleted stopped)) - ;; GFam{File,Directory}Monitor do not - ;; detect the `changed' event reliably. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor)) - '((deleted stopped) - (changed deleted stopped))) - ;; GKqueueFileMonitor does not report the `changed' event. - ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) - '(deleted stopped)) - ;; There could be one or two `changed' events. - (t '((changed deleted stopped) - (changed changed deleted stopped)))) - (write-region - "another text" nil file-notify--test-tmpfile nil 'no-message) - (file-notify--test-wait-event) - (delete-file file-notify--test-tmpfile)) - (file-notify--test-wait-event) - ;; After deleting the file, the descriptor is not valid anymore. - (should-not (file-notify-valid-p file-notify--test-desc)) - (file-notify-rm-watch file-notify--test-desc) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - ;; On emba, `deleted' and `stopped' events of the directory are - ;; not detected. - (let ((file-notify--test-tmpdir - (make-temp-file "file-notify-test-parent" t))) - (should - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) - file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpdir - '(change) #'file-notify--test-event-handler))) - (should (file-notify-valid-p file-notify--test-desc)) - (file-notify--test-with-actions - (cond - ;; w32notify does not raise `deleted' and `stopped' events - ;; for the watched directory. - ((string-equal (file-notify--test-library) "w32notify") - '(created changed deleted)) - ;; SMBSamba reports three `changed' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - '(created changed changed changed deleted deleted stopped)) - ;; There are two `deleted' events, for the file and for the - ;; directory. Except for GFam{File,Directory}Monitor, - ;; GPollFileMonitor and kqueue. And - ;; GFam{File,Directory}Monitor and GPollfileMonitor do not - ;; raise a `changed' event. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) - '(created deleted stopped)) - ((string-equal (file-notify--test-library) "kqueue") - '(created changed deleted stopped)) - ;; GKqueueFileMonitor does not report the `changed' event. - ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) - '(created deleted deleted stopped)) - (t '(created changed deleted deleted stopped))) - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message) - (file-notify--test-wait-event) - (delete-directory file-notify--test-tmpdir 'recursive)) - ;; After deleting the parent directory, the descriptor must not - ;; be valid anymore. - (should-not (file-notify-valid-p file-notify--test-desc)) - ;; w32notify doesn't generate `stopped' events when the parent - ;; directory is deleted, which doesn't provide a chance for - ;; filenotify.el to remove the descriptor from the internal hash - ;; table it maintains. So we must remove the descriptor - ;; manually. - (if (string-equal (file-notify--test-library) "w32notify") - (file-notify--rm-descriptor file-notify--test-desc)) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + (with-file-notify-test + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpfile '(change) #'ignore))) + (should (file-notify-valid-p file-notify--test-desc)) + ;; After calling `file-notify-rm-watch', the descriptor is not valid + ;; anymore. + (file-notify-rm-watch file-notify--test-desc) + (should-not (file-notify-valid-p file-notify--test-desc)) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)) + + (with-file-notify-test + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpfile + '(change) #'file-notify--test-event-handler))) + (should (file-notify-valid-p file-notify--test-desc)) + (file-notify--test-with-actions + (cond + ;; SMBSamba reports three `changed' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + '(changed changed changed changed deleted stopped)) + ;; GFam{File,Directory}Monitor do not detect the `changed' event + ;; reliably. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor)) + '((deleted stopped) + (changed deleted stopped))) + ;; GKqueueFileMonitor does not report the `changed' event. + ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) + '(deleted stopped)) + ;; There could be one or two `changed' events. + (t '((changed deleted stopped) + (changed changed deleted stopped)))) + (write-region "another text" nil file-notify--test-tmpfile nil 'no-message) + (file-notify--test-wait-event) + (delete-file file-notify--test-tmpfile)) + (file-notify--test-wait-event) + ;; After deleting the file, the descriptor is not valid anymore. + (should-not (file-notify-valid-p file-notify--test-desc)) + (file-notify-rm-watch file-notify--test-desc) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)) + + (with-file-notify-test + (delete-file file-notify--test-tmpfile) + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpdir + '(change) #'file-notify--test-event-handler))) + (should (file-notify-valid-p file-notify--test-desc)) + (file-notify--test-with-actions + (cond + ;; w32notify does not raise `deleted' and `stopped' events for + ;; the watched directory. + ((string-equal (file-notify--test-library) "w32notify") + '(created changed deleted)) + ;; SMBSamba reports three `changed' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + '(created changed changed changed deleted deleted stopped)) + ;; There are two `deleted' events, for the file and for the + ;; directory. Except for GFam{File,Directory}Monitor, + ;; GPollFileMonitor and kqueue. And GFam{File,Directory}Monitor + ;; and GPollfileMonitor do not raise a `changed' event. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) + '(created deleted stopped)) + ((string-equal (file-notify--test-library) "kqueue") + '(created changed deleted stopped)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) + '(created deleted deleted stopped)) + (t '(created changed deleted deleted stopped))) + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (file-notify--test-wait-event) + (delete-directory file-notify--test-tmpdir 'recursive)) + ;; After deleting the parent directory, the descriptor must not be + ;; valid anymore. + (should-not (file-notify-valid-p file-notify--test-desc)) + ;; w32notify doesn't generate `stopped' events when the parent + ;; directory is deleted, which doesn't provide a chance for + ;; filenotify.el to remove the descriptor from the internal hash + ;; table it maintains. So we must remove the descriptor manually. + (if (string-equal (file-notify--test-library) "w32notify") + (file-notify--rm-descriptor file-notify--test-desc)) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) (file-notify--deftest-remote file-notify-test05-file-validity "Check `file-notify-valid-p' via file notification for remote files.") @@ -1198,58 +1119,41 @@ delivered." "Check `file-notify-valid-p' for directories." (skip-unless (file-notify--test-local-enabled)) - (unwind-protect - (progn - (should - (setq file-notify--test-tmpfile - (make-temp-file "file-notify-test-parent" t))) - (should - (setq file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpfile '(change) #'ignore))) - (should (file-notify-valid-p file-notify--test-desc)) - ;; After removing the watch, the descriptor must not be valid - ;; anymore. - (file-notify-rm-watch file-notify--test-desc) - (file-notify--test-wait-for-events - (file-notify--test-timeout) - (not (file-notify-valid-p file-notify--test-desc))) - (should-not (file-notify-valid-p file-notify--test-desc)) - (delete-directory file-notify--test-tmpfile 'recursive) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - ;; On emba, `deleted' and `stopped' events of the directory are - ;; not detected. - (progn - (should - (setq file-notify--test-tmpfile - (make-temp-file "file-notify-test-parent" t))) - (should - (setq file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpfile '(change) #'ignore))) - (should (file-notify-valid-p file-notify--test-desc)) - ;; After deleting the directory, the descriptor must not be - ;; valid anymore. - (delete-directory file-notify--test-tmpfile 'recursive) - (file-notify--test-wait-for-events - (file-notify--test-timeout) - (not (file-notify-valid-p file-notify--test-desc))) - (should-not (file-notify-valid-p file-notify--test-desc)) - (if (string-equal (file-notify--test-library) "w32notify") - (file-notify--rm-descriptor file-notify--test-desc)) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + (with-file-notify-test + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpdir '(change) #'ignore))) + (should (file-notify-valid-p file-notify--test-desc)) + ;; After removing the watch, the descriptor must not be valid + ;; anymore. + (file-notify-rm-watch file-notify--test-desc) + (file-notify--test-wait-for-events + (file-notify--test-timeout) + (not (file-notify-valid-p file-notify--test-desc))) + (should-not (file-notify-valid-p file-notify--test-desc)) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)) + + (with-file-notify-test + (should + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpdir '(change) #'ignore))) + (should (file-notify-valid-p file-notify--test-desc)) + ;; After deleting the directory, the descriptor must not be valid + ;; anymore. + (delete-directory file-notify--test-tmpdir 'recursive) + (file-notify--test-wait-for-events + (file-notify--test-timeout) + (not (file-notify-valid-p file-notify--test-desc))) + (should-not (file-notify-valid-p file-notify--test-desc)) + (if (string-equal (file-notify--test-library) "w32notify") + (file-notify--rm-descriptor file-notify--test-desc)) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) (file-notify--deftest-remote file-notify-test06-dir-validity "Check `file-notify-valid-p' via file notification for remote directories.") @@ -1259,89 +1163,79 @@ delivered." :tags '(:expensive-test) (skip-unless (file-notify--test-local-enabled)) - (should - (setq file-notify--test-tmpfile - (make-temp-file "file-notify-test-parent" t))) - (should - (setq file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpfile - '(change) #'file-notify--test-event-handler))) - (unwind-protect - (let ((n 10);00) - source-file-list target-file-list - (default-directory file-notify--test-tmpfile)) - (dotimes (i n) - ;; It matters which direction we rename, at least for - ;; kqueue. This backend parses directories in alphabetic - ;; order (x%d before y%d). So we rename into both directions. - (if (evenp i) - (progn - (push (expand-file-name (format "x%d" i)) source-file-list) - (push (expand-file-name (format "y%d" i)) target-file-list)) - (push (expand-file-name (format "y%d" i)) source-file-list) - (push (expand-file-name (format "x%d" i)) target-file-list))) - (file-notify--test-with-actions - (cond - ;; SMBSamba fires both `created' and `changed' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - (let (r) - (dotimes (_i (+ n n) r) - (setq r (append '(created changed) r))))) - (t (make-list (+ n n) 'created))) - (let ((source-file-list source-file-list) - (target-file-list target-file-list)) - (while (and source-file-list target-file-list) - (file-notify--test-wait-event) - (write-region "" nil (pop source-file-list) nil 'no-message) - (file-notify--test-wait-event) - (write-region "" nil (pop target-file-list) nil 'no-message)))) - (file-notify--test-with-actions - (cond - ;; w32notify fires both `deleted' and `renamed' events. - ((string-equal (file-notify--test-library) "w32notify") - (let (r) - (dotimes (_i n r) - (setq r (append '(deleted renamed) r))))) - ;; SMBWindows fires both `changed' and `deleted' events. - ((eq (file-notify--test-monitor) 'SMBWindows) - (let (r) - (dotimes (_i n r) - (setq r (append '(changed deleted) r))))) - ;; SMBSamba fires both `changed' and `deleted' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - (let (r) - (dotimes (_i n r) - (setq r (append '(changed changed deleted) r))))) - ;; GFam{File,Directory}Monitor and GPollFileMonitor fire - ;; `changed' and `deleted' events, sometimes in random - ;; order. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) - (let (r) - (dotimes (_i n (cons :random r)) - (setq r (append '(changed deleted) r))))) - (t (make-list n 'renamed))) - (let ((source-file-list source-file-list) - (target-file-list target-file-list)) - (while (and source-file-list target-file-list) - (file-notify--test-wait-event) - (rename-file (pop source-file-list) (pop target-file-list) t)))) - (file-notify--test-with-actions (make-list n 'deleted) - (dolist (file target-file-list) - (file-notify--test-wait-event) - (delete-file file))) - (delete-directory file-notify--test-tmpfile) - (if (string-equal (file-notify--test-library) "w32notify") - (file-notify--rm-descriptor file-notify--test-desc)) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) - -;; Unpredictable failures, eg https://hydra.nixos.org/build/86016286 + (with-file-notify-test + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpdir + '(change) #'file-notify--test-event-handler))) + (let ((n 10);00) + source-file-list target-file-list + (default-directory file-notify--test-tmpdir)) + (dotimes (i n) + ;; It matters which direction we rename, at least for kqueue. + ;; This backend parses directories in alphabetic order (x%d + ;; before y%d). So we rename into both directions. + (if (evenp i) + (progn + (push (expand-file-name (format "x%d" i)) source-file-list) + (push (expand-file-name (format "y%d" i)) target-file-list)) + (push (expand-file-name (format "y%d" i)) source-file-list) + (push (expand-file-name (format "x%d" i)) target-file-list))) + (file-notify--test-with-actions + (cond + ;; SMBSamba fires both `created' and `changed' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + (let (r) + (dotimes (_i (+ n n) r) + (setq r (append '(created changed) r))))) + (t (make-list (+ n n) 'created))) + (let ((source-file-list source-file-list) + (target-file-list target-file-list)) + (while (and source-file-list target-file-list) + (file-notify--test-wait-event) + (write-region "" nil (pop source-file-list) nil 'no-message) + (file-notify--test-wait-event) + (write-region "" nil (pop target-file-list) nil 'no-message)))) + (file-notify--test-with-actions + (cond + ;; w32notify fires both `deleted' and `renamed' events. + ((string-equal (file-notify--test-library) "w32notify") + (let (r) + (dotimes (_i n r) + (setq r (append '(deleted renamed) r))))) + ;; SMBWindows fires both `changed' and `deleted' events. + ((eq (file-notify--test-monitor) 'SMBWindows) + (let (r) + (dotimes (_i n r) + (setq r (append '(changed deleted) r))))) + ;; SMBSamba fires both `changed' and `deleted' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + (let (r) + (dotimes (_i n r) + (setq r (append '(changed changed deleted) r))))) + ;; GFam{File,Directory}Monitor and GPollFileMonitor fire + ;; `changed' and `deleted' events, sometimes in random order. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) + (let (r) + (dotimes (_i n (cons :random r)) + (setq r (append '(changed deleted) r))))) + (t (make-list n 'renamed))) + (let ((source-file-list source-file-list) + (target-file-list target-file-list)) + (while (and source-file-list target-file-list) + (file-notify--test-wait-event) + (rename-file (pop source-file-list) (pop target-file-list) t)))) + (file-notify--test-with-actions (make-list n 'deleted) + (dolist (file target-file-list) + (file-notify--test-wait-event) + (delete-file file))) + (file-notify--rm-descriptor file-notify--test-desc) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)))) + (file-notify--deftest-remote file-notify-test07-many-events "Check that events are not dropped for remote directories.") @@ -1350,95 +1244,85 @@ delivered." :tags '(:expensive-test) (skip-unless (file-notify--test-local-enabled)) - (unwind-protect - (progn - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) - (should - (setq file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpfile - '(change) #'file-notify--test-event-handler))) - (should (file-notify-valid-p file-notify--test-desc)) - (file-notify--test-with-actions - (cond - ;; SMBSamba reports four `changed' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - '(changed changed changed changed)) - ;; GKqueueFileMonitor does not report the `changed' event. - ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) '()) - ;; There could be one or two `changed' events. - (t '((changed) - (changed changed)))) - ;; There shouldn't be any problem, because the file is kept. - (with-temp-buffer - (let ((buffer-file-name file-notify--test-tmpfile) - (make-backup-files t) - (backup-by-copying t) - (kept-new-versions 1) - (delete-old-versions t)) - (insert "another text") - (save-buffer)))) - ;; After saving the buffer, the descriptor is still valid. - (should (file-notify-valid-p file-notify--test-desc)) - (delete-file file-notify--test-tmpfile) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - ;; It doesn't work for kqueue, because we don't use an implicit - ;; directory monitor. - (unless (string-equal (file-notify--test-library) "kqueue") - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message) - (should - (setq file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpfile - '(change) #'file-notify--test-event-handler))) - (should (file-notify-valid-p file-notify--test-desc)) - (file-notify--test-with-actions - (cond - ;; SMBWindows reports two `changed' events. - ((eq (file-notify--test-monitor) 'SMBWindows) - '(changed changed)) - ;; SMBSamba reports four `changed' events. - ((eq (file-notify--test-monitor) 'SMBSamba) - '(changed changed changed changed)) - ;; GFam{File,Directory}Monitor and GPollFileMonitor - ;; report only the `changed' event. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) - '(changed)) - ;; GKqueueFileMonitor does not report the `changed' event. - ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) - '(renamed created)) - (t '(renamed created changed))) - ;; The file is renamed when creating a backup. It shall - ;; still be watched. - (with-temp-buffer - (let ((buffer-file-name file-notify--test-tmpfile) - (make-backup-files t) - (backup-by-copying nil) - (backup-by-copying-when-mismatch nil) - (kept-new-versions 1) - (delete-old-versions t)) - (insert "another text") - (save-buffer)))) - ;; After saving the buffer, the descriptor is still valid. - (should (file-notify-valid-p file-notify--test-desc)) - (delete-file file-notify--test-tmpfile) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + (with-file-notify-test + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpfile + '(change) #'file-notify--test-event-handler))) + (should (file-notify-valid-p file-notify--test-desc)) + (file-notify--test-with-actions + (cond + ;; SMBSamba reports four `changed' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + '(changed changed changed changed)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) '()) + ;; There could be one or two `changed' events. + (t '((changed) + (changed changed)))) + ;; There shouldn't be any problem, because the file is kept. + (with-temp-buffer + (let ((buffer-file-name file-notify--test-tmpfile) + (make-backup-files t) + (backup-by-copying t) + (kept-new-versions 1) + (delete-old-versions t)) + (insert "another text") + (save-buffer)))) + ;; After saving the buffer, the descriptor is still valid. + (should (file-notify-valid-p file-notify--test-desc)) + (file-notify--rm-descriptor file-notify--test-desc) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)) + + (with-file-notify-test + ;; It doesn't work for kqueue, because we don't use an implicit + ;; directory monitor. + (unless (string-equal (file-notify--test-library) "kqueue") + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpfile + '(change) #'file-notify--test-event-handler))) + (should (file-notify-valid-p file-notify--test-desc)) + (file-notify--test-with-actions + (cond + ;; SMBWindows reports two `changed' events. + ((eq (file-notify--test-monitor) 'SMBWindows) + '(changed changed)) + ;; SMBSamba reports four `changed' events. + ((eq (file-notify--test-monitor) 'SMBSamba) + '(changed changed changed changed)) + ;; GFam{File,Directory}Monitor and GPollFileMonitor + ;; report only the `changed' event. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) + '(changed)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) + '(renamed created)) + (t '(renamed created changed))) + ;; The file is renamed when creating a backup. It shall still be + ;; watched. + (with-temp-buffer + (let ((buffer-file-name file-notify--test-tmpfile) + (make-backup-files t) + (backup-by-copying nil) + (backup-by-copying-when-mismatch nil) + (kept-new-versions 1) + (delete-old-versions t)) + (insert "another text") + (save-buffer)))) + ;; After saving the buffer, the descriptor is still valid. + (should (file-notify-valid-p file-notify--test-desc)) + (file-notify--rm-descriptor file-notify--test-desc) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)))) (file-notify--deftest-remote file-notify-test08-backup "Check that backup keeps file notification for remote files.") @@ -1453,157 +1337,143 @@ the file watch." :tags '(:expensive-test) (skip-unless (file-notify--test-local-enabled)) - ;; A directory to be watched. - (should - (setq file-notify--test-tmpfile - (make-temp-file "file-notify-test-parent" t))) - ;; A file to be watched. - (should - (setq file-notify--test-tmpfile1 - (let ((file-notify--test-tmpdir file-notify--test-tmpfile)) - (file-notify--test-make-temp-name)))) - (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message) - (unwind-protect - (cl-flet (;; Directory monitor. - (dir-callback (event file) - (let ((file-notify--test-desc file-notify--test-desc1)) - (file-notify--test-event-handler event file))) - ;; File monitor. - (file-callback (event file) - (let ((file-notify--test-desc file-notify--test-desc2)) - (file-notify--test-event-handler event file)))) - (should - (setq file-notify--test-desc1 - (file-notify--test-add-watch - file-notify--test-tmpfile - '(change) #'dir-callback) - ;; This is needed for `file-notify--test-monitor'. - file-notify--test-desc file-notify--test-desc1)) - (should - (setq file-notify--test-desc2 - (file-notify--test-add-watch - file-notify--test-tmpfile1 - '(change) #'file-callback))) - (should (file-notify-valid-p file-notify--test-desc1)) - (should (file-notify-valid-p file-notify--test-desc2)) - (should-not (equal file-notify--test-desc1 file-notify--test-desc2)) - (let ((n 10));0)) - ;; Run the test. - (file-notify--test-with-actions - ;; There could be one or two `changed' events. - (list - ;; SMBSamba. Sometimes, tha last `changed' event is - ;; missing, so we add two alternatives. - (append - '(:random) - ;; Just the file monitor. - (make-list (* (/ n 2) 5) 'changed) - ;; Just the directory monitor. Strange, not all - ;; `changed' events do arrive. - (make-list (1- (* (/ n 2) 10)) 'changed) - (make-list (/ n 2) 'created) - (make-list (/ n 2) 'created)) - (append - '(:random) - ;; Just the file monitor. - (make-list (* (/ n 2) 5) 'changed) - ;; Just the directory monitor. This is the alternative - ;; with all `changed' events. - (make-list (* (/ n 2) 10) 'changed) - (make-list (/ n 2) 'created) - (make-list (/ n 2) 'created)) - ;; cygwin. - (append - '(:random) - (make-list (/ n 2) 'changed) - (make-list (/ n 2) 'created) - (make-list (/ n 2) 'changed)) - (append - '(:random) - ;; Directory monitor and file monitor. - (make-list (/ n 2) 'changed) - (make-list (/ n 2) 'changed) - ;; Just the directory monitor. - (make-list (/ n 2) 'created) - (make-list (/ n 2) 'changed)) - (append - '(:random) - ;; Directory monitor and file monitor. - (make-list (/ n 2) 'changed) - (make-list (/ n 2) 'changed) - (make-list (/ n 2) 'changed) - (make-list (/ n 2) 'changed) - ;; Just the directory monitor. - (make-list (/ n 2) 'created) - (make-list (/ n 2) 'changed)) - (append - '(:random) - ;; Just the directory monitor. GKqueueFileMonitor - ;; does not report the `changed' event. - (make-list (/ n 2) 'created))) - (dotimes (i n) - (file-notify--test-wait-event) - (if (evenp i) - (write-region - "any text" nil file-notify--test-tmpfile1 t 'no-message) - (let ((file-notify--test-tmpdir file-notify--test-tmpfile)) - (write-region - "any text" nil - (file-notify--test-make-temp-name) nil 'no-message)))))) - - ;; If we delete the file, the directory monitor shall still be - ;; active. We receive the `deleted' event from both the - ;; directory and the file monitor. The `stopped' event is - ;; from the file monitor. It's undecided in which order the - ;; directory and the file monitor are triggered. - (file-notify--test-with-actions - '((:random deleted deleted stopped) - (:random deleted deleted deleted stopped)) - (delete-file file-notify--test-tmpfile1)) - (should (file-notify-valid-p file-notify--test-desc1)) - (should-not (file-notify-valid-p file-notify--test-desc2)) - - ;; Now we delete the directory. - (file-notify--test-with-actions - (cond - ;; GFam{File,Directory}Monitor, GPollFileMonitor and - ;; kqueue raise just one `deleted' event for the - ;; directory. - ((memq (file-notify--test-monitor) - '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) - '(deleted stopped)) - ((string-equal (file-notify--test-library) "kqueue") - '(deleted stopped)) - (t (append - ;; The directory monitor raises a `deleted' event for - ;; every file contained in the directory, we must - ;; count them. - (make-list - (length - (directory-files - file-notify--test-tmpfile nil - directory-files-no-dot-files-regexp 'nosort)) - 'deleted) - ;; The events of the directory itself. - (cond - ;; w32notify does not raise `deleted' and `stopped' - ;; events for the watched directory. - ((string-equal (file-notify--test-library) "w32notify") - '()) - (t '(deleted stopped)))))) - (delete-directory file-notify--test-tmpfile 'recursive)) - (unless (getenv "EMACS_EMBA_CI") - (should-not (file-notify-valid-p file-notify--test-desc1)) - (should-not (file-notify-valid-p file-notify--test-desc2))) - (when (string-equal (file-notify--test-library) "w32notify") - (file-notify--rm-descriptor file-notify--test-desc1) - (file-notify--rm-descriptor file-notify--test-desc2)) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + (with-file-notify-test + (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) + (cl-flet (;; Directory monitor. + (dir-callback (event file) + (let ((file-notify--test-desc file-notify--test-desc1)) + (file-notify--test-event-handler event file))) + ;; File monitor. + (file-callback (event file) + (let ((file-notify--test-desc file-notify--test-desc2)) + (file-notify--test-event-handler event file)))) + (should + (setq file-notify--test-desc1 + (file-notify--test-add-watch + file-notify--test-tmpdir + '(change) #'dir-callback) + ;; This is needed for `file-notify--test-monitor'. + file-notify--test-desc file-notify--test-desc1)) + (should + (setq file-notify--test-desc2 + (file-notify--test-add-watch + file-notify--test-tmpfile + '(change) #'file-callback))) + (should (file-notify-valid-p file-notify--test-desc1)) + (should (file-notify-valid-p file-notify--test-desc2)) + (should-not (equal file-notify--test-desc1 file-notify--test-desc2)) + (let ((n 10));0)) + ;; Run the test. + (file-notify--test-with-actions + ;; There could be one or two `changed' events. + (list + ;; SMBSamba. Sometimes, tha last `changed' event is + ;; missing, so we add two alternatives. + (append + '(:random) + ;; Just the file monitor. + (make-list (* (/ n 2) 5) 'changed) + ;; Just the directory monitor. Strange, not all `changed' + ;; events do arrive. + (make-list (1- (* (/ n 2) 10)) 'changed) + (make-list (/ n 2) 'created) + (make-list (/ n 2) 'created)) + (append + '(:random) + ;; Just the file monitor. + (make-list (* (/ n 2) 5) 'changed) + ;; Just the directory monitor. This is the alternative + ;; with all `changed' events. + (make-list (* (/ n 2) 10) 'changed) + (make-list (/ n 2) 'created) + (make-list (/ n 2) 'created)) + ;; cygwin. + (append + '(:random) + (make-list (/ n 2) 'changed) + (make-list (/ n 2) 'created) + (make-list (/ n 2) 'changed)) + (append + '(:random) + ;; Directory monitor and file monitor. + (make-list (/ n 2) 'changed) + (make-list (/ n 2) 'changed) + ;; Just the directory monitor. + (make-list (/ n 2) 'created) + (make-list (/ n 2) 'changed)) + (append + '(:random) + ;; Directory monitor and file monitor. + (make-list (/ n 2) 'changed) + (make-list (/ n 2) 'changed) + (make-list (/ n 2) 'changed) + (make-list (/ n 2) 'changed) + ;; Just the directory monitor. + (make-list (/ n 2) 'created) + (make-list (/ n 2) 'changed)) + (append + '(:random) + ;; Just the directory monitor. GKqueueFileMonitor does not + ;; report the `changed' event. + (make-list (/ n 2) 'created))) + (dotimes (i n) + (file-notify--test-wait-event) + (if (evenp i) + (write-region + "any text" nil file-notify--test-tmpfile t 'no-message) + (write-region + "any text" nil + (file-notify--test-make-temp-name) nil 'no-message))))) + + ;; If we delete the file, the directory monitor shall still be + ;; active. We receive the `deleted' event from both the directory + ;; and the file monitor. The `stopped' event is from the file + ;; monitor. It's undecided in which order the directory and the + ;; file monitor are triggered. + (file-notify--test-with-actions + '((:random deleted deleted stopped) + (:random deleted deleted deleted stopped)) + (delete-file file-notify--test-tmpfile)) + (should (file-notify-valid-p file-notify--test-desc1)) + (should-not (file-notify-valid-p file-notify--test-desc2)) + + ;; Now we delete the directory. + (file-notify--test-with-actions + (cond + ;; GFam{File,Directory}Monitor, GPollFileMonitor and kqueue + ;; raise just one `deleted' event for the directory. + ((memq (file-notify--test-monitor) + '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor)) + '(deleted stopped)) + ((string-equal (file-notify--test-library) "kqueue") + '(deleted stopped)) + (t (append + ;; The directory monitor raises a `deleted' event for + ;; every file contained in the directory, we must count + ;; them. + (make-list + (length + (directory-files + file-notify--test-tmpdir nil + directory-files-no-dot-files-regexp 'nosort)) + 'deleted) + ;; The events of the directory itself. + (cond + ;; w32notify does not raise `deleted' and `stopped' + ;; events for the watched directory. + ((string-equal (file-notify--test-library) "w32notify") + '()) + (t '(deleted stopped)))))) + (delete-directory file-notify--test-tmpdir 'recursive)) + (unless (getenv "EMACS_EMBA_CI") + (should-not (file-notify-valid-p file-notify--test-desc1)) + (should-not (file-notify-valid-p file-notify--test-desc2))) + (when (string-equal (file-notify--test-library) "w32notify") + (file-notify--rm-descriptor file-notify--test-desc1) + (file-notify--rm-descriptor file-notify--test-desc2)) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)))) (file-notify--deftest-remote file-notify-test09-watched-file-in-watched-dir "Check `file-notify-test09-watched-file-in-watched-dir' for remote files.") @@ -1616,39 +1486,31 @@ the file watch." ;; GKqueueFileMonitor, because `file-notify--test-desc' is not set yet. (skip-unless (string-equal (file-notify--test-library) "kqueue")) - (should - (setq file-notify--test-tmpfile - (make-temp-file "file-notify-test-parent" t))) - (unwind-protect - (let ((file-notify--test-tmpdir file-notify--test-tmpfile) - descs) - (should-error - (while t - ;; We watch directories, because we want to reach the upper - ;; limit. Watching a file might not be sufficient, because - ;; most of the libraries implement this as watching the - ;; upper directory. - (setq file-notify--test-tmpfile1 - (make-temp-file "file-notify-test-parent" t) - descs - (cons - (should - (file-notify-add-watch - file-notify--test-tmpfile1 '(change) #'ignore)) - descs))) - :type 'file-notify-error) - ;; Remove watches. If we don't do it prior removing - ;; directories, Emacs crashes in batch mode. - (dolist (desc descs) - (file-notify-rm-watch desc)) - ;; Remove directories. - (delete-directory file-notify--test-tmpfile 'recursive) - - ;; The environment shall be cleaned up. - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + (with-file-notify-test + (let (descs tmpfile) + (should-error + (while t + ;; We watch directories, because we want to reach the upper + ;; limit. Watching a file might not be sufficient, because most + ;; of the libraries implement this as watching the upper + ;; directory. + (setq tmpfile + (make-temp-file + (expand-file-name + "file-notify-test-parent" file-notify--test-tmpdir) + t) + descs + (cons + (should (file-notify-add-watch tmpfile '(change) #'ignore)) + descs))) + :type 'file-notify-error) + ;; Remove watches. If we don't do it prior removing directories, + ;; Emacs crashes in batch mode. + (dolist (desc descs) + (file-notify-rm-watch desc)) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p)))) (file-notify--deftest-remote file-notify-test10-sufficient-resources "Check `file-notify-test10-sufficient-resources' for remote files.") @@ -1660,52 +1522,51 @@ the file watch." ;; This test does not work for kqueue (yet). (skip-when (string-equal (file-notify--test-library) "kqueue")) - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) - file-notify--test-tmpfile1 (file-notify--test-make-temp-name)) - - ;; Symlink a file. - (unwind-protect - (progn - (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message) - ;; Some systems, like MS Windows without sufficient - ;; privileges, do not allow creation of symbolic links. - (condition-case nil - (make-symbolic-link - file-notify--test-tmpfile1 file-notify--test-tmpfile) - (error (ert-skip "`make-symbolic-link' not supported"))) - (should - (setq file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpfile - '(attribute-change change) #'file-notify--test-event-handler))) - (should (file-notify-valid-p file-notify--test-desc)) - - ;; Writing to either the symlink or the target should not - ;; raise any event. - (file-notify--test-with-actions nil - (write-region - "another text" nil file-notify--test-tmpfile nil 'no-message) - (write-region - "another text" nil file-notify--test-tmpfile1 nil 'no-message)) - ;; Sanity check. - (file-notify--test-wait-for-events - (file-notify--test-timeout) - (not (input-pending-p))) - (should-not file-notify--test-events) - - ;; Changing timestamp of the target should not raise any - ;; event. We don't use `nofollow'. - (file-notify--test-with-actions nil - (set-file-times file-notify--test-tmpfile1 '(0 0)) - (set-file-times file-notify--test-tmpfile '(0 0))) - ;; Sanity check. - (file-notify--test-wait-for-events - (file-notify--test-timeout) - (not (input-pending-p))) - (should-not file-notify--test-events) - - ;; Changing timestamp of the symlink shows the event. - (file-notify--test-with-actions + (with-file-notify-test + (ert-with-temp-file file-notify--test-tmpfile1 + :prefix ert-temp-file-prefix :suffix ert-temp-file-suffix + (delete-file file-notify--test-tmpfile) + ;; Symlink a file. + (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message) + ;; Some systems, like MS Windows without sufficient privileges, do + ;; not allow creation of symbolic links. + (condition-case nil + (make-symbolic-link + file-notify--test-tmpfile1 file-notify--test-tmpfile) + (error (ert-skip "`make-symbolic-link' not supported"))) + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpfile + '(attribute-change change) #'file-notify--test-event-handler))) + (should (file-notify-valid-p file-notify--test-desc)) + + ;; Writing to either the symlink or the target should not raise any + ;; event. + (file-notify--test-with-actions nil + (write-region + "another text" nil file-notify--test-tmpfile nil 'no-message) + (write-region + "another text" nil file-notify--test-tmpfile1 nil 'no-message)) + ;; Sanity check. + (file-notify--test-wait-for-events + (file-notify--test-timeout) + (not (input-pending-p))) + (should-not file-notify--test-events) + + ;; Changing timestamp of the target should not raise any event. We + ;; don't use `nofollow'. + (file-notify--test-with-actions nil + (set-file-times file-notify--test-tmpfile1 '(0 0)) + (set-file-times file-notify--test-tmpfile '(0 0))) + ;; Sanity check. + (file-notify--test-wait-for-events + (file-notify--test-timeout) + (not (input-pending-p))) + (should-not file-notify--test-events) + + ;; Changing timestamp of the symlink shows the event. + (file-notify--test-with-actions (cond ;; w32notify does not distinguish between `changed' and ;; `attribute-changed'. @@ -1719,66 +1580,59 @@ the file watch." GKqueueFileMonitor GPollFileMonitor)) '()) (t '(attribute-changed))) - (set-file-times file-notify--test-tmpfile '(0 0) 'nofollow)) - - ;; Deleting the target should not raise any event. - (file-notify--test-with-actions nil - (delete-file file-notify--test-tmpfile1) - (delete-file file-notify--test-tmpfile)) - ;; Sanity check. - (file-notify--test-wait-for-events - (file-notify--test-timeout) - (not (input-pending-p))) - (should-not file-notify--test-events) - - ;; The environment shall be cleaned up. - (file-notify-rm-watch file-notify--test-desc) - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (setq file-notify--test-tmpfile1 (file-notify--test-make-temp-name) - file-notify--test-tmpfile (file-notify--test-make-temp-name)) - - ;; Symlink a directory. - (unwind-protect - (let ((tmpfile (expand-file-name "foo" file-notify--test-tmpfile)) - (tmpfile1 (expand-file-name "foo" file-notify--test-tmpfile1))) - (make-directory file-notify--test-tmpfile1) - (make-symbolic-link file-notify--test-tmpfile1 file-notify--test-tmpfile) - (write-region "any text" nil tmpfile1 nil 'no-message) - (should - (setq file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpfile - '(attribute-change change) #'file-notify--test-event-handler))) - (should (file-notify-valid-p file-notify--test-desc)) - - ;; None of the actions on a file in the symlinked directory - ;; will be reported. - (file-notify--test-with-actions nil - (write-region "another text" nil tmpfile nil 'no-message) - (write-region "another text" nil tmpfile1 nil 'no-message) - (set-file-times tmpfile '(0 0)) - (set-file-times tmpfile '(0 0) 'nofollow) - (set-file-times tmpfile1 '(0 0)) - (set-file-times tmpfile1 '(0 0) 'nofollow) - (delete-file tmpfile) - (delete-file tmpfile1)) - ;; Sanity check. - (file-notify--test-wait-for-events - (file-notify--test-timeout) - (not (input-pending-p))) - (should-not file-notify--test-events) - - ;; The environment shall be cleaned up. - (delete-directory file-notify--test-tmpdir 'recursive) - (file-notify-rm-watch file-notify--test-desc) - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + (set-file-times file-notify--test-tmpfile '(0 0) 'nofollow)) + + ;; Deleting the target should not raise any event. + (file-notify--test-with-actions nil + (delete-file file-notify--test-tmpfile1) + (delete-file file-notify--test-tmpfile)) + ;; Sanity check. + (file-notify--test-wait-for-events + (file-notify--test-timeout) + (not (input-pending-p))) + (should-not file-notify--test-events) + + ;; The environment shall be cleaned up. + (file-notify-rm-watch file-notify--test-desc) + (file-notify--test-cleanup-p))) + + (with-file-notify-test + (ert-with-temp-directory file-notify--test-tmpfile1 + :prefix (concat ert-temp-file-prefix "-parent") :suffix ert-temp-file-suffix + (delete-file file-notify--test-tmpfile) + ;; Symlink a directory. + (let ((tmpfile (expand-file-name "foo" file-notify--test-tmpfile)) + (tmpfile1 (expand-file-name "foo" file-notify--test-tmpfile1))) + (make-symbolic-link file-notify--test-tmpfile1 file-notify--test-tmpfile) + (write-region "any text" nil tmpfile1 nil 'no-message) + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpfile + '(attribute-change change) #'file-notify--test-event-handler))) + (should (file-notify-valid-p file-notify--test-desc)) + + ;; None of the actions on a file in the symlinked directory + ;; will be reported. + (file-notify--test-with-actions nil + (write-region "another text" nil tmpfile nil 'no-message) + (write-region "another text" nil tmpfile1 nil 'no-message) + (set-file-times tmpfile '(0 0)) + (set-file-times tmpfile '(0 0) 'nofollow) + (set-file-times tmpfile1 '(0 0)) + (set-file-times tmpfile1 '(0 0) 'nofollow) + (delete-file tmpfile) + (delete-file tmpfile1)) + ;; Sanity check. + (file-notify--test-wait-for-events + (file-notify--test-timeout) + (not (input-pending-p))) + (should-not file-notify--test-events) + + ;; The environment shall be cleaned up. + (delete-directory file-notify--test-tmpdir 'recursive) + (file-notify-rm-watch file-notify--test-desc) + (file-notify--test-cleanup-p))))) (file-notify--deftest-remote file-notify-test11-symlinks "Check `file-notify-test11-symlinks' for remote files.") @@ -1790,60 +1644,45 @@ the file watch." ;; This test does not work for w32notify snd smb-notify. (skip-when (member (file-notify--test-library) '("w32notify" "smb-notify"))) - (unwind-protect - (progn - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - ;; File monitors like kqueue insist, that the watched file - ;; exists. Directory monitors are not bound to this - ;; restriction. - (when (string-equal (file-notify--test-library) "kqueue") - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message)) - - (should - (setq file-notify--test-desc - (file-notify--test-add-watch - file-notify--test-tmpfile - '(attribute-change change) #'file-notify--test-event-handler))) - (should (file-notify-valid-p file-notify--test-desc)) - - ;; Unmounting the filesystem should stop watching. - (file-notify--test-with-actions '(stopped) - ;; We emulate unmounting by calling - ;; `file-notify-handle-event' with a corresponding event. - (file-notify-handle-event - (make-file-notify - :-event - (list file-notify--test-desc - (pcase (file-notify--test-library) - ((or "inotify" "inotifywait") '(unmount isdir)) - ((or "gfilenotify" "gio") '(unmounted)) - ("kqueue" '(revoke)) - (err (ert-fail (format "Library %s not supported" err)))) - (pcase (file-notify--test-library) - ("kqueue" (file-local-name file-notify--test-tmpfile)) - (_ (file-local-name file-notify--test-tmpdir))) - ;; In the inotify case, there is a 4th slot `cookie'. - ;; Since it is unused for `unmount', we ignore it. - ) - :-callback - (pcase (file-notify--test-library) - ("inotify" #'file-notify--callback-inotify) - ("gfilenotify" #'file-notify--callback-gfilenotify) - ("kqueue" #'file-notify--callback-kqueue) - ((or "inotifywait" "gio") #'file-notify-callback) - (err (ert-fail (format "Library %s not supported" err))))))) - - ;; The watch has been stopped. - (should-not (file-notify-valid-p file-notify--test-desc)) - - ;; The environment shall be cleaned up. - (when (string-equal (file-notify--test-library) "kqueue") - (delete-file file-notify--test-tmpfile)) - (file-notify--test-cleanup-p)) - - ;; Cleanup. - (file-notify--test-cleanup))) + (with-file-notify-test + (should + (setq file-notify--test-desc + (file-notify--test-add-watch + file-notify--test-tmpfile + '(attribute-change change) #'file-notify--test-event-handler))) + (should (file-notify-valid-p file-notify--test-desc)) + + ;; Unmounting the filesystem should stop watching. + (file-notify--test-with-actions '(stopped) + ;; We emulate unmounting by inserting a corresponding event. + (insert-special-event + (make-file-notify + :-event + (list file-notify--test-desc + (pcase (file-notify--test-library) + ((or "inotify" "inotifywait") '(unmount isdir)) + ((or "gfilenotify" "gio") '(unmounted)) + ("kqueue" '(revoke)) + (err (ert-fail (format "Library %s not supported" err)))) + (pcase (file-notify--test-library) + ("kqueue" (file-local-name file-notify--test-tmpfile)) + (_ (file-local-name file-notify--test-tmpdir))) + ;; In the inotify case, there is a 4th slot `cookie'. + ;; Since it is unused for `unmount', we ignore it. + ) + :-callback + (pcase (file-notify--test-library) + ("inotify" #'file-notify--callback-inotify) + ("gfilenotify" #'file-notify--callback-gfilenotify) + ("kqueue" #'file-notify--callback-kqueue) + ((or "inotifywait" "gio") #'file-notify-callback) + (err (ert-fail (format "Library %s not supported" err))))))) + + ;; The watch has been stopped. + (should-not (file-notify-valid-p file-notify--test-desc)) + + ;; The environment shall be cleaned up. + (file-notify--test-cleanup-p))) (file-notify--deftest-remote file-notify-test12-unmount "Check `file-notify-test12-unmount' for remote files.") diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 1cf010f1d14..98328b99b2b 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -7736,7 +7736,10 @@ process sentinels. They shall not disturb each other." ;; selector "remote". (ert-deftest tramp-test46-file-notifications () "Check that Tramp handles file notifications." + :tags '(:unstable) (skip-unless (tramp--test-enabled)) + ;; filenotify.el was reworked in Emacs 31. + (skip-unless (tramp--test-emacs31-p)) (let* ((tmp-name (tramp--test-make-temp-name)) ;(file-notify-debug t) @@ -7755,12 +7758,13 @@ process sentinels. They shall not disturb each other." (progn (tramp--test-message "%S" desc1) (should-not (file-exists-p tmp-name)) - (should (file-notify-valid-p desc1)) (should (file-notify-valid-p desc2)) - ;; Create the file. + ;; Create the file. `file-notify-valid-p' requires that the + ;; watched file exists, so we cannot check it earlier for `desc1'. (write-region "foo" nil tmp-name) (should (file-exists-p tmp-name)) + (should (file-notify-valid-p desc1)) ;; Modify. (write-region "foo" nil tmp-name) (should (file-exists-p tmp-name)) -- 2.39.5