@@ -29,11 +29,83 @@ def ReadAndFilter(fname: string, filter: string): list<string>
2929 return contents
3030enddef
3131
32+ " Accommodate rendering idiosyncrasies (see #16559). For details, refer to
33+ " "VerifyScreenDump()" and the "options" dictionary passed to it: this is
34+ " an implementation of its "FileComparisonPreAction" entry. (This function
35+ " runs in couples with "g:ScreenDumpLookForFFFDChars()".)
36+ def g: ScreenDumpDiscardFFFDChars (
37+ state : dict <number> ,
38+ testdump: list <string> ,
39+ refdump: list <string> )
40+ if empty (state ) || len (testdump) != len (refdump)
41+ return
42+ endif
43+ for lstr: string in keys (state )
44+ const lnum: number = str2nr (lstr)
45+ const fst_fffd_idx: number = stridx (testdump[lnum], " \xef\xbf\xbd " )
46+ # Retroactively discard non- equal line suffixes . It is assumed that no
47+ # runs of U+ EFU+ BFU+ BD and no U+FFFDs are present in "refdump".
48+ if fst_fffd_idx >= 0
49+ # Mask the " ||" character cells and the cursor cell " >." .
50+ const masked_part: string = substitute (
51+ substitute (
52+ strpart (testdump[lnum], 0 , (fst_fffd_idx - 1 )),
53+ ' [>|]|' , ' |.' , ' g' ),
54+ ' |\@<!>' , ' |' , ' g' )
55+ const prev_cell_idx: number = strridx (masked_part, ' |' )
56+ # A series of repeated characters will be found recorded in shorthand;
57+ # e .g . " |α@3" stands for a cell of four " α" s . Replacing any repeated
58+ # multibyte character of a series with a U+ FFFD character will split the
59+ # series and its shorthand record will reflect this fact: " |α@2|�" .
60+ # Therefore, a common prefix to share for two corresponding lines can
61+ # extend to either an ASCII character (s ) cell before the leftmost U+ FFFD
62+ # character cell; or , a last - but- one arbitrary cell before the leftmost
63+ # U+ FFFD character cell; or , an empty string .
64+ const prefix: number = (prev_cell_idx >= 0 )
65+ ? (char2nr (strpart (masked_part, (prev_cell_idx + 1 ), 1 ), true) < 128 )
66+ ? fst_fffd_idx - 1
67+ : (strridx (masked_part, ' |' , (prev_cell_idx - 1 )) >= 0 )
68+ ? prev_cell_idx
69+ : 0
70+ : 0
71+ refdump[lnum] = strpart (refdump[lnum], 0 , prefix)
72+ testdump[lnum] = strpart (testdump[lnum], 0 , prefix)
73+ endif
74+ endfor
75+ enddef
76+
77+ " Accommodate rendering idiosyncrasies (see #16559). For details, refer to
78+ " "VerifyScreenDump()" and the "options" dictionary passed to it: this is
79+ " an implementation of its "NonEqualLineComparisonPostAction" entry. (This
80+ " function runs in couples with "g:ScreenDumpDiscardFFFDChars()".)
81+ def g: ScreenDumpLookForFFFDChars (
82+ state : dict <number> ,
83+ testdump: list <string> ,
84+ lnum: number )
85+ if stridx (testdump[lnum], " \xef\xbf\xbd " ) >= 0
86+ state [string (lnum)] = 1
87+ endif
88+ enddef
3289
3390" Verify that Vim running in terminal buffer "buf" matches the screen dump.
34- " "options" is passed to term_dumpwrite().
35- " Additionally, the "wait" entry can specify the maximum time to wait for the
36- " screen dump to match in msec (default 1000 msec).
91+ "
92+ " A copy of "options" is passed to "term_dumpwrite()". For convenience, this
93+ " dictionary supports other optional entries:
94+ " "wait", (default to 1000 msec at least)
95+ " the maximum time to wait for the screen dump to match in msec.
96+ " "FileComparisonPreAction", (default to a no-op action)
97+ " some Funcref to call, passing the following three arguments, each time
98+ " before the file contents of two screen dumps are compared:
99+ " some dictionary with some state entries;
100+ " the file contents of the newly generated screen dump;
101+ " the file contents of the reference screen dump.
102+ " "NonEqualLineComparisonPostAction", (default to a no-op action)
103+ " some Funcref to call, passing the following three arguments, each time
104+ " after a corresponding pair of lines is found not equal:
105+ " some dictionary with some state entries;
106+ " the file contents of the newly generated screen dump;
107+ " the zero-based number of the line whose copies are not equal.
108+ "
37109" The file name used is "dumps/{filename}.dump".
38110"
39111" To ignore part of the dump, provide a "dumps/{filename}.vim" file with
@@ -53,7 +125,24 @@ func VerifyScreenDump(buf, filename, options, ...)
53125 let filter = ' dumps/' . a: filename . ' .vim'
54126 let testfile = ' failed/' . a: filename . ' .dump'
55127
56- let max_loops = get (a: options , ' wait' , 1000 ) / 1
128+ let options_copy = copy (a: options )
129+ if has_key (options_copy, ' wait' )
130+ let max_loops = max ([0 , remove (options_copy, ' wait' )])
131+ else
132+ let max_loops = 1000
133+ endif
134+ if has_key (options_copy, ' FileComparisonPreAction' )
135+ let FileComparisonPreAction = remove (options_copy, ' FileComparisonPreAction' )
136+ let CopyStringList = {_refdump - > copy (_refdump)}
137+ else
138+ let FileComparisonPreAction = {_state, _testdump, _refdump - > 0 }
139+ let CopyStringList = {_refdump - > _refdump}
140+ endif
141+ if has_key (options_copy, ' NonEqualLineComparisonPostAction' )
142+ let NonEqualLineComparisonPostAction = remove (options_copy, ' NonEqualLineComparisonPostAction' )
143+ else
144+ let NonEqualLineComparisonPostAction = {_state, _testdump, _lnum - > 0 }
145+ endif
57146
58147 " Starting a terminal to make a screendump is always considered flaky.
59148 let g: test_is_flaky = 1
@@ -76,21 +165,25 @@ func VerifyScreenDump(buf, filename, options, ...)
76165 " Leave a bit of time for updating the original window while we spin wait.
77166 sleep 10 m
78167 call delete (testfile)
79- call term_dumpwrite (a: buf , testfile, a: options )
168+ call term_dumpwrite (a: buf , testfile, options_copy )
80169 call assert_report (' See new dump file: call term_dumpload("testdir/' .. testfile .. ' ")' )
81170 " No point in retrying.
82171 let g: run_nr = 10
83172 return 1
84173 endif
85174
86- let refdump = ReadAndFilter (reference, filter )
175+ let refdump_orig = ReadAndFilter (reference, filter )
176+ let state = {}
87177 let i = 0
88178 while 1
89179 " Leave a bit of time for updating the original window while we spin wait.
90180 sleep 1 m
91181 call delete (testfile)
92- call term_dumpwrite (a: buf , testfile, a: options )
182+ call term_dumpwrite (a: buf , testfile, options_copy)
183+ " Filtering done with "FileComparisonPreAction()" may change "refdump*".
184+ let refdump = CopyStringList (refdump_orig)
93185 let testdump = ReadAndFilter (testfile, filter )
186+ call FileComparisonPreAction (state , testdump, refdump)
94187 if refdump == testdump
95188 call delete (testfile)
96189 if did_mkdir
@@ -116,6 +209,7 @@ func VerifyScreenDump(buf, filename, options, ...)
116209 endif
117210 if testdump[j ] != refdump[j ]
118211 let msg = msg . ' ; difference in line ' . (j + 1 ) . ' : "' . testdump[j ] . ' "'
212+ call NonEqualLineComparisonPostAction (state , testdump, j )
119213 endif
120214 endfor
121215
0 commit comments