]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1110: Vim tests are slow and flaky v9.1.1110
authorYee Cheng Chin <ychin.git@gmail.com>
Thu, 13 Feb 2025 19:55:45 +0000 (20:55 +0100)
committerChristian Brabandt <cb@256bit.org>
Thu, 13 Feb 2025 19:55:45 +0000 (20:55 +0100)
Problem:  Vim tests are slow and flaky at the same time due to reliance
          on timeouts which are unreliable.
Solution: improve Vim test performance and reduce flakiness
          (Yee Cheng Chin)

A lot of Vim tests currently rely on waiting a specific amount of time
before asserting a condition. This is bad because 1) it is slow, as the
timeout is hardcoded, 2) it's unreliable as a resource-starved runner
may overshoot the timeout. Also, there are a lot of builtin sleep
commands in commonly used utilities like VerifyScreenDump and WaitFor()
which leads to a lot of unnecessary idle time.

Fix these issues by doing the following:
1. Make utilities like VerifyScreenDump and WaitFor use the lowest wait
   time possible (1 ms). This essentially turns it into a spin wait. On
   fast machines, these will finish very quickly. For existing tests
   that had an implicit reliance on the old timeouts (e.g.
   VerifyScreenDump had a 50ms wait before), fix the tests to wait that
   specific amount explicitly.
2. Fix tests that sleep or wait for long amounts of time to instead
   explicitly use a callback mechanism to be notified when a child
   terminal job has finished. This allows the test to only take as much
   time as possible instead of having to hard code an unreliable
   timeout.

With these fixes, tests should 1) completely quickly on fast machines,
and 2) on slow machines they will still run to completion albeit slowly.
Note that previoulsy both were not true. The hardcoded timeouts meant
that on fast machines the tests were mostly idling wasting time, whereas
on slow machines, the timeouts often were not generous enough to allow
them to run to completion.

closes: #16615

Signed-off-by: Yee Cheng Chin <ychin.git@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
17 files changed:
runtime/doc/terminal.txt
runtime/doc/various.txt
src/testdir/crash/ex_redraw_crash [deleted file]
src/testdir/runtest.vim
src/testdir/screendump.vim
src/testdir/shared.vim
src/testdir/term_util.vim
src/testdir/test_balloon.vim
src/testdir/test_crash.vim
src/testdir/test_listlbr_utf8.vim
src/testdir/test_tagjump.vim
src/testdir/test_terminal.vim
src/testdir/test_terminal2.vim
src/testdir/test_terminal3.vim
src/testdir/test_timers.vim
src/testdir/test_visual.vim
src/version.c

index 43b5e5f247a8a25298b9b8810a66b2eefa7314db..53e2dcd081587987c0c78a708f4f4f97d7eac204 100644 (file)
@@ -1,4 +1,4 @@
-*terminal.txt* For Vim version 9.1.  Last change: 2025 Jan 11
+*terminal.txt* For Vim version 9.1.  Last change: 2025 Feb 13
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -999,7 +999,8 @@ term_wait({buf} [, {time}])                                 *term_wait()*
                Wait for pending updates of {buf} to be handled.
                {buf} is used as with |term_getsize()|.
                {time} is how long to wait for updates to arrive in msec.  If
-               not set then 10 msec will be used.
+               not set then 10 msec will be used.  Queued messages will also
+               be processed similar to |:sleep|.
 
                Can also be used as a |method|: >
                        GetBufnr()->term_wait()
index 440a665629049a36a60727cecceb4c703d6ed5ca..6fd4a5f7f10f2d0819dcd13dedc1f7490b7f65f5 100644 (file)
@@ -1,4 +1,4 @@
-*various.txt*   For Vim version 9.1.  Last change: 2024 Dec 16
+*various.txt*   For Vim version 9.1.  Last change: 2025 Feb 13
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -765,9 +765,8 @@ K                   Run a program to lookup the keyword under the
                        MS-Windows).  "gs" stands for "goto sleep".
                        While sleeping the cursor is positioned in the text,
                        if at a visible position.
