test(messages): skip os_delay during tests

Problem:
Tests that trigger `os_delay` messages may take 1-3 seconds, wasting
build/CI time, since this serves no purpose in tests.

Solution:
- Introduce `msg_delay` for cases where `os_delay` is being used as
  a "UI feature".
- Skip `msg_delay` in tests.
This commit is contained in:
Justin M. Keyes
2025-12-18 21:29:00 -05:00
parent 245a4696a2
commit 2eb11f21eb
13 changed files with 46 additions and 24 deletions

View File

@@ -1992,7 +1992,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags)
emsg(_("W14: Warning: List of file names overflow"));
if (emsg_silent == 0 && !in_assert_fails && !ui_has(kUIMessages)) {
ui_flush();
os_delay(3001, true); // make sure it is noticed
msg_delay(3001, true); // make sure it is noticed
}
top_file_num = 1;
}

View File

@@ -94,7 +94,7 @@ void change_warning(buf_T *buf, int col)
msg_end();
if (msg_silent == 0 && !silent_mode && ui_active() && !ui_has(kUIMessages)) {
ui_flush();
os_delay(1002, true); // give the user time to think about it
msg_delay(1002, true); // give the user time to think about it
}
buf->b_did_warn = true;
redraw_cmdline = false; // don't redraw and erase the message
@@ -133,7 +133,7 @@ void changed(buf_T *buf)
// and don't let the emsg() set msg_scroll.
if (need_wait_return && emsg_silent == 0 && !in_assert_fails && !ui_has(kUIMessages)) {
ui_flush();
os_delay(2002, true);
msg_delay(2002, true);
wait_return(true);
msg_scroll = save_msg_scroll;
} else {

View File

@@ -3030,7 +3030,7 @@ int buf_check_timestamp(buf_T *buf)
if (emsg_silent == 0 && !in_assert_fails && !ui_has(kUIMessages)) {
ui_flush();
// give the user some time to think about it
os_delay(1004, true);
msg_delay(1004, true);
// don't redraw and erase the message
redraw_cmdline = false;

View File

@@ -2393,6 +2393,7 @@ static void highlight_list_two(int cnt, int id)
msg_puts_hl(&("N \bI \b! \b"[cnt / 11]), id, false);
msg_clr_eos();
ui_flush();
// TODO(justinmk): is this delay needed? ":hi" seems to work without it.
os_delay(cnt == 99 ? 40 : (uint64_t)cnt * 50, false);
}

View File

@@ -554,7 +554,7 @@ bool check_compl_option(bool dict_opt)
setcursor();
if (!ui_has(kUIMessages)) {
ui_flush();
os_delay(2004, false);
msg_delay(2004, false);
}
}
return false;

View File

@@ -154,6 +154,7 @@ static const char *err_extra_cmd =
void event_init(void)
{
loop_init(&main_loop, NULL);
env_init();
resize_events = multiqueue_new_child(main_loop.events);
autocmd_init();

View File

@@ -3923,6 +3923,20 @@ int vim_dialog_yesnoallcancel(int type, char *title, char *message, int dflt)
return VIM_CANCEL;
}
/// Force the user to see a message by pausing for `ms` milliseconds.
///
/// TODO(justinmk): Most of these cases may not be needed after "ui2"...
void msg_delay(uint64_t ms, bool ignoreinput)
{
if (nvim_testing) {
// XXX: Skip non-functional (UI only) delay in tests/CI.
ms = 100;
}
DLOG("%" PRIu64 " ms%s", ms, nvim_testing ? " (skipped by NVIM_TEST)" : "");
os_delay(ms, ignoreinput);
}
/// Check if there should be a delay to allow the user to see a message.
///
/// Used before clearing or redrawing the screen or the command line.
@@ -3931,7 +3945,7 @@ void msg_check_for_delay(bool check_msg_scroll)
if ((emsg_on_display || (check_msg_scroll && msg_scroll))
&& !did_wait_return && emsg_silent == 0 && !in_assert_fails && !ui_has(kUIMessages)) {
ui_flush();
os_delay(1006, true);
msg_delay(1006, true);
emsg_on_display = false;
if (check_msg_scroll) {
msg_scroll = false;

View File

@@ -702,9 +702,10 @@ static void normal_redraw_mode_message(NormalState *s)
ui_cursor_shape(); // show different cursor shape
ui_flush();
if (!ui_has(kUIMessages) && (msg_scroll || emsg_on_display)) {
os_delay(1003, true); // wait at least one second
msg_delay(1003, true); // wait at least one second
}
if (ui_has(kUIMessages)) {
// TODO(justinmk): wtf is this delay for? From before 2014.
os_delay(3003, false); // wait up to three seconds
}
State = save_State;

View File

@@ -57,6 +57,11 @@
#include "os/env.c.generated.h"
void env_init(void)
{
nvim_testing = os_env_exists("NVIM_TEST", false);
}
/// Like getenv(), but returns NULL if the variable is empty.
/// Result must be freed by the caller.
/// @see os_env_exists

View File

@@ -10,6 +10,9 @@
#include "nvim/os/stdpaths_defs.h"
#include "nvim/types_defs.h"
// True if when running in a test environment ($NVIM_TEST).
// TODO(justinmk): Can we use v:testing instead?
EXTERN bool nvim_testing INIT( = false);
extern char *default_vim_dir;
extern char *default_vimruntime_dir;
extern char *default_lib_dir;

View File

@@ -744,7 +744,7 @@ void do_tag(char *tag, int type, int count, int forceit, bool verbose)
}
if (ic && !msg_scrolled && msg_silent == 0 && !ui_has(kUIMessages)) {
ui_flush();
os_delay(1007, true);
msg_delay(1007, true);
}
}
@@ -2983,7 +2983,7 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
msg(_("E435: Couldn't find tag, just guessing!"), 0);
if (!msg_scrolled && msg_silent == 0 && !ui_has(kUIMessages)) {
ui_flush();
os_delay(1010, true);
msg_delay(1010, true);
}
}
retval = OK;

