blob: a6e3966096e8a5fcc17e7c69387f1b3e957d8f33 [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 }
961 enddef
Bram Moolenaar968a5b62021-06-15 19:32:40 +0200962 END
963 call writefile(file, 'Xtest.vim')
964
965 let buf = RunVimInTerminal('-S Xtest.vim', {})
966
967 call RunDbgCmd(buf,
968 \ ':debug call Func()',
969 \ ['cmd: call Func()'])
970 call RunDbgCmd(buf, 'next', ['result: 3'])
971 call term_sendkeys(buf, "\r")
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200972 call RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +0200973
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200974 call RunDbgCmd(buf,
975 \ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)',
976 \ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200977 call RunDbgCmd(buf, 'step', ['line 1: echo text .. nr'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200978 call RunDbgCmd(buf, 'echo text', ['asdf'])
979 call RunDbgCmd(buf, 'echo nr', ['42'])
980 call RunDbgCmd(buf, 'echo items', ['[1, 2, 3]'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200981 call RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200982 call RunDbgCmd(buf, 'echo it', ['1'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200983 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
984 call RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor'])
985 call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200986 call RunDbgCmd(buf, 'echo it', ['2'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200987 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
988 call RunDbgCmd(buf, 'step', ['2', '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', ['3'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200991 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
992 call RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor'])
993 call RunDbgCmd(buf, 'step', ['line 5: echo "done"'])
994 call RunDbgCmd(buf, 'cont')
995
996 call RunDbgCmd(buf,
997 \ ':debug call FuncWithDict()',
998 \ ['cmd: call FuncWithDict()'])
999 call RunDbgCmd(buf, 'step', ['line 1: var d = { a: 1, b: 2, }'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001000
1001 call RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001002 call StopVimInTerminal(buf)
1003 call delete('Xtest.vim')
1004endfunc
1005
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001006func Test_debug_backtrace_level()
1007 CheckCWD
1008 let lines =<< trim END
1009 let s:file1_var = 'file1'
1010 let g:global_var = 'global'
1011
1012 func s:File1Func( arg )
1013 let s:file1_var .= a:arg
1014 let local_var = s:file1_var .. ' test1'
1015 let g:global_var .= local_var
1016 source Xtest2.vim
1017 endfunc
1018
1019 call s:File1Func( 'arg1' )
1020 END
1021 call writefile(lines, 'Xtest1.vim')
1022
1023 let lines =<< trim END
1024 let s:file2_var = 'file2'
1025
1026 func s:File2Func( arg )
1027 let s:file2_var .= a:arg
1028 let local_var = s:file2_var .. ' test2'
1029 let g:global_var .= local_var
1030 endfunc
1031
1032 call s:File2Func( 'arg2' )
1033 END
1034 call writefile(lines, 'Xtest2.vim')
1035
1036 let file1 = getcwd() .. '/Xtest1.vim'
1037 let file2 = getcwd() .. '/Xtest2.vim'
1038
1039 " set a breakpoint and source file1.vim
1040 let buf = RunVimInTerminal(
1041 \ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim',
Bram Moolenaar18dc3552020-11-22 14:24:00 +01001042 \ #{wait_for_ruler: 0})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001043
1044 call CheckDbgOutput(buf, [
1045 \ 'Breakpoint in "' .. file1 .. '" line 1',
1046 \ 'Entering Debug mode. Type "cont" to continue.',
1047 \ 'command line..script ' .. file1,
1048 \ 'line 1: let s:file1_var = ''file1'''
Bram Moolenaar18dc3552020-11-22 14:24:00 +01001049 \ ], #{msec: 5000})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001050
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01001051 " step through the initial declarations
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001052 call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] )
1053 call RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] )
1054 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1055 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1056 call RunDbgCmd(buf, 'echo global_var', [ 'global' ] )
1057
1058 " step in to the first function
1059 call RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] )
1060 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] )
1061 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1062 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1063 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1064 call RunDbgCmd(buf,
1065 \'echo global_var',
1066 \[ 'E121: Undefined variable: global_var' ] )
1067 call RunDbgCmd(buf,
1068 \'echo local_var',
1069 \[ 'E121: Undefined variable: local_var' ] )
1070 call RunDbgCmd(buf,
1071 \'echo l:local_var',
1072 \[ 'E121: Undefined variable: l:local_var' ] )
1073
1074 " backtrace up
1075 call RunDbgCmd(buf, 'backtrace', [
1076 \ '\V>backtrace',
1077 \ '\V 2 command line',
1078 \ '\V 1 script ' .. file1 .. '[11]',
1079 \ '\V->0 function <SNR>\.\*_File1Func',
1080 \ '\Vline 1: let s:file1_var .= a:arg',
1081 \ ],
1082 \ #{ match: 'pattern' } )
1083 call RunDbgCmd(buf, 'up', [ '>up' ] )
1084
1085 call RunDbgCmd(buf, 'backtrace', [
1086 \ '\V>backtrace',
1087 \ '\V 2 command line',
1088 \ '\V->1 script ' .. file1 .. '[11]',
1089 \ '\V 0 function <SNR>\.\*_File1Func',
1090 \ '\Vline 1: let s:file1_var .= a:arg',
1091 \ ],
1092 \ #{ match: 'pattern' } )
1093
1094 " Expression evaluation in the script frame (not the function frame)
1095 " FIXME: Unexpected in this scope (a: should not be visibnle)
1096 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1097 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1098 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1099 " FIXME: Unexpected in this scope (global should be found)
1100 call RunDbgCmd(buf,
1101 \'echo global_var',
1102 \[ 'E121: Undefined variable: global_var' ] )
1103 call RunDbgCmd(buf,
1104 \'echo local_var',
1105 \[ 'E121: Undefined variable: local_var' ] )
1106 call RunDbgCmd(buf,
1107 \'echo l:local_var',
1108 \[ 'E121: Undefined variable: l:local_var' ] )
1109
1110
1111 " step while backtraced jumps to the latest frame
1112 call RunDbgCmd(buf, 'step', [
1113 \ 'line 2: let local_var = s:file1_var .. '' test1''' ] )
1114 call RunDbgCmd(buf, 'backtrace', [
1115 \ '\V>backtrace',
1116 \ '\V 2 command line',
1117 \ '\V 1 script ' .. file1 .. '[11]',
1118 \ '\V->0 function <SNR>\.\*_File1Func',
1119 \ '\Vline 2: let local_var = s:file1_var .. '' test1''',
1120 \ ],
1121 \ #{ match: 'pattern' } )
1122
1123 call RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] )
1124 call RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] )
1125 call RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] )
1126
1127 call RunDbgCmd(buf, 'step', [ 'line 4: source Xtest2.vim' ] )
1128 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file2_var = ''file2''' ] )
1129 call RunDbgCmd(buf, 'backtrace', [
1130 \ '\V>backtrace',
1131 \ '\V 3 command line',
1132 \ '\V 2 script ' .. file1 .. '[11]',
1133 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1134 \ '\V->0 script ' .. file2,
1135 \ '\Vline 1: let s:file2_var = ''file2''',
1136 \ ],
1137 \ #{ match: 'pattern' } )
1138
1139 " Expression evaluation in the script frame file2 (not the function frame)
1140 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1141 call RunDbgCmd(buf,
1142 \ 'echo s:file1_var',
1143 \ [ 'E121: Undefined variable: s:file1_var' ] )
1144 call RunDbgCmd(buf, 'echo g:global_var', [ 'globalfile1arg1 test1' ] )
1145 call RunDbgCmd(buf, 'echo global_var', [ 'globalfile1arg1 test1' ] )
1146 call RunDbgCmd(buf,
1147 \'echo local_var',
1148 \[ 'E121: Undefined variable: local_var' ] )
1149 call RunDbgCmd(buf,
1150 \'echo l:local_var',
1151 \[ 'E121: Undefined variable: l:local_var' ] )
1152 call RunDbgCmd(buf,
1153 \ 'echo s:file2_var',
1154 \ [ 'E121: Undefined variable: s:file2_var' ] )
1155
1156 call RunDbgCmd(buf, 'step', [ 'line 3: func s:File2Func( arg )' ] )
1157 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1158
1159 " Up the stack to the other script context
1160 call RunDbgCmd(buf, 'up')
1161 call RunDbgCmd(buf, 'backtrace', [
1162 \ '\V>backtrace',
1163 \ '\V 3 command line',
1164 \ '\V 2 script ' .. file1 .. '[11]',
1165 \ '\V->1 function <SNR>\.\*_File1Func[4]',
1166 \ '\V 0 script ' .. file2,
1167 \ '\Vline 3: func s:File2Func( arg )',
1168 \ ],
1169 \ #{ match: 'pattern' } )
1170 " FIXME: Unexpected. Should see the a: and l: dicts from File1Func
1171 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1172 call RunDbgCmd(buf,
1173 \ 'echo l:local_var',
1174 \ [ 'E121: Undefined variable: l:local_var' ] )
1175
1176 call RunDbgCmd(buf, 'up')
1177 call RunDbgCmd(buf, 'backtrace', [
1178 \ '\V>backtrace',
1179 \ '\V 3 command line',
1180 \ '\V->2 script ' .. file1 .. '[11]',
1181 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1182 \ '\V 0 script ' .. file2,
1183 \ '\Vline 3: func s:File2Func( arg )',
1184 \ ],
1185 \ #{ match: 'pattern' } )
1186
1187 " FIXME: Unexpected (wrong script vars are used)
1188 call RunDbgCmd(buf,
1189 \ 'echo s:file1_var',
1190 \ [ 'E121: Undefined variable: s:file1_var' ] )
1191 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1192
Bram Moolenaare99d4222021-06-13 14:01:26 +02001193 call RunDbgCmd(buf, 'cont')
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001194 call StopVimInTerminal(buf)
1195 call delete('Xtest1.vim')
1196 call delete('Xtest2.vim')
1197endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001198
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001199" Test for setting a breakpoint on a :endif where the :if condition is false
1200" and then quit the script. This should generate an interrupt.
1201func Test_breakpt_endif_intr()
1202 func F()
1203 let g:Xpath ..= 'a'
1204 if v:false
1205 let g:Xpath ..= 'b'
1206 endif
1207 invalid_command
1208 endfunc
1209
1210 let g:Xpath = ''
1211 breakadd func 4 F
1212 try
1213 let caught_intr = 0
1214 debuggreedy
1215 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001216 catch /^Vim:Interrupt$/
1217 call assert_match('\.F, line 4', v:throwpoint)
1218 let caught_intr = 1
1219 endtry
1220 0debuggreedy
1221 call assert_equal(1, caught_intr)
1222 call assert_equal('a', g:Xpath)
1223 breakdel *
1224 delfunc F
1225endfunc
1226
1227" Test for setting a breakpoint on a :else where the :if condition is false
1228" and then quit the script. This should generate an interrupt.
1229func Test_breakpt_else_intr()
1230 func F()
1231 let g:Xpath ..= 'a'
1232 if v:false
1233 let g:Xpath ..= 'b'
1234 else
1235 invalid_command
1236 endif
1237 invalid_command
1238 endfunc
1239
1240 let g:Xpath = ''
1241 breakadd func 4 F
1242 try
1243 let caught_intr = 0
1244 debuggreedy
1245 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001246 catch /^Vim:Interrupt$/
1247 call assert_match('\.F, line 4', v:throwpoint)
1248 let caught_intr = 1
1249 endtry
1250 0debuggreedy
1251 call assert_equal(1, caught_intr)
1252 call assert_equal('a', g:Xpath)
1253 breakdel *
1254 delfunc F
1255endfunc
1256
1257" Test for setting a breakpoint on a :endwhile where the :while condition is
1258" false and then quit the script. This should generate an interrupt.
1259func Test_breakpt_endwhile_intr()
1260 func F()
1261 let g:Xpath ..= 'a'
1262 while v:false
1263 let g:Xpath ..= 'b'
1264 endwhile
1265 invalid_command
1266 endfunc
1267
1268 let g:Xpath = ''
1269 breakadd func 4 F
1270 try
1271 let caught_intr = 0
1272 debuggreedy
1273 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001274 catch /^Vim:Interrupt$/
1275 call assert_match('\.F, line 4', v:throwpoint)
1276 let caught_intr = 1
1277 endtry
1278 0debuggreedy
1279 call assert_equal(1, caught_intr)
1280 call assert_equal('a', g:Xpath)
1281 breakdel *
1282 delfunc F
1283endfunc
1284
Bram Moolenaar16c62322020-08-13 19:20:04 +02001285" Test for setting a breakpoint on a script local function
1286func Test_breakpt_scriptlocal_func()
1287 let g:Xpath = ''
1288 func s:G()
1289 let g:Xpath ..= 'a'
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001290 endfunc
1291
Bram Moolenaar16c62322020-08-13 19:20:04 +02001292 let funcname = expand("<SID>") .. "G"
1293 exe "breakadd func 1 " .. funcname
1294 debuggreedy
1295 redir => output
1296 call feedkeys(":call " .. funcname .. "()\<CR>c\<CR>", "xt")
1297 redir END
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001298 0debuggreedy
Bram Moolenaar16c62322020-08-13 19:20:04 +02001299 call assert_match('Breakpoint in "' .. funcname .. '" line 1', output)
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001300 call assert_equal('a', g:Xpath)
1301 breakdel *
Bram Moolenaar16c62322020-08-13 19:20:04 +02001302 exe "delfunc " .. funcname
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001303endfunc
1304
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001305" vim: shiftwidth=2 sts=2 expandtab