watch_spec.lua 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. local helpers = require('test.functional.helpers')(after_each)
  2. local eq = helpers.eq
  3. local exec_lua = helpers.exec_lua
  4. local clear = helpers.clear
  5. local is_os = helpers.is_os
  6. local mkdir = helpers.mkdir
  7. describe('vim._watch', function()
  8. before_each(function()
  9. clear()
  10. end)
  11. describe('watch', function()
  12. it('detects file changes', function()
  13. local root_dir = helpers.tmpname()
  14. os.remove(root_dir)
  15. mkdir(root_dir)
  16. local result = exec_lua(
  17. [[
  18. local root_dir = ...
  19. local events = {}
  20. local expected_events = 0
  21. local function wait_for_events()
  22. assert(vim.wait(100, function() return #events == expected_events end), 'Timed out waiting for expected number of events. Current events seen so far: ' .. vim.inspect(events))
  23. end
  24. local stop = vim._watch.watch(root_dir, {}, function(path, change_type)
  25. table.insert(events, { path = path, change_type = change_type })
  26. end)
  27. -- Only BSD seems to need some extra time for the watch to be ready to respond to events
  28. if vim.fn.has('bsd') then
  29. vim.wait(50)
  30. end
  31. local watched_path = root_dir .. '/file'
  32. local watched, err = io.open(watched_path, 'w')
  33. assert(not err, err)
  34. expected_events = expected_events + 1
  35. wait_for_events()
  36. watched:close()
  37. os.remove(watched_path)
  38. expected_events = expected_events + 1
  39. wait_for_events()
  40. stop()
  41. -- No events should come through anymore
  42. local watched_path = root_dir .. '/file'
  43. local watched, err = io.open(watched_path, 'w')
  44. assert(not err, err)
  45. vim.wait(50)
  46. watched:close()
  47. os.remove(watched_path)
  48. vim.wait(50)
  49. return events
  50. ]],
  51. root_dir
  52. )
  53. local expected = {
  54. {
  55. change_type = exec_lua([[return vim._watch.FileChangeType.Created]]),
  56. path = root_dir .. '/file',
  57. },
  58. {
  59. change_type = exec_lua([[return vim._watch.FileChangeType.Deleted]]),
  60. path = root_dir .. '/file',
  61. },
  62. }
  63. -- kqueue only reports events on the watched path itself, so creating a file within a
  64. -- watched directory results in a "rename" libuv event on the directory.
  65. if is_os('bsd') then
  66. expected = {
  67. {
  68. change_type = exec_lua([[return vim._watch.FileChangeType.Created]]),
  69. path = root_dir,
  70. },
  71. {
  72. change_type = exec_lua([[return vim._watch.FileChangeType.Created]]),
  73. path = root_dir,
  74. },
  75. }
  76. end
  77. eq(expected, result)
  78. end)
  79. end)
  80. describe('poll', function()
  81. it('detects file changes', function()
  82. local root_dir = helpers.tmpname()
  83. os.remove(root_dir)
  84. mkdir(root_dir)
  85. local result = exec_lua(
  86. [[
  87. local root_dir = ...
  88. local events = {}
  89. local poll_interval_ms = 1000
  90. local poll_wait_ms = poll_interval_ms+200
  91. local expected_events = 0
  92. local function wait_for_events()
  93. assert(vim.wait(poll_wait_ms, function() return #events == expected_events end), 'Timed out waiting for expected number of events. Current events seen so far: ' .. vim.inspect(events))
  94. end
  95. local stop = vim._watch.poll(root_dir, { interval = poll_interval_ms }, function(path, change_type)
  96. table.insert(events, { path = path, change_type = change_type })
  97. end)
  98. vim.wait(100)
  99. local watched_path = root_dir .. '/file'
  100. local watched, err = io.open(watched_path, 'w')
  101. assert(not err, err)
  102. expected_events = expected_events + 2
  103. wait_for_events()
  104. watched:close()
  105. os.remove(watched_path)
  106. expected_events = expected_events + 2
  107. wait_for_events()
  108. stop()
  109. -- No events should come through anymore
  110. local watched_path = root_dir .. '/file'
  111. local watched, err = io.open(watched_path, 'w')
  112. assert(not err, err)
  113. vim.wait(poll_wait_ms)
  114. watched:close()
  115. os.remove(watched_path)
  116. return events
  117. ]],
  118. root_dir
  119. )
  120. eq(4, #result)
  121. eq({
  122. change_type = exec_lua([[return vim._watch.FileChangeType.Created]]),
  123. path = root_dir .. '/file',
  124. }, result[1])
  125. eq({
  126. change_type = exec_lua([[return vim._watch.FileChangeType.Changed]]),
  127. path = root_dir,
  128. }, result[2])
  129. -- The file delete and corresponding directory change events do not happen in any
  130. -- particular order, so allow either
  131. if result[3].path == root_dir then
  132. eq({
  133. change_type = exec_lua([[return vim._watch.FileChangeType.Changed]]),
  134. path = root_dir,
  135. }, result[3])
  136. eq({
  137. change_type = exec_lua([[return vim._watch.FileChangeType.Deleted]]),
  138. path = root_dir .. '/file',
  139. }, result[4])
  140. else
  141. eq({
  142. change_type = exec_lua([[return vim._watch.FileChangeType.Deleted]]),
  143. path = root_dir .. '/file',
  144. }, result[3])
  145. eq({
  146. change_type = exec_lua([[return vim._watch.FileChangeType.Changed]]),
  147. path = root_dir,
  148. }, result[4])
  149. end
  150. end)
  151. end)
  152. end)