1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
|
;;; autorevert-tests.el --- Tests of auto-revert -*- lexical-binding: t -*-
;; Copyright (C) 2015-2025 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; This file is part of GNU Emacs.
;;
;; GNU Emacs is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
;; GNU Emacs is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Some of the tests require access to a remote host files. Since
;; this could be problematic, a mock-up connection method "mock" is
;; used. Emulating a remote connection, it simply calls "sh -i".
;; Tramp's file name handlers still run, so this test is sufficient
;; except for connection establishing.
;; If you want to test a real Tramp connection, set
;; $REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to
;; overwrite the default value. If you want to skip tests accessing a
;; 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
;; $REMOTE_FILE_NOTIFY_LIBRARY shall be set, possible values are
;; "inotifywait", "gio-monitor" and "gvfs-monitor-dir".
;; Local file-notify libraries are auto-detected during Emacs
;; configuration. This can be changed with a respective configuration
;; argument, like
;;
;; --with-file-notification=inotify
;; --with-file-notification=kqueue
;; --with-file-notification=gfile
;; --with-file-notification=w32
;; A whole test run can be performed calling the command `auto-revert-test-all'.
;;; Code:
(require 'tramp)
(require 'ert-x)
(require 'autorevert)
(setq auto-revert-debug nil
auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded"
auto-revert-stop-on-user-input nil
file-notify-debug nil
tramp-verbose 0)
(defun auto-revert--timeout ()
"Time to wait for a message."
(+ auto-revert-interval 0.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"))
(unless (string-equal (getenv "REMOTE_FILE_NOTIFY_LIBRARY") lib)
(add-to-list 'tramp-connection-properties `(nil ,lib nil)))))
(defvar auto-revert--test-enabled-remote-checked nil
"Cached result of `auto-revert--test-enabled-remote'.
If the function did run, the value is a cons cell, the `cdr'
being the result.")
(defun auto-revert--test-enabled-remote ()
"Whether remote file access is enabled."
(unless (consp auto-revert--test-enabled-remote-checked)
(setq
auto-revert--test-enabled-remote-checked
(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))))))
;; Return result.
(cdr auto-revert--test-enabled-remote-checked))
(defun auto-revert--wait-for-revert (buffer)
"Wait until a message reports reversion of BUFFER.
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)))
(while (and (< (float-time (time-subtract nil ct))
(auto-revert--timeout))
(null (string-match
(format-message
"Reverting buffer `%s'" (buffer-name buffer))
(or auto-revert--messages ""))))
(if (and (or file-notify--library
(file-remote-p temporary-file-directory))
(with-current-buffer buffer auto-revert-use-notify))
(read-event nil nil 0.05)
(sleep-for 0.05)))))
(defmacro auto-revert--deftest-remote (test docstring)
"Define ert `TEST-remote' for remote files."
(declare (indent 1))
`(ert-deftest ,(intern (concat (symbol-name test) "-remote")) ()
,docstring
:tags '(:expensive-test :unstable)
(let ((temporary-file-directory
ert-remote-temporary-file-directory)
(auto-revert-remote-files t)
(ert-test (ert-get-test ',test))
vc-handled-backends)
(skip-unless (auto-revert--test-enabled-remote))
(tramp-cleanup-connection
(tramp-dissect-file-name temporary-file-directory) nil 'keep-password)
(condition-case err
(funcall (ert-test-body ert-test))
(error (message "%s" err) (signal (car err) (cdr err)))))))
(defmacro with-auto-revert-test (&rest body)
`(let ((auto-revert-interval-orig auto-revert-interval))
(unwind-protect
(progn
(customize-set-variable 'auto-revert-interval 0.1)
,@body)
(customize-set-variable 'auto-revert-interval auto-revert-interval-orig))))
(defun auto-revert-tests--write-file (text file time-delta &optional append)
(write-region text nil file append 'no-message)
(set-file-times file (time-subtract nil time-delta)))
(ert-deftest auto-revert-test00-auto-revert-mode ()
"Check autorevert for a file."
;; `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 ((times '(60 30 15))
buf)
(unwind-protect
(progn
(auto-revert-tests--write-file "any text" tmpfile (pop times))
(setq buf (find-file-noselect tmpfile))
(with-current-buffer buf
(ert-with-message-capture auto-revert--messages
(should (string-equal (buffer-string) "any text"))
;; `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)
(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)))
;; When the buffer is modified, it shall not be reverted.
(ert-with-message-capture auto-revert--messages
(set-buffer-modified-p t)
(auto-revert-tests--write-file "any text" tmpfile (pop times))
;; Check, that the buffer hasn't been reverted.
(auto-revert--wait-for-revert buf))
(should-not (string-match "any text" (buffer-string)))))
;; Exit.
(ignore-errors
(with-current-buffer buf (set-buffer-modified-p nil))
(kill-buffer buf)))))))
(auto-revert--deftest-remote auto-revert-test00-auto-revert-mode
"Check autorevert for a remote file.")
;; This is inspired by Bug#21841.
(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)))
(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)))
(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))
(setq buf1 (find-file-noselect tmpfile1))
(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"))
;; `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)))
;; Modify files. We wait for a second, in order to have
;; another timestamp.
(auto-revert-tests--write-file
"another text"
(expand-file-name (file-name-nondirectory tmpfile1) tmpdir2)
(pop times))
(auto-revert-tests--write-file
"another text"
(expand-file-name (file-name-nondirectory tmpfile2) tmpdir2)
(pop times))
;;(copy-directory tmpdir2 tmpdir1 nil 'copy-contents)
;; Strange, that `copy-directory' does not work as expected.
;; 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)))
;; 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))))))
;; Exit.
(ignore-errors
(dolist (buf (list buf1 buf2))
(with-current-buffer buf (set-buffer-modified-p nil))
(kill-buffer buf)))))))))))
(auto-revert--deftest-remote auto-revert-test01-auto-revert-several-files
"Check autorevert for several remote files at once.")
;; 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"))
(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))
buf desc)
(unwind-protect
(progn
(auto-revert-tests--write-file "any text" tmpfile (pop times))
(setq buf (find-file-noselect tmpfile))
(with-current-buffer buf
(should-not
(file-notify-valid-p auto-revert-notify-watch-descriptor))
(should (string-equal (buffer-string) "any text"))
;; `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)
(setq desc auto-revert-notify-watch-descriptor)
;; Remove file while reverting. We simulate this by
;; modifying `before-revert-hook'.
(add-hook
'before-revert-hook
(lambda ()
(when auto-revert-debug
(message "%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--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
(file-notify-valid-p auto-revert-notify-watch-descriptor)))
;; 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--wait-for-revert buf))
;; Check, that the buffer has been reverted.
(should (string-match "another text" (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)))
;; 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)))))
;; Exit.
(ignore-errors
(with-current-buffer buf (set-buffer-modified-p nil))
(kill-buffer buf)))))))
(auto-revert--deftest-remote auto-revert-test02-auto-revert-deleted-file
"Check autorevert for a deleted remote file.")
(ert-deftest auto-revert-test03-auto-revert-tail-mode ()
"Check autorevert tail mode."
;; `auto-revert-buffers' runs every 5". And we must wait, until the
;; file has been reverted.
(ert-with-temp-file tmpfile
(let ((times '(30 15))
buf)
(unwind-protect
(ert-with-message-capture auto-revert--messages
(auto-revert-tests--write-file "any text" tmpfile (pop times))
(setq buf (find-file-noselect tmpfile))
(with-current-buffer buf
;; `buffer-stale--default-function' checks for
;; `verify-visited-file-modtime'. We must ensure that it
;; returns nil.
(auto-revert-tail-mode 1)
(should auto-revert-tail-mode)
(erase-buffer)
(insert "modified text\n")
(set-buffer-modified-p nil)
;; Modify file.
(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)))))
;; Exit.
(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."
;; `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))))
(ert-with-message-capture auto-revert--messages
;; Delete file.
(delete-file tmpfile)
(auto-revert--wait-for-revert buf))
;; 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))
(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)))))))
(auto-revert--deftest-remote auto-revert-test04-auto-revert-mode-dired
"Check remote autorevert for dired.")
(defun auto-revert-test--write-file (string file)
"Write STRING to FILE."
(write-region string nil file nil 'no-message))
(defun auto-revert-test--buffer-string (buffer)
"Contents of BUFFER as a string."
(with-current-buffer buffer
(buffer-string)))
(defun auto-revert-test--wait-for (pred max-wait)
"Wait until PRED is true, or MAX-WAIT seconds elapsed."
(let ((ct (current-time)))
(while (and (< (float-time (time-subtract nil ct)) max-wait)
(not (funcall pred)))
(read-event nil nil 0.1))))
(defun auto-revert-test--wait-for-buffer-text (buffer string max-wait)
"Wait until BUFFER has the contents STRING, or MAX-WAIT seconds elapsed."
(auto-revert-test--wait-for
(lambda () (string-equal (auto-revert-test--buffer-string buffer) string))
max-wait))
(defun auto-revert-test--instrument-kill-buffer-hook (buffer)
"Instrument local `kill-buffer-hook' with messages."
(when auto-revert-debug
(with-current-buffer buffer
(add-hook
'kill-buffer-hook
(lambda ()
(message
"%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)))
(with-auto-revert-test
(ert-with-temp-file file-1
(ert-with-temp-file file-2
(ert-with-temp-file file-3
(let* ((auto-revert-use-notify t)
(auto-revert-avoid-polling t)
(was-in-global-auto-revert-mode global-auto-revert-mode)
(file-2b (concat file-2 "-b"))
require-final-newline buf-1 buf-2 buf-3)
(unwind-protect
(progn
(setq buf-1 (find-file-noselect file-1))
(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)
(auto-revert-test--write-file "1-a" file-1)
(should (equal (auto-revert-test--buffer-string buf-1) ""))
(global-auto-revert-mode 1) ; Turn it on.
(should (buffer-local-value
'auto-revert-notify-watch-descriptor buf-1))
(should (buffer-local-value
'auto-revert-notify-watch-descriptor buf-2))
;; buf-1 should have been reverted immediately when the mode
;; was enabled.
(should (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"))
;; Visit a file, and modify it on disk.
(setq buf-3 (find-file-noselect file-3))
(auto-revert-test--instrument-kill-buffer-hook buf-3)
;; Newly opened buffers won't be use notification until the
;; first poll cycle; wait for it.
(auto-revert-test--wait-for
(lambda () (buffer-local-value
'auto-revert-notify-watch-descriptor buf-3))
(auto-revert--timeout))
(should (buffer-local-value
'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"))
;; 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"))
(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,
;; while polling. So increase the timeout.
(auto-revert-test--wait-for-buffer-text
buf-1 "1-b" (* 2 (auto-revert--timeout)))
(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.
(with-current-buffer buf-2
(write-file file-2b))
(should (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))
(should (buffer-local-value
'auto-revert-notify-watch-descriptor buf-2)))
;; Clean up.
(unless was-in-global-auto-revert-mode
(global-auto-revert-mode 0)) ; Turn it off.
(dolist (buf (list buf-1 buf-2 buf-3))
(ignore-errors
(with-current-buffer buf (setq-local kill-buffer-hook nil))
(kill-buffer buf)))
(ignore-errors (delete-file file-2b)))))))))
(auto-revert--deftest-remote auto-revert-test05-global-notify
"Test `global-auto-revert-mode' without polling for remote buffers.")
(ert-deftest auto-revert-test06-write-file ()
"Verify that notification follows `write-file' correctly."
(skip-unless (or file-notify--library
(file-remote-p temporary-file-directory)))
(with-auto-revert-test
(ert-with-temp-file file-1
(let* ((auto-revert-use-notify t)
(file-2 (concat file-1 "-2"))
require-final-newline buf)
(unwind-protect
(progn
(setq buf (find-file-noselect file-1))
(with-current-buffer buf
(insert "A")
(save-buffer)
(auto-revert-mode 1)
(insert "B")
(write-file file-2)
(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"))))
;; Clean up.
(ignore-errors (kill-buffer buf))
(ignore-errors (delete-file file-2)))))))
(auto-revert--deftest-remote auto-revert-test06-write-file
"Test `write-file' in `auto-revert-mode' for remote buffers.")
;; This is inspired by Bug#44638, Bug#71424.
(ert-deftest auto-revert-test07-auto-revert-several-buffers ()
"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
(ert-with-temp-file tmpfile
(let ((auto-revert-use-notify t)
(times '(120 60 30 15))
(num-buffers 10)
require-final-newline buffers)
(unwind-protect
;; Check indirect buffers.
(ert-with-message-capture auto-revert--messages
(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"))
;; `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))
(dolist (clone '(clone nil))
(dotimes (i num-buffers)
(push (make-indirect-buffer
(car (last buffers))
(format "%s-%d-%s"
(buffer-file-name (car (last buffers))) i clone)
clone)
buffers)))
(setq buffers (nreverse buffers))
(dolist (buf buffers)
(with-current-buffer buf
(should (string-equal (buffer-string) "any text"))
(if (string-suffix-p "-nil" (buffer-name buf))
(should-not auto-revert-mode)
(should auto-revert-mode))))
(auto-revert-tests--write-file "another text" tmpfile (pop times))
;; Check, that the buffer has been reverted.
(auto-revert--wait-for-revert (car buffers))
(dolist (buf buffers)
(with-current-buffer buf
(should (string-equal (buffer-string) "another text"))))
;; Disabling autorevert in an indirect buffer does not
;; disable autorevert in the corresponding base buffer.
(dolist (buf (cdr buffers))
(with-current-buffer buf
(auto-revert-mode 0)
(should-not auto-revert-mode))
(with-current-buffer (car buffers)
(should
(buffer-local-value
'auto-revert-notify-watch-descriptor (current-buffer)))
(should auto-revert-mode)))
;; Killing an indirect buffer does not disable autorevert in
;; the corresponding base buffer.
(dolist (buf (cdr buffers))
(kill-buffer buf))
(with-current-buffer (car buffers)
(should
(buffer-local-value
'auto-revert-notify-watch-descriptor (current-buffer)))
(should auto-revert-mode)))
;; Exit.
(ignore-errors
(dolist (buf buffers)
(with-current-buffer buf (set-buffer-modified-p nil))
(kill-buffer buf)))
(setq buffers nil)
(ignore-errors (delete-file tmpfile)))
;; Check direct buffers.
(unwind-protect
(ert-with-message-capture auto-revert--messages
(auto-revert-tests--write-file "any text" tmpfile (pop times))
(dotimes (i num-buffers)
(push (generate-new-buffer
(format "%s-%d" (file-name-nondirectory tmpfile) i))
buffers))
(setq buffers (nreverse buffers))
(dolist (buf buffers)
(with-current-buffer buf
(insert-file-contents tmpfile 'visit)
(should (string-equal (buffer-string) "any text"))
(auto-revert-mode 1)
(should auto-revert-mode)))
(auto-revert-tests--write-file "another text" tmpfile (pop times))
;; Check, that the buffers have been reverted.
(dolist (buf buffers)
(auto-revert--wait-for-revert buf)
(with-current-buffer buf
(should (string-equal (buffer-string) "another text")))))
;; Exit.
(ignore-errors
(dolist (buf buffers)
(with-current-buffer buf (set-buffer-modified-p nil))
(kill-buffer buf)))))));)
(auto-revert--deftest-remote auto-revert-test07-auto-revert-several-buffers
"Check autorevert for several buffers visiting the same remote file.")
;; Mark all tests as unstable on Cygwin (bug#49665).
(when (eq system-type 'cygwin)
(dolist (test (apropos-internal "^auto-revert" #'ert-test-boundp))
(setf (ert-test-tags (ert-get-test test))
(cons :unstable (ert-test-tags (ert-get-test test))))))
(defun auto-revert-test-all (&optional interactive)
"Run all tests for \\[auto-revert]."
(interactive "p")
(if interactive
(ert-run-tests-interactively "^auto-revert-")
(ert-run-tests-batch "^auto-revert-")))
(provide 'auto-revert-tests)
;;; autorevert-tests.el ends here
|