system_spec.lua 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local clear = n.clear
  4. local exec_lua = n.exec_lua
  5. local eq = t.eq
  6. local function system_sync(cmd, opts)
  7. return exec_lua(function()
  8. local obj = vim.system(cmd, opts)
  9. if opts and opts.timeout then
  10. -- Minor delay before calling wait() so the timeout uv timer can have a headstart over the
  11. -- internal call to vim.wait() in wait().
  12. vim.wait(10)
  13. end
  14. local res = obj:wait()
  15. -- Check the process is no longer running
  16. assert(not vim.api.nvim_get_proc(obj.pid), 'process still exists')
  17. return res
  18. end)
  19. end
  20. local function system_async(cmd, opts)
  21. return exec_lua(function()
  22. local done = false
  23. local res --- @type vim.SystemCompleted?
  24. local obj = vim.system(cmd, opts, function(obj)
  25. done = true
  26. res = obj
  27. end)
  28. local ok = vim.wait(10000, function()
  29. return done
  30. end)
  31. assert(ok, 'process did not exit')
  32. -- Check the process is no longer running
  33. assert(not vim.api.nvim_get_proc(obj.pid), 'process still exists')
  34. return res
  35. end)
  36. end
  37. describe('vim.system', function()
  38. before_each(function()
  39. clear()
  40. end)
  41. for name, system in pairs { sync = system_sync, async = system_async } do
  42. describe('(' .. name .. ')', function()
  43. it('can run simple commands', function()
  44. eq('hello\n', system({ 'echo', 'hello' }, { text = true }).stdout)
  45. end)
  46. it('handle input', function()
  47. eq('hellocat', system({ 'cat' }, { stdin = 'hellocat', text = true }).stdout)
  48. end)
  49. it('supports timeout', function()
  50. eq({
  51. code = 124,
  52. signal = 15,
  53. stdout = '',
  54. stderr = '',
  55. }, system({ 'sleep', '10' }, { timeout = 1000 }))
  56. end)
  57. end)
  58. end
  59. it('kill processes', function()
  60. exec_lua(function()
  61. local signal --- @type integer?
  62. local cmd = vim.system({ 'cat', '-' }, { stdin = true }, function(r)
  63. signal = r.signal
  64. end) -- run forever
  65. cmd:kill('sigint')
  66. -- wait for the process not to exist
  67. local done = vim.wait(2000, function()
  68. return signal ~= nil
  69. end)
  70. assert(done, 'process did not exit')
  71. -- Check the process is no longer running
  72. local proc = vim.api.nvim_get_proc(cmd.pid)
  73. assert(not proc, 'process still exists')
  74. assert(signal == 2)
  75. end)
  76. end)
  77. it('SystemObj:wait() does not process non-fast events #27292', function()
  78. eq(
  79. false,
  80. exec_lua(function()
  81. _G.processed = false
  82. local cmd = vim.system({ 'sleep', '1' })
  83. vim.schedule(function()
  84. _G.processed = true
  85. end)
  86. cmd:wait()
  87. return _G.processed
  88. end)
  89. )
  90. eq(true, exec_lua([[return _G.processed]]))
  91. end)
  92. if t.is_os('win') then
  93. it('can resolve windows command extensions', function()
  94. t.write_file('test.bat', 'echo hello world')
  95. system_sync({ 'chmod', '+x', 'test.bat' })
  96. system_sync({ './test' })
  97. end)
  98. end
  99. it('always captures all content of stdout/stderr #30846', function()
  100. t.skip(n.fn.executable('git') == 0, 'missing "git" command')
  101. t.skip(n.fn.isdirectory('.git') == 0, 'missing ".git" directory')
  102. eq(
  103. 0,
  104. exec_lua(function()
  105. local done = 0
  106. local fail = 0
  107. for _ = 1, 200 do
  108. vim.system(
  109. { 'git', 'show', ':0:test/functional/plugin/lsp_spec.lua' },
  110. { text = true },
  111. function(o)
  112. if o.code ~= 0 or #o.stdout == 0 then
  113. fail = fail + 1
  114. end
  115. done = done + 1
  116. end
  117. )
  118. end
  119. local ok = vim.wait(10000, function()
  120. return done == 200
  121. end, 200)
  122. return fail + (ok and 0 or 1)
  123. end)
  124. )
  125. end)
  126. end)