blob: d7207d41a1e882ff086c00191338218a5d2545e2 [file] [log] [blame]
Bram Moolenaarda650582018-02-20 15:51:40 +01001" Functions shared by tests making screen dumps.
2
3" Only load this script once.
Bram Moolenaar7a39dd72019-06-23 00:50:15 +02004if exists('*VerifyScreenDump')
Bram Moolenaarda650582018-02-20 15:51:40 +01005 finish
6endif
7
Bram Moolenaar7a39dd72019-06-23 00:50:15 +02008source shared.vim
9source term_util.vim
Bram Moolenaarf2732452018-06-03 14:47:35 +020010
11" Skip the rest if there is no terminal feature at all.
12if !has('terminal')
Bram Moolenaar6bb2cdf2018-02-24 19:53:53 +010013 finish
14endif
15
Bram Moolenaar11901392022-09-26 19:50:44 +010016" Read a dump file "fname" and if "filter" exists apply it to the text.
17def ReadAndFilter(fname: string, filter: string): list<string>
18 var contents = readfile(fname)
19
20 if filereadable(filter)
21 # do this in the bottom window so that the terminal window is unaffected
22 wincmd j
23 enew
24 setline(1, contents)
25 exe "source " .. filter
26 contents = getline(1, '$')
27 enew!
28 wincmd k
29 redraw
30 endif
31
32 return contents
33enddef
34
35
Bram Moolenaarda650582018-02-20 15:51:40 +010036" Verify that Vim running in terminal buffer "buf" matches the screen dump.
Bram Moolenaar6bb2cdf2018-02-24 19:53:53 +010037" "options" is passed to term_dumpwrite().
Bram Moolenaar3e794272022-05-06 11:21:19 +010038" Additionally, the "wait" entry can specify the maximum time to wait for the
39" screen dump to match in msec (default 1000 msec).
Bram Moolenaarda650582018-02-20 15:51:40 +010040" The file name used is "dumps/{filename}.dump".
Bram Moolenaar11901392022-09-26 19:50:44 +010041"
42" To ignore part of the dump, provide a "dumps/{filename}.vim" file with
43" Vim commands to be applied to both the reference and the current dump, so
44" that parts that are irrelevant are not used for the comparison. The result
45" is NOT written, thus "term_dumpdiff()" shows the difference anyway.
46"
Bram Moolenaar6f8bdab2018-09-09 22:02:24 +020047" Optionally an extra argument can be passed which is prepended to the error
48" message. Use this when using the same dump file with different options.
Bram Moolenaar6f8bdab2018-09-09 22:02:24 +020049" Returns non-zero when verification fails.
50func VerifyScreenDump(buf, filename, options, ...)
Drew Vogelea67ba72025-05-07 22:05:17 +020051 if has('gui_running') && exists("g:check_screendump_called") && g:check_screendump_called == v:false
52 echoerr "VerifyScreenDump() called from a test that lacks a CheckScreendump guard."
53 return 1
54 endif
Bram Moolenaarda650582018-02-20 15:51:40 +010055 let reference = 'dumps/' . a:filename . '.dump'
Bram Moolenaar11901392022-09-26 19:50:44 +010056 let filter = 'dumps/' . a:filename . '.vim'
Bram Moolenaaref7f0e32019-03-30 15:59:51 +010057 let testfile = 'failed/' . a:filename . '.dump'
58
Yee Cheng Chine70587d2025-02-13 20:55:45 +010059 let max_loops = get(a:options, 'wait', 1000) / 1
Bram Moolenaar3e794272022-05-06 11:21:19 +010060
Bram Moolenaar3cdcb092020-03-18 19:18:10 +010061 " Starting a terminal to make a screendump is always considered flaky.
Bram Moolenaar30d53e22020-03-18 21:10:44 +010062 let g:test_is_flaky = 1
Millybaab7c02024-10-28 21:56:14 +010063 let g:giveup_same_error = 0
Bram Moolenaar3cdcb092020-03-18 19:18:10 +010064
Yegappan Lakshmanan560dff42022-02-10 19:52:10 +000065 " wait for the pending updates to be handled.
Yee Cheng Chine70587d2025-02-13 20:55:45 +010066 call TermWait(a:buf, 0)
Yegappan Lakshmanan560dff42022-02-10 19:52:10 +000067
Bram Moolenaar1bc353b2019-09-01 14:45:28 +020068 " Redraw to execute the code that updates the screen. Otherwise we get the
Bram Moolenaar87dcfd72019-04-13 22:35:29 +020069 " text and attributes only from the internal buffer.
70 redraw
71
Bram Moolenaar11901392022-09-26 19:50:44 +010072 if filereadable(reference)
73 let refdump = ReadAndFilter(reference, filter)
74 else
75 " Must be a new screendump, always fail
76 let refdump = []
77 endif
78
Bram Moolenaaref7f0e32019-03-30 15:59:51 +010079 let did_mkdir = 0
80 if !isdirectory('failed')
81 let did_mkdir = 1
82 call mkdir('failed')
83 endif
Bram Moolenaarda650582018-02-20 15:51:40 +010084
85 let i = 0
86 while 1
Yee Cheng Chine70587d2025-02-13 20:55:45 +010087 " leave a bit of time for updating the original window while we spin wait.
88 sleep 1m
Bram Moolenaarda650582018-02-20 15:51:40 +010089 call delete(testfile)
Bram Moolenaar6bb2cdf2018-02-24 19:53:53 +010090 call term_dumpwrite(a:buf, testfile, a:options)
Millybaab7c02024-10-28 21:56:14 +010091
92 if refdump->empty()
93 let msg = 'See new dump file: call term_dumpload("testdir/' .. testfile .. '")'
94 call assert_report(msg)
95 " no point in retrying
96 let g:run_nr = 10
97 return 1
98 endif
99
Bram Moolenaar11901392022-09-26 19:50:44 +0100100 let testdump = ReadAndFilter(testfile, filter)
Bram Moolenaar353aca12019-02-21 17:05:59 +0100101 if refdump == testdump
Bram Moolenaarda650582018-02-20 15:51:40 +0100102 call delete(testfile)
Bram Moolenaaref7f0e32019-03-30 15:59:51 +0100103 if did_mkdir
104 call delete('failed', 'd')
105 endif
Millybaab7c02024-10-28 21:56:14 +0100106 if i > 0
107 call remove(v:errors, -1)
108 endif
Bram Moolenaarda650582018-02-20 15:51:40 +0100109 break
110 endif
Millybaab7c02024-10-28 21:56:14 +0100111
112 " Leave the failed dump around for inspection.
113 let msg = 'See dump file difference: call term_dumpdiff("testdir/' .. testfile .. '", "testdir/' .. reference .. '")'
114 if a:0 == 1
115 let msg = a:1 . ': ' . msg
116 endif
117 if len(testdump) != len(refdump)
118 let msg = msg . '; line count is ' . len(testdump) . ' instead of ' . len(refdump)
119 endif
120 for j in range(len(refdump))
121 if j >= len(testdump)
122 break
Bram Moolenaar353aca12019-02-21 17:05:59 +0100123 endif
Millybaab7c02024-10-28 21:56:14 +0100124 if testdump[j] != refdump[j]
125 let msg = msg . '; difference in line ' . (j + 1) . ': "' . testdump[j] . '"'
126 endif
127 endfor
128
129 " Always add the last error so that it is displayed on timeout.
130 " See TestTimeout() in runtest.vim.
131 if i > 0
132 call remove(v:errors, -1)
133 endif
134 call assert_report(msg)
135
136 let i += 1
137 if i >= max_loops
Bram Moolenaar6f8bdab2018-09-09 22:02:24 +0200138 return 1
Bram Moolenaarda650582018-02-20 15:51:40 +0100139 endif
Bram Moolenaarda650582018-02-20 15:51:40 +0100140 endwhile
Bram Moolenaar6f8bdab2018-09-09 22:02:24 +0200141 return 0
Bram Moolenaarda650582018-02-20 15:51:40 +0100142endfunc