-                       Also process the received netbeans messages. {only
-                       available when compiled with the |+netbeans_intg|
-                       feature}
+                       Queued messages and timers (|+timers|) are processed
+                       during the sleep as well.
 
                                                        *:sl!* *:sleep!*
 :[N]sl[eep]! [N][m]    Same as above, but hide the cursor.
diff --git a/src/testdir/crash/ex_redraw_crash b/src/testdir/crash/ex_redraw_crash
deleted file mode 100644 (file)
index eda294c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-v\1ediv\1evi|gIv|÷³\16\16\16\e\16\16X\80ý\\80ý,\16\16X\80ýX\80ý\\80ý#\r\16X\80ý\\84ý<\80ý\\80ý,X\16\80ùX
index 429e75095f2c2d2ec6a6cedf70c9cc96ed1e4db1..c14f44e652fe8dc5340c45f0c3e596ca5883ca38 100644 (file)
@@ -265,6 +265,9 @@ func RunTheTest(test)
   " buffers.
   %bwipe!
 
+  " Clear all children notifications in case there are stale ones left
+  let g:child_notification = 0
+
   " The test may change the current directory. Save and restore the
   " directory after executing the test.
   let save_cwd = getcwd()
index 84b4864416fef56770308057d6ddd7af12989bac..744f2ab60fe7748cdd3ccd73a41a82b60a8743d7 100644 (file)
@@ -52,14 +52,14 @@ func VerifyScreenDump(buf, filename, options, ...)
   let filter = 'dumps/' . a:filename . '.vim'
   let testfile = 'failed/' . a:filename . '.dump'
 
-  let max_loops = get(a:options, 'wait', 1000) / 10
+  let max_loops = get(a:options, 'wait', 1000) / 1
 
   " Starting a terminal to make a screendump is always considered flaky.
   let g:test_is_flaky = 1
   let g:giveup_same_error = 0
 
   " wait for the pending updates to be handled.
-  call TermWait(a:buf)
+  call TermWait(a:buf, 0)
 
   " Redraw to execute the code that updates the screen.  Otherwise we get the
   " text and attributes only from the internal buffer.
@@ -80,8 +80,8 @@ func VerifyScreenDump(buf, filename, options, ...)
 
   let i = 0
   while 1
-    " leave some time for updating the original window
-    sleep 50m
+    " leave a bit of time for updating the original window while we spin wait.
+    sleep 1m
     call delete(testfile)
     call term_dumpwrite(a:buf, testfile, a:options)
 
index 8ae6fa0213fbb8b0f8e93fe928ad26d271ba8636..f459d879c8daa4e4cb4c5d11c763840f01aa85db 100644 (file)
@@ -136,6 +136,34 @@ func s:kill_server(cmd)
   endif
 endfunc
 
+" Callback function to be invoked by a child terminal job. The parent could
+" then wait for the notification using WaitForChildNotification()
+let g:child_notification = 0
+func Tapi_notify_parent(bufnum, arglist)
+  let g:child_notification = 1
+endfunc
+
+" Generates a command that we can pass to a terminal job that it uses to
+" notify us. Argument 'escape' will specify whether to escape the double
+" quote.
+func TermNotifyParentCmd(escape)
+  call assert_false(has("win32"), 'Windows does not support terminal API right now. Use another method to synchronize timing.')
+  let cmd = '\033]51;["call", "Tapi_notify_parent", []]\007'
+  if a:escape
+    return escape(cmd, '"')
+  endif
+  return cmd
+endfunc
+
+" Wait for a child process to notify us. This allows us to sequence events in
+" conjunction with the child. Currently the only supported notification method
+" is for a terminal job to call Tapi_notify_parent() using terminal API.
+func WaitForChildNotification(...)
+  let timeout = get(a:000, 0, 5000)
+  call WaitFor({-> g:child_notification == 1}, timeout)
+  let g:child_notification = 0
+endfunc
+
 " Wait for up to five seconds for "expr" to become true.  "expr" can be a
 " stringified expression to evaluate, or a funcref without arguments.
 " Using a lambda works best.  Example:
@@ -162,7 +190,7 @@ endfunc
 " A second argument can be used to specify a different timeout in msec.
 "
 " Return zero for success, one for failure (like the assert function).
