xref: /vim-8.2.3635/src/testdir/screendump.vim (revision 94688b8a)
1" Functions shared by tests making screen dumps.
2
3" Only load this script once.
4if exists('*CanRunVimInTerminal')
5  finish
6endif
7
8" For most tests we need to be able to run terminal Vim with 256 colors.  On
9" MS-Windows the console only has 16 colors and the GUI can't run in a
10" terminal.
11func CanRunVimInTerminal()
12  return has('terminal') && !has('win32')
13endfunc
14
15" Skip the rest if there is no terminal feature at all.
16if !has('terminal')
17  finish
18endif
19
20source shared.vim
21
22" Run Vim with "arguments" in a new terminal window.
23" By default uses a size of 20 lines and 75 columns.
24" Returns the buffer number of the terminal.
25"
26" Options is a dictionary, these items are recognized:
27" "rows" - height of the terminal window (max. 20)
28" "cols" - width of the terminal window (max. 78)
29func RunVimInTerminal(arguments, options)
30  " If Vim doesn't exit a swap file remains, causing other tests to fail.
31  " Remove it here.
32  call delete(".swp")
33
34  if exists('$COLORFGBG')
35    " Clear $COLORFGBG to avoid 'background' being set to "dark", which will
36    " only be corrected if the response to t_RB is received, which may be too
37    " late.
38    let $COLORFGBG = ''
39  endif
40
41  " Make a horizontal and vertical split, so that we can get exactly the right
42  " size terminal window.  Works only when the current window is full width.
43  call assert_equal(&columns, winwidth(0))
44  split
45  vsplit
46
47  " Always do this with 256 colors and a light background.
48  set t_Co=256 background=light
49  hi Normal ctermfg=NONE ctermbg=NONE
50
51  " Make the window 20 lines high and 75 columns, unless told otherwise.
52  let rows = get(a:options, 'rows', 20)
53  let cols = get(a:options, 'cols', 75)
54
55  let cmd = GetVimCommandClean()
56
57  " Add -v to have gvim run in the terminal (if possible)
58  let cmd .= ' -v ' . a:arguments
59  let buf = term_start(cmd, {'curwin': 1, 'term_rows': rows, 'term_cols': cols})
60  if &termwinsize == ''
61    " in the GUI we may end up with a different size, try to set it.
62    if term_getsize(buf) != [rows, cols]
63      call term_setsize(buf, rows, cols)
64    endif
65    call assert_equal([rows, cols], term_getsize(buf))
66  else
67    let rows = term_getsize(buf)[0]
68    let cols = term_getsize(buf)[1]
69  endif
70
71  " Wait for "All" or "Top" of the ruler to be shown in the last line or in
72  " the status line of the last window. This can be quite slow (e.g. when
73  " using valgrind).
74  " If it fails then show the terminal contents for debugging.
75  try
76    call WaitFor({-> len(term_getline(buf, rows)) >= cols - 1 || len(term_getline(buf, rows - 1)) >= cols - 1})
77  catch /timed out after/
78    let lines = map(range(1, rows), {key, val -> term_getline(buf, val)})
79    call assert_report('RunVimInTerminal() failed, screen contents: ' . join(lines, "<NL>"))
80  endtry
81
82  return buf
83endfunc
84
85" Stop a Vim running in terminal buffer "buf".
86func StopVimInTerminal(buf)
87  call assert_equal("running", term_getstatus(a:buf))
88
89  " CTRL-O : works both in Normal mode and Insert mode to start a command line.
90  " In Command-line it's inserted, the CTRL-U removes it again.
91  call term_sendkeys(a:buf, "\<C-O>:\<C-U>qa!\<cr>")
92
93  call WaitForAssert({-> assert_equal("finished", term_getstatus(a:buf))})
94  only!
95endfunc
96
97" Verify that Vim running in terminal buffer "buf" matches the screen dump.
98" "options" is passed to term_dumpwrite().
99" The file name used is "dumps/{filename}.dump".
100" Optionally an extra argument can be passed which is prepended to the error
101" message.  Use this when using the same dump file with different options.
102" Will wait for up to a second for the screen dump to match.
103" Returns non-zero when verification fails.
104func VerifyScreenDump(buf, filename, options, ...)
105  let reference = 'dumps/' . a:filename . '.dump'
106  let testfile = a:filename . '.dump.failed'
107
108  let i = 0
109  while 1
110    " leave some time for updating the original window
111    sleep 10m
112    call delete(testfile)
113    call term_dumpwrite(a:buf, testfile, a:options)
114    if readfile(reference) == readfile(testfile)
115      call delete(testfile)
116      break
117    endif
118    if i == 100
119      " Leave the test file around for inspection.
120      let msg = 'See dump file difference: call term_dumpdiff("' . testfile . '", "' . reference . '")'
121      if a:0 == 1
122        let msg = a:1 . ': ' . msg
123      endif
124      call assert_report(msg)
125      return 1
126    endif
127    let i += 1
128  endwhile
129  return 0
130endfunc
131