blob: 71fdedc5cfbd9d36c970f6d9a8cfa80627b0fbcf [file] [log] [blame]
Bram Moolenaar113bf062019-04-17 16:54:05 +02001" Tests for the Vim script debug commands
2
3source shared.vim
4source screendump.vim
Bram Moolenaar8c5a2782019-08-07 23:07:07 +02005source check.vim
Bram Moolenaar113bf062019-04-17 16:54:05 +02006
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02007CheckRunVimInTerminal
8
9func CheckCWD()
10 " Check that the longer lines don't wrap due to the length of the script name
11 " in cwd
12 let script_len = len( getcwd() .. '/Xtest1.vim' )
13 let longest_line = len( 'Breakpoint in "" line 1' )
14 if script_len > ( 75 - longest_line )
15 throw 'Skipped: Your CWD has too many characters'
16 endif
17endfunc
18command! -nargs=0 -bar CheckCWD call CheckCWD()
19
Bram Moolenaar18dc3552020-11-22 14:24:00 +010020" "options" argument can contain:
21" 'msec' - time to wait for a match
22" 'match' - "pattern" to use "lines" as pattern instead of text
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020023func CheckDbgOutput(buf, lines, options = {})
24 " Verify the expected output
25 let lnum = 20 - len(a:lines)
Bram Moolenaar18dc3552020-11-22 14:24:00 +010026 let msec = get(a:options, 'msec', 1000)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020027 for l in a:lines
28 if get(a:options, 'match', 'equal') ==# 'pattern'
Bram Moolenaar18dc3552020-11-22 14:24:00 +010029 call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, msec)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020030 else
Bram Moolenaar18dc3552020-11-22 14:24:00 +010031 call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, msec)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020032 endif
33 let lnum += 1
34 endfor
35endfunc
36
Bram Moolenaar113bf062019-04-17 16:54:05 +020037" Run a Vim debugger command
38" If the expected output argument is supplied, then check for it.
39func RunDbgCmd(buf, cmd, ...)
40 call term_sendkeys(a:buf, a:cmd . "\r")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +020041 call TermWait(a:buf)
Bram Moolenaar113bf062019-04-17 16:54:05 +020042
43 if a:0 != 0
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020044 let options = #{match: 'equal'}
45 if a:0 > 1
46 call extend(options, a:2)
47 endif
48 call CheckDbgOutput(a:buf, a:1, options)
Bram Moolenaar113bf062019-04-17 16:54:05 +020049 endif
50endfunc
51
52" Debugger tests
53func Test_Debugger()
Bram Moolenaar113bf062019-04-17 16:54:05 +020054 " Create a Vim script with some functions
Bram Moolenaare7eb9272019-06-24 00:58:07 +020055 let lines =<< trim END
56 func Foo()
57 let var1 = 1
58 let var2 = Bar(var1) + 9
59 return var2
60 endfunc
61 func Bar(var)
62 let var1 = 2 + a:var
63 let var2 = Bazz(var1) + 4
64 return var2
65 endfunc
66 func Bazz(var)
67 try
68 let var1 = 3 + a:var
69 let var3 = "another var"
70 let var3 = "value2"
71 catch
72 let var4 = "exception"
73 endtry
74 return var1
75 endfunc
76 END
77 call writefile(lines, 'Xtest.vim')
Bram Moolenaar113bf062019-04-17 16:54:05 +020078
79 " Start Vim in a terminal
80 let buf = RunVimInTerminal('-S Xtest.vim', {})
81
82 " Start the Vim debugger
Bram Moolenaarddd33082019-06-03 23:07:25 +020083 call RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()'])
Bram Moolenaar113bf062019-04-17 16:54:05 +020084
85 " Create a few stack frames by stepping through functions
Bram Moolenaarddd33082019-06-03 23:07:25 +020086 call RunDbgCmd(buf, 'step', ['line 1: let var1 = 1'])
87 call RunDbgCmd(buf, 'step', ['line 2: let var2 = Bar(var1) + 9'])
88 call RunDbgCmd(buf, 'step', ['line 1: let var1 = 2 + a:var'])
89 call RunDbgCmd(buf, 'step', ['line 2: let var2 = Bazz(var1) + 4'])
90 call RunDbgCmd(buf, 'step', ['line 1: try'])
91 call RunDbgCmd(buf, 'step', ['line 2: let var1 = 3 + a:var'])
92 call RunDbgCmd(buf, 'step', ['line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +020093
94 " check backtrace
95 call RunDbgCmd(buf, 'backtrace', [
96 \ ' 2 function Foo[2]',
97 \ ' 1 Bar[2]',
98 \ '->0 Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +020099 \ 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200100
101 " Check variables in different stack frames
102 call RunDbgCmd(buf, 'echo var1', ['6'])
103
104 call RunDbgCmd(buf, 'up')
105 call RunDbgCmd(buf, 'back', [
106 \ ' 2 function Foo[2]',
107 \ '->1 Bar[2]',
108 \ ' 0 Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200109 \ 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200110 call RunDbgCmd(buf, 'echo var1', ['3'])
111
112 call RunDbgCmd(buf, 'u')
113 call RunDbgCmd(buf, 'bt', [
114 \ '->2 function Foo[2]',
115 \ ' 1 Bar[2]',
116 \ ' 0 Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200117 \ 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200118 call RunDbgCmd(buf, 'echo var1', ['1'])
119
120 " Undefined variables
121 call RunDbgCmd(buf, 'step')
122 call RunDbgCmd(buf, 'frame 2')
123 call RunDbgCmd(buf, 'echo var3', [
124 \ 'Error detected while processing function Foo[2]..Bar[2]..Bazz:',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200125 \ 'line 4:',
Bram Moolenaar113bf062019-04-17 16:54:05 +0200126 \ 'E121: Undefined variable: var3'])
127
128 " var3 is defined in this level with some other value
129 call RunDbgCmd(buf, 'fr 0')
130 call RunDbgCmd(buf, 'echo var3', ['another var'])
131
132 call RunDbgCmd(buf, 'step')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200133 call RunDbgCmd(buf, '')
134 call RunDbgCmd(buf, '')
135 call RunDbgCmd(buf, '')
136 call RunDbgCmd(buf, '')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200137 call RunDbgCmd(buf, 'step', [
138 \ 'function Foo[2]..Bar',
139 \ 'line 3: End of function'])
140 call RunDbgCmd(buf, 'up')
141
142 " Undefined var2
143 call RunDbgCmd(buf, 'echo var2', [
144 \ 'Error detected while processing function Foo[2]..Bar:',
145 \ 'line 3:',
146 \ 'E121: Undefined variable: var2'])
147
148 " Var2 is defined with 10
149 call RunDbgCmd(buf, 'down')
150 call RunDbgCmd(buf, 'echo var2', ['10'])
151
152 " Backtrace movements
153 call RunDbgCmd(buf, 'b', [
154 \ ' 1 function Foo[2]',
155 \ '->0 Bar',
156 \ 'line 3: End of function'])
157
158 " next command cannot go down, we are on bottom
159 call RunDbgCmd(buf, 'down', ['frame is zero'])
160 call RunDbgCmd(buf, 'up')
161
162 " next command cannot go up, we are on top
163 call RunDbgCmd(buf, 'up', ['frame at highest level: 1'])
164 call RunDbgCmd(buf, 'where', [
165 \ '->1 function Foo[2]',
166 \ ' 0 Bar',
167 \ 'line 3: End of function'])
168
169 " fil is not frame or finish, it is file
170 call RunDbgCmd(buf, 'fil', ['"[No Name]" --No lines in buffer--'])
171
172 " relative backtrace movement
173 call RunDbgCmd(buf, 'fr -1')
174 call RunDbgCmd(buf, 'frame', [
175 \ ' 1 function Foo[2]',
176 \ '->0 Bar',
177 \ 'line 3: End of function'])
178
179 call RunDbgCmd(buf, 'fr +1')
180 call RunDbgCmd(buf, 'fram', [
181 \ '->1 function Foo[2]',
182 \ ' 0 Bar',
183 \ 'line 3: End of function'])
184
185 " go beyond limits does not crash
186 call RunDbgCmd(buf, 'fr 100', ['frame at highest level: 1'])
187 call RunDbgCmd(buf, 'fra', [
188 \ '->1 function Foo[2]',
189 \ ' 0 Bar',
190 \ 'line 3: End of function'])
191
192 call RunDbgCmd(buf, 'frame -40', ['frame is zero'])
193 call RunDbgCmd(buf, 'fram', [
194 \ ' 1 function Foo[2]',
195 \ '->0 Bar',
196 \ 'line 3: End of function'])
197
198 " final result 19
199 call RunDbgCmd(buf, 'cont', ['19'])
200
201 " breakpoints tests
202
203 " Start a debug session, so that reading the last line from the terminal
204 " works properly.
Bram Moolenaar18dc3552020-11-22 14:24:00 +0100205 call RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200206
207 " No breakpoints
208 call RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
209
210 " Place some breakpoints
211 call RunDbgCmd(buf, 'breaka func Bar')
212 call RunDbgCmd(buf, 'breaklis', [' 1 func Bar line 1'])
213 call RunDbgCmd(buf, 'breakadd func 3 Bazz')
214 call RunDbgCmd(buf, 'breaklist', [' 1 func Bar line 1',
215 \ ' 2 func Bazz line 3'])
216
217 " Check whether the breakpoints are hit
218 call RunDbgCmd(buf, 'cont', [
219 \ 'Breakpoint in "Bar" line 1',
220 \ 'function Foo[2]..Bar',
221 \ 'line 1: let var1 = 2 + a:var'])
222 call RunDbgCmd(buf, 'cont', [
223 \ 'Breakpoint in "Bazz" line 3',
224 \ 'function Foo[2]..Bar[2]..Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200225 \ 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200226
227 " Delete the breakpoints
228 call RunDbgCmd(buf, 'breakd 1')
229 call RunDbgCmd(buf, 'breakli', [' 2 func Bazz line 3'])
230 call RunDbgCmd(buf, 'breakdel func 3 Bazz')
231 call RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
232
233 call RunDbgCmd(buf, 'cont')
234
235 " Make sure the breakpoints are removed
236 call RunDbgCmd(buf, ':echo Foo()', ['19'])
237
238 " Delete a non-existing breakpoint
239 call RunDbgCmd(buf, ':breakdel 2', ['E161: Breakpoint not found: 2'])
240
241 " Expression breakpoint
242 call RunDbgCmd(buf, ':breakadd func 2 Bazz')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200243 call RunDbgCmd(buf, ':echo Bazz(1)', [
244 \ 'Entering Debug mode. Type "cont" to continue.',
245 \ 'function Bazz',
246 \ 'line 2: let var1 = 3 + a:var'])
247 call RunDbgCmd(buf, 'step')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200248 call RunDbgCmd(buf, 'step')
249 call RunDbgCmd(buf, 'breaka expr var3')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200250 call RunDbgCmd(buf, 'breakl', [' 3 func Bazz line 2',
251 \ ' 4 expr var3'])
252 call RunDbgCmd(buf, 'cont', ['Breakpoint in "Bazz" line 5',
Bram Moolenaar113bf062019-04-17 16:54:05 +0200253 \ 'Oldval = "''another var''"',
254 \ 'Newval = "''value2''"',
255 \ 'function Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200256 \ 'line 5: catch'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200257
258 call RunDbgCmd(buf, 'breakdel *')
259 call RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
260
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200261 " Check for error cases
262 call RunDbgCmd(buf, 'breakadd abcd', [
263 \ 'Error detected while processing function Bazz:',
264 \ 'line 5:',
265 \ 'E475: Invalid argument: abcd'])
266 call RunDbgCmd(buf, 'breakadd func', ['E475: Invalid argument: func'])
267 call RunDbgCmd(buf, 'breakadd func 2', ['E475: Invalid argument: func 2'])
268 call RunDbgCmd(buf, 'breaka func a()', ['E475: Invalid argument: func a()'])
269 call RunDbgCmd(buf, 'breakd abcd', ['E475: Invalid argument: abcd'])
270 call RunDbgCmd(buf, 'breakd func', ['E475: Invalid argument: func'])
271 call RunDbgCmd(buf, 'breakd func a()', ['E475: Invalid argument: func a()'])
272 call RunDbgCmd(buf, 'breakd func a', ['E161: Breakpoint not found: func a'])
273 call RunDbgCmd(buf, 'breakd expr', ['E475: Invalid argument: expr'])
274 call RunDbgCmd(buf, 'breakd expr x', [
275 \ 'E121: Undefined variable: x',
276 \ 'E161: Breakpoint not found: expr x'])
277
Bram Moolenaar113bf062019-04-17 16:54:05 +0200278 " finish the current function
279 call RunDbgCmd(buf, 'finish', [
280 \ 'function Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200281 \ 'line 8: End of function'])
282 call RunDbgCmd(buf, 'cont')
283
284 " Test for :next
285 call RunDbgCmd(buf, ':debug echo Bar(1)')
286 call RunDbgCmd(buf, 'step')
287 call RunDbgCmd(buf, 'next')
288 call RunDbgCmd(buf, '', [
289 \ 'function Bar',
290 \ 'line 3: return var2'])
291 call RunDbgCmd(buf, 'c')
292
293 " Test for :interrupt
294 call RunDbgCmd(buf, ':debug echo Bazz(1)')
295 call RunDbgCmd(buf, 'step')
296 call RunDbgCmd(buf, 'step')
297 call RunDbgCmd(buf, 'interrupt', [
298 \ 'Exception thrown: Vim:Interrupt',
299 \ 'function Bazz',
300 \ 'line 5: catch'])
301 call RunDbgCmd(buf, 'c')
302
303 " Test for :quit
304 call RunDbgCmd(buf, ':debug echo Foo()')
305 call RunDbgCmd(buf, 'breakdel *')
306 call RunDbgCmd(buf, 'breakadd func 3 Foo')
307 call RunDbgCmd(buf, 'breakadd func 3 Bazz')
308 call RunDbgCmd(buf, 'cont', [
309 \ 'Breakpoint in "Bazz" line 3',
310 \ 'function Foo[2]..Bar[2]..Bazz',
311 \ 'line 3: let var3 = "another var"'])
312 call RunDbgCmd(buf, 'quit', [
313 \ 'Breakpoint in "Foo" line 3',
314 \ 'function Foo',
315 \ 'line 3: return var2'])
316 call RunDbgCmd(buf, 'breakdel *')
317 call RunDbgCmd(buf, 'quit')
318 call RunDbgCmd(buf, 'enew! | only!')
319
320 call StopVimInTerminal(buf)
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200321endfunc
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200322
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200323func Test_Debugger_breakadd()
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200324 " Tests for :breakadd file and :breakadd here
325 " Breakpoints should be set before sourcing the file
326
Bram Moolenaare7eb9272019-06-24 00:58:07 +0200327 let lines =<< trim END
328 let var1 = 10
329 let var2 = 20
330 let var3 = 30
331 let var4 = 40
332 END
333 call writefile(lines, 'Xtest.vim')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200334
335 " Start Vim in a terminal
336 let buf = RunVimInTerminal('Xtest.vim', {})
337 call RunDbgCmd(buf, ':breakadd file 2 Xtest.vim')
338 call RunDbgCmd(buf, ':4 | breakadd here')
339 call RunDbgCmd(buf, ':source Xtest.vim', ['line 2: let var2 = 20'])
340 call RunDbgCmd(buf, 'cont', ['line 4: let var4 = 40'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200341 call RunDbgCmd(buf, 'cont')
342
343 call StopVimInTerminal(buf)
344
345 call delete('Xtest.vim')
Bram Moolenaar16c62322020-08-13 19:20:04 +0200346 %bw!
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200347
Bram Moolenaar16c62322020-08-13 19:20:04 +0200348 call assert_fails('breakadd here', 'E32:')
Bram Moolenaar531be472020-09-23 22:38:05 +0200349 call assert_fails('breakadd file Xtest.vim /\)/', 'E55:')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200350endfunc
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200351
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200352def Test_Debugger_breakadd_expr()
353 var lines =<< trim END
354 vim9script
355 func g:EarlyFunc()
356 endfunc
357 breakadd expr DoesNotExist()
358 func g:LaterFunc()
359 endfunc
360 breakdel *
361 END
362 writefile(lines, 'Xtest.vim')
363
364 # Start Vim in a terminal
365 var buf = RunVimInTerminal('-S Xtest.vim', {wait_for_ruler: 0})
366 call TermWait(buf)
367
368 # Despite the failure the functions are defined
369 RunDbgCmd(buf, ':function g:EarlyFunc',
370 ['function EarlyFunc()', 'endfunction'], {match: 'pattern'})
371 RunDbgCmd(buf, ':function g:LaterFunc',
372 ['function LaterFunc()', 'endfunction'], {match: 'pattern'})
373
374 call StopVimInTerminal(buf)
375 call delete('Xtest.vim')
376enddef
377
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200378func Test_Backtrace_Through_Source()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200379 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200380 let file1 =<< trim END
381 func SourceAnotherFile()
382 source Xtest2.vim
383 endfunc
384
385 func CallAFunction()
386 call SourceAnotherFile()
387 call File2Function()
388 endfunc
389
390 func GlobalFunction()
391 call CallAFunction()
392 endfunc
393 END
394 call writefile(file1, 'Xtest1.vim')
395
396 let file2 =<< trim END
397 func DoAThing()
398 echo "DoAThing"
399 endfunc
400
401 func File2Function()
402 call DoAThing()
403 endfunc
404
405 call File2Function()
406 END
407 call writefile(file2, 'Xtest2.vim')
408
409 let buf = RunVimInTerminal('-S Xtest1.vim', {})
410
411 call RunDbgCmd(buf,
412 \ ':debug call GlobalFunction()',
413 \ ['cmd: call GlobalFunction()'])
414 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
415
416 call RunDbgCmd(buf, 'backtrace', ['>backtrace',
417 \ '->0 function GlobalFunction',
418 \ 'line 1: call CallAFunction()'])
419
420 call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
421 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
422
423 call RunDbgCmd(buf, 'backtrace', ['>backtrace',
424 \ ' 2 function GlobalFunction[1]',
425 \ ' 1 CallAFunction[1]',
426 \ '->0 SourceAnotherFile',
427 \ 'line 1: source Xtest2.vim'])
428
429 " Step into the 'source' command. Note that we print the full trace all the
430 " way though the source command.
431 call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
432 call RunDbgCmd(buf, 'backtrace', [
433 \ '>backtrace',
434 \ ' 3 function GlobalFunction[1]',
435 \ ' 2 CallAFunction[1]',
436 \ ' 1 SourceAnotherFile[1]',
437 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
438 \ 'line 1: func DoAThing()'])
439
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200440 call RunDbgCmd( buf, 'up' )
441 call RunDbgCmd( buf, 'backtrace', [
442 \ '>backtrace',
443 \ ' 3 function GlobalFunction[1]',
444 \ ' 2 CallAFunction[1]',
445 \ '->1 SourceAnotherFile[1]',
446 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
447 \ 'line 1: func DoAThing()' ] )
448
449 call RunDbgCmd( buf, 'up' )
450 call RunDbgCmd( buf, 'backtrace', [
451 \ '>backtrace',
452 \ ' 3 function GlobalFunction[1]',
453 \ '->2 CallAFunction[1]',
454 \ ' 1 SourceAnotherFile[1]',
455 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
456 \ 'line 1: func DoAThing()' ] )
457
458 call RunDbgCmd( buf, 'up' )
459 call RunDbgCmd( buf, 'backtrace', [
460 \ '>backtrace',
461 \ '->3 function GlobalFunction[1]',
462 \ ' 2 CallAFunction[1]',
463 \ ' 1 SourceAnotherFile[1]',
464 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
465 \ 'line 1: func DoAThing()' ] )
466
467 call RunDbgCmd( buf, 'up', [ 'frame at highest level: 3' ] )
468 call RunDbgCmd( buf, 'backtrace', [
469 \ '>backtrace',
470 \ '->3 function GlobalFunction[1]',
471 \ ' 2 CallAFunction[1]',
472 \ ' 1 SourceAnotherFile[1]',
473 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
474 \ 'line 1: func DoAThing()' ] )
475
476 call RunDbgCmd( buf, 'down' )
477 call RunDbgCmd( buf, 'backtrace', [
478 \ '>backtrace',
479 \ ' 3 function GlobalFunction[1]',
480 \ '->2 CallAFunction[1]',
481 \ ' 1 SourceAnotherFile[1]',
482 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
483 \ 'line 1: func DoAThing()' ] )
484
485 call RunDbgCmd( buf, 'down' )
486 call RunDbgCmd( buf, 'backtrace', [
487 \ '>backtrace',
488 \ ' 3 function GlobalFunction[1]',
489 \ ' 2 CallAFunction[1]',
490 \ '->1 SourceAnotherFile[1]',
491 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
492 \ 'line 1: func DoAThing()' ] )
493
494 call RunDbgCmd( buf, 'down' )
495 call RunDbgCmd( buf, 'backtrace', [
496 \ '>backtrace',
497 \ ' 3 function GlobalFunction[1]',
498 \ ' 2 CallAFunction[1]',
499 \ ' 1 SourceAnotherFile[1]',
500 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
501 \ 'line 1: func DoAThing()' ] )
502
503 call RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
504
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200505 " step until we have another meaninfgul trace
506 call RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
507 call RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
508 call RunDbgCmd(buf, 'backtrace', [
509 \ '>backtrace',
510 \ ' 3 function GlobalFunction[1]',
511 \ ' 2 CallAFunction[1]',
512 \ ' 1 SourceAnotherFile[1]',
513 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
514 \ 'line 9: call File2Function()'])
515
516 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
517 call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
518 call RunDbgCmd(buf, 'backtrace', [
519 \ '>backtrace',
520 \ ' 5 function GlobalFunction[1]',
521 \ ' 4 CallAFunction[1]',
522 \ ' 3 SourceAnotherFile[1]',
523 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
524 \ ' 1 function File2Function[1]',
525 \ '->0 DoAThing',
526 \ 'line 1: echo "DoAThing"'])
527
528 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
529 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
530 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
531 call RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
532 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
533 call RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
534 call RunDbgCmd(buf, 'backtrace', [
535 \ '>backtrace',
536 \ ' 1 function GlobalFunction[1]',
537 \ '->0 CallAFunction',
538 \ 'line 2: call File2Function()'])
539
540 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
541 call RunDbgCmd(buf, 'backtrace', [
542 \ '>backtrace',
543 \ ' 2 function GlobalFunction[1]',
544 \ ' 1 CallAFunction[2]',
545 \ '->0 File2Function',
546 \ 'line 1: call DoAThing()'])
547
548 call StopVimInTerminal(buf)
549 call delete('Xtest1.vim')
550 call delete('Xtest2.vim')
551endfunc
552
553func Test_Backtrace_Autocmd()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200554 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200555 let file1 =<< trim END
556 func SourceAnotherFile()
557 source Xtest2.vim
558 endfunc
559
560 func CallAFunction()
561 call SourceAnotherFile()
562 call File2Function()
563 endfunc
564
565 func GlobalFunction()
566 call CallAFunction()
567 endfunc
568
569 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
570 END
571 call writefile(file1, 'Xtest1.vim')
572
573 let file2 =<< trim END
574 func DoAThing()
575 echo "DoAThing"
576 endfunc
577
578 func File2Function()
579 call DoAThing()
580 endfunc
581
582 call File2Function()
583 END
584 call writefile(file2, 'Xtest2.vim')
585
586 let buf = RunVimInTerminal('-S Xtest1.vim', {})
587
588 call RunDbgCmd(buf,
589 \ ':debug doautocmd User TestGlobalFunction',
590 \ ['cmd: doautocmd User TestGlobalFunction'])
591 call RunDbgCmd(buf, 'step', ['cmd: call GlobalFunction() | echo "Done"'])
592
593 " At this point the ontly thing in the stack is the autocommand
594 call RunDbgCmd(buf, 'backtrace', [
595 \ '>backtrace',
596 \ '->0 User Autocommands for "TestGlobalFunction"',
597 \ 'cmd: call GlobalFunction() | echo "Done"'])
598
599 " And now we're back into the call stack
600 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
601 call RunDbgCmd(buf, 'backtrace', [
602 \ '>backtrace',
603 \ ' 1 User Autocommands for "TestGlobalFunction"',
604 \ '->0 function GlobalFunction',
605 \ 'line 1: call CallAFunction()'])
606
607 call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
608 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
609
610 call RunDbgCmd(buf, 'backtrace', [
611 \ '>backtrace',
612 \ ' 3 User Autocommands for "TestGlobalFunction"',
613 \ ' 2 function GlobalFunction[1]',
614 \ ' 1 CallAFunction[1]',
615 \ '->0 SourceAnotherFile',
616 \ 'line 1: source Xtest2.vim'])
617
618 " Step into the 'source' command. Note that we print the full trace all the
619 " way though the source command.
620 call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
621 call RunDbgCmd(buf, 'backtrace', [
622 \ '>backtrace',
623 \ ' 4 User Autocommands for "TestGlobalFunction"',
624 \ ' 3 function GlobalFunction[1]',
625 \ ' 2 CallAFunction[1]',
626 \ ' 1 SourceAnotherFile[1]',
627 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
628 \ 'line 1: func DoAThing()'])
629
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200630 call RunDbgCmd( buf, 'up' )
631 call RunDbgCmd( buf, 'backtrace', [
632 \ '>backtrace',
633 \ ' 4 User Autocommands for "TestGlobalFunction"',
634 \ ' 3 function GlobalFunction[1]',
635 \ ' 2 CallAFunction[1]',
636 \ '->1 SourceAnotherFile[1]',
637 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
638 \ 'line 1: func DoAThing()' ] )
639
640 call RunDbgCmd( buf, 'up' )
641 call RunDbgCmd( buf, 'backtrace', [
642 \ '>backtrace',
643 \ ' 4 User Autocommands for "TestGlobalFunction"',
644 \ ' 3 function GlobalFunction[1]',
645 \ '->2 CallAFunction[1]',
646 \ ' 1 SourceAnotherFile[1]',
647 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
648 \ 'line 1: func DoAThing()' ] )
649
650 call RunDbgCmd( buf, 'up' )
651 call RunDbgCmd( buf, 'backtrace', [
652 \ '>backtrace',
653 \ ' 4 User Autocommands for "TestGlobalFunction"',
654 \ '->3 function GlobalFunction[1]',
655 \ ' 2 CallAFunction[1]',
656 \ ' 1 SourceAnotherFile[1]',
657 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
658 \ 'line 1: func DoAThing()' ] )
659
660 call RunDbgCmd( buf, 'up' )
661 call RunDbgCmd( buf, 'backtrace', [
662 \ '>backtrace',
663 \ '->4 User Autocommands for "TestGlobalFunction"',
664 \ ' 3 function GlobalFunction[1]',
665 \ ' 2 CallAFunction[1]',
666 \ ' 1 SourceAnotherFile[1]',
667 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
668 \ 'line 1: func DoAThing()' ] )
669
670 call RunDbgCmd( buf, 'up', [ 'frame at highest level: 4' ] )
671 call RunDbgCmd( buf, 'backtrace', [
672 \ '>backtrace',
673 \ '->4 User Autocommands for "TestGlobalFunction"',
674 \ ' 3 function GlobalFunction[1]',
675 \ ' 2 CallAFunction[1]',
676 \ ' 1 SourceAnotherFile[1]',
677 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
678 \ 'line 1: func DoAThing()' ] )
679
680 call RunDbgCmd( buf, 'down' )
681 call RunDbgCmd( buf, 'backtrace', [
682 \ '>backtrace',
683 \ ' 4 User Autocommands for "TestGlobalFunction"',
684 \ '->3 function GlobalFunction[1]',
685 \ ' 2 CallAFunction[1]',
686 \ ' 1 SourceAnotherFile[1]',
687 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
688 \ 'line 1: func DoAThing()' ] )
689
690
691 call RunDbgCmd( buf, 'down' )
692 call RunDbgCmd( buf, 'backtrace', [
693 \ '>backtrace',
694 \ ' 4 User Autocommands for "TestGlobalFunction"',
695 \ ' 3 function GlobalFunction[1]',
696 \ '->2 CallAFunction[1]',
697 \ ' 1 SourceAnotherFile[1]',
698 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
699 \ 'line 1: func DoAThing()' ] )
700
701 call RunDbgCmd( buf, 'down' )
702 call RunDbgCmd( buf, 'backtrace', [
703 \ '>backtrace',
704 \ ' 4 User Autocommands for "TestGlobalFunction"',
705 \ ' 3 function GlobalFunction[1]',
706 \ ' 2 CallAFunction[1]',
707 \ '->1 SourceAnotherFile[1]',
708 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
709 \ 'line 1: func DoAThing()' ] )
710
711 call RunDbgCmd( buf, 'down' )
712 call RunDbgCmd( buf, 'backtrace', [
713 \ '>backtrace',
714 \ ' 4 User Autocommands for "TestGlobalFunction"',
715 \ ' 3 function GlobalFunction[1]',
716 \ ' 2 CallAFunction[1]',
717 \ ' 1 SourceAnotherFile[1]',
718 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
719 \ 'line 1: func DoAThing()' ] )
720
721 call RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
722
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200723 " step until we have another meaninfgul trace
724 call RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
725 call RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
726 call RunDbgCmd(buf, 'backtrace', [
727 \ '>backtrace',
728 \ ' 4 User Autocommands for "TestGlobalFunction"',
729 \ ' 3 function GlobalFunction[1]',
730 \ ' 2 CallAFunction[1]',
731 \ ' 1 SourceAnotherFile[1]',
732 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
733 \ 'line 9: call File2Function()'])
734
735 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
736 call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
737 call RunDbgCmd(buf, 'backtrace', [
738 \ '>backtrace',
739 \ ' 6 User Autocommands for "TestGlobalFunction"',
740 \ ' 5 function GlobalFunction[1]',
741 \ ' 4 CallAFunction[1]',
742 \ ' 3 SourceAnotherFile[1]',
743 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
744 \ ' 1 function File2Function[1]',
745 \ '->0 DoAThing',
746 \ 'line 1: echo "DoAThing"'])
747
748 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
749 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
750 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
751 call RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
752 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
753 call RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
754 call RunDbgCmd(buf, 'backtrace', [
755 \ '>backtrace',
756 \ ' 2 User Autocommands for "TestGlobalFunction"',
757 \ ' 1 function GlobalFunction[1]',
758 \ '->0 CallAFunction',
759 \ 'line 2: call File2Function()'])
760
761 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
762 call RunDbgCmd(buf, 'backtrace', [
763 \ '>backtrace',
764 \ ' 3 User Autocommands for "TestGlobalFunction"',
765 \ ' 2 function GlobalFunction[1]',
766 \ ' 1 CallAFunction[2]',
767 \ '->0 File2Function',
768 \ 'line 1: call DoAThing()'])
769
770
771 " Now unwind so that we get back to the original autocommand (and the second
772 " cmd echo "Done")
773 call RunDbgCmd(buf, 'finish', ['line 1: End of function'])
774 call RunDbgCmd(buf, 'backtrace', [
775 \ '>backtrace',
776 \ ' 3 User Autocommands for "TestGlobalFunction"',
777 \ ' 2 function GlobalFunction[1]',
778 \ ' 1 CallAFunction[2]',
779 \ '->0 File2Function',
780 \ 'line 1: End of function'])
781
782 call RunDbgCmd(buf, 'finish', ['line 2: End of function'])
783 call RunDbgCmd(buf, 'backtrace', [
784 \ '>backtrace',
785 \ ' 2 User Autocommands for "TestGlobalFunction"',
786 \ ' 1 function GlobalFunction[1]',
787 \ '->0 CallAFunction',
788 \ 'line 2: End of function'])
789
790 call RunDbgCmd(buf, 'finish', ['line 1: End of function'])
791 call RunDbgCmd(buf, 'backtrace', [
792 \ '>backtrace',
793 \ ' 1 User Autocommands for "TestGlobalFunction"',
794 \ '->0 function GlobalFunction',
795 \ 'line 1: End of function'])
796
797 call RunDbgCmd(buf, 'step', ['cmd: echo "Done"'])
798 call RunDbgCmd(buf, 'backtrace', [
799 \ '>backtrace',
800 \ '->0 User Autocommands for "TestGlobalFunction"',
801 \ 'cmd: echo "Done"'])
802
803 call StopVimInTerminal(buf)
804 call delete('Xtest1.vim')
805 call delete('Xtest2.vim')
806endfunc
807
808func Test_Backtrace_CmdLine()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200809 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200810 let file1 =<< trim END
811 func SourceAnotherFile()
812 source Xtest2.vim
813 endfunc
814
815 func CallAFunction()
816 call SourceAnotherFile()
817 call File2Function()
818 endfunc
819
820 func GlobalFunction()
821 call CallAFunction()
822 endfunc
823
824 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
825 END
826 call writefile(file1, 'Xtest1.vim')
827
828 let file2 =<< trim END
829 func DoAThing()
830 echo "DoAThing"
831 endfunc
832
833 func File2Function()
834 call DoAThing()
835 endfunc
836
837 call File2Function()
838 END
839 call writefile(file2, 'Xtest2.vim')
840
841 let buf = RunVimInTerminal(
842 \ '-S Xtest1.vim -c "debug call GlobalFunction()"',
843 \ {'wait_for_ruler': 0})
844
Bram Moolenaar18dc3552020-11-22 14:24:00 +0100845 " Need to wait for the vim-in-terminal to be ready.
846 " With valgrind this can take quite long.
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200847 call CheckDbgOutput(buf, ['command line',
Bram Moolenaar18dc3552020-11-22 14:24:00 +0100848 \ 'cmd: call GlobalFunction()'], #{msec: 5000})
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200849
850 " At this point the ontly thing in the stack is the cmdline
851 call RunDbgCmd(buf, 'backtrace', [
852 \ '>backtrace',
853 \ '->0 command line',
854 \ 'cmd: call GlobalFunction()'])
855
856 " And now we're back into the call stack
857 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
858 call RunDbgCmd(buf, 'backtrace', [
859 \ '>backtrace',
860 \ ' 1 command line',
861 \ '->0 function GlobalFunction',
862 \ 'line 1: call CallAFunction()'])
863
864 call StopVimInTerminal(buf)
865 call delete('Xtest1.vim')
866 call delete('Xtest2.vim')
867endfunc
868
869func Test_Backtrace_DefFunction()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200870 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200871 let file1 =<< trim END
872 vim9script
873 import File2Function from './Xtest2.vim'
874
875 def SourceAnotherFile()
876 source Xtest2.vim
877 enddef
878
879 def CallAFunction()
880 SourceAnotherFile()
881 File2Function()
882 enddef
883
884 def g:GlobalFunction()
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200885 var some = "some var"
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200886 CallAFunction()
887 enddef
888
889 defcompile
890 END
891 call writefile(file1, 'Xtest1.vim')
892
893 let file2 =<< trim END
894 vim9script
895
896 def DoAThing(): number
Bram Moolenaar1bdae402020-10-03 14:14:56 +0200897 var a = 100 * 2
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200898 a += 3
899 return a
900 enddef
901
902 export def File2Function()
903 DoAThing()
904 enddef
905
906 defcompile
907 File2Function()
908 END
909 call writefile(file2, 'Xtest2.vim')
910
911 let buf = RunVimInTerminal('-S Xtest1.vim', {})
912
913 call RunDbgCmd(buf,
914 \ ':debug call GlobalFunction()',
915 \ ['cmd: call GlobalFunction()'])
916
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200917 call RunDbgCmd(buf, 'step', ['line 1: var some = "some var"'])
918 call RunDbgCmd(buf, 'step', ['line 2: CallAFunction()'])
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200919 call RunDbgCmd(buf, 'echo some', ['some var'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200920
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200921 call RunDbgCmd(buf, 'backtrace', [
922 \ '\V>backtrace',
Bram Moolenaare99d4222021-06-13 14:01:26 +0200923 \ '\V->0 function GlobalFunction',
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200924 \ '\Vline 2: CallAFunction()',
Bram Moolenaare99d4222021-06-13 14:01:26 +0200925 \ ],
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200926 \ #{match: 'pattern'})
927
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200928 call RunDbgCmd(buf, 'step', ['line 1: SourceAnotherFile()'])
929 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200930 " Repeated line, because we fist are in the compiled function before the
931 " EXEC and then in do_cmdline() before the :source command.
Bram Moolenaare99d4222021-06-13 14:01:26 +0200932 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200933 call RunDbgCmd(buf, 'step', ['line 1: vim9script'])
934 call RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number'])
935 call RunDbgCmd(buf, 'step', ['line 9: export def File2Function()'])
936 call RunDbgCmd(buf, 'step', ['line 9: def File2Function()'])
937 call RunDbgCmd(buf, 'step', ['line 13: defcompile'])
938 call RunDbgCmd(buf, 'step', ['line 14: File2Function()'])
939 call RunDbgCmd(buf, 'backtrace', [
940 \ '\V>backtrace',
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200941 \ '\V 3 function GlobalFunction[2]',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200942 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
943 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
944 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
945 \ '\Vline 14: File2Function()'],
946 \ #{match: 'pattern'})
947
948 " Don't step into compiled functions...
Bram Moolenaare99d4222021-06-13 14:01:26 +0200949 call RunDbgCmd(buf, 'next', ['line 15: End of sourced file'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200950 call RunDbgCmd(buf, 'backtrace', [
951 \ '\V>backtrace',
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200952 \ '\V 3 function GlobalFunction[2]',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200953 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
954 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
955 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
956 \ '\Vline 15: End of sourced file'],
957 \ #{match: 'pattern'})
958
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200959 call StopVimInTerminal(buf)
960 call delete('Xtest1.vim')
961 call delete('Xtest2.vim')
962endfunc
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200963
Bram Moolenaar26a44842021-09-02 18:49:06 +0200964func Test_DefFunction_expr()
965 CheckCWD
966 let file3 =<< trim END
967 vim9script
968 g:someVar = "foo"
969 def g:ChangeVar()
970 g:someVar = "bar"
971 echo "changed"
972 enddef
973 defcompile
974 END
975 call writefile(file3, 'Xtest3.vim')
976 let buf = RunVimInTerminal('-S Xtest3.vim', {})
977
978 call RunDbgCmd(buf, ':breakadd expr g:someVar')
979 call RunDbgCmd(buf, ':call g:ChangeVar()', ['Oldval = "''foo''"', 'Newval = "''bar''"', 'function ChangeVar', 'line 2: echo "changed"'])
980
981 call StopVimInTerminal(buf)
982 call delete('Xtest3.vim')
983endfunc
984
Bram Moolenaar17d868b2021-06-27 16:29:53 +0200985func Test_debug_def_and_legacy_function()
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200986 CheckCWD
987 let file =<< trim END
988 vim9script
989 def g:SomeFunc()
990 echo "here"
991 echo "and"
992 echo "there"
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200993 breakadd func 2 LocalFunc
994 LocalFunc()
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200995 enddef
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200996
997 def LocalFunc()
998 echo "first"
999 echo "second"
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001000 breakadd func LegacyFunc
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001001 LegacyFunc()
1002 enddef
1003
1004 func LegacyFunc()
1005 echo "legone"
1006 echo "legtwo"
1007 endfunc
1008
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001009 breakadd func 2 g:SomeFunc
1010 END
1011 call writefile(file, 'XtestDebug.vim')
1012
1013 let buf = RunVimInTerminal('-S XtestDebug.vim', {})
1014
1015 call RunDbgCmd(buf,':call SomeFunc()', ['line 2: echo "and"'])
1016 call RunDbgCmd(buf,'next', ['line 3: echo "there"'])
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001017 call RunDbgCmd(buf,'next', ['line 4: breakadd func 2 LocalFunc'])
1018
1019 " continue, next breakpoint is in LocalFunc()
1020 call RunDbgCmd(buf,'cont', ['line 2: echo "second"'])
1021
1022 " continue, next breakpoint is in LegacyFunc()
1023 call RunDbgCmd(buf,'cont', ['line 1: echo "legone"'])
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001024
1025 call RunDbgCmd(buf, 'cont')
1026
1027 call StopVimInTerminal(buf)
Dominique Pelle6c72fd52021-07-04 12:30:06 +02001028 call delete('XtestDebug.vim')
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001029endfunc
1030
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001031func Test_debug_def_function()
1032 CheckCWD
1033 let file =<< trim END
1034 vim9script
1035 def g:Func()
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001036 var n: number
1037 def Closure(): number
1038 return n + 3
1039 enddef
1040 n += Closure()
1041 echo 'result: ' .. n
1042 enddef
1043
1044 def g:FuncWithArgs(text: string, nr: number, ...items: list<number>)
1045 echo text .. nr
1046 for it in items
1047 echo it
1048 endfor
1049 echo "done"
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001050 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001051
1052 def g:FuncWithDict()
1053 var d = {
1054 a: 1,
1055 b: 2,
1056 }
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001057 # comment
1058 def Inner()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001059 eval 1 + 2
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001060 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001061 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001062
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001063 def g:FuncComment()
1064 # comment
1065 echo "first"
1066 .. "one"
1067 # comment
1068 echo "second"
1069 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001070
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001071 def g:FuncForLoop()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001072 eval 1 + 2
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001073 for i in [11, 22, 33]
Bram Moolenaar31e21762021-07-10 20:43:59 +02001074 eval i + 2
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001075 endfor
1076 echo "done"
1077 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001078
1079 def g:FuncWithSplitLine()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001080 eval 1 + 2
1081 | eval 2 + 3
Bram Moolenaar303215d2021-07-07 20:10:43 +02001082 enddef
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001083 END
1084 call writefile(file, 'Xtest.vim')
1085
1086 let buf = RunVimInTerminal('-S Xtest.vim', {})
1087
1088 call RunDbgCmd(buf,
1089 \ ':debug call Func()',
1090 \ ['cmd: call Func()'])
1091 call RunDbgCmd(buf, 'next', ['result: 3'])
1092 call term_sendkeys(buf, "\r")
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001093 call RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001094
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001095 call RunDbgCmd(buf,
1096 \ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)',
1097 \ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001098 call RunDbgCmd(buf, 'step', ['line 1: echo text .. nr'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001099 call RunDbgCmd(buf, 'echo text', ['asdf'])
1100 call RunDbgCmd(buf, 'echo nr', ['42'])
1101 call RunDbgCmd(buf, 'echo items', ['[1, 2, 3]'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001102 call RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001103 call RunDbgCmd(buf, 'echo it', ['1'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001104 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
1105 call RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor'])
1106 call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001107 call RunDbgCmd(buf, 'echo it', ['2'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001108 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
1109 call RunDbgCmd(buf, 'step', ['2', 'function FuncWithArgs', 'line 4: endfor'])
1110 call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001111 call RunDbgCmd(buf, 'echo it', ['3'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001112 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
1113 call RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor'])
1114 call RunDbgCmd(buf, 'step', ['line 5: echo "done"'])
1115 call RunDbgCmd(buf, 'cont')
1116
1117 call RunDbgCmd(buf,
1118 \ ':debug call FuncWithDict()',
1119 \ ['cmd: call FuncWithDict()'])
1120 call RunDbgCmd(buf, 'step', ['line 1: var d = { a: 1, b: 2, }'])
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001121 call RunDbgCmd(buf, 'step', ['line 6: def Inner()'])
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001122 call RunDbgCmd(buf, 'cont')
1123
1124 call RunDbgCmd(buf, ':breakadd func 1 FuncComment')
1125 call RunDbgCmd(buf, ':call FuncComment()', ['function FuncComment', 'line 2: echo "first" .. "one"'])
1126 call RunDbgCmd(buf, ':breakadd func 3 FuncComment')
1127 call RunDbgCmd(buf, 'cont', ['function FuncComment', 'line 5: echo "second"'])
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001128 call RunDbgCmd(buf, 'cont')
1129
1130 call RunDbgCmd(buf, ':breakadd func 2 FuncForLoop')
1131 call RunDbgCmd(buf, ':call FuncForLoop()', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
1132 call RunDbgCmd(buf, 'echo i', ['11'])
Bram Moolenaar31e21762021-07-10 20:43:59 +02001133 call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 3: eval i + 2'])
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001134 call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 4: endfor'])
1135 call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
1136 call RunDbgCmd(buf, 'echo i', ['22'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001137
Bram Moolenaar303215d2021-07-07 20:10:43 +02001138 call RunDbgCmd(buf, 'breakdel *')
1139 call RunDbgCmd(buf, 'cont')
1140
1141 call RunDbgCmd(buf, ':breakadd func FuncWithSplitLine')
Bram Moolenaar31e21762021-07-10 20:43:59 +02001142 call RunDbgCmd(buf, ':call FuncWithSplitLine()', ['function FuncWithSplitLine', 'line 1: eval 1 + 2 | eval 2 + 3'])
Bram Moolenaar303215d2021-07-07 20:10:43 +02001143
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001144 call RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001145 call StopVimInTerminal(buf)
1146 call delete('Xtest.vim')
1147endfunc
1148
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001149func Test_debug_def_function_with_lambda()
1150 CheckCWD
1151 let lines =<< trim END
1152 vim9script
1153 def g:Func()
1154 var s = 'a'
1155 ['b']->map((_, v) => s)
1156 echo "done"
1157 enddef
1158 breakadd func 2 g:Func
1159 END
1160 call writefile(lines, 'XtestLambda.vim')
1161
1162 let buf = RunVimInTerminal('-S XtestLambda.vim', {})
1163
1164 call RunDbgCmd(buf,
1165 \ ':call g:Func()',
1166 \ ['function Func', 'line 2: [''b'']->map((_, v) => s)'])
1167 call RunDbgCmd(buf,
1168 \ 'next',
1169 \ ['function Func', 'line 3: echo "done"'])
1170
1171 call RunDbgCmd(buf, 'cont')
1172 call StopVimInTerminal(buf)
1173 call delete('XtestLambda.vim')
1174endfunc
1175
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001176func Test_debug_backtrace_level()
1177 CheckCWD
1178 let lines =<< trim END
1179 let s:file1_var = 'file1'
1180 let g:global_var = 'global'
1181
1182 func s:File1Func( arg )
1183 let s:file1_var .= a:arg
1184 let local_var = s:file1_var .. ' test1'
1185 let g:global_var .= local_var
1186 source Xtest2.vim
1187 endfunc
1188
1189 call s:File1Func( 'arg1' )
1190 END
1191 call writefile(lines, 'Xtest1.vim')
1192
1193 let lines =<< trim END
1194 let s:file2_var = 'file2'
1195
1196 func s:File2Func( arg )
1197 let s:file2_var .= a:arg
1198 let local_var = s:file2_var .. ' test2'
1199 let g:global_var .= local_var
1200 endfunc
1201
1202 call s:File2Func( 'arg2' )
1203 END
1204 call writefile(lines, 'Xtest2.vim')
1205
1206 let file1 = getcwd() .. '/Xtest1.vim'
1207 let file2 = getcwd() .. '/Xtest2.vim'
1208
1209 " set a breakpoint and source file1.vim
1210 let buf = RunVimInTerminal(
1211 \ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim',
Bram Moolenaar18dc3552020-11-22 14:24:00 +01001212 \ #{wait_for_ruler: 0})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001213
1214 call CheckDbgOutput(buf, [
1215 \ 'Breakpoint in "' .. file1 .. '" line 1',
1216 \ 'Entering Debug mode. Type "cont" to continue.',
1217 \ 'command line..script ' .. file1,
1218 \ 'line 1: let s:file1_var = ''file1'''
Bram Moolenaar18dc3552020-11-22 14:24:00 +01001219 \ ], #{msec: 5000})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001220
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01001221 " step through the initial declarations
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001222 call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] )
1223 call RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] )
1224 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1225 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1226 call RunDbgCmd(buf, 'echo global_var', [ 'global' ] )
1227
1228 " step in to the first function
1229 call RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] )
1230 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] )
1231 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1232 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1233 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1234 call RunDbgCmd(buf,
1235 \'echo global_var',
1236 \[ 'E121: Undefined variable: global_var' ] )
1237 call RunDbgCmd(buf,
1238 \'echo local_var',
1239 \[ 'E121: Undefined variable: local_var' ] )
1240 call RunDbgCmd(buf,
1241 \'echo l:local_var',
1242 \[ 'E121: Undefined variable: l:local_var' ] )
1243
1244 " backtrace up
1245 call RunDbgCmd(buf, 'backtrace', [
1246 \ '\V>backtrace',
1247 \ '\V 2 command line',
1248 \ '\V 1 script ' .. file1 .. '[11]',
1249 \ '\V->0 function <SNR>\.\*_File1Func',
1250 \ '\Vline 1: let s:file1_var .= a:arg',
1251 \ ],
1252 \ #{ match: 'pattern' } )
1253 call RunDbgCmd(buf, 'up', [ '>up' ] )
1254
1255 call RunDbgCmd(buf, 'backtrace', [
1256 \ '\V>backtrace',
1257 \ '\V 2 command line',
1258 \ '\V->1 script ' .. file1 .. '[11]',
1259 \ '\V 0 function <SNR>\.\*_File1Func',
1260 \ '\Vline 1: let s:file1_var .= a:arg',
1261 \ ],
1262 \ #{ match: 'pattern' } )
1263
1264 " Expression evaluation in the script frame (not the function frame)
1265 " FIXME: Unexpected in this scope (a: should not be visibnle)
1266 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1267 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1268 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1269 " FIXME: Unexpected in this scope (global should be found)
1270 call RunDbgCmd(buf,
1271 \'echo global_var',
1272 \[ 'E121: Undefined variable: global_var' ] )
1273 call RunDbgCmd(buf,
1274 \'echo local_var',
1275 \[ 'E121: Undefined variable: local_var' ] )
1276 call RunDbgCmd(buf,
1277 \'echo l:local_var',
1278 \[ 'E121: Undefined variable: l:local_var' ] )
1279
1280
1281 " step while backtraced jumps to the latest frame
1282 call RunDbgCmd(buf, 'step', [
1283 \ 'line 2: let local_var = s:file1_var .. '' test1''' ] )
1284 call RunDbgCmd(buf, 'backtrace', [
1285 \ '\V>backtrace',
1286 \ '\V 2 command line',
1287 \ '\V 1 script ' .. file1 .. '[11]',
1288 \ '\V->0 function <SNR>\.\*_File1Func',
1289 \ '\Vline 2: let local_var = s:file1_var .. '' test1''',
1290 \ ],
1291 \ #{ match: 'pattern' } )
1292
1293 call RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] )
1294 call RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] )
1295 call RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] )
1296
1297 call RunDbgCmd(buf, 'step', [ 'line 4: source Xtest2.vim' ] )
1298 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file2_var = ''file2''' ] )
1299 call RunDbgCmd(buf, 'backtrace', [
1300 \ '\V>backtrace',
1301 \ '\V 3 command line',
1302 \ '\V 2 script ' .. file1 .. '[11]',
1303 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1304 \ '\V->0 script ' .. file2,
1305 \ '\Vline 1: let s:file2_var = ''file2''',
1306 \ ],
1307 \ #{ match: 'pattern' } )
1308
1309 " Expression evaluation in the script frame file2 (not the function frame)
1310 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1311 call RunDbgCmd(buf,
1312 \ 'echo s:file1_var',
1313 \ [ 'E121: Undefined variable: s:file1_var' ] )
1314 call RunDbgCmd(buf, 'echo g:global_var', [ 'globalfile1arg1 test1' ] )
1315 call RunDbgCmd(buf, 'echo global_var', [ 'globalfile1arg1 test1' ] )
1316 call RunDbgCmd(buf,
1317 \'echo local_var',
1318 \[ 'E121: Undefined variable: local_var' ] )
1319 call RunDbgCmd(buf,
1320 \'echo l:local_var',
1321 \[ 'E121: Undefined variable: l:local_var' ] )
1322 call RunDbgCmd(buf,
1323 \ 'echo s:file2_var',
1324 \ [ 'E121: Undefined variable: s:file2_var' ] )
1325
1326 call RunDbgCmd(buf, 'step', [ 'line 3: func s:File2Func( arg )' ] )
1327 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1328
1329 " Up the stack to the other script context
1330 call RunDbgCmd(buf, 'up')
1331 call RunDbgCmd(buf, 'backtrace', [
1332 \ '\V>backtrace',
1333 \ '\V 3 command line',
1334 \ '\V 2 script ' .. file1 .. '[11]',
1335 \ '\V->1 function <SNR>\.\*_File1Func[4]',
1336 \ '\V 0 script ' .. file2,
1337 \ '\Vline 3: func s:File2Func( arg )',
1338 \ ],
1339 \ #{ match: 'pattern' } )
1340 " FIXME: Unexpected. Should see the a: and l: dicts from File1Func
1341 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1342 call RunDbgCmd(buf,
1343 \ 'echo l:local_var',
1344 \ [ 'E121: Undefined variable: l:local_var' ] )
1345
1346 call RunDbgCmd(buf, 'up')
1347 call RunDbgCmd(buf, 'backtrace', [
1348 \ '\V>backtrace',
1349 \ '\V 3 command line',
1350 \ '\V->2 script ' .. file1 .. '[11]',
1351 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1352 \ '\V 0 script ' .. file2,
1353 \ '\Vline 3: func s:File2Func( arg )',
1354 \ ],
1355 \ #{ match: 'pattern' } )
1356
1357 " FIXME: Unexpected (wrong script vars are used)
1358 call RunDbgCmd(buf,
1359 \ 'echo s:file1_var',
1360 \ [ 'E121: Undefined variable: s:file1_var' ] )
1361 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1362
Bram Moolenaare99d4222021-06-13 14:01:26 +02001363 call RunDbgCmd(buf, 'cont')
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001364 call StopVimInTerminal(buf)
1365 call delete('Xtest1.vim')
1366 call delete('Xtest2.vim')
1367endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001368
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001369" Test for setting a breakpoint on a :endif where the :if condition is false
1370" and then quit the script. This should generate an interrupt.
1371func Test_breakpt_endif_intr()
1372 func F()
1373 let g:Xpath ..= 'a'
1374 if v:false
1375 let g:Xpath ..= 'b'
1376 endif
1377 invalid_command
1378 endfunc
1379
1380 let g:Xpath = ''
1381 breakadd func 4 F
1382 try
1383 let caught_intr = 0
1384 debuggreedy
1385 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001386 catch /^Vim:Interrupt$/
1387 call assert_match('\.F, line 4', v:throwpoint)
1388 let caught_intr = 1
1389 endtry
1390 0debuggreedy
1391 call assert_equal(1, caught_intr)
1392 call assert_equal('a', g:Xpath)
1393 breakdel *
1394 delfunc F
1395endfunc
1396
1397" Test for setting a breakpoint on a :else where the :if condition is false
1398" and then quit the script. This should generate an interrupt.
1399func Test_breakpt_else_intr()
1400 func F()
1401 let g:Xpath ..= 'a'
1402 if v:false
1403 let g:Xpath ..= 'b'
1404 else
1405 invalid_command
1406 endif
1407 invalid_command
1408 endfunc
1409
1410 let g:Xpath = ''
1411 breakadd func 4 F
1412 try
1413 let caught_intr = 0
1414 debuggreedy
1415 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001416 catch /^Vim:Interrupt$/
1417 call assert_match('\.F, line 4', v:throwpoint)
1418 let caught_intr = 1
1419 endtry
1420 0debuggreedy
1421 call assert_equal(1, caught_intr)
1422 call assert_equal('a', g:Xpath)
1423 breakdel *
1424 delfunc F
1425endfunc
1426
1427" Test for setting a breakpoint on a :endwhile where the :while condition is
1428" false and then quit the script. This should generate an interrupt.
1429func Test_breakpt_endwhile_intr()
1430 func F()
1431 let g:Xpath ..= 'a'
1432 while v:false
1433 let g:Xpath ..= 'b'
1434 endwhile
1435 invalid_command
1436 endfunc
1437
1438 let g:Xpath = ''
1439 breakadd func 4 F
1440 try
1441 let caught_intr = 0
1442 debuggreedy
1443 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001444 catch /^Vim:Interrupt$/
1445 call assert_match('\.F, line 4', v:throwpoint)
1446 let caught_intr = 1
1447 endtry
1448 0debuggreedy
1449 call assert_equal(1, caught_intr)
1450 call assert_equal('a', g:Xpath)
1451 breakdel *
1452 delfunc F
1453endfunc
1454
Bram Moolenaar16c62322020-08-13 19:20:04 +02001455" Test for setting a breakpoint on a script local function
1456func Test_breakpt_scriptlocal_func()
1457 let g:Xpath = ''
1458 func s:G()
1459 let g:Xpath ..= 'a'
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001460 endfunc
1461
Bram Moolenaar16c62322020-08-13 19:20:04 +02001462 let funcname = expand("<SID>") .. "G"
1463 exe "breakadd func 1 " .. funcname
1464 debuggreedy
1465 redir => output
1466 call feedkeys(":call " .. funcname .. "()\<CR>c\<CR>", "xt")
1467 redir END
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001468 0debuggreedy
Bram Moolenaar16c62322020-08-13 19:20:04 +02001469 call assert_match('Breakpoint in "' .. funcname .. '" line 1', output)
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001470 call assert_equal('a', g:Xpath)
1471 breakdel *
Bram Moolenaar16c62322020-08-13 19:20:04 +02001472 exe "delfunc " .. funcname
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001473endfunc
1474
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001475" vim: shiftwidth=2 sts=2 expandtab