-func WaitForAssert(assert, ...)
+func g:WaitForAssert(assert, ...)
   let timeout = get(a:000, 0, 5000)
   if s:WaitForCommon(v:null, a:assert, timeout) < 0
     return 1
@@ -200,11 +228,11 @@ func s:WaitForCommon(expr, assert, timeout)
       call remove(v:errors, -1)
     endif
 
-    sleep 10m
+    sleep 1m
     if exists('*reltimefloat')
       let slept = float2nr(reltimefloat(reltime(start)) * 1000)
     else
-      let slept += 10
+      let slept += 1
     endif
   endwhile
 
index 67b21cb96261407f9d85da507c636adcb7e8bf95..19362aafdbf6722928e8d273c7c2daca2501b443 100644 (file)
@@ -157,14 +157,14 @@ func StopVimInTerminal(buf, kill = 1)
   call assert_equal("running", term_getstatus(a:buf))
 
   " Wait for all the pending updates to terminal to complete
-  call TermWait(a:buf)
+  call TermWait(a:buf, 1)
 
   " CTRL-O : works both in Normal mode and Insert mode to start a command line.
   " In Command-line it's inserted, the CTRL-U removes it again.
   call term_sendkeys(a:buf, "\<C-O>:\<C-U>qa!\<cr>")
 
   " Wait for all the pending updates to terminal to complete
-  call TermWait(a:buf)
+  call TermWait(a:buf, 1)
 
   " Wait for the terminal to end.
   call WaitForAssert({-> assert_equal("finished", term_getstatus(a:buf))})
index 80d58319681d28539e9a7618c930e91bc1f2a8ff..3db37a76b0c85614332a4ddc9aa4f7b1308c13e1 100644 (file)
@@ -36,6 +36,7 @@ func Test_balloon_eval_term()
   call TermWait(buf, 50)
   call term_sendkeys(buf, 'll')
   call term_sendkeys(buf, ":call Trigger()\<CR>")
+  sleep 150m " Wait for balloon to show up (100ms balloondelay time)
   call VerifyScreenDump(buf, 'Test_balloon_eval_term_01', {})
 
   " Make sure the balloon still shows after 'updatetime' passed and CursorHold
index c83ddf29ea1ca6e41a85282bdf5d80b86658ecce..85b1290d700faea8bab7939a320a492dc38c7835 100644 (file)
@@ -4,11 +4,15 @@ source screendump.vim
 
 CheckScreendump
 
+" Run the command in terminal and wait for it to complete via notification
+func s:RunCommandAndWait(buf, cmd)
+  call term_sendkeys(a:buf, a:cmd .. "; printf '" .. TermNotifyParentCmd(v:false) .. "'\<cr>")
+  call WaitForChildNotification()
+endfunc
+
 func Test_crash1()
   CheckNotBSD
   CheckExecutable dash
-  " Test 7 fails on Mac ...
-  CheckNotMac
 
   " The following used to crash Vim
   let opts = #{cmd: 'sh'}
@@ -19,70 +23,59 @@ func Test_crash1()
   let file = 'crash/poc_huaf1'
   let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  && echo "crash 1: [OK]" > X_crash1_result.txt' .. "\<cr>")
-  call TermWait(buf, 50)
+  call s:RunCommandAndWait(buf, args ..
+    \ '  && echo "crash 1: [OK]" > X_crash1_result.txt')
 
   let file = 'crash/poc_huaf2'
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  && echo "crash 2: [OK]" >> X_crash1_result.txt' .. "\<cr>")
-  call TermWait(buf, 50)
+  call s:RunCommandAndWait(buf, args ..
+    \ '  && echo "crash 2: [OK]" >> X_crash1_result.txt')
 
   let file = 'crash/poc_huaf3'
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  && echo "crash 3: [OK]" >> X_crash1_result.txt' .. "\<cr>")
-  call TermWait(buf, 100)
+  call s:RunCommandAndWait(buf, args ..
+    \ '  && echo "crash 3: [OK]" >> X_crash1_result.txt')
 
   let file = 'crash/bt_quickfix_poc'
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  && echo "crash 4: [OK]" >> X_crash1_result.txt' .. "\<cr>")
+  call s:RunCommandAndWait(buf, args ..
+    \ '  && echo "crash 4: [OK]" >> X_crash1_result.txt')
   " clean up
   call delete('Xerr')
