termxx_spec.lua 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. local luv = require('luv')
  2. local helpers = require('test.functional.helpers')(after_each)
  3. local clear, command, nvim, testprg =
  4. helpers.clear, helpers.command, helpers.nvim, helpers.testprg
  5. local eval, eq, neq, retry =
  6. helpers.eval, helpers.eq, helpers.neq, helpers.retry
  7. local matches = helpers.matches
  8. local ok = helpers.ok
  9. local feed = helpers.feed
  10. local pcall_err = helpers.pcall_err
  11. local assert_alive = helpers.assert_alive
  12. local iswin = helpers.iswin
  13. describe('autocmd TermClose', function()
  14. before_each(function()
  15. clear()
  16. nvim('set_option', 'shell', testprg('shell-test'))
  17. command('set shellcmdflag=EXE shellredir= shellpipe= shellquote= shellxquote=')
  18. end)
  19. local function test_termclose_delete_own_buf()
  20. command('autocmd TermClose * bdelete!')
  21. command('terminal')
  22. matches('^Vim%(bdelete%):E937: Attempt to delete a buffer that is in use: term://',
  23. pcall_err(command, 'bdelete!'))
  24. assert_alive()
  25. end
  26. -- TODO: fixed after merging patches for `can_unload_buffer`?
  27. pending('TermClose deleting its own buffer, altbuf = buffer 1 #10386', function()
  28. test_termclose_delete_own_buf()
  29. end)
  30. it('TermClose deleting its own buffer, altbuf NOT buffer 1 #10386', function()
  31. command('edit foo1')
  32. test_termclose_delete_own_buf()
  33. end)
  34. it('triggers when fast-exiting terminal job stops', function()
  35. command('autocmd TermClose * let g:test_termclose = 23')
  36. command('terminal')
  37. -- shell-test exits immediately.
  38. retry(nil, nil, function() neq(-1, eval('jobwait([&channel], 0)[0]')) end)
  39. retry(nil, nil, function() eq(23, eval('g:test_termclose')) end)
  40. end)
  41. it('triggers when long-running terminal job gets stopped', function()
  42. nvim('set_option', 'shell', iswin() and 'cmd.exe' or 'sh')
  43. command('autocmd TermClose * let g:test_termclose = 23')
  44. command('terminal')
  45. command('call jobstop(b:terminal_job_id)')
  46. retry(nil, nil, function() eq(23, eval('g:test_termclose')) end)
  47. end)
  48. it('kills job trapping SIGTERM', function()
  49. if iswin() then return end
  50. nvim('set_option', 'shell', 'sh')
  51. nvim('set_option', 'shellcmdflag', '-c')
  52. command([[ let g:test_job = jobstart('trap "" TERM && echo 1 && sleep 60', { ]]
  53. .. [[ 'on_stdout': {-> execute('let g:test_job_started = 1')}, ]]
  54. .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]])
  55. retry(nil, nil, function() eq(1, eval('get(g:, "test_job_started", 0)')) end)
  56. luv.update_time()
  57. local start = luv.now()
  58. command('call jobstop(g:test_job)')
  59. retry(nil, nil, function() eq(1, eval('get(g:, "test_job_exited", 0)')) end)
  60. luv.update_time()
  61. local duration = luv.now() - start
  62. -- Nvim begins SIGTERM after KILL_TIMEOUT_MS.
  63. ok(duration >= 2000)
  64. ok(duration <= 4000) -- Epsilon for slow CI
  65. end)
  66. it('kills PTY job trapping SIGHUP and SIGTERM', function()
  67. if iswin() then return end
  68. nvim('set_option', 'shell', 'sh')
  69. nvim('set_option', 'shellcmdflag', '-c')
  70. command([[ let g:test_job = jobstart('trap "" HUP TERM && echo 1 && sleep 60', { ]]
  71. .. [[ 'pty': 1,]]
  72. .. [[ 'on_stdout': {-> execute('let g:test_job_started = 1')}, ]]
  73. .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]])
  74. retry(nil, nil, function() eq(1, eval('get(g:, "test_job_started", 0)')) end)
  75. luv.update_time()
  76. local start = luv.now()
  77. command('call jobstop(g:test_job)')
  78. retry(nil, nil, function() eq(1, eval('get(g:, "test_job_exited", 0)')) end)
  79. luv.update_time()
  80. local duration = luv.now() - start
  81. -- Nvim begins SIGKILL after (2 * KILL_TIMEOUT_MS).
  82. ok(duration >= 4000)
  83. ok(duration <= 7000) -- Epsilon for slow CI
  84. end)
  85. it('reports the correct <abuf>', function()
  86. command('set hidden')
  87. command('autocmd TermClose * let g:abuf = expand("<abuf>")')
  88. command('edit foo')
  89. command('edit bar')
  90. eq(2, eval('bufnr("%")'))
  91. command('terminal')
  92. retry(nil, nil, function() eq(3, eval('bufnr("%")')) end)
  93. command('buffer 1')
  94. retry(nil, nil, function() eq(1, eval('bufnr("%")')) end)
  95. command('3bdelete!')
  96. retry(nil, nil, function() eq('3', eval('g:abuf')) end)
  97. feed('<c-c>:qa!<cr>')
  98. end)
  99. it('exposes v:event.status', function()
  100. command('set shellcmdflag=EXIT')
  101. command('autocmd TermClose * let g:status = v:event.status')
  102. command('terminal 0')
  103. retry(nil, nil, function() eq(0, eval('g:status')) end)
  104. command('terminal 42')
  105. retry(nil, nil, function() eq(42, eval('g:status')) end)
  106. end)
  107. end)
  108. it('autocmd TermEnter, TermLeave', function()
  109. clear()
  110. command('let g:evs = []')
  111. command('autocmd TermOpen * call add(g:evs, ["TermOpen", mode()])')
  112. command('autocmd TermClose * call add(g:evs, ["TermClose", mode()])')
  113. command('autocmd TermEnter * call add(g:evs, ["TermEnter", mode()])')
  114. command('autocmd TermLeave * call add(g:evs, ["TermLeave", mode()])')
  115. command('terminal')
  116. feed('i')
  117. eq({ {'TermOpen', 'n'}, {'TermEnter', 't'}, }, eval('g:evs'))
  118. feed([[<C-\><C-n>]])
  119. feed('A')
  120. eq({ {'TermOpen', 'n'}, {'TermEnter', 't'}, {'TermLeave', 'n'}, {'TermEnter', 't'}, }, eval('g:evs'))
  121. -- TermLeave is also triggered by :quit.
  122. command('split foo')
  123. command('wincmd w')
  124. feed('i')
  125. command('q!')
  126. eq(
  127. {
  128. {'TermOpen', 'n'},
  129. {'TermEnter', 't'},
  130. {'TermLeave', 'n'},
  131. {'TermEnter', 't'},
  132. {'TermLeave', 'n'},
  133. {'TermEnter', 't'},
  134. {'TermClose', 't'},
  135. {'TermLeave', 'n'},
  136. },
  137. eval('g:evs'))
  138. end)