From 2782d1e1a1d8945f0efe54091035f1a967f63f44 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Wed, 9 Dec 2020 14:49:58 +0100 Subject: [PATCH] Improve tests for gio file notifications * .gitlab-ci.yml (test-filenotify-gio): Call "make -k". * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-notify-add-watch): Set connection property "gio-file-monitor". * lisp/net/tramp-sh.el (tramp-get-remote-gio-file-monitor): New defun. (tramp-sh-handle-file-notify-add-watch): Use it. * test/lisp/filenotify-tests.el (file-notify--test-read-event): Simplify. (file-notify--test-monitor): Handle also remote "gio monitor". (file-notify-test03-events, file-notify-test04-autorevert) (file-notify-test05-file-validity, file-notify-test08-backup) (file-notify-test09-watched-file-in-watched-dir): Handle GKqueueFileMonitor. --- .gitlab-ci.yml | 2 +- lisp/net/tramp-gvfs.el | 3 ++ lisp/net/tramp-sh.el | 28 ++++++++++++ test/lisp/filenotify-tests.el | 80 ++++++++++++++++++++++++++--------- 4 files changed, 92 insertions(+), 21 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f4e08d59dd0..bab2573c883 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -91,7 +91,7 @@ test-filenotify-gio: - ./autogen.sh autoconf - ./configure --without-makeinfo --with-file-notification=gfile - make bootstrap - - make -C test autorevert-tests filenotify-tests + - make -k -C test autorevert-tests filenotify-tests test-gnustep: stage: test diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index c2028c4908c..1722c53be05 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -1434,6 +1434,9 @@ If FILE-SYSTEM is non-nil, return file system attributes." (unless (process-live-p p) (tramp-error p 'file-notify-error "Monitoring not supported for `%s'" file-name)) + ;; Set "gio-file-monitor" property. We believe, that "gio + ;; monitor" uses polling when applied for mounted files. + (tramp-set-connection-property p "gio-file-monitor" 'GPollFileMonitor) p)))) (defun tramp-gvfs-monitor-process-filter (proc string) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 79a7feae469..98537a100f3 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -3834,6 +3834,10 @@ Fall back to normal file name handler if no Tramp handler exists." (unless (process-live-p p) (tramp-error p 'file-notify-error "Monitoring not supported for `%s'" file-name)) + ;; Set "gio-file-monitor" property if needed. + (when (string-equal (file-name-nondirectory command) "gio") + (tramp-set-connection-property + p "gio-file-monitor" (tramp-get-remote-gio-file-monitor v))) p)))) (defun tramp-sh-gio-monitor-process-filter (proc string) @@ -5753,6 +5757,30 @@ This command is returned only if `delete-by-moving-to-trash' is non-nil." (tramp-message vec 5 "Finding a suitable `gio-monitor' command") (tramp-find-executable vec "gio" (tramp-get-remote-path vec) t t))) +(defun tramp-get-remote-gio-file-monitor (vec) + "Determine remote GFileMonitor." + (with-tramp-connection-property vec "gio-file-monitor" + (with-current-buffer (tramp-get-connection-buffer vec) + (tramp-message vec 5 "Finding the used GFileMonitor") + (when-let ((gio (tramp-get-remote-gio-monitor vec))) + ;; Search for the used FileMonitor. There is no known way to + ;; get this information directly from gio, so we check for + ;; linked libraries of libgio. + (when (tramp-send-command-and-check vec (concat "ldd " gio)) + (goto-char (point-min)) + (when (re-search-forward "\\S-+/libgio\\S-+") + (when (tramp-send-command-and-check + vec (concat "strings " (match-string 0))) + (goto-char (point-min)) + (re-search-forward + (format + "^%s$" + (regexp-opt + '("GFamFileMonitor" "GFenFileMonitor" + "GInotifyFileMonitor" "GKqueueFileMonitor"))) + nil 'noerror) + (intern (match-string 0))))))))) + (defun tramp-get-remote-gvfs-monitor-dir (vec) "Determine remote `gvfs-monitor-dir' command." (with-tramp-connection-property vec "gvfs-monitor-dir" diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el index 268c3185bc6..25017dd3261 100644 --- a/test/lisp/filenotify-tests.el +++ b/test/lisp/filenotify-tests.el @@ -108,11 +108,8 @@ There are different timeouts for local and remote file notification libraries." ;; gio/gpollfilemonitor.c declares POLL_TIME_SECS 5. So we must ;; wait at least this time in the GPollFileMonitor case. A ;; similar timeout seems to be needed in the GFamFileMonitor case, - ;; at least on Cygwin. - ((and (string-equal (file-notify--test-library) "gfilenotify") - (memq (file-notify--test-monitor) - '(GFamFileMonitor GPollFileMonitor))) - 7) + ;; at least on cygwin. + ((memq (file-notify--test-monitor) '(GFamFileMonitor GPollFileMonitor)) 7) ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe") 1) ((file-remote-p temporary-file-directory) 0.1) (t 0.01)))) @@ -264,13 +261,19 @@ This returns only for the local case and gfilenotify; otherwise it is nil. ;; 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. - (unless (file-remote-p temporary-file-directory) - (or (cdr (assq file-notify--test-desc file-notify--test-monitors)) - (when (functionp 'gfile-monitor-name) - (add-to-list 'file-notify--test-monitors - (cons file-notify--test-desc - (gfile-monitor-name file-notify--test-desc))) - (cdr (assq file-notify--test-desc file-notify--test-monitors)))))) + ;; So far, we know the monitors GFamFileMonitor, GFenFileMonitor, + ;; GInotifyFileMonitor, GKqueueFileMonitor and GPollFileMonitor. + (or (cdr (assq file-notify--test-desc file-notify--test-monitors)) + (progn + (add-to-list + 'file-notify--test-monitors + (cons file-notify--test-desc + (if (file-remote-p temporary-file-directory) + (tramp-get-connection-property + file-notify--test-desc "gio-file-monitor" nil) + (and (functionp 'gfile-monitor-name) + (gfile-monitor-name file-notify--test-desc))))) + (cdr (assq file-notify--test-desc file-notify--test-monitors))))) (defmacro file-notify--deftest-remote (test docstring &optional unstable) "Define ert `TEST-remote' for remote files. @@ -457,7 +460,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." (unwind-protect ;; Check, that removing watch descriptors out of order do not - ;; harm. This fails on Cygwin because of timing issues unless a + ;; harm. This fails on cygwin because of timing issues unless a ;; long `sit-for' is added before the call to ;; `file-notify--test-read-event'. (unless (eq system-type 'cygwin) @@ -631,13 +634,15 @@ delivered." (cond ;; gvfs-monitor-dir on cygwin does not detect the ;; `created' event reliably. - ((string-equal - (file-notify--test-library) "gvfs-monitor-dir.exe") + ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe") '((deleted stopped) (created deleted stopped))) ;; cygwin does not raise a `changed' event. ((eq system-type 'cygwin) '(created deleted stopped)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) + '(created deleted stopped)) (t '(created changed deleted stopped))) (write-region "another text" nil file-notify--test-tmpfile nil 'no-message) @@ -668,6 +673,9 @@ delivered." ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe") '((deleted stopped) (changed deleted stopped))) + ;; GKqueueFileMonitor does not report the `changed' event. + ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) + '(deleted stopped)) ;; There could be one or two `changed' events. (t '((changed deleted stopped) (changed changed deleted stopped)))) @@ -718,6 +726,9 @@ delivered." '(created deleted stopped)) ((string-equal (file-notify--test-library) "kqueue") '(created changed deleted stopped)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((equal (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) @@ -767,6 +778,9 @@ delivered." ;; directory are not detected. ((getenv "EMACS_EMBA_CI") '(created changed created changed deleted deleted)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) + '(created created deleted deleted deleted stopped)) (t '(created changed created changed deleted deleted deleted stopped))) (write-region @@ -823,6 +837,9 @@ delivered." '(created created deleted deleted stopped)) ((string-equal (file-notify--test-library) "kqueue") '(created changed renamed deleted stopped)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((equal (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) @@ -859,6 +876,8 @@ delivered." ((string-equal (file-notify--test-library) "w32notify") '((changed changed) (changed changed changed changed))) + ;; GKqueueFileMonitor does not report the `attribute-changed' event. + ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) nil) ;; For kqueue and in the remote case, `write-region' ;; raises also an `attribute-changed' event. ((or (string-equal (file-notify--test-library) "kqueue") @@ -925,6 +944,10 @@ delivered." ;; timeouts. (setq file-notify--test-desc auto-revert-notify-watch-descriptor) + ;; GKqueueFileMonitor does not report the `changed' event. + (skip-unless + (not (equal (file-notify--test-monitor) 'GKqueueFileMonitor))) + ;; Check, that file notification has been used. (should auto-revert-mode) (should auto-revert-use-notify) @@ -956,7 +979,7 @@ delivered." ;; 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. + ;; 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)) @@ -1028,6 +1051,9 @@ delivered." ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe") '((deleted stopped) (changed deleted stopped))) + ;; GKqueueFileMonitor does not report the `changed' event. + ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) + '(deleted stopped)) ;; There could be one or two `changed' events. (t '((changed deleted stopped) (changed changed deleted stopped)))) @@ -1077,6 +1103,9 @@ delivered." '(created deleted stopped)) ((string-equal (file-notify--test-library) "kqueue") '(created changed deleted stopped)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((equal (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) @@ -1254,9 +1283,12 @@ delivered." '(change) #'file-notify--test-event-handler))) (should (file-notify-valid-p file-notify--test-desc)) (file-notify--test-with-actions - ;; There could be one or two `changed' events. - '((changed) - (changed changed)) + (cond + ;; GKqueueFileMonitor does not report the `changed' event. + ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) nil) + ;; 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) @@ -1294,6 +1326,9 @@ delivered." ;; On cygwin we only get the `changed' event. ((eq system-type 'cygwin) '(changed)) + ;; GKqueueFileMonitor does not report the `changed' event. + ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) + '(renamed created)) (t '(renamed created changed))) ;; The file is renamed when creating a backup. It shall ;; still be watched. @@ -1391,7 +1426,12 @@ the file watch." (make-list (/ n 2) 'changed) ;; Just the directory monitor. (make-list (/ n 2) 'created) - (make-list (/ n 2) 'changed))) + (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-read-event) (if (zerop (mod i 2)) -- 2.39.2