-  " This test takes a bit longer
-  call TermWait(buf, 1000)
 
   let file = 'crash/poc_tagfunc.vim'
   let args = printf(cmn_args, vim, file)
   " using || because this poc causes vim to exit with exitstatus != 0
-  call term_sendkeys(buf, args ..
-    \ '  || echo "crash 5: [OK]" >> X_crash1_result.txt' .. "\<cr>")
+  call s:RunCommandAndWait(buf, args ..
+    \ '  || echo "crash 5: [OK]" >> X_crash1_result.txt')
 
-  call TermWait(buf, 100)
 
   let file = 'crash/bt_quickfix1_poc'
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  && echo "crash 6: [OK]" >> X_crash1_result.txt' .. "\<cr>")
+  call s:RunCommandAndWait(buf, args ..
+    \ '  && echo "crash 6: [OK]" >> X_crash1_result.txt')
   " clean up
   call delete('X')
-  call TermWait(buf, 3000)
 
   let file = 'crash/vim_regsub_both_poc'
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  && echo "crash 7: [OK]" >> X_crash1_result.txt' .. "\<cr>")
-  call TermWait(buf, 3000)
+  call s:RunCommandAndWait(buf, args ..
+    \ '  && echo "crash 7: [OK]" >> X_crash1_result.txt')
 
   let file = 'crash/vim_msg_trunc_poc'
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  || echo "crash 8: [OK]" >> X_crash1_result.txt' .. "\<cr>")
-  call TermWait(buf, 3000)
+  call s:RunCommandAndWait(buf, args ..
+    \ '  || echo "crash 8: [OK]" >> X_crash1_result.txt')
 
   let file = 'crash/crash_scrollbar'
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  && echo "crash 9: [OK]" >> X_crash1_result.txt' .. "\<cr>")
-  call TermWait(buf, 1000)
+  call s:RunCommandAndWait(buf, args ..
+    \ '  && echo "crash 9: [OK]" >> X_crash1_result.txt')
 
   let file = 'crash/editing_arg_idx_POC_1'
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  || echo "crash 10: [OK]" >> X_crash1_result.txt' .. "\<cr>")
-  call TermWait(buf, 1000)
+  call s:RunCommandAndWait(buf, args ..
+    \ '  || echo "crash 10: [OK]" >> X_crash1_result.txt')
   call delete('Xerr')
   call delete('@')
 
@@ -113,7 +106,6 @@ endfunc
 func Test_crash1_2()
   CheckNotBSD
   CheckExecutable dash
-  let g:test_is_flaky = 1
 
   " The following used to crash Vim
   let opts = #{cmd: 'sh'}
@@ -125,37 +117,32 @@ func Test_crash1_2()
   let file = 'crash/poc1'
   let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  && echo "crash 1: [OK]" > '.. result .. "\<cr>")
-  call TermWait(buf, 150)
+  call s:RunCommandAndWait(buf, args ..
+    \ '  && echo "crash 1: [OK]" > '.. result)
 
   let file = 'crash/poc_win_enter_ext'
   let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  && echo "crash 2: [OK]" >> '.. result .. "\<cr>")
-  call TermWait(buf, 350)
+  call s:RunCommandAndWait(buf, args ..
+    \ '  && echo "crash 2: [OK]" >> '.. result)
 
   let file = 'crash/poc_suggest_trie_walk'
   let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ '  && echo "crash 3: [OK]" >> '.. result .. "\<cr>")
-  call TermWait(buf, 150)
+  call s:RunCommandAndWait(buf, args ..
+    \ '  && echo "crash 3: [OK]" >> '.. result)
 
   let file = 'crash/poc_did_set_langmap'
   let cmn_args = "%s -u NONE -i NONE -n -X -m -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ ' ; echo "crash 4: [OK]" >> '.. result .. "\<cr>")
