blob: 411909d1c7dbbc93a06063165f73320105935638 [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)
321
322 " Tests for :breakadd file and :breakadd here
323 " Breakpoints should be set before sourcing the file
324
Bram Moolenaare7eb9272019-06-24 00:58:07 +0200325 let lines =<< trim END
326 let var1 = 10
327 let var2 = 20
328 let var3 = 30
329 let var4 = 40
330 END
331 call writefile(lines, 'Xtest.vim')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200332
333 " Start Vim in a terminal
334 let buf = RunVimInTerminal('Xtest.vim', {})
335 call RunDbgCmd(buf, ':breakadd file 2 Xtest.vim')
336 call RunDbgCmd(buf, ':4 | breakadd here')
337 call RunDbgCmd(buf, ':source Xtest.vim', ['line 2: let var2 = 20'])
338 call RunDbgCmd(buf, 'cont', ['line 4: let var4 = 40'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200339 call RunDbgCmd(buf, 'cont')
340
341 call StopVimInTerminal(buf)
342
343 call delete('Xtest.vim')
Bram Moolenaar16c62322020-08-13 19:20:04 +0200344 %bw!
345 call assert_fails('breakadd here', 'E32:')
Bram Moolenaar531be472020-09-23 22:38:05 +0200346 call assert_fails('breakadd file Xtest.vim /\)/', 'E55:')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200347endfunc
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200348
349func Test_Backtrace_Through_Source()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200350 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200351 let file1 =<< trim END
352 func SourceAnotherFile()
353 source Xtest2.vim
354 endfunc
355
356 func CallAFunction()
357 call SourceAnotherFile()
358 call File2Function()
359 endfunc
360
361 func GlobalFunction()
362 call CallAFunction()
363 endfunc
364 END
365 call writefile(file1, 'Xtest1.vim')
366
367 let file2 =<< trim END
368 func DoAThing()
369 echo "DoAThing"
370 endfunc
371
372 func File2Function()
373 call DoAThing()
374 endfunc
375
376 call File2Function()
377 END
378 call writefile(file2, 'Xtest2.vim')
379
380 let buf = RunVimInTerminal('-S Xtest1.vim', {})
381
382 call RunDbgCmd(buf,
383 \ ':debug call GlobalFunction()',
384 \ ['cmd: call GlobalFunction()'])
385 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
386
387 call RunDbgCmd(buf, 'backtrace', ['>backtrace',
388 \ '->0 function GlobalFunction',
389 \ 'line 1: call CallAFunction()'])
390
391 call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
392 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
393
394 call RunDbgCmd(buf, 'backtrace', ['>backtrace',
395 \ ' 2 function GlobalFunction[1]',
396 \ ' 1 CallAFunction[1]',
397 \ '->0 SourceAnotherFile',
398 \ 'line 1: source Xtest2.vim'])
399
400 " Step into the 'source' command. Note that we print the full trace all the
401 " way though the source command.
402 call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
403 call RunDbgCmd(buf, 'backtrace', [
404 \ '>backtrace',
405 \ ' 3 function GlobalFunction[1]',
406 \ ' 2 CallAFunction[1]',
407 \ ' 1 SourceAnotherFile[1]',
408 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
409 \ 'line 1: func DoAThing()'])
410
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200411 call RunDbgCmd( buf, 'up' )
412 call RunDbgCmd( buf, 'backtrace', [
413 \ '>backtrace',
414 \ ' 3 function GlobalFunction[1]',
415 \ ' 2 CallAFunction[1]',
416 \ '->1 SourceAnotherFile[1]',
417 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
418 \ 'line 1: func DoAThing()' ] )
419
420 call RunDbgCmd( buf, 'up' )
421 call RunDbgCmd( buf, 'backtrace', [
422 \ '>backtrace',
423 \ ' 3 function GlobalFunction[1]',
424 \ '->2 CallAFunction[1]',
425 \ ' 1 SourceAnotherFile[1]',
426 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
427 \ 'line 1: func DoAThing()' ] )
428
429 call RunDbgCmd( buf, 'up' )
430 call RunDbgCmd( buf, 'backtrace', [
431 \ '>backtrace',
432 \ '->3 function GlobalFunction[1]',
433 \ ' 2 CallAFunction[1]',
434 \ ' 1 SourceAnotherFile[1]',
435 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
436 \ 'line 1: func DoAThing()' ] )
437
438 call RunDbgCmd( buf, 'up', [ 'frame at highest level: 3' ] )
439 call RunDbgCmd( buf, 'backtrace', [
440 \ '>backtrace',
441 \ '->3 function GlobalFunction[1]',
442 \ ' 2 CallAFunction[1]',
443 \ ' 1 SourceAnotherFile[1]',
444 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
445 \ 'line 1: func DoAThing()' ] )
446
447 call RunDbgCmd( buf, 'down' )
448 call RunDbgCmd( buf, 'backtrace', [
449 \ '>backtrace',
450 \ ' 3 function GlobalFunction[1]',
451 \ '->2 CallAFunction[1]',
452 \ ' 1 SourceAnotherFile[1]',
453 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
454 \ 'line 1: func DoAThing()' ] )
455
456 call RunDbgCmd( buf, 'down' )
457 call RunDbgCmd( buf, 'backtrace', [
458 \ '>backtrace',
459 \ ' 3 function GlobalFunction[1]',
460 \ ' 2 CallAFunction[1]',
461 \ '->1 SourceAnotherFile[1]',
462 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
463 \ 'line 1: func DoAThing()' ] )
464
465 call RunDbgCmd( buf, 'down' )
466 call RunDbgCmd( buf, 'backtrace', [
467 \ '>backtrace',
468 \ ' 3 function GlobalFunction[1]',
469 \ ' 2 CallAFunction[1]',
470 \ ' 1 SourceAnotherFile[1]',
471 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
472 \ 'line 1: func DoAThing()' ] )
473
474 call RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
475
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200476 " step until we have another meaninfgul trace
477 call RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
478 call RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
479 call RunDbgCmd(buf, 'backtrace', [
480 \ '>backtrace',
481 \ ' 3 function GlobalFunction[1]',
482 \ ' 2 CallAFunction[1]',
483 \ ' 1 SourceAnotherFile[1]',
484 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
485 \ 'line 9: call File2Function()'])
486
487 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
488 call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
489 call RunDbgCmd(buf, 'backtrace', [
490 \ '>backtrace',
491 \ ' 5 function GlobalFunction[1]',
492 \ ' 4 CallAFunction[1]',
493 \ ' 3 SourceAnotherFile[1]',
494 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
495 \ ' 1 function File2Function[1]',
496 \ '->0 DoAThing',
497 \ 'line 1: echo "DoAThing"'])
498
499 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
500 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
501 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
502 call RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
503 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
504 call RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
505 call RunDbgCmd(buf, 'backtrace', [
506 \ '>backtrace',
507 \ ' 1 function GlobalFunction[1]',
508 \ '->0 CallAFunction',
509 \ 'line 2: call File2Function()'])
510
511 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
512 call RunDbgCmd(buf, 'backtrace', [
513 \ '>backtrace',
514 \ ' 2 function GlobalFunction[1]',
515 \ ' 1 CallAFunction[2]',
516 \ '->0 File2Function',
517 \ 'line 1: call DoAThing()'])
518
519 call StopVimInTerminal(buf)
520 call delete('Xtest1.vim')
521 call delete('Xtest2.vim')
522endfunc
523
524func Test_Backtrace_Autocmd()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200525 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200526 let file1 =<< trim END
527 func SourceAnotherFile()
528 source Xtest2.vim
529 endfunc
530
531 func CallAFunction()
532 call SourceAnotherFile()
533 call File2Function()
534 endfunc
535
536 func GlobalFunction()
537 call CallAFunction()
538 endfunc
539
540 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
541 END
542 call writefile(file1, 'Xtest1.vim')
543
544 let file2 =<< trim END
545 func DoAThing()
546 echo "DoAThing"
547 endfunc
548
549 func File2Function()
550 call DoAThing()
551 endfunc
552
553 call File2Function()
554 END
555 call writefile(file2, 'Xtest2.vim')
556
557 let buf = RunVimInTerminal('-S Xtest1.vim', {})
558
559 call RunDbgCmd(buf,
560 \ ':debug doautocmd User TestGlobalFunction',
561 \ ['cmd: doautocmd User TestGlobalFunction'])
562 call RunDbgCmd(buf, 'step', ['cmd: call GlobalFunction() | echo "Done"'])
563
564 " At this point the ontly thing in the stack is the autocommand
565 call RunDbgCmd(buf, 'backtrace', [
566 \ '>backtrace',
567 \ '->0 User Autocommands for "TestGlobalFunction"',
568 \ 'cmd: call GlobalFunction() | echo "Done"'])
569
570 " And now we're back into the call stack
571 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
572 call RunDbgCmd(buf, 'backtrace', [
573 \ '>backtrace',
574 \ ' 1 User Autocommands for "TestGlobalFunction"',
575 \ '->0 function GlobalFunction',
576 \ 'line 1: call CallAFunction()'])
577
578 call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
579 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
580
581 call RunDbgCmd(buf, 'backtrace', [
582 \ '>backtrace',
583 \ ' 3 User Autocommands for "TestGlobalFunction"',
584 \ ' 2 function GlobalFunction[1]',
585 \ ' 1 CallAFunction[1]',
586 \ '->0 SourceAnotherFile',
587 \ 'line 1: source Xtest2.vim'])
588
589 " Step into the 'source' command. Note that we print the full trace all the
590 " way though the source command.
591 call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
592 call RunDbgCmd(buf, 'backtrace', [
593 \ '>backtrace',
594 \ ' 4 User Autocommands for "TestGlobalFunction"',
595 \ ' 3 function GlobalFunction[1]',
596 \ ' 2 CallAFunction[1]',
597 \ ' 1 SourceAnotherFile[1]',
598 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
599 \ 'line 1: func DoAThing()'])
600
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200601 call RunDbgCmd( buf, 'up' )
602 call RunDbgCmd( buf, 'backtrace', [
603 \ '>backtrace',
604 \ ' 4 User Autocommands for "TestGlobalFunction"',
605 \ ' 3 function GlobalFunction[1]',
606 \ ' 2 CallAFunction[1]',
607 \ '->1 SourceAnotherFile[1]',
608 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
609 \ 'line 1: func DoAThing()' ] )
610
611 call RunDbgCmd( buf, 'up' )
612 call RunDbgCmd( buf, 'backtrace', [
613 \ '>backtrace',
614 \ ' 4 User Autocommands for "TestGlobalFunction"',
615 \ ' 3 function GlobalFunction[1]',
616 \ '->2 CallAFunction[1]',
617 \ ' 1 SourceAnotherFile[1]',
618 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
619 \ 'line 1: func DoAThing()' ] )
620
621 call RunDbgCmd( buf, 'up' )
622 call RunDbgCmd( buf, 'backtrace', [
623 \ '>backtrace',
624 \ ' 4 User Autocommands for "TestGlobalFunction"',
625 \ '->3 function GlobalFunction[1]',
626 \ ' 2 CallAFunction[1]',
627 \ ' 1 SourceAnotherFile[1]',
628 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
629 \ 'line 1: func DoAThing()' ] )
630
631 call RunDbgCmd( buf, 'up' )
632 call RunDbgCmd( buf, 'backtrace', [
633 \ '>backtrace',
634 \ '->4 User Autocommands for "TestGlobalFunction"',
635 \ ' 3 function GlobalFunction[1]',
636 \ ' 2 CallAFunction[1]',
637 \ ' 1 SourceAnotherFile[1]',
638 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
639 \ 'line 1: func DoAThing()' ] )
640
641 call RunDbgCmd( buf, 'up', [ 'frame at highest level: 4' ] )
642 call RunDbgCmd( buf, 'backtrace', [
643 \ '>backtrace',
644 \ '->4 User Autocommands for "TestGlobalFunction"',
645 \ ' 3 function GlobalFunction[1]',
646 \ ' 2 CallAFunction[1]',
647 \ ' 1 SourceAnotherFile[1]',
648 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
649 \ 'line 1: func DoAThing()' ] )
650
651 call RunDbgCmd( buf, 'down' )
652 call RunDbgCmd( buf, 'backtrace', [
653 \ '>backtrace',
654 \ ' 4 User Autocommands for "TestGlobalFunction"',
655 \ '->3 function GlobalFunction[1]',
656 \ ' 2 CallAFunction[1]',
657 \ ' 1 SourceAnotherFile[1]',
658 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
659 \ 'line 1: func DoAThing()' ] )
660
661
662 call RunDbgCmd( buf, 'down' )
663 call RunDbgCmd( buf, 'backtrace', [
664 \ '>backtrace',
665 \ ' 4 User Autocommands for "TestGlobalFunction"',
666 \ ' 3 function GlobalFunction[1]',
667 \ '->2 CallAFunction[1]',
668 \ ' 1 SourceAnotherFile[1]',
669 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
670 \ 'line 1: func DoAThing()' ] )
671
672 call RunDbgCmd( buf, 'down' )
673 call RunDbgCmd( buf, 'backtrace', [
674 \ '>backtrace',
675 \ ' 4 User Autocommands for "TestGlobalFunction"',
676 \ ' 3 function GlobalFunction[1]',
677 \ ' 2 CallAFunction[1]',
678 \ '->1 SourceAnotherFile[1]',
679 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
680 \ 'line 1: func DoAThing()' ] )
681
682 call RunDbgCmd( buf, 'down' )
683 call RunDbgCmd( buf, 'backtrace', [
684 \ '>backtrace',
685 \ ' 4 User Autocommands for "TestGlobalFunction"',
686 \ ' 3 function GlobalFunction[1]',
687 \ ' 2 CallAFunction[1]',
688 \ ' 1 SourceAnotherFile[1]',
689 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
690 \ 'line 1: func DoAThing()' ] )
691
692 call RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
693
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200694 " step until we have another meaninfgul trace
695 call RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
696 call RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
697 call RunDbgCmd(buf, 'backtrace', [
698 \ '>backtrace',
699 \ ' 4 User Autocommands for "TestGlobalFunction"',
700 \ ' 3 function GlobalFunction[1]',
701 \ ' 2 CallAFunction[1]',
702 \ ' 1 SourceAnotherFile[1]',
703 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
704 \ 'line 9: call File2Function()'])
705
706 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
707 call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
708 call RunDbgCmd(buf, 'backtrace', [
709 \ '>backtrace',
710 \ ' 6 User Autocommands for "TestGlobalFunction"',
711 \ ' 5 function GlobalFunction[1]',
712 \ ' 4 CallAFunction[1]',
713 \ ' 3 SourceAnotherFile[1]',
714 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
715 \ ' 1 function File2Function[1]',
716 \ '->0 DoAThing',
717 \ 'line 1: echo "DoAThing"'])
718
719 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
720 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
721 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
722 call RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
723 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
724 call RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
725 call RunDbgCmd(buf, 'backtrace', [
726 \ '>backtrace',
727 \ ' 2 User Autocommands for "TestGlobalFunction"',
728 \ ' 1 function GlobalFunction[1]',
729 \ '->0 CallAFunction',
730 \ 'line 2: call File2Function()'])
731
732 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
733 call RunDbgCmd(buf, 'backtrace', [
734 \ '>backtrace',
735 \ ' 3 User Autocommands for "TestGlobalFunction"',
736 \ ' 2 function GlobalFunction[1]',
737 \ ' 1 CallAFunction[2]',
738 \ '->0 File2Function',
739 \ 'line 1: call DoAThing()'])
740
741
742 " Now unwind so that we get back to the original autocommand (and the second
743 " cmd echo "Done")
744 call RunDbgCmd(buf, 'finish', ['line 1: End of function'])
745 call RunDbgCmd(buf, 'backtrace', [
746 \ '>backtrace',
747 \ ' 3 User Autocommands for "TestGlobalFunction"',
748 \ ' 2 function GlobalFunction[1]',
749 \ ' 1 CallAFunction[2]',
750 \ '->0 File2Function',
751 \ 'line 1: End of function'])
752
753 call RunDbgCmd(buf, 'finish', ['line 2: End of function'])
754 call RunDbgCmd(buf, 'backtrace', [
755 \ '>backtrace',
756 \ ' 2 User Autocommands for "TestGlobalFunction"',
757 \ ' 1 function GlobalFunction[1]',
758 \ '->0 CallAFunction',
759 \ 'line 2: End of function'])
760
761 call RunDbgCmd(buf, 'finish', ['line 1: End of function'])
762 call RunDbgCmd(buf, 'backtrace', [
763 \ '>backtrace',
764 \ ' 1 User Autocommands for "TestGlobalFunction"',
765 \ '->0 function GlobalFunction',
766 \ 'line 1: End of function'])
767
768 call RunDbgCmd(buf, 'step', ['cmd: echo "Done"'])
769 call RunDbgCmd(buf, 'backtrace', [
770 \ '>backtrace',
771 \ '->0 User Autocommands for "TestGlobalFunction"',
772 \ 'cmd: echo "Done"'])
773
774 call StopVimInTerminal(buf)
775 call delete('Xtest1.vim')
776 call delete('Xtest2.vim')
777endfunc
778
779func Test_Backtrace_CmdLine()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200780 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200781 let file1 =<< trim END
782 func SourceAnotherFile()
783 source Xtest2.vim
784 endfunc
785
786 func CallAFunction()
787 call SourceAnotherFile()
788 call File2Function()
789 endfunc
790
791 func GlobalFunction()
792 call CallAFunction()
793 endfunc
794
795 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
796 END
797 call writefile(file1, 'Xtest1.vim')
798
799 let file2 =<< trim END
800 func DoAThing()
801 echo "DoAThing"
802 endfunc
803
804 func File2Function()
805 call DoAThing()
806 endfunc
807
808 call File2Function()
809 END
810 call writefile(file2, 'Xtest2.vim')
811
812 let buf = RunVimInTerminal(
813 \ '-S Xtest1.vim -c "debug call GlobalFunction()"',
814 \ {'wait_for_ruler': 0})
815
Bram Moolenaar18dc3552020-11-22 14:24:00 +0100816 " Need to wait for the vim-in-terminal to be ready.
817 " With valgrind this can take quite long.
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200818 call CheckDbgOutput(buf, ['command line',
Bram Moolenaar18dc3552020-11-22 14:24:00 +0100819 \ 'cmd: call GlobalFunction()'], #{msec: 5000})
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200820
821 " At this point the ontly thing in the stack is the cmdline
822 call RunDbgCmd(buf, 'backtrace', [
823 \ '>backtrace',
824 \ '->0 command line',
825 \ 'cmd: call GlobalFunction()'])
826
827 " And now we're back into the call stack
828 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
829 call RunDbgCmd(buf, 'backtrace', [
830 \ '>backtrace',
831 \ ' 1 command line',
832 \ '->0 function GlobalFunction',
833 \ 'line 1: call CallAFunction()'])
834
835 call StopVimInTerminal(buf)
836 call delete('Xtest1.vim')
837 call delete('Xtest2.vim')
838endfunc
839
840func Test_Backtrace_DefFunction()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200841 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200842 let file1 =<< trim END
843 vim9script
844 import File2Function from './Xtest2.vim'
845
846 def SourceAnotherFile()
847 source Xtest2.vim
848 enddef
849
850 def CallAFunction()
851 SourceAnotherFile()
852 File2Function()
853 enddef
854
855 def g:GlobalFunction()
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200856 var some = "some var"
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200857 CallAFunction()
858 enddef
859
860 defcompile
861 END
862 call writefile(file1, 'Xtest1.vim')
863
864 let file2 =<< trim END
865 vim9script
866
867 def DoAThing(): number
Bram Moolenaar1bdae402020-10-03 14:14:56 +0200868 var a = 100 * 2
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200869 a += 3
870 return a
871 enddef
872
873 export def File2Function()
874 DoAThing()
875 enddef
876
877 defcompile
878 File2Function()
879 END
880 call writefile(file2, 'Xtest2.vim')
881
882 let buf = RunVimInTerminal('-S Xtest1.vim', {})
883
884 call RunDbgCmd(buf,
885 \ ':debug call GlobalFunction()',
886 \ ['cmd: call GlobalFunction()'])
887
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200888 call RunDbgCmd(buf, 'step', ['line 1: var some = "some var"'])
889 call RunDbgCmd(buf, 'step', ['line 2: CallAFunction()'])
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200890 call RunDbgCmd(buf, 'echo some', ['some var'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200891
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200892 call RunDbgCmd(buf, 'backtrace', [
893 \ '\V>backtrace',
Bram Moolenaare99d4222021-06-13 14:01:26 +0200894 \ '\V->0 function GlobalFunction',
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200895 \ '\Vline 2: CallAFunction()',
Bram Moolenaare99d4222021-06-13 14:01:26 +0200896 \ ],
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200897 \ #{match: 'pattern'})
898
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200899 call RunDbgCmd(buf, 'step', ['line 1: SourceAnotherFile()'])
900 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200901 " Repeated line, because we fist are in the compiled function before the
902 " EXEC and then in do_cmdline() before the :source command.
Bram Moolenaare99d4222021-06-13 14:01:26 +0200903 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200904 call RunDbgCmd(buf, 'step', ['line 1: vim9script'])
905 call RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number'])
906 call RunDbgCmd(buf, 'step', ['line 9: export def File2Function()'])
907 call RunDbgCmd(buf, 'step', ['line 9: def File2Function()'])
908 call RunDbgCmd(buf, 'step', ['line 13: defcompile'])
909 call RunDbgCmd(buf, 'step', ['line 14: File2Function()'])
910 call RunDbgCmd(buf, 'backtrace', [
911 \ '\V>backtrace',
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200912 \ '\V 3 function GlobalFunction[2]',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200913 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
914 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
915 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
916 \ '\Vline 14: File2Function()'],
917 \ #{match: 'pattern'})
918
919 " Don't step into compiled functions...
Bram Moolenaare99d4222021-06-13 14:01:26 +0200920 call RunDbgCmd(buf, 'next', ['line 15: End of sourced file'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200921 call RunDbgCmd(buf, 'backtrace', [
922 \ '\V>backtrace',
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200923 \ '\V 3 function GlobalFunction[2]',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200924 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
925 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
926 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
927 \ '\Vline 15: End of sourced file'],
928 \ #{match: 'pattern'})
929
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200930 call StopVimInTerminal(buf)
931 call delete('Xtest1.vim')
932 call delete('Xtest2.vim')
933endfunc
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200934
Bram Moolenaar968a5b62021-06-15 19:32:40 +0200935func Test_debug_def_function()
936 CheckCWD
937 let file =<< trim END
938 vim9script
939 def g:Func()
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200940 var n: number
941 def Closure(): number
942 return n + 3
943 enddef
944 n += Closure()
945 echo 'result: ' .. n
946 enddef
947
948 def g:FuncWithArgs(text: string, nr: number, ...items: list<number>)
949 echo text .. nr
950 for it in items
951 echo it
952 endfor
953 echo "done"
Bram Moolenaar968a5b62021-06-15 19:32:40 +0200954 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200955
956 def g:FuncWithDict()
957 var d = {
958 a: 1,
959 b: 2,
960 }
Bram Moolenaar59b50c32021-06-17 22:27:48 +0200961 # comment
962 def Inner()
963 eval 1
964 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200965 enddef
Bram Moolenaar968a5b62021-06-15 19:32:40 +0200966 END
967 call writefile(file, 'Xtest.vim')
968
969 let buf = RunVimInTerminal('-S Xtest.vim', {})
970
971 call RunDbgCmd(buf,
972 \ ':debug call Func()',
973 \ ['cmd: call Func()'])
974 call RunDbgCmd(buf, 'next', ['result: 3'])
975 call term_sendkeys(buf, "\r")
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200976 call RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +0200977
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200978 call RunDbgCmd(buf,
979 \ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)',
980 \ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200981 call RunDbgCmd(buf, 'step', ['line 1: echo text .. nr'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200982 call RunDbgCmd(buf, 'echo text', ['asdf'])
983 call RunDbgCmd(buf, 'echo nr', ['42'])
984 call RunDbgCmd(buf, 'echo items', ['[1, 2, 3]'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200985 call RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200986 call RunDbgCmd(buf, 'echo it', ['1'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200987 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
988 call RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor'])
989 call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200990 call RunDbgCmd(buf, 'echo it', ['2'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200991 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
992 call RunDbgCmd(buf, 'step', ['2', 'function FuncWithArgs', 'line 4: endfor'])
993 call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200994 call RunDbgCmd(buf, 'echo it', ['3'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200995 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
996 call RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor'])
997 call RunDbgCmd(buf, 'step', ['line 5: echo "done"'])
998 call RunDbgCmd(buf, 'cont')
999
1000 call RunDbgCmd(buf,
1001 \ ':debug call FuncWithDict()',
1002 \ ['cmd: call FuncWithDict()'])
1003 call RunDbgCmd(buf, 'step', ['line 1: var d = { a: 1, b: 2, }'])
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001004 call RunDbgCmd(buf, 'step', ['line 6: def Inner()'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001005
1006 call RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001007 call StopVimInTerminal(buf)
1008 call delete('Xtest.vim')
1009endfunc
1010
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001011func Test_debug_backtrace_level()
1012 CheckCWD
1013 let lines =<< trim END
1014 let s:file1_var = 'file1'
1015 let g:global_var = 'global'
1016
1017 func s:File1Func( arg )
1018 let s:file1_var .= a:arg
1019 let local_var = s:file1_var .. ' test1'
1020 let g:global_var .= local_var
1021 source Xtest2.vim
1022 endfunc
1023
1024 call s:File1Func( 'arg1' )
1025 END
1026 call writefile(lines, 'Xtest1.vim')
1027
1028 let lines =<< trim END
1029 let s:file2_var = 'file2'
1030
1031 func s:File2Func( arg )
1032 let s:file2_var .= a:arg
1033 let local_var = s:file2_var .. ' test2'
1034 let g:global_var .= local_var
1035 endfunc
1036
1037 call s:File2Func( 'arg2' )
1038 END
1039 call writefile(lines, 'Xtest2.vim')
1040
1041 let file1 = getcwd() .. '/Xtest1.vim'
1042 let file2 = getcwd() .. '/Xtest2.vim'
1043
1044 " set a breakpoint and source file1.vim
1045 let buf = RunVimInTerminal(
1046 \ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim',
Bram Moolenaar18dc3552020-11-22 14:24:00 +01001047 \ #{wait_for_ruler: 0})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001048
1049 call CheckDbgOutput(buf, [
1050 \ 'Breakpoint in "' .. file1 .. '" line 1',
1051 \ 'Entering Debug mode. Type "cont" to continue.',
1052 \ 'command line..script ' .. file1,
1053 \ 'line 1: let s:file1_var = ''file1'''
Bram Moolenaar18dc3552020-11-22 14:24:00 +01001054 \ ], #{msec: 5000})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001055
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01001056 " step through the initial declarations
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001057 call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] )
1058 call RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] )
1059 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1060 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1061 call RunDbgCmd(buf, 'echo global_var', [ 'global' ] )
1062
1063 " step in to the first function
1064 call RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] )
1065 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] )
1066 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1067 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1068 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1069 call RunDbgCmd(buf,
1070 \'echo global_var',
1071 \[ 'E121: Undefined variable: global_var' ] )
1072 call RunDbgCmd(buf,
1073 \'echo local_var',
1074 \[ 'E121: Undefined variable: local_var' ] )
1075 call RunDbgCmd(buf,
1076 \'echo l:local_var',
1077 \[ 'E121: Undefined variable: l:local_var' ] )
1078
1079 " backtrace up
1080 call RunDbgCmd(buf, 'backtrace', [
1081 \ '\V>backtrace',
1082 \ '\V 2 command line',
1083 \ '\V 1 script ' .. file1 .. '[11]',
1084 \ '\V->0 function <SNR>\.\*_File1Func',
1085 \ '\Vline 1: let s:file1_var .= a:arg',
1086 \ ],
1087 \ #{ match: 'pattern' } )
1088 call RunDbgCmd(buf, 'up', [ '>up' ] )
1089
1090 call RunDbgCmd(buf, 'backtrace', [
1091 \ '\V>backtrace',
1092 \ '\V 2 command line',
1093 \ '\V->1 script ' .. file1 .. '[11]',
1094 \ '\V 0 function <SNR>\.\*_File1Func',
1095 \ '\Vline 1: let s:file1_var .= a:arg',
1096 \ ],
1097 \ #{ match: 'pattern' } )
1098
1099 " Expression evaluation in the script frame (not the function frame)
1100 " FIXME: Unexpected in this scope (a: should not be visibnle)
1101 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1102 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1103 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1104 " FIXME: Unexpected in this scope (global should be found)
1105 call RunDbgCmd(buf,
1106 \'echo global_var',
1107 \[ 'E121: Undefined variable: global_var' ] )
1108 call RunDbgCmd(buf,
1109 \'echo local_var',
1110 \[ 'E121: Undefined variable: local_var' ] )
1111 call RunDbgCmd(buf,
1112 \'echo l:local_var',
1113 \[ 'E121: Undefined variable: l:local_var' ] )
1114
1115
1116 " step while backtraced jumps to the latest frame
1117 call RunDbgCmd(buf, 'step', [
1118 \ 'line 2: let local_var = s:file1_var .. '' test1''' ] )
1119 call RunDbgCmd(buf, 'backtrace', [
1120 \ '\V>backtrace',
1121 \ '\V 2 command line',
1122 \ '\V 1 script ' .. file1 .. '[11]',
1123 \ '\V->0 function <SNR>\.\*_File1Func',
1124 \ '\Vline 2: let local_var = s:file1_var .. '' test1''',
1125 \ ],
1126 \ #{ match: 'pattern' } )
1127
1128 call RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] )
1129 call RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] )
1130 call RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] )
1131
1132 call RunDbgCmd(buf, 'step', [ 'line 4: source Xtest2.vim' ] )
1133 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file2_var = ''file2''' ] )
1134 call RunDbgCmd(buf, 'backtrace', [
1135 \ '\V>backtrace',
1136 \ '\V 3 command line',
1137 \ '\V 2 script ' .. file1 .. '[11]',
1138 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1139 \ '\V->0 script ' .. file2,
1140 \ '\Vline 1: let s:file2_var = ''file2''',
1141 \ ],
1142 \ #{ match: 'pattern' } )
1143
1144 " Expression evaluation in the script frame file2 (not the function frame)
1145 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1146 call RunDbgCmd(buf,
1147 \ 'echo s:file1_var',
1148 \ [ 'E121: Undefined variable: s:file1_var' ] )
1149 call RunDbgCmd(buf, 'echo g:global_var', [ 'globalfile1arg1 test1' ] )
1150 call RunDbgCmd(buf, 'echo global_var', [ 'globalfile1arg1 test1' ] )
1151 call RunDbgCmd(buf,
1152 \'echo local_var',
1153 \[ 'E121: Undefined variable: local_var' ] )
1154 call RunDbgCmd(buf,
1155 \'echo l:local_var',
1156 \[ 'E121: Undefined variable: l:local_var' ] )
1157 call RunDbgCmd(buf,
1158 \ 'echo s:file2_var',
1159 \ [ 'E121: Undefined variable: s:file2_var' ] )
1160
1161 call RunDbgCmd(buf, 'step', [ 'line 3: func s:File2Func( arg )' ] )
1162 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1163
1164 " Up the stack to the other script context
1165 call RunDbgCmd(buf, 'up')
1166 call RunDbgCmd(buf, 'backtrace', [
1167 \ '\V>backtrace',
1168 \ '\V 3 command line',
1169 \ '\V 2 script ' .. file1 .. '[11]',
1170 \ '\V->1 function <SNR>\.\*_File1Func[4]',
1171 \ '\V 0 script ' .. file2,
1172 \ '\Vline 3: func s:File2Func( arg )',
1173 \ ],
1174 \ #{ match: 'pattern' } )
1175 " FIXME: Unexpected. Should see the a: and l: dicts from File1Func
1176 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1177 call RunDbgCmd(buf,
1178 \ 'echo l:local_var',
1179 \ [ 'E121: Undefined variable: l:local_var' ] )
1180
1181 call RunDbgCmd(buf, 'up')
1182 call RunDbgCmd(buf, 'backtrace', [
1183 \ '\V>backtrace',
1184 \ '\V 3 command line',
1185 \ '\V->2 script ' .. file1 .. '[11]',
1186 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1187 \ '\V 0 script ' .. file2,
1188 \ '\Vline 3: func s:File2Func( arg )',
1189 \ ],
1190 \ #{ match: 'pattern' } )
1191
1192 " FIXME: Unexpected (wrong script vars are used)
1193 call RunDbgCmd(buf,
1194 \ 'echo s:file1_var',
1195 \ [ 'E121: Undefined variable: s:file1_var' ] )
1196 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1197
Bram Moolenaare99d4222021-06-13 14:01:26 +02001198 call RunDbgCmd(buf, 'cont')
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001199 call StopVimInTerminal(buf)
1200 call delete('Xtest1.vim')
1201 call delete('Xtest2.vim')
1202endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001203
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001204" Test for setting a breakpoint on a :endif where the :if condition is false
1205" and then quit the script. This should generate an interrupt.
1206func Test_breakpt_endif_intr()
1207 func F()
1208 let g:Xpath ..= 'a'
1209 if v:false
1210 let g:Xpath ..= 'b'
1211 endif
1212 invalid_command
1213 endfunc
1214
1215 let g:Xpath = ''
1216 breakadd func 4 F
1217 try
1218 let caught_intr = 0
1219 debuggreedy
1220 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001221 catch /^Vim:Interrupt$/
1222 call assert_match('\.F, line 4', v:throwpoint)
1223 let caught_intr = 1
1224 endtry
1225 0debuggreedy
1226 call assert_equal(1, caught_intr)
1227 call assert_equal('a', g:Xpath)
1228 breakdel *
1229 delfunc F
1230endfunc
1231
1232" Test for setting a breakpoint on a :else where the :if condition is false
1233" and then quit the script. This should generate an interrupt.
1234func Test_breakpt_else_intr()
1235 func F()
1236 let g:Xpath ..= 'a'
1237 if v:false
1238 let g:Xpath ..= 'b'
1239 else
1240 invalid_command
1241 endif
1242 invalid_command
1243 endfunc
1244
1245 let g:Xpath = ''
1246 breakadd func 4 F
1247 try
1248 let caught_intr = 0
1249 debuggreedy
1250 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001251 catch /^Vim:Interrupt$/
1252 call assert_match('\.F, line 4', v:throwpoint)
1253 let caught_intr = 1
1254 endtry
1255 0debuggreedy
1256 call assert_equal(1, caught_intr)
1257 call assert_equal('a', g:Xpath)
1258 breakdel *
1259 delfunc F
1260endfunc
1261
1262" Test for setting a breakpoint on a :endwhile where the :while condition is
1263" false and then quit the script. This should generate an interrupt.
1264func Test_breakpt_endwhile_intr()
1265 func F()
1266 let g:Xpath ..= 'a'
1267 while v:false
1268 let g:Xpath ..= 'b'
1269 endwhile
1270 invalid_command
1271 endfunc
1272
1273 let g:Xpath = ''
1274 breakadd func 4 F
1275 try
1276 let caught_intr = 0
1277 debuggreedy
1278 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001279 catch /^Vim:Interrupt$/
1280 call assert_match('\.F, line 4', v:throwpoint)
1281 let caught_intr = 1
1282 endtry
1283 0debuggreedy
1284 call assert_equal(1, caught_intr)
1285 call assert_equal('a', g:Xpath)
1286 breakdel *
1287 delfunc F
1288endfunc
1289
Bram Moolenaar16c62322020-08-13 19:20:04 +02001290" Test for setting a breakpoint on a script local function
1291func Test_breakpt_scriptlocal_func()
1292 let g:Xpath = ''
1293 func s:G()
1294 let g:Xpath ..= 'a'
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001295 endfunc
1296
Bram Moolenaar16c62322020-08-13 19:20:04 +02001297 let funcname = expand("<SID>") .. "G"
1298 exe "breakadd func 1 " .. funcname
1299 debuggreedy
1300 redir => output
1301 call feedkeys(":call " .. funcname .. "()\<CR>c\<CR>", "xt")
1302 redir END
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001303 0debuggreedy
Bram Moolenaar16c62322020-08-13 19:20:04 +02001304 call assert_match('Breakpoint in "' .. funcname .. '" line 1', output)
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001305 call assert_equal('a', g:Xpath)
1306 breakdel *
Bram Moolenaar16c62322020-08-13 19:20:04 +02001307 exe "delfunc " .. funcname
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001308endfunc
1309
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001310" vim: shiftwidth=2 sts=2 expandtab