From e089ad76fc7e5dd417905e115a7a8425210a0d7f Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Tue, 15 Jul 2025 18:57:49 +0200 Subject: [PATCH] Improve autorevert-tests * doc/misc/trampver.texi: * lisp/net/trampver.el: Change version to "2.8.1-pre". * lisp/autorevert.el (auto-revert-mode, auto-revert-tail-mode) (auto-revert-notify-handler, auto-revert--end-lockout): Use `auto-revert-buffer'. (auto-revert-notify-handler): Rearrange setting current buffer. (auto-revert-handler): Add debug message. Rearrange check. Cancel lockout timer if running. * lisp/net/tramp.el (tramp-barf-if-file-missing) (with-parsed-tramp-file-name, tramp-skeleton-file-truename): * lisp/net/tramp-archive.el (with-parsed-tramp-archive-file-name): * lisp/net/tramp-message.el (tramp-with-demoted-errors): Fix debug declatation. * lisp/net/tramp-sh.el (tramp-sh-gio-monitor-process-filter): Do not prepend remote prefix. * test/lisp/autorevert-tests.el: Unify file notification libraries "gio-monitor" and "gvfs-monitor-dir" to "gio". (top): Set some Tramp related variables. (auto-revert--timeout): Increase value. (auto-revert--test-enabled-remote) (auto-revert-test02-auto-revert-deleted-file): Do not check for EMACS_HYDRA_CI environment variable. (auto-revert--wait-for-revert): Fix regexp to search for. (auto-revert--deftest-remote): Fix debug declatation. Do not tag :unstable. (with-auto-revert-test): Fix debug declatation. Adapt revert intervals. (auto-revert-test*): Start with (file-notify-rm-all-watches). Use `buffer-string' and `string-match-p'. (auto-revert-test00-auto-revert-mode): Unlock initial lockout. (auto-revert-test01-auto-revert-several-files): Rearrange temporary directory and file settings. (auto-revert-test02-auto-revert-deleted-file): Adapt debug message. (auto-revert-test03-auto-revert-tail-mode): Use `with-auto-revert-test'. (auto-revert-test04-auto-revert-mode-dired): Use `ert-with-temp-directory'. Adapt prefix of tmpfile. (auto-revert-test04-auto-revert-mode-dired) (auto-revert-test05-global-notify, auto-revert-test06-write-file): Wait for proper file modification. (auto-revert-test--instrument-kill-buffer-hook): Fix debug message. (auto-revert-test07-auto-revert-several-buffers): Use `with-auto-revert-test. * test/lisp/filenotify-tests.el: Unify file notification libraries "gio-monitor" and "gvfs-monitor-dir" to "gio". (file-notify--deftest-remote): Fix debug declatation. Do not skip for "gio". (file-notify--test-with-actions): Fix debug declatation. * test/lisp/net/tramp-tests.el (filenotify): Require. (ert-remote-temporary-file-directory) (tramp-test41-special-characters, tramp-test42-utf8) (tramp-test45-asynchronous-requests): Do not check for EMACS_HYDRA_CI environment variable. (tramp-test46-file-notifications): New test. (cherry picked from commit 4c9b37660771776563cf79bb3a2b6e692aa05ca2) --- doc/misc/trampver.texi | 2 +- lisp/autorevert.el | 62 +++--- lisp/net/tramp-archive.el | 2 +- lisp/net/tramp-message.el | 2 +- lisp/net/tramp-sh.el | 7 +- lisp/net/tramp.el | 6 +- lisp/net/trampver.el | 6 +- test/lisp/autorevert-tests.el | 355 ++++++++++++++++++++++------------ test/lisp/filenotify-tests.el | 26 ++- test/lisp/net/tramp-tests.el | 80 ++++++-- 10 files changed, 342 insertions(+), 206 deletions(-) diff --git a/doc/misc/trampver.texi b/doc/misc/trampver.texi index a6e305534aa..bfae103a782 100644 --- a/doc/misc/trampver.texi +++ b/doc/misc/trampver.texi @@ -7,7 +7,7 @@ @c In the Tramp GIT, the version number and the bug report address @c are auto-frobbed from configure.ac. -@set trampver 2.8.0 +@set trampver 2.8.1-pre @set trampurl https://www.gnu.org/software/tramp/ @set tramp-bug-report-address tramp-devel@@gnu.org @set emacsver 28.1 diff --git a/lisp/autorevert.el b/lisp/autorevert.el index aab160c25bf..492bb565c25 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -415,7 +415,7 @@ without being changed in the part that is already in the buffer." (auto-revert-remove-current-buffer)) (auto-revert-set-timer) (when auto-revert-mode - (auto-revert-buffers) + (auto-revert-buffer (current-buffer)) (setq auto-revert-tail-mode nil))) @@ -470,7 +470,7 @@ Use `auto-revert-mode' for changes other than appends!" (y-or-n-p "File changed on disk, content may be missing. \ Perform a full revert? ") ;; Use this (not just revert-buffer) for point-preservation. - (auto-revert-buffers)) + (auto-revert-buffer (current-buffer))) ;; else we might reappend our own end when we save (add-hook 'before-save-hook (lambda () (auto-revert-tail-mode 0)) nil t) (or (local-variable-p 'auto-revert-tail-pos) ; don't lose prior position @@ -716,9 +716,9 @@ system.") (message "auto-revert-notify-handler %S" event)) (when (buffer-live-p buffer) - (if (eq action 'stopped) - ;; File notification has stopped. Continue with polling. - (with-current-buffer buffer + (with-current-buffer buffer + (if (eq action 'stopped) + ;; File notification has stopped. Continue with polling. (when (or ;; A buffer associated with a file. (and (stringp buffer-file-name) @@ -730,9 +730,8 @@ system.") (auto-revert-notify-rm-watch) ;; Restart the timer if it wasn't running. (unless auto-revert-timer - (auto-revert-set-timer)))) + (auto-revert-set-timer))) - (with-current-buffer buffer (when (or ;; A buffer associated with a file. (and (stringp buffer-file-name) @@ -761,7 +760,7 @@ system.") ;; Revert it when first entry or it was reverted intervals ago. (when (> (float-time (time-since auto-revert--last-time)) auto-revert--lockout-interval) - (auto-revert-handler)))))))))) + (auto-revert-buffer buffer)))))))))) (defun auto-revert--end-lockout (buffer) "End the lockout period after a notification. @@ -770,7 +769,7 @@ If the buffer needs to be reverted, do it now." (with-current-buffer buffer (setq auto-revert--lockout-timer nil) (when auto-revert-notify-modified-p - (auto-revert-handler))))) + (auto-revert-buffer buffer))))) ;;;###autoload (progn @@ -809,36 +808,37 @@ Run BODY." (defun auto-revert-handler () "Revert current buffer, if appropriate. This is an internal function used by Auto-Revert Mode." + (when auto-revert-debug + (message "auto-revert-handler %S" (current-buffer))) (let* ((buffer (current-buffer)) size ;; Tramp caches the file attributes. Setting ;; `remote-file-name-inhibit-cache' forces Tramp to reread ;; the values. (remote-file-name-inhibit-cache t) (revert - (if buffer-file-name - (and (or auto-revert-remote-files - (not (file-remote-p buffer-file-name))) - (or (not auto-revert-notify-watch-descriptor) - auto-revert-notify-modified-p) - (not (memq (current-buffer) inhibit-auto-revert-buffers)) - (if auto-revert-tail-mode - (and (file-readable-p buffer-file-name) - (/= auto-revert-tail-pos - (setq size - (file-attribute-size - (file-attributes buffer-file-name))))) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t))) - (and (or auto-revert-mode - global-auto-revert-non-file-buffers) - (not (memq (current-buffer) inhibit-auto-revert-buffers)) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t)))) + (and (or auto-revert-remote-files + (not (file-remote-p default-directory))) + (or (not auto-revert-notify-watch-descriptor) + auto-revert-notify-modified-p) + (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (if (and buffer-file-name auto-revert-tail-mode) + (and (file-readable-p buffer-file-name) + (/= auto-revert-tail-pos + (setq size + (file-attribute-size + (file-attributes buffer-file-name))))) + (and (or auto-revert-mode auto-revert--global-mode) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t))))) eob eoblist) + (when (timerp auto-revert--lockout-timer) + (cancel-timer auto-revert--lockout-timer)) (setq auto-revert-notify-modified-p nil - auto-revert--last-time (current-time)) + auto-revert--last-time + (if revert (current-time) auto-revert--last-time) + auto-revert--lockout-timer nil) + (when revert (when (and auto-revert-verbose (not (eq revert 'fast))) diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el index 0a1c44d3673..3de909911b4 100644 --- a/lisp/net/tramp-archive.el +++ b/lisp/net/tramp-archive.el @@ -557,7 +557,7 @@ A variable `foo-archive' (or `archive') will be bound to the archive name part of FILENAME, assuming `foo' (or nil) is the value of VAR. OTOH, the variable `foo-hop' (or `hop') won't be offered." - (declare (debug (form symbolp body)) + (declare (debug (form symbolp &rest body)) (indent 2)) (let ((bindings (mapcar diff --git a/lisp/net/tramp-message.el b/lisp/net/tramp-message.el index cf75d60e32f..0ef76061081 100644 --- a/lisp/net/tramp-message.el +++ b/lisp/net/tramp-message.el @@ -452,7 +452,7 @@ an input event arrives. The other arguments are passed to `tramp-error'." BODY is executed like wrapped by `with-demoted-errors'. FORMAT is a format-string containing a %-sequence meaning to substitute the resulting error message." - (declare (indent 2) (debug (symbolp form body))) + (declare (indent 2) (debug (symbolp form &rest body))) (let ((err (make-symbol "err"))) `(condition-case-unless-debug ,err (progn ,@body) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 41fecbf02c6..649f3e7bd37 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -3872,8 +3872,6 @@ Fall back to normal file name handler if no Tramp handler exists." (defun tramp-sh-gio-monitor-process-filter (proc string) "Read output from \"gio monitor\" and add corresponding `file-notify' events." (let ((events (process-get proc 'tramp-events)) - (remote-prefix - (file-remote-p (tramp-get-default-directory (process-buffer proc)))) (rest-string (process-get proc 'tramp-rest-string)) pos) (when rest-string @@ -3935,10 +3933,7 @@ Fall back to normal file name handler if no Tramp handler exists." proc (list (intern-soft (match-string 2 string))) - ;; File names are returned as absolute paths. We - ;; must add the remote prefix. - (concat remote-prefix file) - (when file1 (concat remote-prefix file1))))) + file file1))) (setq string (replace-match "" nil nil string)) ;; Add an Emacs event now. ;; `insert-special-event' exists since Emacs 31. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index d64f6ba37ac..5a19e4be1ae 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -2102,7 +2102,7 @@ of `current-buffer'." "Execute BODY and return the result. In case of an error, raise a `file-missing' error if FILENAME does not exist, otherwise propagate the error." - (declare (indent 2) (debug (symbolp form body))) + (declare (indent 2) (debug (tramp-file-name-p form &rest body))) (let ((err (make-symbol "err"))) `(condition-case ,err (let (signal-hook-function) ,@body) @@ -2141,7 +2141,7 @@ Remaining args are Lisp expressions to be evaluated (inside an implicit If VAR is nil, then we bind `v' to the structure and `method', `user', `domain', `host', `port', `localname', `hop' to the components." - (declare (indent 2) (debug (form symbolp body))) + (declare (indent 2) (debug (form symbolp &rest body))) (let ((bindings (mapcar (lambda (elem) @@ -3601,7 +3601,7 @@ BODY is the backend specific code." (defmacro tramp-skeleton-file-truename (filename &rest body) "Skeleton for `tramp-*-handle-file-truename'. BODY is the backend specific code." - (declare (indent 1) (debug (form body))) + (declare (indent 1) (debug (form &rest body))) ;; Preserve trailing "/". `(funcall (if (directory-name-p ,filename) #'file-name-as-directory #'identity) diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el index 65e60c0464a..56e525e8d81 100644 --- a/lisp/net/trampver.el +++ b/lisp/net/trampver.el @@ -7,7 +7,7 @@ ;; Maintainer: Michael Albinus ;; Keywords: comm, processes ;; Package: tramp -;; Version: 2.8.0 +;; Version: 2.8.1-pre ;; Package-Requires: ((emacs "28.1")) ;; Package-Type: multi ;; URL: https://www.gnu.org/software/tramp/ @@ -40,7 +40,7 @@ ;; ./configure" to change them. ;;;###tramp-autoload -(defconst tramp-version "2.8.0" +(defconst tramp-version "2.8.1-pre" "This version of Tramp.") ;;;###tramp-autoload @@ -76,7 +76,7 @@ ;; Check for Emacs version. (let ((x (if (not (string-version-lessp emacs-version "28.1")) "ok" - (format "Tramp 2.8.0 is not fit for %s" + (format "Tramp 2.8.1-pre is not fit for %s" (replace-regexp-in-string "\n" "" (emacs-version)))))) (unless (string-equal "ok" x) (error "%s" x))) diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el index 4aab58a6f02..9b46ec68b99 100644 --- a/test/lisp/autorevert-tests.el +++ b/test/lisp/autorevert-tests.el @@ -37,7 +37,7 @@ ;; of a respective command. The first command found is used. In ;; order to use a dedicated one, the environment variable ;; $REMOTE_FILE_NOTIFY_LIBRARY shall be set, possible values are -;; "inotifywait", "gio-monitor" and "gvfs-monitor-dir". +;; "inotifywait", "gio" and "smb-notify". ;; Local file-notify libraries are auto-detected during Emacs ;; configuration. This can be changed with a respective configuration @@ -56,22 +56,33 @@ (require 'ert-x) (require 'autorevert) -(setq auto-revert-debug nil +(setq auth-source-cache-expiry nil + auth-source-save-behavior nil + auto-revert-debug nil auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded" auto-revert-stop-on-user-input nil + ert-temp-file-prefix "auto-revert-test" + ert-temp-file-suffix "" file-notify-debug nil - tramp-verbose 0) + password-cache-expiry nil + remote-file-name-inhibit-cache nil + tramp-allow-unsafe-temporary-files t + tramp-cache-read-persistent-data t ;; For auth-sources. + tramp-verbose 0 + ;; When the remote user id is 0, Tramp refuses unsafe temporary files. + tramp-allow-unsafe-temporary-files + (or tramp-allow-unsafe-temporary-files noninteractive)) (defun auto-revert--timeout () "Time to wait for a message." - (+ auto-revert-interval 0.1)) + (+ auto-revert-interval 1)) (defvar auto-revert--messages nil "Used to collect messages issued during a section of a test.") ;; Filter suppressed remote file-notify libraries. (when (stringp (getenv "REMOTE_FILE_NOTIFY_LIBRARY")) - (dolist (lib '("inotifywait" "gio-monitor" "gvfs-monitor-dir")) + (dolist (lib '("inotifywait" "gio" "smb-notify")) (unless (string-equal (getenv "REMOTE_FILE_NOTIFY_LIBRARY") lib) (add-to-list 'tramp-connection-properties `(nil ,lib nil))))) @@ -88,7 +99,6 @@ being the result.") (cons t (ignore-errors (and - (not (getenv "EMACS_HYDRA_CI")) (file-remote-p ert-remote-temporary-file-directory) (file-directory-p ert-remote-temporary-file-directory) (file-writable-p ert-remote-temporary-file-directory)))))) @@ -100,12 +110,13 @@ being the result.") This expects `auto-revert--messages' to be bound by `ert-with-message-capture' before calling." ;; Remote files do not cooperate well with timers. So we count ourselves. - (let ((ct (current-time))) + (let ((ct (current-time)) + (text-quoting-style 'grave)) (while (and (< (float-time (time-subtract nil ct)) (auto-revert--timeout)) - (null (string-match - (format-message - "Reverting buffer `%s'" (buffer-name buffer)) + (null (string-match-p + (rx bol "Reverting buffer `" + (literal (buffer-name buffer)) "'" eol) (or auto-revert--messages "")))) (if (and (or file-notify--library (file-remote-p temporary-file-directory)) @@ -115,10 +126,10 @@ This expects `auto-revert--messages' to be bound by (defmacro auto-revert--deftest-remote (test docstring) "Define ert `TEST-remote' for remote files." - (declare (indent 1)) + (declare (indent 1) (debug (symbolp stringp))) `(ert-deftest ,(intern (concat (symbol-name test) "-remote")) () ,docstring - :tags '(:expensive-test :unstable) + :tags '(:expensive-test) (let ((temporary-file-directory ert-remote-temporary-file-directory) (auto-revert-remote-files t) @@ -132,12 +143,14 @@ This expects `auto-revert--messages' to be bound by (error (message "%s" err) (signal (car err) (cdr err))))))) (defmacro with-auto-revert-test (&rest body) + (declare (debug t)) `(let ((auto-revert-interval-orig auto-revert-interval) (auto-revert--lockout-interval-orig auto-revert--lockout-interval)) (unwind-protect (progn - (customize-set-variable 'auto-revert-interval 0.1) - (setq auto-revert--lockout-interval 0.05) + (unless (file-remote-p temporary-file-directory) + (customize-set-variable 'auto-revert-interval 0.1) + (setq auto-revert--lockout-interval 0.05)) ,@body) (customize-set-variable 'auto-revert-interval auto-revert-interval-orig) (setq auto-revert--lockout-interval auto-revert--lockout-interval-orig)))) @@ -148,6 +161,8 @@ This expects `auto-revert--messages' to be bound by (ert-deftest auto-revert-test00-auto-revert-mode () "Check autorevert for a file." + (file-notify-rm-all-watches) + ;; `auto-revert-buffers' runs every 5". And we must wait, until the ;; file has been reverted. (with-auto-revert-test @@ -160,18 +175,30 @@ This expects `auto-revert--messages' to be bound by (setq buf (find-file-noselect tmpfile)) (with-current-buffer buf (ert-with-message-capture auto-revert--messages - (should (string-equal (buffer-string) "any text")) + (should + (string-equal + (substring-no-properties (buffer-string)) "any text")) ;; `buffer-stale--default-function' checks for ;; `verify-visited-file-modtime'. We must ensure that it - ;; returns nil. + ;; returns nil. We also clean up. (auto-revert-mode 1) (should auto-revert-mode) + ;; There was already an initial call of + ;; `auto-revert-handler', which locks file + ;; notification. Reset this lock. + (setq auto-revert--last-time 0) + (auto-revert-test--wait-for + (lambda () (null auto-revert--lockout-timer)) + (auto-revert--timeout)) - (auto-revert-tests--write-file "another text" tmpfile (pop times)) + (auto-revert-tests--write-file + "another text" tmpfile (pop times)) ;; Check, that the buffer has been reverted. (auto-revert--wait-for-revert buf)) - (should (string-match "another text" (buffer-string))) + (should + (string-match-p + "another text" (substring-no-properties (buffer-string)))) ;; When the buffer is modified, it shall not be reverted. (ert-with-message-capture auto-revert--messages @@ -180,7 +207,9 @@ This expects `auto-revert--messages' to be bound by ;; Check, that the buffer hasn't been reverted. (auto-revert--wait-for-revert buf)) - (should-not (string-match "any text" (buffer-string))))) + (should-not + (string-match-p + "any text" (substring-no-properties (buffer-string)))))) ;; Exit. (ignore-errors @@ -194,27 +223,35 @@ This expects `auto-revert--messages' to be bound by (ert-deftest auto-revert-test01-auto-revert-several-files () "Check autorevert for several files at once." (skip-unless (executable-find "cp" (file-remote-p temporary-file-directory))) + (file-notify-rm-all-watches) - (ert-with-temp-directory tmpdir1 - (ert-with-temp-directory tmpdir2 - (ert-with-temp-file tmpfile1 - :prefix (expand-file-name "auto-revert-test" tmpdir1) - (ert-with-temp-file tmpfile2 - :prefix (expand-file-name "auto-revert-test" tmpdir1) - (with-auto-revert-test - (let* ((cp (executable-find "cp" (file-remote-p temporary-file-directory))) + (with-auto-revert-test + (ert-with-temp-directory tmpdir1 + :prefix "auto-revert-test-parent" + (ert-with-temp-directory tmpdir2 + :prefix "auto-revert-test-parent" + (ert-with-temp-file tmpfile1 + :prefix (expand-file-name "auto-revert-test" tmpdir1) + (ert-with-temp-file tmpfile2 + :prefix (expand-file-name "auto-revert-test" tmpdir1) + (let* ((cp (executable-find + "cp" (file-remote-p temporary-file-directory))) (times '(120 60 30 15)) buf1 buf2) (unwind-protect (ert-with-message-capture auto-revert--messages - (auto-revert-tests--write-file "any text" tmpfile1 (pop times)) + (auto-revert-tests--write-file + "any text" tmpfile1 (pop times)) (setq buf1 (find-file-noselect tmpfile1)) - (auto-revert-tests--write-file "any text" tmpfile2 (pop times)) + (auto-revert-tests--write-file + "any text" tmpfile2 (pop times)) (setq buf2 (find-file-noselect tmpfile2)) (dolist (buf (list buf1 buf2)) (with-current-buffer buf - (should (string-equal (buffer-string) "any text")) + (should + (string-equal + (substring-no-properties (buffer-string)) "any text")) ;; `buffer-stale--default-function' checks for ;; `verify-visited-file-modtime'. We must ensure that ;; it returns nil. @@ -236,14 +273,17 @@ This expects `auto-revert--messages' to be bound by ;; The following shell command is not portable on all ;; platforms, unfortunately. (shell-command - (format "%s -f %s/* %s" - cp (file-local-name tmpdir2) (file-local-name tmpdir1))) + (format "%s -f %s/* %s" cp + (file-local-name tmpdir2) (file-local-name tmpdir1))) ;; Check, that the buffers have been reverted. (dolist (buf (list buf1 buf2)) (with-current-buffer buf (auto-revert--wait-for-revert buf) - (should (string-match "another text" (buffer-string)))))) + (should + (string-match-p + "another text" + (substring-no-properties (buffer-string))))))) ;; Exit. (ignore-errors @@ -257,16 +297,11 @@ This expects `auto-revert--messages' to be bound by ;; This is inspired by Bug#23276. (ert-deftest auto-revert-test02-auto-revert-deleted-file () "Check autorevert for a deleted file." - ;; Repeated unpredictable failures, bug#32645. - :tags '(:unstable) - ;; Unlikely to be hydra-specific? - ;; (skip-when (getenv "EMACS_HYDRA_CI")) + (file-notify-rm-all-watches) + (with-auto-revert-test (ert-with-temp-file tmpfile - (let (;; Try to catch bug#32645. - (auto-revert-debug (getenv "EMACS_HYDRA_CI")) - (file-notify-debug (getenv "EMACS_HYDRA_CI")) - (times '(120 60 30 15)) + (let ((times '(120 60 30 15)) buf desc) (unwind-protect (progn @@ -275,7 +310,9 @@ This expects `auto-revert--messages' to be bound by (with-current-buffer buf (should-not (file-notify-valid-p auto-revert-notify-watch-descriptor)) - (should (string-equal (buffer-string) "any text")) + (should + (string-equal + (substring-no-properties (buffer-string)) "any text")) ;; `buffer-stale--default-function' checks for ;; `verify-visited-file-modtime'. We must ensure that ;; it returns nil. @@ -289,51 +326,47 @@ This expects `auto-revert--messages' to be bound by 'before-revert-hook (lambda () (when auto-revert-debug - (message "%s deleted" buffer-file-name)) + (message "before-revert-hook %s deleted" buffer-file-name)) (delete-file buffer-file-name)) nil t) (ert-with-message-capture auto-revert--messages - (auto-revert-tests--write-file "another text" tmpfile (pop times)) + (auto-revert-tests--write-file + "another text" tmpfile (pop times)) (should (eq desc auto-revert-notify-watch-descriptor)) (auto-revert--wait-for-revert buf)) ;; Check, that the buffer hasn't been reverted. File ;; notification should be disabled, falling back to ;; polling. - (should (string-match "any text" (buffer-string))) - ;; With w32notify, and on emba, the `stopped' events are not sent. - (or (eq file-notify--library 'w32notify) - (getenv "EMACS_EMBA_CI") - (should-not - ;; The auto-revert timer is wont to establish a new - ;; watch soon after the previous descriptor is - ;; destroyed, which not unnaturally interferes with - ;; our testing for its destruction, since descriptor - ;; IDs are reused. Therefore, test the identity of - ;; the previous descriptor, not just its validity. - (and (eq desc auto-revert-notify-watch-descriptor) - (file-notify-valid-p auto-revert-notify-watch-descriptor)))) + (should + (string-match-p + "any text" (substring-no-properties (buffer-string)))) ;; Once the file has been recreated, the buffer shall be ;; reverted. (kill-local-variable 'before-revert-hook) (ert-with-message-capture auto-revert--messages - (auto-revert-tests--write-file "another text" tmpfile (pop times)) + (auto-revert-tests--write-file + "another text" tmpfile (pop times)) (auto-revert--wait-for-revert buf)) ;; Check, that the buffer has been reverted. - (should (string-match "another text" (buffer-string))) + (should + (string-match-p + "another text" (substring-no-properties (buffer-string)))) ;; When file notification is used, it must be reenabled ;; after recreation of the file. We cannot expect that ;; the descriptor is the same, so we just check the ;; existence. - (should (eq (null desc) (null auto-revert-notify-watch-descriptor))) + (should + (eq (null desc) (null auto-revert-notify-watch-descriptor))) ;; An empty file shall still be reverted. (ert-with-message-capture auto-revert--messages (auto-revert-tests--write-file "" tmpfile (pop times)) (auto-revert--wait-for-revert buf)) ;; Check, that the buffer has been reverted. - (should (string-equal "" (buffer-string))))) + (should + (string-equal "" (substring-no-properties (buffer-string)))))) ;; Exit. (ignore-errors @@ -345,6 +378,9 @@ This expects `auto-revert--messages' to be bound by (ert-deftest auto-revert-test03-auto-revert-tail-mode () "Check autorevert tail mode." + (file-notify-rm-all-watches) + + (with-auto-revert-test ;; `auto-revert-buffers' runs every 5". And we must wait, until the ;; file has been reverted. (ert-with-temp-file tmpfile @@ -365,69 +401,90 @@ This expects `auto-revert--messages' to be bound by (set-buffer-modified-p nil) ;; Modify file. - (auto-revert-tests--write-file "another text" tmpfile (pop times) 'append) + (auto-revert-tests--write-file + "another text" tmpfile (pop times) 'append) ;; Check, that the buffer has been reverted. (auto-revert--wait-for-revert buf) (should - (string-match "modified text\nanother text" (buffer-string))))) + (string-match-p + "modified text\nanother text" + (substring-no-properties (buffer-string)))))) ;; Exit. - (ignore-errors (kill-buffer buf)))))) + (ignore-errors (kill-buffer buf))))))) (auto-revert--deftest-remote auto-revert-test03-auto-revert-tail-mode "Check remote autorevert tail mode.") (ert-deftest auto-revert-test04-auto-revert-mode-dired () "Check autorevert for dired." + (file-notify-rm-all-watches) + ;; `auto-revert-buffers' runs every 5". And we must wait, until the ;; file has been reverted. (with-auto-revert-test - (ert-with-temp-file tmpfile - (let* ((name (file-name-nondirectory tmpfile)) - (times '(30)) - buf) - (unwind-protect - (progn - (setq buf (dired-noselect temporary-file-directory)) - (with-current-buffer buf - ;; `buffer-stale--default-function' checks for - ;; `verify-visited-file-modtime'. We must ensure that it - ;; returns nil. - (auto-revert-mode 1) - (should auto-revert-mode) - (should - (string-match name (substring-no-properties (buffer-string)))) - ;; If we don't sleep for a while, this test fails on - ;; MS-Windows. - (if (eq system-type 'windows-nt) - (sleep-for 0.5)) - - (ert-with-message-capture auto-revert--messages - ;; Delete file. - (delete-file tmpfile) - (auto-revert--wait-for-revert buf)) - (if (eq system-type 'windows-nt) - (sleep-for 1)) - ;; Check, that the buffer has been reverted. - (should-not - (string-match name (substring-no-properties (buffer-string)))) - - (ert-with-message-capture auto-revert--messages - ;; Make dired buffer modified. Check, that the buffer has - ;; been still reverted. - (set-buffer-modified-p t) - (auto-revert-tests--write-file "any text" tmpfile (pop times)) + (ert-with-temp-directory tmpdir + :prefix "auto-revert-test-parent" + (ert-with-temp-file tmpfile + :prefix (expand-file-name "auto-revert-test" tmpdir) + (let* ((name (file-name-nondirectory tmpfile)) + (times '(30)) + buf) + (unwind-protect + (progn + (setq buf (dired-noselect tmpdir)) + (with-current-buffer buf + ;; `buffer-stale--default-function' checks for + ;; `verify-visited-file-modtime'. We must ensure that + ;; it returns nil. + (auto-revert-mode 1) + (should auto-revert-mode) + (should + (string-match-p + (rx bow (literal name) eow) + (substring-no-properties (buffer-string)))) + ;; If we don't sleep for a while, this test fails on + ;; MS-Windows. + (if (eq system-type 'windows-nt) + (sleep-for 0.5)) + + ;; File stamps of remote files have an accuracy of 1 + ;; second. Wait a little bit. + (when (file-remote-p tmpfile) + (sleep-for (auto-revert--timeout))) + (ert-with-message-capture auto-revert--messages + ;; Delete file. + (delete-file tmpfile) + (auto-revert--wait-for-revert buf)) + (if (eq system-type 'windows-nt) + (sleep-for 1)) + ;; Check, that the buffer has been reverted. + (should-not + (string-match-p + (rx bow (literal name) eow) + (substring-no-properties (buffer-string)))) + + ;; File stamps of remote files have an accuracy of 1 + ;; second. Wait a little bit. + (when (file-remote-p tmpfile) + (sleep-for (auto-revert--timeout))) + (ert-with-message-capture auto-revert--messages + ;; Make dired buffer modified. Check, that the + ;; buffer has been still reverted. + (set-buffer-modified-p t) + (auto-revert-tests--write-file "any text" tmpfile (pop times)) + (auto-revert--wait-for-revert buf)) + ;; Check, that the buffer has been reverted. + (should + (string-match-p + (rx bow (literal name) eow) + (substring-no-properties (buffer-string)))))) - (auto-revert--wait-for-revert buf)) - ;; Check, that the buffer has been reverted. - (should - (string-match name (substring-no-properties (buffer-string)))))) - - ;; Exit. - (ignore-errors - (with-current-buffer buf (set-buffer-modified-p nil)) - (kill-buffer buf))))))) + ;; Exit. + (ignore-errors + (with-current-buffer buf (set-buffer-modified-p nil)) + (kill-buffer buf)))))))) (auto-revert--deftest-remote auto-revert-test04-auto-revert-mode-dired "Check remote autorevert for dired.") @@ -439,7 +496,7 @@ This expects `auto-revert--messages' to be bound by (defun auto-revert-test--buffer-string (buffer) "Contents of BUFFER as a string." (with-current-buffer buffer - (buffer-string))) + (substring-no-properties (buffer-string)))) (defun auto-revert-test--wait-for (pred max-wait) "Wait until PRED is true, or MAX-WAIT seconds elapsed." @@ -462,13 +519,15 @@ This expects `auto-revert--messages' to be bound by 'kill-buffer-hook (lambda () (message - "%s killed\n%s" (current-buffer) (with-output-to-string (backtrace)))) + "%S killed\n%s" (current-buffer) (with-output-to-string (backtrace)))) nil 'local)))) (ert-deftest auto-revert-test05-global-notify () "Test `global-auto-revert-mode' without polling." (skip-unless (or file-notify--library (file-remote-p temporary-file-directory))) + (file-notify-rm-all-watches) + (with-auto-revert-test (ert-with-temp-file file-1 (ert-with-temp-file file-2 @@ -484,8 +543,13 @@ This expects `auto-revert--messages' to be bound by (auto-revert-test--instrument-kill-buffer-hook buf-1) (setq buf-2 (find-file-noselect file-2)) (auto-revert-test--instrument-kill-buffer-hook buf-2) + ;; File stamps of remote files have an accuracy of 1 + ;; second. Wait a little bit. + (when (file-remote-p file-1) + (sleep-for (auto-revert--timeout))) (auto-revert-test--write-file "1-a" file-1) - (should (equal (auto-revert-test--buffer-string buf-1) "")) + (should + (string-equal (auto-revert-test--buffer-string buf-1) "")) (global-auto-revert-mode 1) ; Turn it on. @@ -494,15 +558,20 @@ This expects `auto-revert--messages' to be bound by (should (buffer-local-value 'auto-revert-notify-watch-descriptor buf-2)) + ;; Allow for some time to handle notification events. + (auto-revert-test--wait-for-buffer-text + buf-1 "1-a" (auto-revert--timeout)) ;; buf-1 should have been reverted immediately when the mode ;; was enabled. - (should (equal (auto-revert-test--buffer-string buf-1) "1-a")) + (should + (string-equal (auto-revert-test--buffer-string buf-1) "1-a")) ;; Alter a file. (auto-revert-test--write-file "2-a" file-2) ;; Allow for some time to handle notification events. (auto-revert-test--wait-for-buffer-text buf-2 "2-a" 1) - (should (equal (auto-revert-test--buffer-string buf-2) "2-a")) + (should + (string-equal (auto-revert-test--buffer-string buf-2) "2-a")) ;; Visit a file, and modify it on disk. (setq buf-3 (find-file-noselect file-3)) @@ -517,11 +586,13 @@ This expects `auto-revert--messages' to be bound by 'auto-revert-notify-watch-descriptor buf-3)) (auto-revert-test--write-file "3-a" file-3) (auto-revert-test--wait-for-buffer-text buf-3 "3-a" 1) - (should (equal (auto-revert-test--buffer-string buf-3) "3-a")) + (should + (string-equal (auto-revert-test--buffer-string buf-3) "3-a")) ;; Delete a visited file, and re-create it with new contents. (delete-file file-1) - (should (equal (auto-revert-test--buffer-string buf-1) "1-a")) + (should + (string-equal (auto-revert-test--buffer-string buf-1) "1-a")) (auto-revert-test--write-file "1-b" file-1) ;; Since the file is deleted, it needs at least ;; `auto-revert-interval' to recognize the new file, @@ -531,10 +602,12 @@ This expects `auto-revert--messages' to be bound by (should (buffer-local-value 'auto-revert-notify-watch-descriptor buf-1)) - ;; Write a buffer to a new file, then modify the new file on disk. + ;; Write a buffer to a new file, then modify the new + ;; file on disk. (with-current-buffer buf-2 (write-file file-2b)) - (should (equal (auto-revert-test--buffer-string buf-2) "2-a")) + (should + (string-equal (auto-revert-test--buffer-string buf-2) "2-a")) (auto-revert-test--write-file "2-b" file-2b) (auto-revert-test--wait-for-buffer-text buf-2 "2-b" (auto-revert--timeout)) @@ -557,6 +630,8 @@ This expects `auto-revert--messages' to be bound by "Verify that notification follows `write-file' correctly." (skip-unless (or file-notify--library (file-remote-p temporary-file-directory))) + (file-notify-rm-all-watches) + (with-auto-revert-test (ert-with-temp-file file-1 (let* ((auto-revert-use-notify t) @@ -574,10 +649,15 @@ This expects `auto-revert--messages' to be bound by (insert "B") (write-file file-2) + ;; File stamps of remote files have an accuracy of 1 + ;; second. Wait a little bit. + (when (file-remote-p file-1) + (sleep-for (auto-revert--timeout))) (auto-revert-test--write-file "C" file-2) (auto-revert-test--wait-for-buffer-text buf "C" (auto-revert--timeout)) - (should (equal (buffer-string) "C")))) + (should + (string-equal (substring-no-properties (buffer-string)) "C")))) ;; Clean up. (ignore-errors (kill-buffer buf)) @@ -591,7 +671,9 @@ This expects `auto-revert--messages' to be bound by "Check autorevert for several buffers visiting the same file." (skip-unless (or file-notify--library (file-remote-p temporary-file-directory))) - ;; (with-auto-revert-test + (file-notify-rm-all-watches) + + (with-auto-revert-test (ert-with-temp-file tmpfile (let ((auto-revert-use-notify t) (times '(120 60 30 15)) @@ -604,7 +686,9 @@ This expects `auto-revert--messages' to be bound by (auto-revert-tests--write-file "any text" tmpfile (pop times)) (push (find-file-noselect tmpfile) buffers) (with-current-buffer (car buffers) - (should (string-equal (buffer-string) "any text")) + (should + (string-equal + (substring-no-properties (buffer-string)) "any text")) ;; `buffer-stale--default-function' checks for ;; `verify-visited-file-modtime'. We must ensure that ;; it returns nil. @@ -622,7 +706,9 @@ This expects `auto-revert--messages' to be bound by (setq buffers (nreverse buffers)) (dolist (buf buffers) (with-current-buffer buf - (should (string-equal (buffer-string) "any text")) + (should + (string-equal + (substring-no-properties (buffer-string)) "any text")) (if (string-suffix-p "-nil" (buffer-name buf)) (should-not auto-revert-mode) (should auto-revert-mode)))) @@ -632,7 +718,9 @@ This expects `auto-revert--messages' to be bound by (auto-revert--wait-for-revert (car buffers)) (dolist (buf buffers) (with-current-buffer buf - (should (string-equal (buffer-string) "another text")))) + (should + (string-equal + (substring-no-properties (buffer-string)) "another text")))) ;; Disabling autorevert in an indirect buffer does not ;; disable autorevert in the corresponding base buffer. @@ -677,7 +765,9 @@ This expects `auto-revert--messages' to be bound by (dolist (buf buffers) (with-current-buffer buf (insert-file-contents tmpfile 'visit) - (should (string-equal (buffer-string) "any text")) + (should + (string-equal + (substring-no-properties (buffer-string)) "any text")) (auto-revert-mode 1) (should auto-revert-mode))) @@ -686,19 +776,23 @@ This expects `auto-revert--messages' to be bound by (dolist (buf buffers) (auto-revert--wait-for-revert buf) (with-current-buffer buf - (should (string-equal (buffer-string) "another text"))))) + (should + (string-equal + (substring-no-properties (buffer-string)) "another text"))))) ;; Exit. (ignore-errors (dolist (buf buffers) (with-current-buffer buf (set-buffer-modified-p nil)) - (kill-buffer buf)))))));) + (kill-buffer buf)))))))) (auto-revert--deftest-remote auto-revert-test07-auto-revert-several-buffers "Check autorevert for several buffers visiting the same remote file.") (ert-deftest auto-revert-test08-auto-revert-inhibit-auto-revert () "Check the power of `inhibit-auto-revert'." + (file-notify-rm-all-watches) + ;; `auto-revert-buffers' runs every 5". And we must wait, until the ;; file has been reverted. (with-auto-revert-test @@ -715,14 +809,19 @@ This expects `auto-revert--messages' to be bound by (auto-revert-mode 1) (should auto-revert-mode) - (auto-revert-tests--write-file "another text" tmpfile (pop times)) + (auto-revert-tests--write-file + "another text" tmpfile (pop times)) ;; Check, that the buffer hasn't been reverted. (auto-revert--wait-for-revert buf) - (should-not (string-match "another text" (buffer-string)))) + (should-not + (string-match-p + "another text" (substring-no-properties (buffer-string))))) ;; Check, that the buffer has been reverted. (auto-revert--wait-for-revert buf) - (should (string-match "another text" (buffer-string)))))) + (should + (string-match-p + "another text" (substring-no-properties (buffer-string))))))) ;; Exit. (ignore-errors diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el index 1a041b0c46c..506d79ecfb3 100644 --- a/test/lisp/filenotify-tests.el +++ b/test/lisp/filenotify-tests.el @@ -33,11 +33,11 @@ ;; remote host, set this environment variable to "/dev/null" or ;; whatever is appropriate on your system. -;; For the remote file-notify library, Tramp checks for the existence -;; of a respective command. The first command found is used. In -;; order to use a dedicated one, the environment variable +;; For the remote file-notify library, Tramp checks for the existence of +;; a respective command. The first command found is used. In order to +;; use a dedicated one, the environment variable ;; $REMOTE_FILE_NOTIFY_LIBRARY shall be set, possible values are -;; "inotifywait", "gio-monitor", "gvfs-monitor-dir", and "smb-notify". +;; "inotifywait", "gio", and "smb-notify". ;; Local file-notify libraries are auto-detected during Emacs ;; configuration. This can be changed with a respective configuration @@ -58,7 +58,7 @@ ;; Filter suppressed remote file-notify libraries. (when (stringp (getenv "REMOTE_FILE_NOTIFY_LIBRARY")) - (dolist (lib '("inotifywait" "gio-monitor" "gvfs-monitor-dir" "smb-notify")) + (dolist (lib '("inotifywait" "gio" "smb-notify")) (unless (string-equal (getenv "REMOTE_FILE_NOTIFY_LIBRARY") lib) (add-to-list 'tramp-connection-properties `(nil ,lib nil))))) @@ -238,9 +238,9 @@ remote host, or nil." (defun file-notify--test-monitor () "The used monitor for the test, as a symbol. -This returns only for (local) gfilenotify or (remote) gio library; -otherwise it is nil. `file-notify--test-desc' must be a valid -watch descriptor." +This returns only for (local) gfilenotify, (remote) gio or (remote) +smb-notify libraries; otherwise it is nil. `file-notify--test-desc' +must be a valid watch descriptor." ;; We cache the result, because after `file-notify-rm-watch', ;; `gfile-monitor-name' does not return a proper result anymore. ;; But we still need this information. So far, we know the monitors @@ -277,7 +277,7 @@ watch descriptor." (defmacro file-notify--deftest-remote (test docstring &optional unstable) "Define ert `TEST-remote' for remote files. If UNSTABLE is non-nil, the test is tagged as `:unstable'." - (declare (indent 1)) + (declare (indent 1) (debug (symbolp stringp &optional form))) `(ert-deftest ,(intern (concat (symbol-name test) "-remote")) () ,docstring :tags (if ,unstable '(:expensive-test :unstable) '(:expensive-test)) @@ -285,9 +285,6 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." (ert-test (ert-get-test ',test)) vc-handled-backends) (skip-unless (file-notify--test-remote-enabled)) - ;; These tests do not work for remote gio/GInotifyFileMonitor. - ;; Needs further investigation. - (skip-when (string-equal (file-notify--test-library) "gio")) (tramp-cleanup-connection (tramp-dissect-file-name temporary-file-directory) t 'keep-password) (file-notify--test-cleanup) @@ -623,7 +620,7 @@ just an indicator for comparison. Don't wait longer than timeout seconds for the actions to be delivered." - (declare (indent 1) (debug (form body))) + (declare (indent 1) (debug (form &rest body))) `(let* ((actions (if (consp (car ,actions)) ,actions (list ,actions))) (max-length (apply @@ -1615,7 +1612,8 @@ the file watch." "Check that file notification does not use too many resources." :tags '(:expensive-test) (skip-unless (file-notify--test-local-enabled)) - ;; This test is intended for kqueue only. + ;; This test is intended for kqueue only. We cannot check for + ;; GKqueueFileMonitor, because `file-notify--test-desc' is not set yet. (skip-unless (string-equal (file-notify--test-library) "kqueue")) (should diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 4dccc970aa7..1cf010f1d14 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -45,8 +45,8 @@ ;; might be too heavy. Setting $REMOTE_PARALLEL_PROCESSES to a proper ;; value less than 10 could help. -;; This test suite obeys the environment variables $EMACS_HYDRA_CI and -;; $EMACS_EMBA_CI, used on the Emacs CI/CD platforms. +;; This test suite obeys the environment variable $EMACS_EMBA_CI, used +;; on the Emacs CI/CD platforms. ;; The following test tags are used: `:expensive-test', ;; `:tramp-asynchronous-processes' and `:unstable'. @@ -60,6 +60,7 @@ (require 'dired-aux) (require 'tramp) (require 'ert-x) +(require 'filenotify) (require 'tar-mode) (require 'trace) (require 'vc) @@ -121,11 +122,7 @@ (unless (and (null noninteractive) (file-directory-p "~/")) (setenv "HOME" temporary-file-directory)) (format "/mock::%s" temporary-file-directory))) - "Temporary directory for remote file tests.") - - ;; This should happen on hydra only. - (when (getenv "EMACS_HYDRA_CI") - (add-to-list 'tramp-remote-path 'tramp-own-remote-path)))) + "Temporary directory for remote file tests."))) ;; Beautify batch mode. (when noninteractive @@ -2435,8 +2432,7 @@ This checks also `file-name-as-directory', `file-name-directory', ;; Bug#10085. (when (tramp--test-enabled) ;; Packages like tramp-gvfs.el might be disabled. (dolist (non-essential '(nil t)) - ;; We must clear `tramp-default-method'. On hydra, it is "ftp", - ;; which ruins the tests. + ;; We must clear `tramp-default-method'. (let ((tramp-default-method (file-remote-p ert-remote-temporary-file-directory 'method)) (host-port @@ -4911,7 +4907,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (unwind-protect (progn ;; We cannot use "/bin/true" and "/bin/false"; those paths - ;; do not exist on hydra and on MS Windows. + ;; do not exist on MS Windows. (should (zerop (process-file "true"))) (should-not (zerop (process-file "false"))) (should-not (zerop (process-file "binary-does-not-exist"))) @@ -7307,7 +7303,6 @@ This requires restrictions of file name syntax." (ert-deftest tramp-test41-special-characters () "Check special characters in file names." (skip-unless (tramp--test-enabled)) - (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 245s (skip-unless (not (tramp--test-rsync-p))) (skip-unless (not (tramp--test-rclone-p))) (skip-unless (not (or (eq system-type 'darwin) (tramp--test-macos-p)))) @@ -7386,7 +7381,6 @@ This requires restrictions of file name syntax." (ert-deftest tramp-test42-utf8 () "Check UTF8 encoding in file names and file contents." (skip-unless (tramp--test-enabled)) - (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 620s (skip-unless (not (tramp--test-container-p))) (skip-unless (not (tramp--test-rsync-p))) (skip-unless (not (tramp--test-windows-nt-and-out-of-band-p))) @@ -7543,17 +7537,12 @@ process sentinels. They shall not disturb each other." (cond ((ignore-errors (string-to-number (getenv "REMOTE_PARALLEL_PROCESSES")))) - ((getenv "EMACS_HYDRA_CI") 5) (t 10))) ;; PuTTY-based methods can only share up to 10 connections. (tramp-use-connection-share (if (and (tramp--test-putty-p) (>= number-proc 10)) 'suppress (bound-and-true-p tramp-use-connection-share))) - ;; On hydra, timings are bad. - (timer-repeat - (cond - ((getenv "EMACS_HYDRA_CI") 10) - (t 1))) + (timer-repeat 1) ;; This is when all timers start. We check inside the ;; timer function, that we don't exceed timeout. (timer-start (current-time)) @@ -7743,6 +7732,58 @@ process sentinels. They shall not disturb each other." (delete-directory tmp-name) (delete-file (concat tmp-name ".tar.gz")))) +;; More exhaustive tests are performed in filenotify-tests.el, +;; selector "remote". +(ert-deftest tramp-test46-file-notifications () + "Check that Tramp handles file notifications." + (skip-unless (tramp--test-enabled)) + + (let* ((tmp-name (tramp--test-make-temp-name)) + ;(file-notify-debug t) + (desc1 + (ignore-error file-notify-error + (file-notify-add-watch + tmp-name '(change attribute-change) #'ignore))) + (desc2 + (ignore-error file-notify-error + (file-notify-add-watch + ert-remote-temporary-file-directory + '(change attribute-change) #'ignore)))) + (skip-unless (and desc1 desc2)) + + (unwind-protect + (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. + (write-region "foo" nil tmp-name) + (should (file-exists-p tmp-name)) + ;; Modify. + (write-region "foo" nil tmp-name) + (should (file-exists-p tmp-name)) + ;; Delete. + (delete-file tmp-name) + (should-not (file-exists-p tmp-name)) + + (while (read-event nil nil 0.1)) + ;; This has been stopped because the file was deleted. + (should-not (file-notify-valid-p desc1)) + + ;; This is still valid. + (should (file-notify-valid-p desc2)) + (file-notify-rm-watch desc2) + (should-not (file-notify-valid-p desc2))) + + ;; Cleanup. + (ignore-errors (delete-file tmp-name)) + ;; `file-notify-rm-all-watches' exists since Emacs 30.1. + ;; We don't want to see compiler warnings for older Emacsen. + (when (fboundp 'file-notify-rm-all-watches) + (with-no-warnings (file-notify-rm-all-watches)))))) + (ert-deftest tramp-test47-read-password () "Check Tramp password handling." :tags '(:expensive-test) @@ -8320,6 +8361,9 @@ If INTERACTIVE is non-nil, the tests are run interactively." ;; * Check, why direct async processes do not work for ;; `tramp-test45-asynchronous-requests'. +;; Starting with Emacs 29, use `ert-with-temp-file' and +;; `ert-with-temp-directory'. + (provide 'tramp-tests) ;;; tramp-tests.el ends here -- 2.39.5