View File

@@ -215,18 +215,14 @@ static void tui_set_term_mode(TUIData *tui, TermMode mode, bool set)
void tui_handle_term_mode(TUIData *tui, TermMode mode, TermModeState state)
FUNC_ATTR_NONNULL_ALL
{
static TriState is_test = kNone;
if (is_test == kNone) {
// XXX: Skip some logs which are noisy in CI. #33599
is_test = os_env_exists("NVIM_TEST", false);
}
bool is_set = false;
switch (state) {
case kTermModeNotRecognized:
case kTermModePermanentlyReset:
// TODO(bfredl): This is really ILOG but we want it in all builds.
// add to show_verbose_terminfo() without being too racy ????
if (is_test == kFalse) {
if (!nvim_testing) {
// Very noisy in CI, don't log during tests. #33599
WLOG("TUI: terminal mode %d unavailable, state %d", mode, state);
}
// If the mode is not recognized, or if the terminal emulator does not allow it to be changed,
@@ -238,7 +234,8 @@ void tui_handle_term_mode(TUIData *tui, TermMode mode, TermModeState state)
FALLTHROUGH;
case kTermModeReset:
// The terminal supports changing the given mode
if (is_test == kFalse) {
if (!nvim_testing) {
// Very noisy in CI, don't log during tests. #33599
WLOG("TUI: terminal mode %d detected, state %d", mode, state);
}
switch (mode) {

View File

@@ -53,8 +53,7 @@ describe('startup', function()
it('prevents remote UI infinite loop', function()
clear()
local screen
screen = Screen.new(84, 3)
local screen = Screen.new(84, 3)
fn.jobstart(
{ nvim_prog, '-u', 'NONE', '--server', eval('v:servername'), '--remote-ui' },
{ term = true }
@@ -84,8 +83,7 @@ describe('startup', function()
it('-D does not hang #12647', function()
clear()
local screen
screen = Screen.new(60, 7)
local screen = Screen.new(60, 7)
-- not the same colors on windows for some reason
screen._default_attr_ids = nil
local id = fn.jobstart({
@@ -1414,16 +1412,18 @@ describe('user config init', function()
write_file(
table.concat({ xconfig, 'nvim', 'init.vim' }, pathsep),
[[
let g:vim_rc = 1
]]
let g:vim_rc = 1
]]
)
end)
it('loads default lua config, but shows an error', function()
clear { args_rm = { '-u' }, env = xenv }
feed('<cr><c-c>') -- Dismiss "Conflicting config …" message.
eq(1, eval('g:lua_rc'))
matches('^E5422: Conflicting configs', exec_capture('messages'))
t.matches(
'E5422: Conflicting configs: "Xhome.Xconfig.nvim.init.lua" "Xhome.Xconfig.nvim.init.vim"',
eval('v:errmsg')
)
end)
end)
end)