filenotify-tests.el 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  1. ;;; filenotify-tests.el --- Tests of file notifications -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
  3. ;; Author: Michael Albinus <michael.albinus@gmx.de>
  4. ;; This program is free software: you can redistribute it and/or
  5. ;; modify it under the terms of the GNU General Public License as
  6. ;; published by the Free Software Foundation, either version 3 of the
  7. ;; License, or (at your option) any later version.
  8. ;;
  9. ;; This program is distributed in the hope that it will be useful, but
  10. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;; General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with this program. If not, see `http://www.gnu.org/licenses/'.
  16. ;;; Commentary:
  17. ;; Some of the tests require access to a remote host files. Since
  18. ;; this could be problematic, a mock-up connection method "mock" is
  19. ;; used. Emulating a remote connection, it simply calls "sh -i".
  20. ;; Tramp's file name handlers still run, so this test is sufficient
  21. ;; except for connection establishing.
  22. ;; If you want to test a real Tramp connection, set
  23. ;; $REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to
  24. ;; overwrite the default value. If you want to skip tests accessing a
  25. ;; remote host, set this environment variable to "/dev/null" or
  26. ;; whatever is appropriate on your system.
  27. ;; A whole test run can be performed calling the command `file-notify-test-all'.
  28. ;;; Code:
  29. (require 'ert)
  30. (require 'filenotify)
  31. (require 'tramp)
  32. ;; There is no default value on w32 systems, which could work out of the box.
  33. (defconst file-notify-test-remote-temporary-file-directory
  34. (cond
  35. ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
  36. ((eq system-type 'windows-nt) null-device)
  37. (t (add-to-list
  38. 'tramp-methods
  39. '("mock"
  40. (tramp-login-program "sh")
  41. (tramp-login-args (("-i")))
  42. (tramp-remote-shell "/bin/sh")
  43. (tramp-remote-shell-args ("-c"))
  44. (tramp-connection-timeout 10)))
  45. (format "/mock::%s" temporary-file-directory)))
  46. "Temporary directory for Tramp tests.")
  47. (defvar file-notify--test-tmpfile nil)
  48. (defvar file-notify--test-tmpfile1 nil)
  49. (defvar file-notify--test-desc nil)
  50. (defvar file-notify--test-desc1 nil)
  51. (defvar file-notify--test-desc2 nil)
  52. (defvar file-notify--test-results nil)
  53. (defvar file-notify--test-event nil)
  54. (defvar file-notify--test-events nil)
  55. (defvar file-notify--test-monitors nil)
  56. (defun file-notify--test-read-event ()
  57. "Read one event.
  58. There are different timeouts for local and remote file notification libraries."
  59. (read-event
  60. nil nil
  61. (cond
  62. ;; gio/gpollfilemonitor.c declares POLL_TIME_SECS 5. So we must
  63. ;; wait at least this time in the GPollFileMonitor case. A
  64. ;; similar timeout seems to be needed in the GFamFileMonitor case,
  65. ;; at least on Cygwin.
  66. ((and (string-equal (file-notify--test-library) "gfilenotify")
  67. (memq (file-notify--test-monitor)
  68. '(GFamFileMonitor GPollFileMonitor)))
  69. 7)
  70. ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe") 1)
  71. ((file-remote-p temporary-file-directory) 0.1)
  72. (t 0.01))))
  73. (defun file-notify--test-timeout ()
  74. "Timeout to wait for arriving a bunch of events, in seconds."
  75. (cond
  76. ((file-remote-p temporary-file-directory) 6)
  77. ((string-equal (file-notify--test-library) "w32notify") 4)
  78. ((eq system-type 'cygwin) 6)
  79. (t 3)))
  80. (defmacro file-notify--wait-for-events (timeout until)
  81. "Wait for and return file notification events until form UNTIL is true.
  82. TIMEOUT is the maximum time to wait for, in seconds."
  83. `(with-timeout (,timeout (ignore))
  84. (while (null ,until)
  85. (file-notify--test-read-event))))
  86. (defun file-notify--test-no-descriptors ()
  87. "Check that `file-notify-descriptors' is an empty hash table.
  88. Return nil when any other file notification watch is still active."
  89. ;; Give read events a last chance.
  90. (file-notify--wait-for-events
  91. (file-notify--test-timeout)
  92. (zerop (hash-table-count file-notify-descriptors)))
  93. ;; Now check.
  94. (zerop (hash-table-count file-notify-descriptors)))
  95. (defun file-notify--test-no-descriptors-explainer ()
  96. "Explain why `file-notify--test-no-descriptors' fails."
  97. (let ((result (list "Watch descriptor(s) existent:")))
  98. (maphash
  99. (lambda (key value) (push (cons key value) result))
  100. file-notify-descriptors)
  101. (nreverse result)))
  102. (put 'file-notify--test-no-descriptors 'ert-explainer
  103. 'file-notify--test-no-descriptors-explainer)
  104. (defun file-notify--test-cleanup-p ()
  105. "Check, that the test has cleaned up the environment as much as needed."
  106. ;; `file-notify--test-event' should not be set but bound
  107. ;; dynamically.
  108. (should-not file-notify--test-event)
  109. ;; The test should have cleaned up this already. Let's check
  110. ;; nevertheless.
  111. (should (file-notify--test-no-descriptors)))
  112. (defun file-notify--test-cleanup ()
  113. "Cleanup after a test."
  114. (file-notify-rm-watch file-notify--test-desc)
  115. (file-notify-rm-watch file-notify--test-desc1)
  116. (file-notify-rm-watch file-notify--test-desc2)
  117. (ignore-errors
  118. (delete-file (file-newest-backup file-notify--test-tmpfile)))
  119. (ignore-errors
  120. (if (file-directory-p file-notify--test-tmpfile)
  121. (delete-directory file-notify--test-tmpfile 'recursive)
  122. (delete-file file-notify--test-tmpfile)))
  123. (ignore-errors
  124. (if (file-directory-p file-notify--test-tmpfile1)
  125. (delete-directory file-notify--test-tmpfile1 'recursive)
  126. (delete-file file-notify--test-tmpfile1)))
  127. (ignore-errors
  128. (when (file-remote-p temporary-file-directory)
  129. (tramp-cleanup-connection
  130. (tramp-dissect-file-name temporary-file-directory) nil 'keep-password)))
  131. (setq file-notify--test-tmpfile nil
  132. file-notify--test-tmpfile1 nil
  133. file-notify--test-desc nil
  134. file-notify--test-desc1 nil
  135. file-notify--test-desc2 nil
  136. file-notify--test-results nil
  137. file-notify--test-events nil
  138. file-notify--test-monitors nil))
  139. (setq password-cache-expiry nil
  140. tramp-verbose 0
  141. tramp-message-show-message nil)
  142. ;; This shall happen on hydra only.
  143. (when (getenv "NIX_STORE")
  144. (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
  145. ;; We do not want to try and fail `file-notify-add-watch'.
  146. (defun file-notify--test-local-enabled ()
  147. "Whether local file notification is enabled.
  148. This is needed for local `temporary-file-directory' only, in the
  149. remote case we return always t."
  150. (or file-notify--library
  151. (file-remote-p temporary-file-directory)))
  152. (defvar file-notify--test-remote-enabled-checked nil
  153. "Cached result of `file-notify--test-remote-enabled'.
  154. If the function did run, the value is a cons cell, the `cdr'
  155. being the result.")
  156. (defun file-notify--test-remote-enabled ()
  157. "Whether remote file notification is enabled."
  158. (unless (consp file-notify--test-remote-enabled-checked)
  159. (let (desc)
  160. (ignore-errors
  161. (and
  162. (file-remote-p file-notify-test-remote-temporary-file-directory)
  163. (file-directory-p file-notify-test-remote-temporary-file-directory)
  164. (file-writable-p file-notify-test-remote-temporary-file-directory)
  165. (setq desc
  166. (file-notify-add-watch
  167. file-notify-test-remote-temporary-file-directory
  168. '(change) #'ignore))))
  169. (setq file-notify--test-remote-enabled-checked (cons t desc))
  170. (when desc (file-notify-rm-watch desc))))
  171. ;; Return result.
  172. (cdr file-notify--test-remote-enabled-checked))
  173. (defun file-notify--test-library ()
  174. "The used library for the test, as a string.
  175. In the remote case, it is the process name which runs on the
  176. remote host, or nil."
  177. (if (null (file-remote-p temporary-file-directory))
  178. (symbol-name file-notify--library)
  179. (and (consp file-notify--test-remote-enabled-checked)
  180. (processp (cdr file-notify--test-remote-enabled-checked))
  181. (replace-regexp-in-string
  182. "<[[:digit:]]+>\\'" ""
  183. (process-name (cdr file-notify--test-remote-enabled-checked))))))
  184. (defun file-notify--test-monitor ()
  185. "The used monitor for the test, as a symbol.
  186. This returns only for the local case and gfilenotify; otherwise it is nil.
  187. `file-notify--test-desc' must be a valid watch descriptor."
  188. ;; We cache the result, because after `file-notify-rm-watch',
  189. ;; `gfile-monitor-name' does not return a proper result anymore.
  190. ;; But we still need this information.
  191. (unless (file-remote-p temporary-file-directory)
  192. (or (cdr (assq file-notify--test-desc file-notify--test-monitors))
  193. (when (functionp 'gfile-monitor-name)
  194. (add-to-list 'file-notify--test-monitors
  195. (cons file-notify--test-desc
  196. (gfile-monitor-name file-notify--test-desc)))
  197. (cdr (assq file-notify--test-desc file-notify--test-monitors))))))
  198. (defmacro file-notify--deftest-remote (test docstring)
  199. "Define ert `TEST-remote' for remote files."
  200. (declare (indent 1))
  201. `(ert-deftest ,(intern (concat (symbol-name test) "-remote")) ()
  202. ,docstring
  203. :tags '(:expensive-test)
  204. (let* ((temporary-file-directory
  205. file-notify-test-remote-temporary-file-directory)
  206. (ert-test (ert-get-test ',test)))
  207. (skip-unless (file-notify--test-remote-enabled))
  208. (tramp-cleanup-connection
  209. (tramp-dissect-file-name temporary-file-directory) nil 'keep-password)
  210. (funcall (ert-test-body ert-test)))))
  211. (ert-deftest file-notify-test00-availability ()
  212. "Test availability of `file-notify'."
  213. (skip-unless (file-notify--test-local-enabled))
  214. (unwind-protect
  215. (progn
  216. ;; Report the native library which has been used.
  217. (message "Library: `%s'" (file-notify--test-library))
  218. (should
  219. (setq file-notify--test-desc
  220. (file-notify-add-watch
  221. temporary-file-directory '(change) #'ignore)))
  222. (when (file-notify--test-monitor)
  223. (message "Monitor: `%s'" (file-notify--test-monitor)))
  224. (file-notify-rm-watch file-notify--test-desc)
  225. ;; The environment shall be cleaned up.
  226. (file-notify--test-cleanup-p))
  227. ;; Cleanup.
  228. (file-notify--test-cleanup)))
  229. (file-notify--deftest-remote file-notify-test00-availability
  230. "Test availability of `file-notify' for remote files.")
  231. (ert-deftest file-notify-test01-add-watch ()
  232. "Check `file-notify-add-watch'."
  233. (skip-unless (file-notify--test-local-enabled))
  234. (unwind-protect
  235. (progn
  236. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
  237. file-notify--test-tmpfile1
  238. (format
  239. "%s/%s" file-notify--test-tmpfile (md5 (current-time-string))))
  240. ;; Check, that different valid parameters are accepted.
  241. (should
  242. (setq file-notify--test-desc
  243. (file-notify-add-watch
  244. temporary-file-directory '(change) #'ignore)))
  245. (file-notify-rm-watch file-notify--test-desc)
  246. (should
  247. (setq file-notify--test-desc
  248. (file-notify-add-watch
  249. temporary-file-directory '(attribute-change) #'ignore)))
  250. (file-notify-rm-watch file-notify--test-desc)
  251. (should
  252. (setq file-notify--test-desc
  253. (file-notify-add-watch
  254. temporary-file-directory '(change attribute-change) #'ignore)))
  255. (file-notify-rm-watch file-notify--test-desc)
  256. (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
  257. (should
  258. (setq file-notify--test-desc
  259. (file-notify-add-watch
  260. file-notify--test-tmpfile '(change attribute-change) #'ignore)))
  261. (file-notify-rm-watch file-notify--test-desc)
  262. (delete-file file-notify--test-tmpfile)
  263. ;; Check error handling.
  264. (should-error (file-notify-add-watch 1 2 3 4)
  265. :type 'wrong-number-of-arguments)
  266. (should
  267. (equal (should-error
  268. (file-notify-add-watch 1 2 3))
  269. '(wrong-type-argument 1)))
  270. (should
  271. (equal (should-error
  272. (file-notify-add-watch temporary-file-directory 2 3))
  273. '(wrong-type-argument 2)))
  274. (should
  275. (equal (should-error
  276. (file-notify-add-watch temporary-file-directory '(change) 3))
  277. '(wrong-type-argument 3)))
  278. ;; The upper directory of a file must exist.
  279. (should
  280. (equal (should-error
  281. (file-notify-add-watch
  282. file-notify--test-tmpfile1
  283. '(change attribute-change) #'ignore))
  284. `(file-notify-error
  285. "Directory does not exist" ,file-notify--test-tmpfile)))
  286. ;; The environment shall be cleaned up.
  287. (file-notify--test-cleanup-p))
  288. ;; Cleanup.
  289. (file-notify--test-cleanup)))
  290. (file-notify--deftest-remote file-notify-test01-add-watch
  291. "Check `file-notify-add-watch' for remote files.")
  292. (defun file-notify--test-event-test ()
  293. "Ert test function to be called by `file-notify--test-event-handler'.
  294. We cannot pass arguments, so we assume that `file-notify--test-event'
  295. is bound somewhere."
  296. ;; Check the descriptor.
  297. (should (equal (car file-notify--test-event) file-notify--test-desc))
  298. ;; Check the file name.
  299. (should
  300. (string-prefix-p
  301. (file-notify--event-watched-file file-notify--test-event)
  302. (file-notify--event-file-name file-notify--test-event)))
  303. ;; Check the second file name if exists.
  304. (when (eq (nth 1 file-notify--test-event) 'renamed)
  305. (should
  306. (string-prefix-p
  307. (file-notify--event-watched-file file-notify--test-event)
  308. (file-notify--event-file1-name file-notify--test-event)))))
  309. (defun file-notify--test-event-handler (event)
  310. "Run a test over FILE-NOTIFY--TEST-EVENT.
  311. For later analysis, append the test result to `file-notify--test-results'
  312. and the event to `file-notify--test-events'."
  313. (let* ((file-notify--test-event event)
  314. (result
  315. (ert-run-test (make-ert-test :body 'file-notify--test-event-test))))
  316. ;; Do not add lock files, this would confuse the checks.
  317. (unless (string-match
  318. (regexp-quote ".#")
  319. (file-notify--event-file-name file-notify--test-event))
  320. ;;(message "file-notify--test-event-handler result: %s event: %S"
  321. ;;(null (ert-test-failed-p result)) file-notify--test-event)
  322. (setq file-notify--test-events
  323. (append file-notify--test-events `(,file-notify--test-event))
  324. file-notify--test-results
  325. (append file-notify--test-results `(,result))))))
  326. (defun file-notify--test-make-temp-name ()
  327. "Create a temporary file name for test."
  328. (expand-file-name
  329. (make-temp-name "file-notify-test") temporary-file-directory))
  330. (defun file-notify--test-with-events-check (events)
  331. "Check whether received events match one of the EVENTS alternatives."
  332. (let (result)
  333. (dolist (elt events result)
  334. (setq result
  335. (or result
  336. (if (eq (car elt) :random)
  337. (equal (sort (cdr elt) 'string-lessp)
  338. (sort (mapcar #'cadr file-notify--test-events)
  339. 'string-lessp))
  340. (equal elt (mapcar #'cadr file-notify--test-events))))))))
  341. (defun file-notify--test-with-events-explainer (events)
  342. "Explain why `file-notify--test-with-events-check' fails."
  343. (if (null (cdr events))
  344. (format "Received events do not match expected events\n%s\n%s"
  345. (mapcar #'cadr file-notify--test-events) (car events))
  346. (format
  347. "Received events do not match any sequence of expected events\n%s\n%s"
  348. (mapcar #'cadr file-notify--test-events) events)))
  349. (put 'file-notify--test-with-events-check 'ert-explainer
  350. 'file-notify--test-with-events-explainer)
  351. (defmacro file-notify--test-with-events (events &rest body)
  352. "Run BODY collecting events and then compare with EVENTS.
  353. EVENTS is either a simple list of events, or a list of lists of
  354. events, which represent different possible results. The first
  355. event of a list could be the pseudo event `:random', which is
  356. just an indicator for comparison.
  357. Don't wait longer than timeout seconds for the events to be
  358. delivered."
  359. (declare (indent 1))
  360. `(let* ((events (if (consp (car ,events)) ,events (list ,events)))
  361. (max-length
  362. (apply
  363. 'max
  364. (mapcar
  365. (lambda (x) (length (if (eq (car x) :random) (cdr x) x)))
  366. events)))
  367. create-lockfiles)
  368. ;; Flush pending events.
  369. (file-notify--test-read-event)
  370. (file-notify--wait-for-events
  371. (file-notify--test-timeout)
  372. (not (input-pending-p)))
  373. (setq file-notify--test-events nil
  374. file-notify--test-results nil)
  375. ,@body
  376. (file-notify--wait-for-events
  377. ;; More events need more time. Use some fudge factor.
  378. (* (ceiling max-length 100) (file-notify--test-timeout))
  379. (= max-length (length file-notify--test-events)))
  380. ;; Check the result sequence just to make sure that all events
  381. ;; are as expected.
  382. (dolist (result file-notify--test-results)
  383. (when (ert-test-failed-p result)
  384. (ert-fail
  385. (cadr (ert-test-result-with-condition-condition result)))))
  386. ;; One of the possible event sequences shall match.
  387. (should (file-notify--test-with-events-check events))))
  388. (ert-deftest file-notify-test02-events ()
  389. "Check file creation/change/removal notifications."
  390. (skip-unless (file-notify--test-local-enabled))
  391. (unwind-protect
  392. (progn
  393. ;; Check file creation, change and deletion. It doesn't work
  394. ;; for kqueue, because we don't use an implicit directory
  395. ;; monitor.
  396. (unless (string-equal (file-notify--test-library) "kqueue")
  397. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
  398. (should
  399. (setq file-notify--test-desc
  400. (file-notify-add-watch
  401. file-notify--test-tmpfile
  402. '(change) #'file-notify--test-event-handler)))
  403. (file-notify--test-with-events
  404. (cond
  405. ;; gvfs-monitor-dir on cygwin does not detect the
  406. ;; `created' event reliably.
  407. ((string-equal
  408. (file-notify--test-library) "gvfs-monitor-dir.exe")
  409. '((deleted stopped)
  410. (created deleted stopped)))
  411. ;; cygwin does not raise a `changed' event.
  412. ((eq system-type 'cygwin)
  413. '(created deleted stopped))
  414. (t '(created changed deleted stopped)))
  415. (write-region
  416. "another text" nil file-notify--test-tmpfile nil 'no-message)
  417. (file-notify--test-read-event)
  418. (delete-file file-notify--test-tmpfile))
  419. (file-notify-rm-watch file-notify--test-desc))
  420. ;; Check file change and deletion.
  421. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
  422. (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
  423. (should
  424. (setq file-notify--test-desc
  425. (file-notify-add-watch
  426. file-notify--test-tmpfile
  427. '(change) #'file-notify--test-event-handler)))
  428. (file-notify--test-with-events
  429. (cond
  430. ;; gvfs-monitor-dir on cygwin does not detect the
  431. ;; `changed' event reliably.
  432. ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
  433. '((deleted stopped)
  434. (changed deleted stopped)))
  435. ;; There could be one or two `changed' events.
  436. (t '((changed deleted stopped)
  437. (changed changed deleted stopped))))
  438. (write-region
  439. "another text" nil file-notify--test-tmpfile nil 'no-message)
  440. (file-notify--test-read-event)
  441. (delete-file file-notify--test-tmpfile))
  442. (file-notify-rm-watch file-notify--test-desc)
  443. ;; Check file creation, change and deletion when watching a
  444. ;; directory. There must be a `stopped' event when deleting
  445. ;; the directory.
  446. (let ((temporary-file-directory
  447. (make-temp-file "file-notify-test-parent" t)))
  448. (should
  449. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
  450. file-notify--test-desc
  451. (file-notify-add-watch
  452. temporary-file-directory
  453. '(change) #'file-notify--test-event-handler)))
  454. (file-notify--test-with-events
  455. (cond
  456. ;; w32notify does not raise `deleted' and `stopped'
  457. ;; events for the watched directory.
  458. ((string-equal (file-notify--test-library) "w32notify")
  459. '(created changed deleted))
  460. ;; gvfs-monitor-dir on cygwin does not detect the
  461. ;; `created' event reliably.
  462. ((string-equal
  463. (file-notify--test-library) "gvfs-monitor-dir.exe")
  464. '((deleted stopped)
  465. (created deleted stopped)))
  466. ;; There are two `deleted' events, for the file and for
  467. ;; the directory. Except for cygwin and kqueue. And
  468. ;; cygwin does not raise a `changed' event.
  469. ((eq system-type 'cygwin)
  470. '(created deleted stopped))
  471. ((string-equal (file-notify--test-library) "kqueue")
  472. '(created changed deleted stopped))
  473. (t '(created changed deleted deleted stopped)))
  474. (write-region
  475. "any text" nil file-notify--test-tmpfile nil 'no-message)
  476. (file-notify--test-read-event)
  477. (delete-directory temporary-file-directory 'recursive))
  478. (file-notify-rm-watch file-notify--test-desc))
  479. ;; Check copy of files inside a directory.
  480. (let ((temporary-file-directory
  481. (make-temp-file "file-notify-test-parent" t)))
  482. (should
  483. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
  484. file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
  485. file-notify--test-desc
  486. (file-notify-add-watch
  487. temporary-file-directory
  488. '(change) #'file-notify--test-event-handler)))
  489. (file-notify--test-with-events
  490. (cond
  491. ;; w32notify does not distinguish between `changed' and
  492. ;; `attribute-changed'. It does not raise `deleted'
  493. ;; and `stopped' events for the watched directory.
  494. ((string-equal (file-notify--test-library) "w32notify")
  495. '(created changed created changed
  496. changed changed changed
  497. deleted deleted))
  498. ;; gvfs-monitor-dir on cygwin does not detect the
  499. ;; `created' event reliably.
  500. ((string-equal
  501. (file-notify--test-library) "gvfs-monitor-dir.exe")
  502. '((deleted stopped)
  503. (created created deleted stopped)))
  504. ;; There are three `deleted' events, for two files and
  505. ;; for the directory. Except for cygwin and kqueue.
  506. ((eq system-type 'cygwin)
  507. '(created created changed changed deleted stopped))
  508. ((string-equal (file-notify--test-library) "kqueue")
  509. '(created changed created changed deleted stopped))
  510. (t '(created changed created changed
  511. deleted deleted deleted stopped)))
  512. (write-region
  513. "any text" nil file-notify--test-tmpfile nil 'no-message)
  514. (file-notify--test-read-event)
  515. (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1)
  516. ;; The next two events shall not be visible.
  517. (file-notify--test-read-event)
  518. (set-file-modes file-notify--test-tmpfile 000)
  519. (file-notify--test-read-event)
  520. (set-file-times file-notify--test-tmpfile '(0 0))
  521. (file-notify--test-read-event)
  522. (delete-directory temporary-file-directory 'recursive))
  523. (file-notify-rm-watch file-notify--test-desc))
  524. ;; Check rename of files inside a directory.
  525. (let ((temporary-file-directory
  526. (make-temp-file "file-notify-test-parent" t)))
  527. (should
  528. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
  529. file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
  530. file-notify--test-desc
  531. (file-notify-add-watch
  532. temporary-file-directory
  533. '(change) #'file-notify--test-event-handler)))
  534. (file-notify--test-with-events
  535. (cond
  536. ;; w32notify does not raise `deleted' and `stopped'
  537. ;; events for the watched directory.
  538. ((string-equal (file-notify--test-library) "w32notify")
  539. '(created changed renamed deleted))
  540. ;; gvfs-monitor-dir on cygwin does not detect the
  541. ;; `created' event reliably.
  542. ((string-equal
  543. (file-notify--test-library) "gvfs-monitor-dir.exe")
  544. '((deleted stopped)
  545. (created deleted stopped)))
  546. ;; There are two `deleted' events, for the file and for
  547. ;; the directory. Except for cygwin and kqueue. And
  548. ;; cygwin raises `created' and `deleted' events instead
  549. ;; of a `renamed' event.
  550. ((eq system-type 'cygwin)
  551. '(created created deleted deleted stopped))
  552. ((string-equal (file-notify--test-library) "kqueue")
  553. '(created changed renamed deleted stopped))
  554. (t '(created changed renamed deleted deleted stopped)))
  555. (write-region
  556. "any text" nil file-notify--test-tmpfile nil 'no-message)
  557. (file-notify--test-read-event)
  558. (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1)
  559. ;; After the rename, we won't get events anymore.
  560. (file-notify--test-read-event)
  561. (delete-directory temporary-file-directory 'recursive))
  562. (file-notify-rm-watch file-notify--test-desc))
  563. ;; Check attribute change. Does not work for cygwin.
  564. (unless (eq system-type 'cygwin)
  565. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
  566. (write-region
  567. "any text" nil file-notify--test-tmpfile nil 'no-message)
  568. (should
  569. (setq file-notify--test-desc
  570. (file-notify-add-watch
  571. file-notify--test-tmpfile
  572. '(attribute-change) #'file-notify--test-event-handler)))
  573. (file-notify--test-with-events
  574. (cond
  575. ;; w32notify does not distinguish between `changed' and
  576. ;; `attribute-changed'. Under MS Windows 7, we get
  577. ;; four `changed' events, and under MS Windows 10 just
  578. ;; two. Strange.
  579. ((string-equal (file-notify--test-library) "w32notify")
  580. '((changed changed)
  581. (changed changed changed changed)))
  582. ;; For kqueue and in the remote case, `write-region'
  583. ;; raises also an `attribute-changed' event.
  584. ((or (string-equal (file-notify--test-library) "kqueue")
  585. (file-remote-p temporary-file-directory))
  586. '(attribute-changed attribute-changed attribute-changed))
  587. (t '(attribute-changed attribute-changed)))
  588. (write-region
  589. "any text" nil file-notify--test-tmpfile nil 'no-message)
  590. (file-notify--test-read-event)
  591. (set-file-modes file-notify--test-tmpfile 000)
  592. (file-notify--test-read-event)
  593. (set-file-times file-notify--test-tmpfile '(0 0))
  594. (file-notify--test-read-event)
  595. (delete-file file-notify--test-tmpfile))
  596. (file-notify-rm-watch file-notify--test-desc))
  597. ;; The environment shall be cleaned up.
  598. (file-notify--test-cleanup-p))
  599. ;; Cleanup.
  600. (file-notify--test-cleanup)))
  601. (file-notify--deftest-remote file-notify-test02-events
  602. "Check file creation/change/removal notifications for remote files.")
  603. (require 'autorevert)
  604. (setq auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded"
  605. auto-revert-remote-files t
  606. auto-revert-stop-on-user-input nil)
  607. (ert-deftest file-notify-test03-autorevert ()
  608. "Check autorevert via file notification."
  609. (skip-unless (file-notify--test-local-enabled))
  610. ;; `auto-revert-buffers' runs every 5". And we must wait, until the
  611. ;; file has been reverted.
  612. (let ((timeout (if (file-remote-p temporary-file-directory) 60 10))
  613. buf)
  614. (unwind-protect
  615. (progn
  616. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
  617. (write-region
  618. "any text" nil file-notify--test-tmpfile nil 'no-message)
  619. (setq buf (find-file-noselect file-notify--test-tmpfile))
  620. (with-current-buffer buf
  621. (should (string-equal (buffer-string) "any text"))
  622. ;; `buffer-stale--default-function' checks for
  623. ;; `verify-visited-file-modtime'. We must ensure that it
  624. ;; returns nil.
  625. (sleep-for 1)
  626. (auto-revert-mode 1)
  627. ;; `auto-revert-buffers' runs every 5".
  628. (with-timeout (timeout (ignore))
  629. (while (null auto-revert-notify-watch-descriptor)
  630. (sleep-for 1)))
  631. ;; `file-notify--test-monitor' needs to know
  632. ;; `file-notify--test-desc' in order to compute proper
  633. ;; timeouts.
  634. (setq file-notify--test-desc auto-revert-notify-watch-descriptor)
  635. ;; Check, that file notification has been used.
  636. (should auto-revert-mode)
  637. (should auto-revert-use-notify)
  638. (should auto-revert-notify-watch-descriptor)
  639. ;; Modify file. We wait for a second, in order to have
  640. ;; another timestamp.
  641. (with-current-buffer (get-buffer-create "*Messages*")
  642. (narrow-to-region (point-max) (point-max)))
  643. (sleep-for 1)
  644. (write-region
  645. "another text" nil file-notify--test-tmpfile nil 'no-message)
  646. ;; Check, that the buffer has been reverted.
  647. (with-current-buffer (get-buffer-create "*Messages*")
  648. (file-notify--wait-for-events
  649. timeout
  650. (string-match
  651. (format-message "Reverting buffer `%s'." (buffer-name buf))
  652. (buffer-string))))
  653. (should (string-match "another text" (buffer-string)))
  654. ;; Stop file notification. Autorevert shall still work via polling.
  655. (file-notify-rm-watch auto-revert-notify-watch-descriptor)
  656. (file-notify--wait-for-events
  657. timeout (null auto-revert-use-notify))
  658. (should-not auto-revert-use-notify)
  659. (should-not auto-revert-notify-watch-descriptor)
  660. ;; Modify file. We wait for two seconds, in order to
  661. ;; have another timestamp. One second seems to be too
  662. ;; short.
  663. (with-current-buffer (get-buffer-create "*Messages*")
  664. (narrow-to-region (point-max) (point-max)))
  665. (sleep-for 2)
  666. (write-region
  667. "foo bla" nil file-notify--test-tmpfile nil 'no-message)
  668. ;; Check, that the buffer has been reverted.
  669. (with-current-buffer (get-buffer-create "*Messages*")
  670. (file-notify--wait-for-events
  671. timeout
  672. (string-match
  673. (format-message "Reverting buffer `%s'." (buffer-name buf))
  674. (buffer-string))))
  675. (should (string-match "foo bla" (buffer-string))))
  676. ;; The environment shall be cleaned up.
  677. (file-notify--test-cleanup-p))
  678. ;; Cleanup.
  679. (with-current-buffer "*Messages*" (widen))
  680. (ignore-errors (kill-buffer buf))
  681. (file-notify--test-cleanup))))
  682. (file-notify--deftest-remote file-notify-test03-autorevert
  683. "Check autorevert via file notification for remote files.")
  684. (ert-deftest file-notify-test04-file-validity ()
  685. "Check `file-notify-valid-p' for files."
  686. (skip-unless (file-notify--test-local-enabled))
  687. (unwind-protect
  688. (progn
  689. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
  690. (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
  691. (should
  692. (setq file-notify--test-desc
  693. (file-notify-add-watch
  694. file-notify--test-tmpfile '(change) #'ignore)))
  695. (should (file-notify-valid-p file-notify--test-desc))
  696. ;; After calling `file-notify-rm-watch', the descriptor is not
  697. ;; valid anymore.
  698. (file-notify-rm-watch file-notify--test-desc)
  699. (should-not (file-notify-valid-p file-notify--test-desc))
  700. (delete-file file-notify--test-tmpfile)
  701. ;; The environment shall be cleaned up.
  702. (file-notify--test-cleanup-p))
  703. ;; Cleanup.
  704. (file-notify--test-cleanup))
  705. (unwind-protect
  706. (progn
  707. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
  708. (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
  709. (should
  710. (setq file-notify--test-desc
  711. (file-notify-add-watch
  712. file-notify--test-tmpfile
  713. '(change) #'file-notify--test-event-handler)))
  714. (should (file-notify-valid-p file-notify--test-desc))
  715. (file-notify--test-with-events
  716. (cond
  717. ;; gvfs-monitor-dir on cygwin does not detect the
  718. ;; `changed' event reliably.
  719. ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
  720. '((deleted stopped)
  721. (changed deleted stopped)))
  722. ;; There could be one or two `changed' events.
  723. (t '((changed deleted stopped)
  724. (changed changed deleted stopped))))
  725. (write-region
  726. "another text" nil file-notify--test-tmpfile nil 'no-message)
  727. (file-notify--test-read-event)
  728. (delete-file file-notify--test-tmpfile))
  729. ;; After deleting the file, the descriptor is not valid anymore.
  730. (should-not (file-notify-valid-p file-notify--test-desc))
  731. (file-notify-rm-watch file-notify--test-desc)
  732. ;; The environment shall be cleaned up.
  733. (file-notify--test-cleanup-p))
  734. ;; Cleanup.
  735. (file-notify--test-cleanup))
  736. (unwind-protect
  737. (let ((temporary-file-directory
  738. (make-temp-file "file-notify-test-parent" t)))
  739. (should
  740. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
  741. file-notify--test-desc
  742. (file-notify-add-watch
  743. temporary-file-directory
  744. '(change) #'file-notify--test-event-handler)))
  745. (should (file-notify-valid-p file-notify--test-desc))
  746. (file-notify--test-with-events
  747. (cond
  748. ;; w32notify does not raise `deleted' and `stopped' events
  749. ;; for the watched directory.
  750. ((string-equal (file-notify--test-library) "w32notify")
  751. '(created changed deleted))
  752. ;; gvfs-monitor-dir on cygwin does not detect the `created'
  753. ;; event reliably.
  754. ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
  755. '((deleted stopped)
  756. (created deleted stopped)))
  757. ;; There are two `deleted' events, for the file and for the
  758. ;; directory. Except for cygwin and kqueue. And cygwin
  759. ;; does not raise a `changed' event.
  760. ((eq system-type 'cygwin)
  761. '(created deleted stopped))
  762. ((string-equal (file-notify--test-library) "kqueue")
  763. '(created changed deleted stopped))
  764. (t '(created changed deleted deleted stopped)))
  765. (write-region
  766. "any text" nil file-notify--test-tmpfile nil 'no-message)
  767. (file-notify--test-read-event)
  768. (delete-directory temporary-file-directory t))
  769. ;; After deleting the parent directory, the descriptor must
  770. ;; not be valid anymore.
  771. (should-not (file-notify-valid-p file-notify--test-desc))
  772. ;; The environment shall be cleaned up.
  773. (file-notify--test-cleanup-p))
  774. ;; Cleanup.
  775. (file-notify--test-cleanup)))
  776. (file-notify--deftest-remote file-notify-test04-file-validity
  777. "Check `file-notify-valid-p' via file notification for remote files.")
  778. (ert-deftest file-notify-test05-dir-validity ()
  779. "Check `file-notify-valid-p' for directories."
  780. (skip-unless (file-notify--test-local-enabled))
  781. (unwind-protect
  782. (progn
  783. (should
  784. (setq file-notify--test-tmpfile
  785. (make-temp-file "file-notify-test-parent" t)))
  786. (should
  787. (setq file-notify--test-desc
  788. (file-notify-add-watch
  789. file-notify--test-tmpfile '(change) #'ignore)))
  790. (should (file-notify-valid-p file-notify--test-desc))
  791. ;; After removing the watch, the descriptor must not be valid
  792. ;; anymore.
  793. (file-notify-rm-watch file-notify--test-desc)
  794. (file-notify--wait-for-events
  795. (file-notify--test-timeout)
  796. (not (file-notify-valid-p file-notify--test-desc)))
  797. (should-not (file-notify-valid-p file-notify--test-desc))
  798. (delete-directory file-notify--test-tmpfile t)
  799. ;; The environment shall be cleaned up.
  800. (file-notify--test-cleanup-p))
  801. ;; Cleanup.
  802. (file-notify--test-cleanup))
  803. (unwind-protect
  804. (progn
  805. (should
  806. (setq file-notify--test-tmpfile
  807. (make-temp-file "file-notify-test-parent" t)))
  808. (should
  809. (setq file-notify--test-desc
  810. (file-notify-add-watch
  811. file-notify--test-tmpfile '(change) #'ignore)))
  812. (should (file-notify-valid-p file-notify--test-desc))
  813. ;; After deleting the directory, the descriptor must not be
  814. ;; valid anymore.
  815. (delete-directory file-notify--test-tmpfile t)
  816. (file-notify--wait-for-events
  817. (file-notify--test-timeout)
  818. (not (file-notify-valid-p file-notify--test-desc)))
  819. (should-not (file-notify-valid-p file-notify--test-desc))
  820. ;; The environment shall be cleaned up.
  821. (file-notify--test-cleanup-p))
  822. ;; Cleanup.
  823. (file-notify--test-cleanup)))
  824. (file-notify--deftest-remote file-notify-test05-dir-validity
  825. "Check `file-notify-valid-p' via file notification for remote directories.")
  826. (ert-deftest file-notify-test06-many-events ()
  827. "Check that events are not dropped."
  828. :tags '(:expensive-test)
  829. (skip-unless (file-notify--test-local-enabled))
  830. (should
  831. (setq file-notify--test-tmpfile
  832. (make-temp-file "file-notify-test-parent" t)))
  833. (should
  834. (setq file-notify--test-desc
  835. (file-notify-add-watch
  836. file-notify--test-tmpfile
  837. '(change) #'file-notify--test-event-handler)))
  838. (unwind-protect
  839. (let ((n 1000)
  840. source-file-list target-file-list
  841. (default-directory file-notify--test-tmpfile))
  842. (dotimes (i n)
  843. ;; It matters which direction we rename, at least for
  844. ;; kqueue. This backend parses directories in alphabetic
  845. ;; order (x%d before y%d). So we rename into both directions.
  846. (if (zerop (mod i 2))
  847. (progn
  848. (push (expand-file-name (format "x%d" i)) source-file-list)
  849. (push (expand-file-name (format "y%d" i)) target-file-list))
  850. (push (expand-file-name (format "y%d" i)) source-file-list)
  851. (push (expand-file-name (format "x%d" i)) target-file-list)))
  852. (file-notify--test-with-events (make-list (+ n n) 'created)
  853. (let ((source-file-list source-file-list)
  854. (target-file-list target-file-list))
  855. (while (and source-file-list target-file-list)
  856. (file-notify--test-read-event)
  857. (write-region "" nil (pop source-file-list) nil 'no-message)
  858. (file-notify--test-read-event)
  859. (write-region "" nil (pop target-file-list) nil 'no-message))))
  860. (file-notify--test-with-events
  861. (cond
  862. ;; w32notify fires both `deleted' and `renamed' events.
  863. ((string-equal (file-notify--test-library) "w32notify")
  864. (let (r)
  865. (dotimes (_i n r)
  866. (setq r (append '(deleted renamed) r)))))
  867. ;; cygwin fires `changed' and `deleted' events, sometimes
  868. ;; in random order.
  869. ((eq system-type 'cygwin)
  870. (let (r)
  871. (dotimes (_i n (cons :random r))
  872. (setq r (append '(changed deleted) r)))))
  873. (t (make-list n 'renamed)))
  874. (let ((source-file-list source-file-list)
  875. (target-file-list target-file-list))
  876. (while (and source-file-list target-file-list)
  877. (file-notify--test-read-event)
  878. (rename-file (pop source-file-list) (pop target-file-list) t))))
  879. (file-notify--test-with-events (make-list n 'deleted)
  880. (dolist (file target-file-list)
  881. (file-notify--test-read-event)
  882. (delete-file file)))
  883. (delete-directory file-notify--test-tmpfile)
  884. ;; The environment shall be cleaned up.
  885. (file-notify--test-cleanup-p))
  886. ;; Cleanup.
  887. (file-notify--test-cleanup)))
  888. (file-notify--deftest-remote file-notify-test06-many-events
  889. "Check that events are not dropped for remote directories.")
  890. (ert-deftest file-notify-test07-backup ()
  891. "Check that backup keeps file notification."
  892. (skip-unless (file-notify--test-local-enabled))
  893. (unwind-protect
  894. (progn
  895. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
  896. (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
  897. (should
  898. (setq file-notify--test-desc
  899. (file-notify-add-watch
  900. file-notify--test-tmpfile
  901. '(change) #'file-notify--test-event-handler)))
  902. (should (file-notify-valid-p file-notify--test-desc))
  903. (file-notify--test-with-events
  904. ;; There could be one or two `changed' events.
  905. '((changed)
  906. (changed changed))
  907. ;; There shouldn't be any problem, because the file is kept.
  908. (with-temp-buffer
  909. (let ((buffer-file-name file-notify--test-tmpfile)
  910. (make-backup-files t)
  911. (backup-by-copying t)
  912. (kept-new-versions 1)
  913. (delete-old-versions t))
  914. (insert "another text")
  915. (save-buffer))))
  916. ;; After saving the buffer, the descriptor is still valid.
  917. (should (file-notify-valid-p file-notify--test-desc))
  918. (delete-file file-notify--test-tmpfile)
  919. ;; The environment shall be cleaned up.
  920. (file-notify--test-cleanup-p))
  921. ;; Cleanup.
  922. (file-notify--test-cleanup))
  923. (unwind-protect
  924. ;; It doesn't work for kqueue, because we don't use an implicit
  925. ;; directory monitor.
  926. (unless (string-equal (file-notify--test-library) "kqueue")
  927. (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
  928. (write-region
  929. "any text" nil file-notify--test-tmpfile nil 'no-message)
  930. (should
  931. (setq file-notify--test-desc
  932. (file-notify-add-watch
  933. file-notify--test-tmpfile
  934. '(change) #'file-notify--test-event-handler)))
  935. (should (file-notify-valid-p file-notify--test-desc))
  936. (file-notify--test-with-events
  937. (cond
  938. ;; On cygwin we only get the `changed' event.
  939. ((eq system-type 'cygwin) '(changed))
  940. (t '(renamed created changed)))
  941. ;; The file is renamed when creating a backup. It shall
  942. ;; still be watched.
  943. (with-temp-buffer
  944. (let ((buffer-file-name file-notify--test-tmpfile)
  945. (make-backup-files t)
  946. (backup-by-copying nil)
  947. (backup-by-copying-when-mismatch nil)
  948. (kept-new-versions 1)
  949. (delete-old-versions t))
  950. (insert "another text")
  951. (save-buffer))))
  952. ;; After saving the buffer, the descriptor is still valid.
  953. (should (file-notify-valid-p file-notify--test-desc))
  954. (delete-file file-notify--test-tmpfile)
  955. ;; The environment shall be cleaned up.
  956. (file-notify--test-cleanup-p))
  957. ;; Cleanup.
  958. (file-notify--test-cleanup)))
  959. (file-notify--deftest-remote file-notify-test07-backup
  960. "Check that backup keeps file notification for remote files.")
  961. (ert-deftest file-notify-test08-watched-file-in-watched-dir ()
  962. "Watches a directory and a file in that directory separately.
  963. Checks that the callbacks are only called with events with
  964. descriptors that were issued when registering the watches. This
  965. test caters for the situation in bug#22736 where the callback for
  966. the directory received events for the file with the descriptor of
  967. the file watch."
  968. :tags '(:expensive-test)
  969. (skip-unless (file-notify--test-local-enabled))
  970. ;; A directory to be watched.
  971. (should
  972. (setq file-notify--test-tmpfile
  973. (make-temp-file "file-notify-test-parent" t)))
  974. ;; A file to be watched.
  975. (should
  976. (setq file-notify--test-tmpfile1
  977. (let ((temporary-file-directory file-notify--test-tmpfile))
  978. (file-notify--test-make-temp-name))))
  979. (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message)
  980. (unwind-protect
  981. (cl-flet (;; Directory monitor.
  982. (dir-callback (event)
  983. (let ((file-notify--test-desc file-notify--test-desc1))
  984. (file-notify--test-event-handler event)))
  985. ;; File monitor.
  986. (file-callback (event)
  987. (let ((file-notify--test-desc file-notify--test-desc2))
  988. (file-notify--test-event-handler event))))
  989. (should
  990. (setq file-notify--test-desc1
  991. (file-notify-add-watch
  992. file-notify--test-tmpfile
  993. '(change) #'dir-callback)
  994. ;; This is needed for `file-notify--test-monitor'.
  995. file-notify--test-desc file-notify--test-desc1))
  996. (should
  997. (setq file-notify--test-desc2
  998. (file-notify-add-watch
  999. file-notify--test-tmpfile1
  1000. '(change) #'file-callback)))
  1001. (should (file-notify-valid-p file-notify--test-desc1))
  1002. (should (file-notify-valid-p file-notify--test-desc2))
  1003. (should-not (equal file-notify--test-desc1 file-notify--test-desc2))
  1004. (let ((n 100))
  1005. ;; Run the test.
  1006. (file-notify--test-with-events
  1007. ;; There could be one or two `changed' events.
  1008. (list
  1009. ;; cygwin.
  1010. (append
  1011. '(:random)
  1012. (make-list (/ n 2) 'changed)
  1013. (make-list (/ n 2) 'created)
  1014. (make-list (/ n 2) 'changed))
  1015. (append
  1016. '(:random)
  1017. ;; Directory monitor and file monitor.
  1018. (make-list (/ n 2) 'changed)
  1019. (make-list (/ n 2) 'changed)
  1020. ;; Just the directory monitor.
  1021. (make-list (/ n 2) 'created)
  1022. (make-list (/ n 2) 'changed))
  1023. (append
  1024. '(:random)
  1025. ;; Directory monitor and file monitor.
  1026. (make-list (/ n 2) 'changed)
  1027. (make-list (/ n 2) 'changed)
  1028. (make-list (/ n 2) 'changed)
  1029. (make-list (/ n 2) 'changed)
  1030. ;; Just the directory monitor.
  1031. (make-list (/ n 2) 'created)
  1032. (make-list (/ n 2) 'changed)))
  1033. (dotimes (i n)
  1034. (file-notify--test-read-event)
  1035. (if (zerop (mod i 2))
  1036. (write-region
  1037. "any text" nil file-notify--test-tmpfile1 t 'no-message)
  1038. (let ((temporary-file-directory file-notify--test-tmpfile))
  1039. (write-region
  1040. "any text" nil
  1041. (file-notify--test-make-temp-name) nil 'no-message))))))
  1042. ;; If we delete the file, the directory monitor shall still be
  1043. ;; active. We receive the `deleted' event from both the
  1044. ;; directory and the file monitor. The `stopped' event is
  1045. ;; from the file monitor. It's undecided in which order the
  1046. ;; the directory and the file monitor are triggered.
  1047. (file-notify--test-with-events '(:random deleted deleted stopped)
  1048. (delete-file file-notify--test-tmpfile1))
  1049. (should (file-notify-valid-p file-notify--test-desc1))
  1050. (should-not (file-notify-valid-p file-notify--test-desc2))
  1051. ;; Now we delete the directory.
  1052. (file-notify--test-with-events
  1053. (cond
  1054. ;; In kqueue and for cygwin, just one `deleted' event for
  1055. ;; the directory is received.
  1056. ((or (eq system-type 'cygwin)
  1057. (string-equal (file-notify--test-library) "kqueue"))
  1058. '(deleted stopped))
  1059. (t (append
  1060. ;; The directory monitor raises a `deleted' event for
  1061. ;; every file contained in the directory, we must
  1062. ;; count them.
  1063. (make-list
  1064. (length
  1065. (directory-files
  1066. file-notify--test-tmpfile nil
  1067. directory-files-no-dot-files-regexp 'nosort))
  1068. 'deleted)
  1069. ;; The events of the directory itself.
  1070. (cond
  1071. ;; w32notify does not raise `deleted' and `stopped'
  1072. ;; events for the watched directory.
  1073. ((string-equal (file-notify--test-library) "w32notify") '())
  1074. (t '(deleted stopped))))))
  1075. (delete-directory file-notify--test-tmpfile 'recursive))
  1076. (should-not (file-notify-valid-p file-notify--test-desc1))
  1077. (should-not (file-notify-valid-p file-notify--test-desc2))
  1078. ;; The environment shall be cleaned up.
  1079. (file-notify--test-cleanup-p))
  1080. ;; Cleanup.
  1081. (file-notify--test-cleanup)))
  1082. (file-notify--deftest-remote file-notify-test08-watched-file-in-watched-dir
  1083. "Check `file-notify-test08-watched-file-in-watched-dir' for remote files.")
  1084. (ert-deftest file-notify-test09-sufficient-resources ()
  1085. "Check that file notification does not use too many resources."
  1086. :tags '(:expensive-test)
  1087. (skip-unless (file-notify--test-local-enabled))
  1088. ;; This test is intended for kqueue only.
  1089. (skip-unless (string-equal (file-notify--test-library) "kqueue"))
  1090. (should
  1091. (setq file-notify--test-tmpfile
  1092. (make-temp-file "file-notify-test-parent" t)))
  1093. (unwind-protect
  1094. (let ((temporary-file-directory file-notify--test-tmpfile)
  1095. descs)
  1096. (should-error
  1097. (while t
  1098. ;; We watch directories, because we want to reach the upper
  1099. ;; limit. Watching a file might not be sufficient, because
  1100. ;; most of the libraries implement this as watching the
  1101. ;; upper directory.
  1102. (setq file-notify--test-tmpfile1
  1103. (make-temp-file "file-notify-test-parent" t)
  1104. descs
  1105. (cons
  1106. (should
  1107. (file-notify-add-watch
  1108. file-notify--test-tmpfile1 '(change) #'ignore))
  1109. descs)))
  1110. :type 'file-notify-error)
  1111. ;; Remove watches. If we don't do it prior removing
  1112. ;; directories, Emacs crashes in batch mode.
  1113. (dolist (desc descs)
  1114. (file-notify-rm-watch desc))
  1115. ;; Remove directories.
  1116. (delete-directory file-notify--test-tmpfile 'recursive)
  1117. ;; The environment shall be cleaned up.
  1118. (file-notify--test-cleanup-p))
  1119. ;; Cleanup.
  1120. (file-notify--test-cleanup)))
  1121. (file-notify--deftest-remote file-notify-test09-sufficient-resources
  1122. "Check `file-notify-test09-sufficient-resources' for remote files.")
  1123. (defun file-notify-test-all (&optional interactive)
  1124. "Run all tests for \\[file-notify]."
  1125. (interactive "p")
  1126. (if interactive
  1127. (ert-run-tests-interactively "^file-notify-")
  1128. (ert-run-tests-batch "^file-notify-")))
  1129. ;; TODO:
  1130. ;; * kqueue does not send all expected `deleted' events. Maybe due to
  1131. ;; the missing directory monitor.
  1132. ;; * For w32notify, no `deleted' and `stopped' events arrive when a
  1133. ;; directory is removed.
  1134. ;; * For cygwin and w32notify, no `attribute-changed' events arrive.
  1135. ;; They send `changed' events instead.
  1136. ;; * cygwin does not send all expected `changed' and `deleted' events.
  1137. ;; Probably due to timing issues.
  1138. (provide 'file-notify-tests)
  1139. ;;; filenotify-tests.el ends here