diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/automated/file-notify-tests.el | 585 |
1 files changed, 405 insertions, 180 deletions
diff --git a/test/automated/file-notify-tests.el b/test/automated/file-notify-tests.el index 7bf7b0b3d15..de64f5086d2 100644 --- a/test/automated/file-notify-tests.el +++ b/test/automated/file-notify-tests.el | |||
| @@ -61,11 +61,14 @@ | |||
| 61 | (defvar file-notify--test-results nil) | 61 | (defvar file-notify--test-results nil) |
| 62 | (defvar file-notify--test-event nil) | 62 | (defvar file-notify--test-event nil) |
| 63 | (defvar file-notify--test-events nil) | 63 | (defvar file-notify--test-events nil) |
| 64 | (defvar file-notify--test-expected-events nil) | ||
| 65 | 64 | ||
| 66 | (defun file-notify--test-timeout () | 65 | (defun file-notify--test-timeout () |
| 67 | "Timeout to wait for arriving events, in seconds." | 66 | "Timeout to wait for arriving events, in seconds." |
| 68 | (if (file-remote-p temporary-file-directory) 6 3)) | 67 | (cond |
| 68 | ((file-remote-p temporary-file-directory) 6) | ||
| 69 | ((string-equal (file-notify--test-library) "w32notify") 20) | ||
| 70 | ((eq system-type 'cygwin) 10) | ||
| 71 | (t 3))) | ||
| 69 | 72 | ||
| 70 | (defun file-notify--test-cleanup () | 73 | (defun file-notify--test-cleanup () |
| 71 | "Cleanup after a test." | 74 | "Cleanup after a test." |
| @@ -89,8 +92,7 @@ | |||
| 89 | file-notify--test-tmpfile1 nil | 92 | file-notify--test-tmpfile1 nil |
| 90 | file-notify--test-desc nil | 93 | file-notify--test-desc nil |
| 91 | file-notify--test-results nil | 94 | file-notify--test-results nil |
| 92 | file-notify--test-events nil | 95 | file-notify--test-events nil) |
| 93 | file-notify--test-expected-events nil) | ||
| 94 | (when file-notify--test-event | 96 | (when file-notify--test-event |
| 95 | (error "file-notify--test-event should not be set but bound dynamically"))) | 97 | (error "file-notify--test-event should not be set but bound dynamically"))) |
| 96 | 98 | ||
| @@ -133,6 +135,18 @@ being the result.") | |||
| 133 | ;; Return result. | 135 | ;; Return result. |
| 134 | (cdr file-notify--test-remote-enabled-checked)) | 136 | (cdr file-notify--test-remote-enabled-checked)) |
| 135 | 137 | ||
| 138 | (defun file-notify--test-library () | ||
| 139 | "The used library for the test, as a string. | ||
| 140 | In the remote case, it is the process name which runs on the | ||
| 141 | remote host, or nil." | ||
| 142 | (if (null (file-remote-p temporary-file-directory)) | ||
| 143 | (symbol-name file-notify--library) | ||
| 144 | (and (consp file-notify--test-remote-enabled-checked) | ||
| 145 | (processp (cdr file-notify--test-remote-enabled-checked)) | ||
| 146 | (replace-regexp-in-string | ||
| 147 | "<[[:digit:]]+>\\'" "" | ||
| 148 | (process-name (cdr file-notify--test-remote-enabled-checked)))))) | ||
| 149 | |||
| 136 | (defmacro file-notify--deftest-remote (test docstring) | 150 | (defmacro file-notify--deftest-remote (test docstring) |
| 137 | "Define ert `TEST-remote' for remote files." | 151 | "Define ert `TEST-remote' for remote files." |
| 138 | (declare (indent 1)) | 152 | (declare (indent 1)) |
| @@ -151,12 +165,7 @@ being the result.") | |||
| 151 | "Test availability of `file-notify'." | 165 | "Test availability of `file-notify'." |
| 152 | (skip-unless (file-notify--test-local-enabled)) | 166 | (skip-unless (file-notify--test-local-enabled)) |
| 153 | ;; Report the native library which has been used. | 167 | ;; Report the native library which has been used. |
| 154 | (if (null (file-remote-p temporary-file-directory)) | 168 | (message "Library: `%s'" (file-notify--test-library)) |
| 155 | (message "Local library: `%s'" file-notify--library) | ||
| 156 | (message "Remote command: `%s'" | ||
| 157 | (replace-regexp-in-string | ||
| 158 | "<[[:digit:]]+>\\'" "" | ||
| 159 | (process-name (cdr file-notify--test-remote-enabled-checked))))) | ||
| 160 | (should | 169 | (should |
| 161 | (setq file-notify--test-desc | 170 | (setq file-notify--test-desc |
| 162 | (file-notify-add-watch temporary-file-directory '(change) 'ignore))) | 171 | (file-notify-add-watch temporary-file-directory '(change) 'ignore))) |
| @@ -190,12 +199,13 @@ being the result.") | |||
| 190 | (file-notify-add-watch | 199 | (file-notify-add-watch |
| 191 | temporary-file-directory '(change attribute-change) 'ignore))) | 200 | temporary-file-directory '(change attribute-change) 'ignore))) |
| 192 | (file-notify-rm-watch file-notify--test-desc) | 201 | (file-notify-rm-watch file-notify--test-desc) |
| 193 | ;; The file does not need to exist, just the upper directory. | 202 | (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 194 | (should | 203 | (should |
| 195 | (setq file-notify--test-desc | 204 | (setq file-notify--test-desc |
| 196 | (file-notify-add-watch | 205 | (file-notify-add-watch |
| 197 | file-notify--test-tmpfile '(change attribute-change) 'ignore))) | 206 | file-notify--test-tmpfile '(change attribute-change) 'ignore))) |
| 198 | (file-notify-rm-watch file-notify--test-desc) | 207 | (file-notify-rm-watch file-notify--test-desc) |
| 208 | (delete-file file-notify--test-tmpfile) | ||
| 199 | 209 | ||
| 200 | ;; Check error handling. | 210 | ;; Check error handling. |
| 201 | (should-error (file-notify-add-watch 1 2 3 4) | 211 | (should-error (file-notify-add-watch 1 2 3 4) |
| @@ -236,16 +246,17 @@ is bound somewhere." | |||
| 236 | (should | 246 | (should |
| 237 | (or (string-equal (file-notify--event-file-name file-notify--test-event) | 247 | (or (string-equal (file-notify--event-file-name file-notify--test-event) |
| 238 | file-notify--test-tmpfile) | 248 | file-notify--test-tmpfile) |
| 239 | (string-equal (directory-file-name | 249 | (string-equal (file-notify--event-file-name file-notify--test-event) |
| 240 | (file-name-directory | 250 | file-notify--test-tmpfile1) |
| 241 | (file-notify--event-file-name file-notify--test-event))) | 251 | (string-equal (file-notify--event-file-name file-notify--test-event) |
| 242 | file-notify--test-tmpfile))) | 252 | temporary-file-directory))) |
| 243 | ;; Check the second file name if exists. | 253 | ;; Check the second file name if exists. |
| 244 | (when (eq (nth 1 file-notify--test-event) 'renamed) | 254 | (when (eq (nth 1 file-notify--test-event) 'renamed) |
| 245 | (should | 255 | (should |
| 246 | (string-equal | 256 | (or (string-equal (file-notify--event-file1-name file-notify--test-event) |
| 247 | (file-notify--event-file1-name file-notify--test-event) | 257 | file-notify--test-tmpfile1) |
| 248 | file-notify--test-tmpfile1)))) | 258 | (string-equal (file-notify--event-file1-name file-notify--test-event) |
| 259 | temporary-file-directory))))) | ||
| 249 | 260 | ||
| 250 | (defun file-notify--test-event-handler (event) | 261 | (defun file-notify--test-event-handler (event) |
| 251 | "Run a test over FILE-NOTIFY--TEST-EVENT. | 262 | "Run a test over FILE-NOTIFY--TEST-EVENT. |
| @@ -254,7 +265,7 @@ and the event to `file-notify--test-events'." | |||
| 254 | (let* ((file-notify--test-event event) | 265 | (let* ((file-notify--test-event event) |
| 255 | (result | 266 | (result |
| 256 | (ert-run-test (make-ert-test :body 'file-notify--test-event-test)))) | 267 | (ert-run-test (make-ert-test :body 'file-notify--test-event-test)))) |
| 257 | ;; Do not add temporary files, this would confuse the checks. | 268 | ;; Do not add lock files, this would confuse the checks. |
| 258 | (unless (string-match | 269 | (unless (string-match |
| 259 | (regexp-quote ".#") | 270 | (regexp-quote ".#") |
| 260 | (file-notify--event-file-name file-notify--test-event)) | 271 | (file-notify--event-file-name file-notify--test-event)) |
| @@ -278,137 +289,246 @@ TIMEOUT is the maximum time to wait for, in seconds." | |||
| 278 | 289 | ||
| 279 | (defmacro file-notify--test-with-events (events &rest body) | 290 | (defmacro file-notify--test-with-events (events &rest body) |
| 280 | "Run BODY collecting events and then compare with EVENTS. | 291 | "Run BODY collecting events and then compare with EVENTS. |
| 281 | Don't wait longer than timeout seconds for the events to be delivered." | 292 | EVENTS is either a simple list of events, or a list of lists of |
| 293 | events, which represent different possible results. Don't wait | ||
| 294 | longer than timeout seconds for the events to be delivered." | ||
| 282 | (declare (indent 1)) | 295 | (declare (indent 1)) |
| 283 | (let ((outer (make-symbol "outer"))) | 296 | (let ((outer (make-symbol "outer"))) |
| 284 | `(let ((,outer file-notify--test-events)) | 297 | `(let* ((,outer file-notify--test-events) |
| 285 | (setq file-notify--test-expected-events | 298 | (events (if (consp (car ,events)) ,events (list ,events))) |
| 286 | (append file-notify--test-expected-events ,events)) | 299 | (max-length (apply 'max (mapcar 'length events))) |
| 300 | create-lockfiles result) | ||
| 301 | ;; Flush pending events. | ||
| 302 | (file-notify--wait-for-events | ||
| 303 | (file-notify--test-timeout) | ||
| 304 | (input-pending-p)) | ||
| 287 | (let (file-notify--test-events) | 305 | (let (file-notify--test-events) |
| 288 | ,@body | 306 | ,@body |
| 289 | (file-notify--wait-for-events | 307 | (file-notify--wait-for-events |
| 290 | (file-notify--test-timeout) | 308 | ;; More events need more time. Use some fudge factor. |
| 291 | (= (length ,events) (length file-notify--test-events))) | 309 | (* (ceiling max-length 100) (file-notify--test-timeout)) |
| 292 | (should (equal ,events (mapcar #'cadr file-notify--test-events))) | 310 | (= max-length (length file-notify--test-events))) |
| 311 | ;; One of the possible results shall match. | ||
| 312 | (should | ||
| 313 | (dolist (elt events result) | ||
| 314 | (setq result | ||
| 315 | (or result | ||
| 316 | (equal elt (mapcar #'cadr file-notify--test-events)))))) | ||
| 293 | (setq ,outer (append ,outer file-notify--test-events))) | 317 | (setq ,outer (append ,outer file-notify--test-events))) |
| 294 | (setq file-notify--test-events ,outer)))) | 318 | (setq file-notify--test-events ,outer)))) |
| 295 | 319 | ||
| 296 | (ert-deftest file-notify-test02-events () | 320 | (ert-deftest file-notify-test02-events () |
| 297 | "Check file creation/change/removal notifications." | 321 | "Check file creation/change/removal notifications." |
| 298 | (skip-unless (file-notify--test-local-enabled)) | 322 | (skip-unless (file-notify--test-local-enabled)) |
| 299 | ;; Under cygwin there are so bad timings that it doesn't make sense to test. | ||
| 300 | (skip-unless (not (eq system-type 'cygwin))) | ||
| 301 | |||
| 302 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) | ||
| 303 | file-notify--test-tmpfile1 (file-notify--test-make-temp-name)) | ||
| 304 | 323 | ||
| 305 | (unwind-protect | 324 | (unwind-protect |
| 306 | (progn | 325 | (progn |
| 307 | ;; Check creation, change and deletion. | 326 | ;; Check file creation, change and deletion. It doesn't work |
| 308 | (setq file-notify--test-desc | 327 | ;; for cygwin and kqueue, because we don't use an implicit |
| 309 | (file-notify-add-watch | 328 | ;; directory monitor (kqueue), or the timings are too bad (cygwin). |
| 310 | file-notify--test-tmpfile | 329 | (unless (or (eq system-type 'cygwin) |
| 311 | '(change) 'file-notify--test-event-handler)) | 330 | (string-equal (file-notify--test-library) "kqueue")) |
| 312 | (file-notify--test-with-events '(created changed deleted) | 331 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) |
| 332 | (should | ||
| 333 | (setq file-notify--test-desc | ||
| 334 | (file-notify-add-watch | ||
| 335 | file-notify--test-tmpfile | ||
| 336 | '(change) 'file-notify--test-event-handler))) | ||
| 337 | (file-notify--test-with-events | ||
| 338 | (cond | ||
| 339 | ;; cygwin recognizes only `deleted' and `stopped' events. | ||
| 340 | ((eq system-type 'cygwin) | ||
| 341 | '(deleted stopped)) | ||
| 342 | (t '(created changed deleted stopped))) | ||
| 343 | (write-region | ||
| 344 | "another text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 345 | (read-event nil nil 0.1) | ||
| 346 | (delete-file file-notify--test-tmpfile)) | ||
| 347 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | ||
| 348 | (let (file-notify--test-events) | ||
| 349 | (file-notify-rm-watch file-notify--test-desc))) | ||
| 350 | |||
| 351 | ;; Check file change and deletion. | ||
| 352 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) | ||
| 353 | (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 354 | (should | ||
| 355 | (setq file-notify--test-desc | ||
| 356 | (file-notify-add-watch | ||
| 357 | file-notify--test-tmpfile | ||
| 358 | '(change) 'file-notify--test-event-handler))) | ||
| 359 | (file-notify--test-with-events | ||
| 360 | (cond | ||
| 361 | ;; cygwin recognizes only `deleted' and `stopped' events. | ||
| 362 | ((eq system-type 'cygwin) | ||
| 363 | '(deleted stopped)) | ||
| 364 | ;; inotify and kqueue raise just one `changed' event. | ||
| 365 | ((or (string-equal "inotify" (file-notify--test-library)) | ||
| 366 | (string-equal "kqueue" (file-notify--test-library))) | ||
| 367 | '(changed deleted stopped)) | ||
| 368 | ;; gfilenotify raises one or two `changed' events | ||
| 369 | ;; randomly, no chance to test. So we accept both cases. | ||
| 370 | ((string-equal "gfilenotify" (file-notify--test-library)) | ||
| 371 | '((changed deleted stopped) | ||
| 372 | (changed changed deleted stopped))) | ||
| 373 | (t '(changed changed deleted stopped))) | ||
| 374 | (read-event nil nil 0.1) | ||
| 313 | (write-region | 375 | (write-region |
| 314 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 376 | "another text" nil file-notify--test-tmpfile nil 'no-message) |
| 377 | (read-event nil nil 0.1) | ||
| 315 | (delete-file file-notify--test-tmpfile)) | 378 | (delete-file file-notify--test-tmpfile)) |
| 316 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | 379 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. |
| 317 | (let (file-notify--test-events) | 380 | (let (file-notify--test-events) |
| 318 | (file-notify-rm-watch file-notify--test-desc)) | 381 | (file-notify-rm-watch file-notify--test-desc)) |
| 319 | 382 | ||
| 320 | ;; Check creation, change and deletion. There must be a | 383 | ;; Check file creation, change and deletion when watching a |
| 321 | ;; `stopped' event when deleting the directory. It doesn't | 384 | ;; directory. There must be a `stopped' event when deleting |
| 322 | ;; work for w32notify. | 385 | ;; the directory. |
| 323 | (unless (eq file-notify--library 'w32notify) | 386 | (let ((temporary-file-directory |
| 324 | (make-directory file-notify--test-tmpfile) | 387 | (make-temp-file "file-notify-test-parent" t))) |
| 325 | (setq file-notify--test-desc | 388 | (should |
| 326 | (file-notify-add-watch | 389 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) |
| 327 | file-notify--test-tmpfile | 390 | file-notify--test-desc |
| 328 | '(change) 'file-notify--test-event-handler)) | 391 | (file-notify-add-watch |
| 392 | temporary-file-directory | ||
| 393 | '(change) 'file-notify--test-event-handler))) | ||
| 329 | (file-notify--test-with-events | 394 | (file-notify--test-with-events |
| 330 | ;; There are two `deleted' events, for the file and for | 395 | (cond |
| 331 | ;; the directory. | 396 | ;; w32notify does raise a `stopped' event when a |
| 332 | '(created changed deleted deleted stopped) | 397 | ;; watched directory is deleted. |
| 398 | ((string-equal (file-notify--test-library) "w32notify") | ||
| 399 | '(created changed deleted)) | ||
| 400 | ;; cygwin recognizes only `deleted' and `stopped' events. | ||
| 401 | ((eq system-type 'cygwin) | ||
| 402 | '(deleted stopped)) | ||
| 403 | ;; There are two `deleted' events, for the file and for | ||
| 404 | ;; the directory. Except for kqueue. | ||
| 405 | ((string-equal (file-notify--test-library) "kqueue") | ||
| 406 | '(created changed deleted stopped)) | ||
| 407 | (t '(created changed deleted deleted stopped))) | ||
| 408 | (read-event nil nil 0.1) | ||
| 333 | (write-region | 409 | (write-region |
| 334 | "any text" nil (expand-file-name "foo" file-notify--test-tmpfile) | 410 | "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 335 | nil 'no-message) | 411 | (read-event nil nil 0.1) |
| 336 | (delete-directory file-notify--test-tmpfile 'recursive)) | 412 | (delete-directory temporary-file-directory 'recursive)) |
| 337 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | 413 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. |
| 338 | (let (file-notify--test-events) | 414 | (let (file-notify--test-events) |
| 339 | (file-notify-rm-watch file-notify--test-desc))) | 415 | (file-notify-rm-watch file-notify--test-desc))) |
| 340 | 416 | ||
| 341 | ;; Check copy. | 417 | ;; Check copy of files inside a directory. |
| 342 | (setq file-notify--test-desc | 418 | (let ((temporary-file-directory |
| 343 | (file-notify-add-watch | 419 | (make-temp-file "file-notify-test-parent" t))) |
| 344 | file-notify--test-tmpfile | 420 | (should |
| 345 | '(change) 'file-notify--test-event-handler)) | 421 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) |
| 346 | (should file-notify--test-desc) | 422 | file-notify--test-tmpfile1 (file-notify--test-make-temp-name) |
| 347 | (file-notify--test-with-events | 423 | file-notify--test-desc |
| 348 | ;; w32notify does not distinguish between `changed' and | 424 | (file-notify-add-watch |
| 349 | ;; `attribute-changed'. | 425 | temporary-file-directory |
| 350 | (if (eq file-notify--library 'w32notify) | 426 | '(change) 'file-notify--test-event-handler))) |
| 351 | '(created changed changed deleted) | 427 | (file-notify--test-with-events |
| 352 | '(created changed deleted)) | 428 | (cond |
| 353 | (write-region | 429 | ;; w32notify does not distinguish between `changed' and |
| 354 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 430 | ;; `attribute-changed'. |
| 355 | (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) | 431 | ((string-equal (file-notify--test-library) "w32notify") |
| 356 | ;; The next two events shall not be visible. | 432 | '(created changed created changed changed changed changed |
| 357 | (set-file-modes file-notify--test-tmpfile 000) | 433 | deleted deleted)) |
| 358 | (read-event nil nil 0.1) ; In order to distinguish the events. | 434 | ;; cygwin recognizes only `deleted' and `stopped' events. |
| 359 | (set-file-times file-notify--test-tmpfile '(0 0)) | 435 | ((eq system-type 'cygwin) |
| 360 | (delete-file file-notify--test-tmpfile) | 436 | '(deleted stopped)) |
| 361 | (delete-file file-notify--test-tmpfile1)) | 437 | ;; There are three `deleted' events, for two files and |
| 362 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | 438 | ;; for the directory. Except for kqueue. |
| 363 | (let (file-notify--test-events) | 439 | ((string-equal (file-notify--test-library) "kqueue") |
| 364 | (file-notify-rm-watch file-notify--test-desc)) | 440 | '(created changed created changed deleted stopped)) |
| 441 | (t '(created changed created changed | ||
| 442 | deleted deleted deleted stopped))) | ||
| 443 | (read-event nil nil 0.1) | ||
| 444 | (write-region | ||
| 445 | "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 446 | (read-event nil nil 0.1) | ||
| 447 | (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) | ||
| 448 | ;; The next two events shall not be visible. | ||
| 449 | (read-event nil nil 0.1) | ||
| 450 | (set-file-modes file-notify--test-tmpfile 000) | ||
| 451 | (read-event nil nil 0.1) | ||
| 452 | (set-file-times file-notify--test-tmpfile '(0 0)) | ||
| 453 | (read-event nil nil 0.1) | ||
| 454 | (delete-directory temporary-file-directory 'recursive)) | ||
| 455 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | ||
| 456 | (let (file-notify--test-events) | ||
| 457 | (file-notify-rm-watch file-notify--test-desc))) | ||
| 365 | 458 | ||
| 366 | ;; Check rename. | 459 | ;; Check rename of files inside a directory. |
| 367 | (setq file-notify--test-desc | 460 | (let ((temporary-file-directory |
| 368 | (file-notify-add-watch | 461 | (make-temp-file "file-notify-test-parent" t))) |
| 369 | file-notify--test-tmpfile | 462 | (should |
| 370 | '(change) 'file-notify--test-event-handler)) | 463 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) |
| 371 | (should file-notify--test-desc) | 464 | file-notify--test-tmpfile1 (file-notify--test-make-temp-name) |
| 372 | (file-notify--test-with-events '(created changed renamed) | 465 | file-notify--test-desc |
| 373 | (write-region | 466 | (file-notify-add-watch |
| 374 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 467 | temporary-file-directory |
| 375 | (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) | 468 | '(change) 'file-notify--test-event-handler))) |
| 376 | ;; After the rename, we won't get events anymore. | 469 | (file-notify--test-with-events |
| 377 | (delete-file file-notify--test-tmpfile1)) | 470 | (cond |
| 378 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | 471 | ;; w32notify does not distinguish between `changed' and |
| 379 | (let (file-notify--test-events) | 472 | ;; `attribute-changed'. |
| 380 | (file-notify-rm-watch file-notify--test-desc)) | 473 | ((string-equal (file-notify--test-library) "w32notify") |
| 474 | '(created changed renamed deleted)) | ||
| 475 | ;; cygwin recognizes only `deleted' and `stopped' events. | ||
| 476 | ((eq system-type 'cygwin) | ||
| 477 | '(deleted stopped)) | ||
| 478 | ;; There are two `deleted' events, for the file and for | ||
| 479 | ;; the directory. Except for kqueue. | ||
| 480 | ((string-equal (file-notify--test-library) "kqueue") | ||
| 481 | '(created changed renamed deleted stopped)) | ||
| 482 | (t '(created changed renamed deleted deleted stopped))) | ||
| 483 | (read-event nil nil 0.1) | ||
| 484 | (write-region | ||
| 485 | "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 486 | (read-event nil nil 0.1) | ||
| 487 | (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) | ||
| 488 | ;; After the rename, we won't get events anymore. | ||
| 489 | (read-event nil nil 0.1) | ||
| 490 | (delete-directory temporary-file-directory 'recursive)) | ||
| 491 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | ||
| 492 | (let (file-notify--test-events) | ||
| 493 | (file-notify-rm-watch file-notify--test-desc))) | ||
| 381 | 494 | ||
| 382 | ;; Check attribute change. It doesn't work for w32notify. | 495 | ;; Check attribute change. Does not work for cygwin. |
| 383 | (unless (eq file-notify--library 'w32notify) | 496 | (unless (eq system-type 'cygwin) |
| 384 | (setq file-notify--test-desc | 497 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) |
| 385 | (file-notify-add-watch | 498 | (write-region |
| 386 | file-notify--test-tmpfile | 499 | "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 387 | '(attribute-change) 'file-notify--test-event-handler)) | 500 | (should |
| 388 | (file-notify--test-with-events | 501 | (setq file-notify--test-desc |
| 389 | (if (file-remote-p temporary-file-directory) | 502 | (file-notify-add-watch |
| 390 | ;; In the remote case, `write-region' raises also an | 503 | file-notify--test-tmpfile |
| 391 | ;; `attribute-changed' event. | 504 | '(attribute-change) 'file-notify--test-event-handler))) |
| 392 | '(attribute-changed attribute-changed attribute-changed) | 505 | (file-notify--test-with-events |
| 393 | '(attribute-changed attribute-changed)) | 506 | (cond |
| 394 | ;; We must use short delays between the operations. | 507 | ;; w32notify does not distinguish between `changed' and |
| 395 | ;; Otherwise, not all events arrive us in the remote case. | 508 | ;; `attribute-changed'. |
| 396 | (write-region | 509 | ((string-equal (file-notify--test-library) "w32notify") |
| 397 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 510 | '(changed changed changed changed)) |
| 398 | (read-event nil nil 0.1) | 511 | ;; For kqueue and in the remote case, `write-region' |
| 399 | (set-file-modes file-notify--test-tmpfile 000) | 512 | ;; raises also an `attribute-changed' event. |
| 400 | (read-event nil nil 0.1) | 513 | ((or (string-equal (file-notify--test-library) "kqueue") |
| 401 | (set-file-times file-notify--test-tmpfile '(0 0)) | 514 | (file-remote-p temporary-file-directory)) |
| 402 | (read-event nil nil 0.1) | 515 | '(attribute-changed attribute-changed attribute-changed)) |
| 403 | (delete-file file-notify--test-tmpfile)) | 516 | (t '(attribute-changed attribute-changed))) |
| 517 | (read-event nil nil 0.1) | ||
| 518 | (write-region | ||
| 519 | "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 520 | (read-event nil nil 0.1) | ||
| 521 | (set-file-modes file-notify--test-tmpfile 000) | ||
| 522 | (read-event nil nil 0.1) | ||
| 523 | (set-file-times file-notify--test-tmpfile '(0 0)) | ||
| 524 | (read-event nil nil 0.1) | ||
| 525 | (delete-file file-notify--test-tmpfile)) | ||
| 404 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | 526 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. |
| 405 | (let (file-notify--test-events) | 527 | (let (file-notify--test-events) |
| 406 | (file-notify-rm-watch file-notify--test-desc))) | 528 | (file-notify-rm-watch file-notify--test-desc))) |
| 407 | 529 | ||
| 408 | ;; Check the global sequence again just to make sure that | 530 | ;; Check the global sequence again just to make sure that |
| 409 | ;; `file-notify--test-events' has been set correctly. | 531 | ;; `file-notify--test-events' has been set correctly. |
| 410 | (should (equal (mapcar #'cadr file-notify--test-events) | ||
| 411 | file-notify--test-expected-events)) | ||
| 412 | (should file-notify--test-results) | 532 | (should file-notify--test-results) |
| 413 | (dolist (result file-notify--test-results) | 533 | (dolist (result file-notify--test-results) |
| 414 | (when (ert-test-failed-p result) | 534 | (when (ert-test-failed-p result) |
| @@ -476,28 +596,31 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 476 | (should (string-match "another text" (buffer-string))) | 596 | (should (string-match "another text" (buffer-string))) |
| 477 | 597 | ||
| 478 | ;; Stop file notification. Autorevert shall still work via polling. | 598 | ;; Stop file notification. Autorevert shall still work via polling. |
| 479 | (file-notify-rm-watch auto-revert-notify-watch-descriptor) | 599 | ;; It doesn't work for `w32notify'. |
| 480 | (file-notify--wait-for-events | 600 | (unless (string-equal (file-notify--test-library) "w32notify") |
| 481 | timeout (null auto-revert-use-notify)) | 601 | (file-notify-rm-watch auto-revert-notify-watch-descriptor) |
| 482 | (should-not auto-revert-use-notify) | ||
| 483 | (should-not auto-revert-notify-watch-descriptor) | ||
| 484 | |||
| 485 | ;; Modify file. We wait for two seconds, in order to have | ||
| 486 | ;; another timestamp. One second seems to be too short. | ||
| 487 | (with-current-buffer (get-buffer-create "*Messages*") | ||
| 488 | (narrow-to-region (point-max) (point-max))) | ||
| 489 | (sleep-for 2) | ||
| 490 | (write-region | ||
| 491 | "foo bla" nil file-notify--test-tmpfile nil 'no-message) | ||
| 492 | |||
| 493 | ;; Check, that the buffer has been reverted. | ||
| 494 | (with-current-buffer (get-buffer-create "*Messages*") | ||
| 495 | (file-notify--wait-for-events | 602 | (file-notify--wait-for-events |
| 496 | timeout | 603 | timeout (null auto-revert-use-notify)) |
| 497 | (string-match | 604 | (should-not auto-revert-use-notify) |
| 498 | (format-message "Reverting buffer `%s'." (buffer-name buf)) | 605 | (should-not auto-revert-notify-watch-descriptor) |
| 499 | (buffer-string)))) | 606 | |
| 500 | (should (string-match "foo bla" (buffer-string))))) | 607 | ;; Modify file. We wait for two seconds, in order to |
| 608 | ;; have another timestamp. One second seems to be too | ||
| 609 | ;; short. | ||
| 610 | (with-current-buffer (get-buffer-create "*Messages*") | ||
| 611 | (narrow-to-region (point-max) (point-max))) | ||
| 612 | (sleep-for 2) | ||
| 613 | (write-region | ||
| 614 | "foo bla" nil file-notify--test-tmpfile nil 'no-message) | ||
| 615 | |||
| 616 | ;; Check, that the buffer has been reverted. | ||
| 617 | (with-current-buffer (get-buffer-create "*Messages*") | ||
| 618 | (file-notify--wait-for-events | ||
| 619 | timeout | ||
| 620 | (string-match | ||
| 621 | (format-message "Reverting buffer `%s'." (buffer-name buf)) | ||
| 622 | (buffer-string)))) | ||
| 623 | (should (string-match "foo bla" (buffer-string)))))) | ||
| 501 | 624 | ||
| 502 | ;; Cleanup. | 625 | ;; Cleanup. |
| 503 | (with-current-buffer "*Messages*" (widen)) | 626 | (with-current-buffer "*Messages*" (widen)) |
| @@ -510,51 +633,94 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 510 | (ert-deftest file-notify-test04-file-validity () | 633 | (ert-deftest file-notify-test04-file-validity () |
| 511 | "Check `file-notify-valid-p' for files." | 634 | "Check `file-notify-valid-p' for files." |
| 512 | (skip-unless (file-notify--test-local-enabled)) | 635 | (skip-unless (file-notify--test-local-enabled)) |
| 513 | ;; Under cygwin there are so bad timings that it doesn't make sense to test. | ||
| 514 | (skip-unless (not (eq system-type 'cygwin))) | ||
| 515 | 636 | ||
| 516 | (unwind-protect | 637 | (unwind-protect |
| 517 | (progn | 638 | (progn |
| 518 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) | 639 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) |
| 519 | file-notify--test-desc | 640 | (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 520 | (file-notify-add-watch | 641 | (should |
| 521 | file-notify--test-tmpfile | 642 | (setq file-notify--test-desc |
| 522 | '(change) #'file-notify--test-event-handler)) | 643 | (file-notify-add-watch |
| 523 | (file-notify--test-with-events '(created changed deleted) | 644 | file-notify--test-tmpfile |
| 645 | '(change) #'file-notify--test-event-handler))) | ||
| 646 | (should (file-notify-valid-p file-notify--test-desc)) | ||
| 647 | ;; After calling `file-notify-rm-watch', the descriptor is not | ||
| 648 | ;; valid anymore. | ||
| 649 | (file-notify-rm-watch file-notify--test-desc) | ||
| 650 | (should-not (file-notify-valid-p file-notify--test-desc)) | ||
| 651 | (delete-file file-notify--test-tmpfile)) | ||
| 652 | |||
| 653 | ;; Cleanup. | ||
| 654 | (file-notify--test-cleanup)) | ||
| 655 | |||
| 656 | (unwind-protect | ||
| 657 | (progn | ||
| 658 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) | ||
| 659 | (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 660 | (should | ||
| 661 | (setq file-notify--test-desc | ||
| 662 | (file-notify-add-watch | ||
| 663 | file-notify--test-tmpfile | ||
| 664 | '(change) #'file-notify--test-event-handler))) | ||
| 665 | (file-notify--test-with-events | ||
| 666 | (cond | ||
| 667 | ;; cygwin recognizes only `deleted' and `stopped' events. | ||
| 668 | ((eq system-type 'cygwin) | ||
| 669 | '(deleted stopped)) | ||
| 670 | ;; inotify and kqueue raise just one `changed' event. | ||
| 671 | ((or (string-equal "inotify" (file-notify--test-library)) | ||
| 672 | (string-equal "kqueue" (file-notify--test-library))) | ||
| 673 | '(changed deleted stopped)) | ||
| 674 | ;; gfilenotify raises one or two `changed' events | ||
| 675 | ;; randomly, no chance to test. So we accept both cases. | ||
| 676 | ((string-equal "gfilenotify" (file-notify--test-library)) | ||
| 677 | '((changed deleted stopped) | ||
| 678 | (changed changed deleted stopped))) | ||
| 679 | (t '(changed changed deleted stopped))) | ||
| 524 | (should (file-notify-valid-p file-notify--test-desc)) | 680 | (should (file-notify-valid-p file-notify--test-desc)) |
| 681 | (read-event nil nil 0.1) | ||
| 525 | (write-region | 682 | (write-region |
| 526 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 683 | "another text" nil file-notify--test-tmpfile nil 'no-message) |
| 684 | (read-event nil nil 0.1) | ||
| 527 | (delete-file file-notify--test-tmpfile)) | 685 | (delete-file file-notify--test-tmpfile)) |
| 528 | ;; After deleting the file, the descriptor is still valid. | 686 | ;; After deleting the file, the descriptor is not valid anymore. |
| 529 | (should (file-notify-valid-p file-notify--test-desc)) | 687 | (should-not (file-notify-valid-p file-notify--test-desc)) |
| 530 | ;; After removing the watch, the descriptor must not be valid | 688 | (file-notify-rm-watch file-notify--test-desc)) |
| 531 | ;; anymore. | ||
| 532 | (file-notify-rm-watch file-notify--test-desc) | ||
| 533 | (should-not (file-notify-valid-p file-notify--test-desc))) | ||
| 534 | 689 | ||
| 535 | ;; Cleanup. | 690 | ;; Cleanup. |
| 536 | (file-notify--test-cleanup)) | 691 | (file-notify--test-cleanup)) |
| 537 | 692 | ||
| 538 | (unwind-protect | 693 | (unwind-protect |
| 539 | ;; The batch-mode operation of w32notify is fragile (there's no | 694 | ;; w32notify does not send a `stopped' event when deleting a |
| 540 | ;; input threads to send the message to). | 695 | ;; directory. The test does not work, therefore. |
| 541 | ;(unless (and noninteractive (eq file-notify--library 'w32notify)) | 696 | (unless (string-equal (file-notify--test-library) "w32notify") |
| 542 | (unless (eq file-notify--library 'w32notify) | 697 | (let ((temporary-file-directory |
| 543 | (let ((temporary-file-directory | ||
| 544 | (make-temp-file "file-notify-test-parent" t))) | 698 | (make-temp-file "file-notify-test-parent" t))) |
| 545 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) | 699 | (should |
| 546 | file-notify--test-desc | 700 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) |
| 547 | (file-notify-add-watch | 701 | file-notify--test-desc |
| 548 | file-notify--test-tmpfile | 702 | (file-notify-add-watch |
| 549 | '(change) #'file-notify--test-event-handler)) | 703 | temporary-file-directory |
| 550 | (file-notify--test-with-events '(created changed deleted stopped) | 704 | '(change) #'file-notify--test-event-handler))) |
| 551 | (should (file-notify-valid-p file-notify--test-desc)) | 705 | (file-notify--test-with-events |
| 552 | (write-region | 706 | (cond |
| 553 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 707 | ;; cygwin recognizes only `deleted' and `stopped' events. |
| 708 | ((eq system-type 'cygwin) | ||
| 709 | '(deleted stopped)) | ||
| 710 | ;; There are two `deleted' events, for the file and for | ||
| 711 | ;; the directory. Except for kqueue. | ||
| 712 | ((string-equal (file-notify--test-library) "kqueue") | ||
| 713 | '(created changed deleted stopped)) | ||
| 714 | (t '(created changed deleted deleted stopped))) | ||
| 715 | (should (file-notify-valid-p file-notify--test-desc)) | ||
| 716 | (read-event nil nil 0.1) | ||
| 717 | (write-region | ||
| 718 | "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 719 | (read-event nil nil 0.1) | ||
| 554 | (delete-directory temporary-file-directory t)) | 720 | (delete-directory temporary-file-directory t)) |
| 555 | ;; After deleting the parent directory, the descriptor must | 721 | ;; After deleting the parent directory, the descriptor must |
| 556 | ;; not be valid anymore. | 722 | ;; not be valid anymore. |
| 557 | (should-not (file-notify-valid-p file-notify--test-desc)))) | 723 | (should-not (file-notify-valid-p file-notify--test-desc)))) |
| 558 | 724 | ||
| 559 | ;; Cleanup. | 725 | ;; Cleanup. |
| 560 | (file-notify--test-cleanup))) | 726 | (file-notify--test-cleanup))) |
| @@ -571,10 +737,11 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 571 | (setq file-notify--test-tmpfile | 737 | (setq file-notify--test-tmpfile |
| 572 | (file-name-as-directory (file-notify--test-make-temp-name))) | 738 | (file-name-as-directory (file-notify--test-make-temp-name))) |
| 573 | (make-directory file-notify--test-tmpfile) | 739 | (make-directory file-notify--test-tmpfile) |
| 574 | (setq file-notify--test-desc | 740 | (should |
| 575 | (file-notify-add-watch | 741 | (setq file-notify--test-desc |
| 576 | file-notify--test-tmpfile | 742 | (file-notify-add-watch |
| 577 | '(change) #'file-notify--test-event-handler)) | 743 | file-notify--test-tmpfile |
| 744 | '(change) #'file-notify--test-event-handler))) | ||
| 578 | (should (file-notify-valid-p file-notify--test-desc)) | 745 | (should (file-notify-valid-p file-notify--test-desc)) |
| 579 | ;; After removing the watch, the descriptor must not be valid | 746 | ;; After removing the watch, the descriptor must not be valid |
| 580 | ;; anymore. | 747 | ;; anymore. |
| @@ -590,20 +757,22 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 590 | (unwind-protect | 757 | (unwind-protect |
| 591 | ;; The batch-mode operation of w32notify is fragile (there's no | 758 | ;; The batch-mode operation of w32notify is fragile (there's no |
| 592 | ;; input threads to send the message to). | 759 | ;; input threads to send the message to). |
| 593 | (unless (and noninteractive (eq file-notify--library 'w32notify)) | 760 | (unless (and noninteractive |
| 761 | (string-equal (file-notify--test-library) "w32notify")) | ||
| 594 | (setq file-notify--test-tmpfile | 762 | (setq file-notify--test-tmpfile |
| 595 | (file-name-as-directory (file-notify--test-make-temp-name))) | 763 | (file-name-as-directory (file-notify--test-make-temp-name))) |
| 596 | (make-directory file-notify--test-tmpfile) | 764 | (make-directory file-notify--test-tmpfile) |
| 597 | (setq file-notify--test-desc | 765 | (should |
| 598 | (file-notify-add-watch | 766 | (setq file-notify--test-desc |
| 599 | file-notify--test-tmpfile | 767 | (file-notify-add-watch |
| 600 | '(change) #'file-notify--test-event-handler)) | 768 | file-notify--test-tmpfile |
| 769 | '(change) #'file-notify--test-event-handler))) | ||
| 601 | (should (file-notify-valid-p file-notify--test-desc)) | 770 | (should (file-notify-valid-p file-notify--test-desc)) |
| 602 | ;; After deleting the directory, the descriptor must not be | 771 | ;; After deleting the directory, the descriptor must not be |
| 603 | ;; valid anymore. | 772 | ;; valid anymore. |
| 604 | (delete-directory file-notify--test-tmpfile t) | 773 | (delete-directory file-notify--test-tmpfile t) |
| 605 | (file-notify--wait-for-events | 774 | (file-notify--wait-for-events |
| 606 | (file-notify--test-timeout) | 775 | (file-notify--test-timeout) |
| 607 | (not (file-notify-valid-p file-notify--test-desc))) | 776 | (not (file-notify-valid-p file-notify--test-desc))) |
| 608 | (should-not (file-notify-valid-p file-notify--test-desc))) | 777 | (should-not (file-notify-valid-p file-notify--test-desc))) |
| 609 | 778 | ||
| @@ -613,6 +782,62 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 613 | (file-notify--deftest-remote file-notify-test05-dir-validity | 782 | (file-notify--deftest-remote file-notify-test05-dir-validity |
| 614 | "Check `file-notify-valid-p' via file notification for remote directories.") | 783 | "Check `file-notify-valid-p' via file notification for remote directories.") |
| 615 | 784 | ||
| 785 | (ert-deftest file-notify-test06-many-events () | ||
| 786 | "Check that events are not dropped." | ||
| 787 | :tags '(:expensive-test) | ||
| 788 | (skip-unless (file-notify--test-local-enabled)) | ||
| 789 | ;; Under cygwin events arrive in random order. Impossible to define a test. | ||
| 790 | (skip-unless (not (eq system-type 'cygwin))) | ||
| 791 | |||
| 792 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) | ||
| 793 | (make-directory file-notify--test-tmpfile) | ||
| 794 | (should | ||
| 795 | (setq file-notify--test-desc | ||
| 796 | (file-notify-add-watch | ||
| 797 | file-notify--test-tmpfile | ||
| 798 | '(change) 'file-notify--test-event-handler))) | ||
| 799 | (unwind-protect | ||
| 800 | (let ((n 1000) | ||
| 801 | source-file-list target-file-list | ||
| 802 | (default-directory file-notify--test-tmpfile)) | ||
| 803 | (dotimes (i n) | ||
| 804 | ;; It matters which direction we rename, at least for | ||
| 805 | ;; kqueue. This backend parses directories in alphabetic | ||
| 806 | ;; order (x%d before y%d). So we rename both directions. | ||
| 807 | (if (zerop (mod i 2)) | ||
| 808 | (progn | ||
| 809 | (push (expand-file-name (format "x%d" i)) source-file-list) | ||
| 810 | (push (expand-file-name (format "y%d" i)) target-file-list)) | ||
| 811 | (push (expand-file-name (format "y%d" i)) source-file-list) | ||
| 812 | (push (expand-file-name (format "x%d" i)) target-file-list))) | ||
| 813 | (file-notify--test-with-events (make-list (+ n n) 'created) | ||
| 814 | (let ((source-file-list source-file-list) | ||
| 815 | (target-file-list target-file-list)) | ||
| 816 | (while (and source-file-list target-file-list) | ||
| 817 | (read-event nil nil 0.1) | ||
| 818 | (write-region "" nil (pop source-file-list) nil 'no-message) | ||
| 819 | (read-event nil nil 0.1) | ||
| 820 | (write-region "" nil (pop target-file-list) nil 'no-message)))) | ||
| 821 | (file-notify--test-with-events | ||
| 822 | (cond | ||
| 823 | ;; w32notify fires both `deleted' and `renamed' events. | ||
| 824 | ((string-equal (file-notify--test-library) "w32notify") | ||
| 825 | (let (r) | ||
| 826 | (dotimes (_i n r) | ||
| 827 | (setq r (append '(deleted renamed) r))))) | ||
| 828 | (t (make-list n 'renamed))) | ||
| 829 | (let ((source-file-list source-file-list) | ||
| 830 | (target-file-list target-file-list)) | ||
| 831 | (while (and source-file-list target-file-list) | ||
| 832 | (rename-file (pop source-file-list) (pop target-file-list) t)))) | ||
| 833 | (file-notify--test-with-events (make-list n 'deleted) | ||
| 834 | (dolist (file target-file-list) | ||
| 835 | (delete-file file)))) | ||
| 836 | (file-notify--test-cleanup))) | ||
| 837 | |||
| 838 | (file-notify--deftest-remote file-notify-test06-many-events | ||
| 839 | "Check that events are not dropped for remote directories.") | ||
| 840 | |||
| 616 | (defun file-notify-test-all (&optional interactive) | 841 | (defun file-notify-test-all (&optional interactive) |
| 617 | "Run all tests for \\[file-notify]." | 842 | "Run all tests for \\[file-notify]." |
| 618 | (interactive "p") | 843 | (interactive "p") |
| @@ -623,7 +848,7 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 623 | ;; TODO: | 848 | ;; TODO: |
| 624 | 849 | ||
| 625 | ;; * For w32notify, no stopped events arrive when a directory is removed. | 850 | ;; * For w32notify, no stopped events arrive when a directory is removed. |
| 626 | ;; * Try to handle arriving events under cygwin reliably. | 851 | ;; * Check, why cygwin recognizes only `deleted' and `stopped' events. |
| 627 | 852 | ||
| 628 | (provide 'file-notify-tests) | 853 | (provide 'file-notify-tests) |
| 629 | ;;; file-notify-tests.el ends here | 854 | ;;; file-notify-tests.el ends here |