-  call TermWait(buf, 150)
+  call s:RunCommandAndWait(buf, args ..
+    \ ' ; echo "crash 4: [OK]" >> '.. result)
 
   let file = 'crash/reverse_text_overflow'
   let cmn_args = "%s -u NONE -i NONE -n -X -m -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args ..
-    \ ' ; echo "crash 5: [OK]" >> '.. result .. "\<cr>")
-  call TermWait(buf, 150)
+  call s:RunCommandAndWait(buf, args ..
+    \ ' ; echo "crash 5: [OK]" >> '.. result)
 
   " clean up
   exe buf .. "bw!"
@@ -181,64 +168,49 @@ func Test_crash1_3()
   let buf = RunVimInTerminal('sh', #{cmd: 'sh'})
 
   let file = 'crash/poc_ex_substitute'
-  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'\<cr>"
+  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args)
-  call TermWait(buf, 150)
+  call s:RunCommandAndWait(buf, args)
 
   let file = 'crash/poc_uaf_exec_instructions'
-  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'\<cr>"
+  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args)
-  call TermWait(buf, 150)
+  call s:RunCommandAndWait(buf, args)
 
   let file = 'crash/poc_uaf_check_argument_types'
-  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'\<cr>"
+  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args)
-  call TermWait(buf, 150)
+  call s:RunCommandAndWait(buf, args)
 
   let file = 'crash/double_free'
-  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'\<cr>"
+  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args)
-  call TermWait(buf, 50)
+  call s:RunCommandAndWait(buf, args)
 
   let file = 'crash/dialog_changed_uaf'
-  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'\<cr>"
+  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args)
-  call TermWait(buf, 150)
+  call s:RunCommandAndWait(buf, args)
 
   let file = 'crash/nullpointer'
-  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'\<cr>"
+  let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args)
-  call TermWait(buf, 50)
+  call s:RunCommandAndWait(buf, args)
 
   let file = 'crash/heap_overflow3'
   let cmn_args = "%s -u NONE -i NONE -n -X -m -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args)
-  call TermWait(buf, 150)
+  call s:RunCommandAndWait(buf, args)
 
   let file = 'crash/heap_overflow_glob2regpat'
   let cmn_args = "%s -u NONE -i NONE -n -X -m -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args)
-  call TermWait(buf, 50)
+  call s:RunCommandAndWait(buf, args)
 
   let file = 'crash/nullptr_regexp_nfa'
   let cmn_args = "%s -u NONE -i NONE -n -X -m -n -e -s -S %s -c ':qa!'"
   let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args)
-  call TermWait(buf, 50)
-
-  let file = 'crash/ex_redraw_crash'
-  let cmn_args = "%s -u NONE -i NONE -n -m -X -Z -e -s -S %s -c ':qa!'"
-  let args = printf(cmn_args, vim, file)
-  call term_sendkeys(buf, args)
-  call TermWait(buf, 150)
+  call s:RunCommandAndWait(buf, args)
 
   " clean up
   exe buf .. "bw!"
index 693f2015fcf9f36ddc989f687ba7b2948c41f170..bd0578eff98e6b543931629c4e059fdd53c915e3 100644 (file)
@@ -370,6 +370,7 @@ endfunc
 func Test_visual_ends_before_showbreak()
   CheckScreendump
 
+  " Redraw at the end is necessary due to https://github.com/vim/vim/issues/16620
   let lines =<< trim END
       vim9script
       &wrap = true
@@ -377,6 +378,7 @@ func Test_visual_ends_before_showbreak()
       &showbreak = '↪ '
       ['xxxxx ' .. 'y'->repeat(&columns - 6) .. ' zzzz']->setline(1)
       normal! wvel
