diff options
| author | Michael Albinus | 2022-01-31 15:26:06 +0100 |
|---|---|---|
| committer | Michael Albinus | 2022-01-31 15:26:06 +0100 |
| commit | 3ca32105d2bd88120e2ecf9a28febc6c78b3eb0d (patch) | |
| tree | 580c1f25689f9caba52f8f4b542671ba32ee3a44 /test/src | |
| parent | 6da021fce86a06a97b0bff76f69aa57759533dc9 (diff) | |
| download | emacs-3ca32105d2bd88120e2ecf9a28febc6c78b3eb0d.tar.gz emacs-3ca32105d2bd88120e2ecf9a28febc6c78b3eb0d.zip | |
Extend filelock-tests.el for bug#53207
* test/src/filelock-tests.el (filelock-tests--fixture): Make it a
defmacro. Adapt callees.
(filelock-tests-unlock-spoiled, filelock-tests-kill-buffer-spoiled):
Simplify.
(filelock-tests-detect-external-change): New test
Diffstat (limited to 'test/src')
| -rw-r--r-- | test/src/filelock-tests.el | 217 |
1 files changed, 122 insertions, 95 deletions
diff --git a/test/src/filelock-tests.el b/test/src/filelock-tests.el index 21478a1a0f2..97642669a0d 100644 --- a/test/src/filelock-tests.el +++ b/test/src/filelock-tests.el | |||
| @@ -31,26 +31,26 @@ | |||
| 31 | (require 'ert-x) | 31 | (require 'ert-x) |
| 32 | (require 'seq) | 32 | (require 'seq) |
| 33 | 33 | ||
| 34 | (defun filelock-tests--fixture (test-function) | 34 | (defmacro filelock-tests--fixture (&rest body) |
| 35 | "Call TEST-FUNCTION under a test fixture. | 35 | "Call BODY under a test fixture. |
| 36 | Create a test directory and a buffer whose `buffer-file-name' and | 36 | Create a test directory and a buffer whose `buffer-file-name' and |
| 37 | `buffer-file-truename' are a file within it, then call | 37 | `buffer-file-truename' are a file within it, then call BODY. |
| 38 | TEST-FUNCTION. Finally, delete the buffer and the test | 38 | Finally, delete the buffer and the test directory." |
| 39 | directory." | 39 | (declare (debug (body))) |
| 40 | (ert-with-temp-directory temp-dir | 40 | `(ert-with-temp-directory temp-dir |
| 41 | (let ((name (concat (file-name-as-directory temp-dir) | 41 | (let ((name (concat (file-name-as-directory temp-dir) |
| 42 | "userfile")) | 42 | "userfile")) |
| 43 | (create-lockfiles t)) | 43 | (create-lockfiles t)) |
| 44 | (with-temp-buffer | 44 | (with-temp-buffer |
| 45 | (setq buffer-file-name name | 45 | (setq buffer-file-name name |
| 46 | buffer-file-truename name) | 46 | buffer-file-truename name) |
| 47 | (unwind-protect | 47 | (unwind-protect |
| 48 | (save-current-buffer | 48 | (save-current-buffer |
| 49 | (funcall test-function)) | 49 | ,@body) |
| 50 | ;; Set `buffer-file-truename' nil to prevent unlocking, | 50 | ;; Set `buffer-file-truename' nil to prevent unlocking, |
| 51 | ;; which might prompt the user and/or signal errors. | 51 | ;; which might prompt the user and/or signal errors. |
| 52 | (setq buffer-file-name nil | 52 | (setq buffer-file-name nil |
| 53 | buffer-file-truename nil)))))) | 53 | buffer-file-truename nil)))))) |
| 54 | 54 | ||
| 55 | (defun filelock-tests--make-lock-name (file-name) | 55 | (defun filelock-tests--make-lock-name (file-name) |
| 56 | "Return the lock file name for FILE-NAME. | 56 | "Return the lock file name for FILE-NAME. |
| @@ -86,105 +86,132 @@ the case)." | |||
| 86 | (ert-deftest filelock-tests-lock-unlock-no-errors () | 86 | (ert-deftest filelock-tests-lock-unlock-no-errors () |
| 87 | "Check that locking and unlocking works without error." | 87 | "Check that locking and unlocking works without error." |
| 88 | (filelock-tests--fixture | 88 | (filelock-tests--fixture |
| 89 | (lambda () | 89 | (should-not (file-locked-p (buffer-file-name))) |
| 90 | (should-not (file-locked-p (buffer-file-name))) | ||
| 91 | 90 | ||
| 92 | ;; inserting text should lock the buffer's file. | 91 | ;; Inserting text should lock the buffer's file. |
| 93 | (insert "this locks the buffer's file") | 92 | (insert "this locks the buffer's file") |
| 94 | (filelock-tests--should-be-locked) | 93 | (filelock-tests--should-be-locked) |
| 95 | (unlock-buffer) | 94 | (unlock-buffer) |
| 96 | (set-buffer-modified-p nil) | 95 | (set-buffer-modified-p nil) |
| 97 | (should-not (file-locked-p (buffer-file-name))) | 96 | (should-not (file-locked-p (buffer-file-name))) |
| 98 | 97 | ||
| 99 | ;; `set-buffer-modified-p' should lock the buffer's file. | 98 | ;; `set-buffer-modified-p' should lock the buffer's file. |
| 100 | (set-buffer-modified-p t) | 99 | (set-buffer-modified-p t) |
| 101 | (filelock-tests--should-be-locked) | 100 | (filelock-tests--should-be-locked) |
| 102 | (unlock-buffer) | 101 | (unlock-buffer) |
| 103 | (should-not (file-locked-p (buffer-file-name))) | 102 | (should-not (file-locked-p (buffer-file-name))) |
| 104 | 103 | ||
| 105 | (should-not (file-locked-p (buffer-file-name)))))) | 104 | (should-not (file-locked-p (buffer-file-name))))) |
| 106 | 105 | ||
| 107 | (ert-deftest filelock-tests-lock-spoiled () | 106 | (ert-deftest filelock-tests-lock-spoiled () |
| 108 | "Check `lock-buffer' ." | 107 | "Check `lock-buffer'." |
| 109 | (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support | 108 | (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support |
| 110 | (filelock-tests--fixture | 109 | (filelock-tests--fixture |
| 111 | (lambda () | 110 | (filelock-tests--spoil-lock-file buffer-file-truename) |
| 112 | (filelock-tests--spoil-lock-file buffer-file-truename) | 111 | ;; FIXME: errors when locking a file are ignored; should they be? |
| 113 | ;; FIXME: errors when locking a file are ignored; should they be? | 112 | (set-buffer-modified-p t) |
| 114 | (set-buffer-modified-p t) | 113 | (filelock-tests--unspoil-lock-file buffer-file-truename) |
| 115 | (filelock-tests--unspoil-lock-file buffer-file-truename) | 114 | (should-not (file-locked-p buffer-file-truename)))) |
| 116 | (should-not (file-locked-p buffer-file-truename))))) | ||
| 117 | 115 | ||
| 118 | (ert-deftest filelock-tests-file-locked-p-spoiled () | 116 | (ert-deftest filelock-tests-file-locked-p-spoiled () |
| 119 | "Check that `file-locked-p' fails if the lockfile is \"spoiled\"." | 117 | "Check that `file-locked-p' fails if the lockfile is \"spoiled\"." |
| 120 | (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support | 118 | (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support |
| 121 | (filelock-tests--fixture | 119 | (filelock-tests--fixture |
| 122 | (lambda () | 120 | (filelock-tests--spoil-lock-file buffer-file-truename) |
| 123 | (filelock-tests--spoil-lock-file buffer-file-truename) | 121 | (let ((err (should-error (file-locked-p (buffer-file-name))))) |
| 124 | (let ((err (should-error (file-locked-p (buffer-file-name))))) | 122 | (should (equal (seq-subseq err 0 2) |
| 125 | (should (equal (seq-subseq err 0 2) | 123 | (if (eq system-type 'windows-nt) |
| 126 | (if (eq system-type 'windows-nt) | 124 | '(permission-denied "Testing file lock") |
| 127 | '(permission-denied "Testing file lock") | 125 | '(file-error "Testing file lock"))))))) |
| 128 | '(file-error "Testing file lock")))))))) | ||
| 129 | 126 | ||
| 130 | (ert-deftest filelock-tests-unlock-spoiled () | 127 | (ert-deftest filelock-tests-unlock-spoiled () |
| 131 | "Check that `unlock-buffer' fails if the lockfile is \"spoiled\"." | 128 | "Check that `unlock-buffer' fails if the lockfile is \"spoiled\"." |
| 132 | (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support | 129 | (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support |
| 133 | (filelock-tests--fixture | 130 | (filelock-tests--fixture |
| 134 | (lambda () | 131 | ;; Set the buffer modified with file locking temporarily disabled. |
| 135 | ;; Set the buffer modified with file locking temporarily | 132 | (let ((create-lockfiles nil)) |
| 136 | ;; disabled. | 133 | (set-buffer-modified-p t)) |
| 137 | (let ((create-lockfiles nil)) | 134 | (should-not (file-locked-p buffer-file-truename)) |
| 138 | (set-buffer-modified-p t)) | 135 | (filelock-tests--spoil-lock-file buffer-file-truename) |
| 139 | (should-not (file-locked-p buffer-file-truename)) | 136 | |
| 140 | (filelock-tests--spoil-lock-file buffer-file-truename) | 137 | ;; Errors from `unlock-buffer' should call |
| 141 | 138 | ;; `userlock--handle-unlock-error' (bug#46397). | |
| 142 | ;; Errors from `unlock-buffer' should call | 139 | (cl-letf (((symbol-function 'userlock--handle-unlock-error) |
| 143 | ;; `userlock--handle-unlock-error' (bug#46397). | 140 | (lambda (err) (signal (car err) (cdr err))))) |
| 144 | (let (errors) | 141 | (should (equal |
| 145 | (cl-letf (((symbol-function 'userlock--handle-unlock-error) | 142 | (if (eq system-type 'windows-nt) |
| 146 | (lambda (err) (push err errors)))) | 143 | '(permission-denied "Unlocking file") |
| 147 | (unlock-buffer)) | 144 | '(file-error "Unlocking file")) |
| 148 | (should (consp errors)) | 145 | (seq-subseq (should-error (unlock-buffer)) 0 2)))))) |
| 149 | (should (equal | ||
| 150 | (if (eq system-type 'windows-nt) | ||
| 151 | '(permission-denied "Unlocking file") | ||
| 152 | '(file-error "Unlocking file")) | ||
| 153 | (seq-subseq (car errors) 0 2))) | ||
| 154 | (should (equal (length errors) 1)))))) | ||
| 155 | 146 | ||
| 156 | (ert-deftest filelock-tests-kill-buffer-spoiled () | 147 | (ert-deftest filelock-tests-kill-buffer-spoiled () |
| 157 | "Check that `kill-buffer' fails if a lockfile is \"spoiled\"." | 148 | "Check that `kill-buffer' fails if a lockfile is \"spoiled\"." |
| 158 | (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support | 149 | (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support |
| 159 | (filelock-tests--fixture | 150 | (filelock-tests--fixture |
| 160 | (lambda () | 151 | ;; Set the buffer modified with file locking temporarily disabled. |
| 161 | ;; Set the buffer modified with file locking temporarily | 152 | (let ((create-lockfiles nil)) |
| 162 | ;; disabled. | 153 | (set-buffer-modified-p t)) |
| 163 | (let ((create-lockfiles nil)) | 154 | (should-not (file-locked-p buffer-file-truename)) |
| 164 | (set-buffer-modified-p t)) | 155 | (filelock-tests--spoil-lock-file buffer-file-truename) |
| 165 | (should-not (file-locked-p buffer-file-truename)) | 156 | |
| 166 | (filelock-tests--spoil-lock-file buffer-file-truename) | 157 | ;; Kill the current buffer. Because the buffer is modified Emacs |
| 167 | 158 | ;; will attempt to unlock it. Temporarily bind `yes-or-no-p' to a | |
| 168 | ;; Kill the current buffer. Because the buffer is modified Emacs | 159 | ;; function that fakes a "yes" answer for the "Buffer modified; |
| 169 | ;; will attempt to unlock it. Temporarily bind `yes-or-no-p' to | 160 | ;; kill anyway?" prompt. |
| 170 | ;; a function that fakes a "yes" answer for the "Buffer modified; | 161 | ;; |
| 171 | ;; kill anyway?" prompt. | 162 | ;; File errors from unlocking files should call |
| 172 | ;; | 163 | ;; `userlock--handle-unlock-error' (bug#46397). |
| 173 | ;; File errors from unlocking files should call | 164 | (cl-letf (((symbol-function 'yes-or-no-p) #'always) |
| 174 | ;; `userlock--handle-unlock-error' (bug#46397). | 165 | ((symbol-function 'userlock--handle-unlock-error) |
| 175 | (let (errors) | 166 | (lambda (err) (signal (car err) (cdr err))))) |
| 167 | (should (equal | ||
| 168 | (if (eq system-type 'windows-nt) | ||
| 169 | '(permission-denied "Unlocking file") | ||
| 170 | '(file-error "Unlocking file")) | ||
| 171 | (seq-subseq (should-error (kill-buffer)) 0 2)))))) | ||
| 172 | |||
| 173 | (ert-deftest filelock-tests-detect-external-change () | ||
| 174 | "Check that an external file modification is reported." | ||
| 175 | (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support | ||
| 176 | (skip-unless (executable-find "touch")) | ||
| 177 | (skip-unless (executable-find "echo")) | ||
| 178 | (dolist (cl '(t nil)) | ||
| 179 | (filelock-tests--fixture | ||
| 180 | (let ((create-lockfiles cl)) | ||
| 181 | (write-region "foo" nil (buffer-file-name)) | ||
| 182 | (revert-buffer nil 'noconfirm) | ||
| 183 | (should-not (file-locked-p (buffer-file-name))) | ||
| 184 | |||
| 185 | ;; Just changing the file modification on disk doesn't hurt, | ||
| 186 | ;; because file contents in buffer and on disk look equal. | ||
| 187 | (shell-command (format "touch %s" (buffer-file-name))) | ||
| 188 | (insert "bar") | ||
| 189 | (when cl (filelock-tests--should-be-locked)) | ||
| 190 | |||
| 191 | ;; Bug#53207: with `create-lockfiles' nil, saving the buffer | ||
| 192 | ;; results in a prompt. | ||
| 176 | (cl-letf (((symbol-function 'yes-or-no-p) | 193 | (cl-letf (((symbol-function 'yes-or-no-p) |
| 177 | (lambda (&rest _) t)) | 194 | (lambda (_) (ert-fail "Test failed unexpectedly")))) |
| 178 | ((symbol-function 'userlock--handle-unlock-error) | 195 | (save-buffer)) |
| 179 | (lambda (err) (push err errors)))) | 196 | (should-not (file-locked-p (buffer-file-name))) |
| 180 | (kill-buffer)) | 197 | |
| 181 | (should (consp errors)) | 198 | ;; Changing the file contents on disk hurts when buffer is |
| 182 | (should (equal | 199 | ;; modified. There shall be a query, which we answer. |
| 183 | (if (eq system-type 'windows-nt) | 200 | ;; *Messages* buffer is checked for prompt. |
| 184 | '(permission-denied "Unlocking file") | 201 | (shell-command (format "echo bar >>%s" (buffer-file-name))) |
| 185 | '(file-error "Unlocking file")) | 202 | (cl-letf (((symbol-function 'read-char-choice) |
| 186 | (seq-subseq (car errors) 0 2))) | 203 | (lambda (prompt &rest _) (message "%s" prompt) ?y))) |
| 187 | (should (equal (length errors) 1)))))) | 204 | (ert-with-message-capture captured-messages |
| 205 | ;; `ask-user-about-supersession-threat' does not work in | ||
| 206 | ;; batch mode, let's simulate interactiveness. | ||
| 207 | (let (noninteractive) | ||
| 208 | (insert "baz")) | ||
| 209 | (should (string-match-p | ||
| 210 | (format | ||
| 211 | "^%s changed on disk; really edit the buffer\\?" | ||
| 212 | (file-name-nondirectory (buffer-file-name))) | ||
| 213 | captured-messages)))) | ||
| 214 | (when cl (filelock-tests--should-be-locked)))))) | ||
| 188 | 215 | ||
| 189 | (provide 'filelock-tests) | 216 | (provide 'filelock-tests) |
| 190 | ;;; filelock-tests.el ends here | 217 | ;;; filelock-tests.el ends here |