+      redraw
   END
   call writefile(lines, 'XvisualEndsBeforeShowbreak', 'D')
   let buf = RunVimInTerminal('-S XvisualEndsBeforeShowbreak', #{rows: 6})
index c2419375a066e14775f697c92e236f2c153ad221..67bd95fe1176a45322b810b5c3ab26856813c301 100644 (file)
@@ -751,15 +751,15 @@ func Test_tag_guess()
   call writefile(code, 'Xfoo', 'D')
 
   let v:statusmsg = ''
-  ta func1
+  silent ta func1
   call assert_match('E435:', v:statusmsg)
   call assert_equal(2, line('.'))
   let v:statusmsg = ''
-  ta func2
+  silent ta func2
   call assert_match('E435:', v:statusmsg)
   call assert_equal(4, line('.'))
   let v:statusmsg = ''
-  ta func3
+  silent ta func3
   call assert_match('E435:', v:statusmsg)
   call assert_equal(5, line('.'))
   call assert_fails('ta func4', 'E434:')
@@ -1625,7 +1625,7 @@ func Test_tag_guess_short()
 
   let v:statusmsg = ''
   let @/ = ''
-  ta y
+  silent ta y
   call assert_match('E435:', v:statusmsg)
   call assert_equal(2, line('.'))
   call assert_match('<y', @/)
index d3744fab1b472ae29e00d4f12a7e2cba062fe9a8..9dbdfdac086677e5a94d3bd74904493b8efb1de7 100644 (file)
@@ -60,8 +60,8 @@ func Test_terminal_TerminalWinOpen()
   close
 
   if has("unix")
-    terminal ++hidden ++open sleep 1
-    sleep 1
+    terminal ++hidden ++open echo
+    call WaitForAssert({-> assert_equal('terminal', &buftype)})
     call assert_fails("echo b:done", 'E121:')
   endif
 
index 5c4563ccf7f69da661723fa9473fd40cc5ea3aa8..542f2ec53e8b03799b2f74d46e612f1875ae0bce 100644 (file)
@@ -292,11 +292,6 @@ endfunc
 func Test_termwinscroll_topline2()
   " calling the terminal API doesn't work on Windows
   CheckNotMSWindows
-  let g:test_is_flaky = 1
-  let g:print_complete = 0
-  func! Tapi_print_complete(bufnum, arglist)
-    let g:print_complete = 1
-  endfunc
 
   set termwinscroll=50000 mouse=a
   set shell=sh
@@ -310,17 +305,15 @@ func Test_termwinscroll_topline2()
   let num1 = &termwinscroll / 1000 * 999
   call writefile(range(num1), 'Xtext', 'D')
   call term_sendkeys(buf, "cat Xtext\<CR>")
-  call term_sendkeys(buf, 'printf ''\033]51;["call", "Tapi_print_complete", []]\007''' .. "\<cr>")
+  call term_sendkeys(buf, "printf '" .. TermNotifyParentCmd(v:false) .. "'\<cr>")
   let rows = term_getsize(buf)[0]
   let cnt = 0
-  while !g:print_complete && cnt <= 1000
-    " max number of runs
+  while !g:child_notification && cnt <= 50000
+    " Spin wait to process the terminal print as quickly as possible. This is
+    " more efficient than calling WaitForChildNotification() as we don't want
+    " to sleep here as the print is I/O-bound.
     let cnt += 1
-    " sleep a bit, to give the the terminal some time to finish
-
-    " It may take a while to finish on a slow system
-    " so wait a bit and handle the callback
-    call term_wait(buf)
+    call term_wait(buf, 0)
   endwhile
   call WaitForAssert({-> assert_match(string(num1 - 1), term_getline(buf, rows - 1) .. '\|' .. term_getline(buf, rows - 2))})
   call feedkeys("\<C-W>N", 'xt')
@@ -347,8 +340,6 @@ func Test_termwinscroll_topline2()
 
   exe buf . 'bwipe!'
   set termwinscroll& mouse& sh&
-  delfunc Tapi_print_complete
-  unlet! g:print_complete
 endfunc
 
 " Resizing the terminal window caused an ml_get error.
index 5865d18f4f9250fe5aba1b07d2f512e4524a92e1..0e5f70b944fab343694e97066f4cff5b08f14b00 100644 (file)
@@ -75,22 +75,30 @@ func Terminal_color(group_name, highlight_cmds, highlight_opt, open_cmds)
 
   let lines = [
        \ 'call setline(1, range(20))',
+    \ 'func NotifyParent()',
+    \ '  call echoraw("' .. TermNotifyParentCmd(v:true) .. '")',
+    \ 'endfunc',
        \ 'func OpenTerm()',
        \ '  set noruler',
-       \ "  call term_start('cat', #{vertical: 1, " .. a:highlight_opt .. "})",
+       \ "  call term_start('cat', #{vertical: 1, "
+    \      .. 'exit_cb: {->NotifyParent()}, '
+    \      .. a:highlight_opt .. "})",
+    \ '  call NotifyParent()',
        \ ] + a:open_cmds + [
        \ 'endfunc',
-       \ ] + a:highlight_cmds
+       \ ] + a:highlight_cmds + [
+    \ 'call NotifyParent()',
+    \ ]
   call writefile(lines, 'XtermStart', 'D')
   let buf = RunVimInTerminal('-S XtermStart', #{rows: 15})
-  call TermWait(buf, 100)
+  call WaitForChildNotification()
   call term_sendkeys(buf, ":call OpenTerm()\<CR>")
-  call TermWait(buf, 50)
+  call WaitForChildNotification()
   call term_sendkeys(buf, "hello\<CR>")
   call VerifyScreenDump(buf, 'Test_terminal_color_' .. a:group_name, {})
 
   call term_sendkeys(buf, "\<C-D>")
-  call TermWait(buf, 50)
+  call WaitForChildNotification()
   call StopVimInTerminal(buf)
 endfunc
 
@@ -270,11 +278,11 @@ func Test_terminal_in_popup()
        \ ]
   call writefile(lines, 'XtermPopup', 'D')
   let buf = RunVimInTerminal('-S XtermPopup', #{rows: 15})
-  call TermWait(buf, 200)
+  call TermWait(buf,0)
   call term_sendkeys(buf, ":call OpenTerm(0)\<CR>")
-  call TermWait(buf, 800)
+  call TermWait(buf,0)
   call term_sendkeys(buf, ":\<CR>")
-  call TermWait(buf, 500)
+  call TermWait(buf,0)
   call term_sendkeys(buf, "\<C-W>:echo getwinvar(g:winid, \"&buftype\") win_gettype(g:winid)\<CR>")
   call VerifyScreenDump(buf, 'Test_terminal_popup_1', {})
 
@@ -282,16 +290,16 @@ func Test_terminal_in_popup()
   call VerifyScreenDump(buf, 'Test_terminal_popup_2', {})
  
   call term_sendkeys(buf, ":call OpenTerm(1)\<CR>")
-  call TermWait(buf, 800)
+  call TermWait(buf,0)
   call term_sendkeys(buf, ":set hlsearch\<CR>")
-  call TermWait(buf, 500)
+  call TermWait(buf,0)
   call term_sendkeys(buf, "/edit\<CR>")
   call VerifyScreenDump(buf, 'Test_terminal_popup_3', {})
  
   call term_sendkeys(buf, "\<C-W>:call HidePopup()\<CR>")
   call VerifyScreenDump(buf, 'Test_terminal_popup_4', {})
   call term_sendkeys(buf, "\<CR>")
-  call TermWait(buf, 50)
+  call TermWait(buf,0)
 
   call term_sendkeys(buf, "\<C-W>:call ClosePopup()\<CR>")
   call VerifyScreenDump(buf, 'Test_terminal_popup_5', {})
@@ -307,9 +315,9 @@ func Test_terminal_in_popup()
   call term_sendkeys(buf, "A")
   call VerifyScreenDump(buf, 'Test_terminal_popup_8', {})
 
-  call TermWait(buf, 50)
+  call TermWait(buf,0)
   call term_sendkeys(buf, ":q\<CR>")
-  call TermWait(buf, 250)  " wait for terminal to vanish
+  call WaitForAssert({-> assert_equal(0, match(term_getline(buf, 6), '^5\s*$'))}, 250) " wait for terminal to vanish
 
   call StopVimInTerminal(buf)
 endfunc
@@ -353,27 +361,32 @@ func Terminal_in_popup_color(group_name, highlight_cmds, highlight_opt, popup_cm
 
   let lines = [
        \ 'call setline(1, range(20))',
+    \ 'func NotifyParent(...)',
+    \ '  call echoraw("' .. TermNotifyParentCmd(v:true) .. '")',
+    \ 'endfunc',
        \ 'func OpenTerm()',
-       \ "  let s:buf = term_start('cat', #{hidden: 1, "
+       \ "  let s:buf = term_start('cat', #{hidden: 1, term_finish: 'close', "
        \ .. a:highlight_opt .. "})",
-       \ '  let g:winid = popup_create(s:buf, #{border: [], '
-  \ .. a:popup_opt .. '})',
-  \ ] + a:popup_cmds + [
+    \ '  let g:winid = popup_create(s:buf, #{border: [], '
+    \      .. 'callback: {->NotifyParent()}, '
+    \      .. a:popup_opt .. '})',
+    \ ] + a:popup_cmds + [
+    \ '  call NotifyParent()',
        \ 'endfunc',
-       \ ] + a:highlight_cmds
+       \ ] + a:highlight_cmds + [
+    \ 'call NotifyParent()',
+    \ ]
   call writefile(lines, 'XtermPopup', 'D')
   let buf = RunVimInTerminal('-S XtermPopup', #{rows: 15})
-  call TermWait(buf, 100)
+  call WaitForChildNotification()
   call term_sendkeys(buf, ":set noruler\<CR>")
   call term_sendkeys(buf, ":call OpenTerm()\<CR>")
-  call TermWait(buf, 50)
+  call WaitForChildNotification()
   call term_sendkeys(buf, "hello\<CR>")
   call VerifyScreenDump(buf, 'Test_terminal_popup_' .. a:group_name, {})
 
   call term_sendkeys(buf, "\<C-D>")
-  call TermWait(buf, 50)
-  call term_sendkeys(buf, ":q\<CR>")
-  call TermWait(buf, 50)  " wait for terminal to vanish
+  call WaitForChildNotification()
   call StopVimInTerminal(buf)
 endfunc
 
index 4bde75faab9f0505dee3ec5b9e2b55906f034ae4..d2f621c26d3d0957fb4325a1b672bf1807a090f3 100644 (file)
@@ -44,11 +44,15 @@ func Test_timer_repeat_three()
   let slept = WaitFor('g:val == 3')
   call assert_equal(3, g:val)
   if has('reltime')
+    " Timer has an internal 1ms allowance in calculating due time, so it's
+    " possible for each timer to undershoot by 1ms resulting in only 49*3=147
+    " ms elapsed. Additionally we started the timer before we called
+    " WaitFor(), so the reported time could be a couple more ms below 147.
     if has('mac')
-      " Mac on Travis can be slow.
-      call assert_inrange(149, 400, slept)
+      " Mac in CI can be slow.
+      call assert_inrange(145, 400, slept)
     else
-      call assert_inrange(149, 250, slept)
+      call assert_inrange(145, 250, slept)
     endif
   else
     call assert_inrange(80, 200, slept)
@@ -143,13 +147,13 @@ def Test_timer_stopall_with_popup()
   # Another timer will fire in half a second and close it early after stopping
   # all timers.
   var pop = popup_create('Popup', {time: 10000})
-  var tmr = timer_start(500, (_) => {
+  var tmr = timer_start(100, (_) => {
     timer_stopall()
     popup_clear()
   })
-  sleep 1
+  sleep 100m
+  g:WaitForAssert(() => assert_equal([], popup_list()), 1000)
   assert_equal([], timer_info(tmr))
-  assert_equal([], popup_list())
 enddef
 
 func Test_timer_paused()
index 03335a464d62f3750faa1c5d3277bbdebe8aba5c..6c2ef59f9321eeec170f725e51d7991183cd75c5 100644 (file)
@@ -1559,10 +1559,12 @@ endfunc
 func Test_visual_hl_with_showbreak()
   CheckScreendump
 
+  " Redraw at the end is necessary due to https://github.com/vim/vim/issues/16620
   let lines =<< trim END
     setlocal showbreak=+
     call setline(1, repeat('a', &columns + 10))
     normal g$v4lo
+    redraw
   END
   call writefile(lines, 'XTest_visual_sbr', 'D')
 
index 1745ef3db34f6dd3602c2ccd6a52d300a667670c..85110f83f03f0e0c50d8ff2feb24ae5c31c583e0 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1110,
 /**/
     1109,
 /**/