blob: 5b12c58778153ae4e3b10915faca29adf51487ae [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 Moolenaar17d868b2021-06-27 16:29:53 +0200935func Test_debug_def_and_legacy_function()
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200936 CheckCWD
937 let file =<< trim END
938 vim9script
939 def g:SomeFunc()
940 echo "here"
941 echo "and"
942 echo "there"
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200943 breakadd func 2 LocalFunc
944 LocalFunc()
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200945 enddef
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200946
947 def LocalFunc()
948 echo "first"
949 echo "second"
Bram Moolenaar8cec9272021-06-23 20:20:53 +0200950 breakadd func LegacyFunc
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200951 LegacyFunc()
952 enddef
953
954 func LegacyFunc()
955 echo "legone"
956 echo "legtwo"
957 endfunc
958
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200959 breakadd func 2 g:SomeFunc
960 END
961 call writefile(file, 'XtestDebug.vim')
962
963 let buf = RunVimInTerminal('-S XtestDebug.vim', {})
964
965 call RunDbgCmd(buf,':call SomeFunc()', ['line 2: echo "and"'])
966 call RunDbgCmd(buf,'next', ['line 3: echo "there"'])
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200967 call RunDbgCmd(buf,'next', ['line 4: breakadd func 2 LocalFunc'])
968
969 " continue, next breakpoint is in LocalFunc()
970 call RunDbgCmd(buf,'cont', ['line 2: echo "second"'])
971
972 " continue, next breakpoint is in LegacyFunc()
973 call RunDbgCmd(buf,'cont', ['line 1: echo "legone"'])
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200974
975 call RunDbgCmd(buf, 'cont')
976
977 call StopVimInTerminal(buf)
Dominique Pelle6c72fd52021-07-04 12:30:06 +0200978 call delete('XtestDebug.vim')
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200979endfunc
980
Bram Moolenaar968a5b62021-06-15 19:32:40 +0200981func Test_debug_def_function()
982 CheckCWD
983 let file =<< trim END
984 vim9script
985 def g:Func()
Bram Moolenaar6bc30b02021-06-16 19:19:55 +0200986 var n: number
987 def Closure(): number
988 return n + 3
989 enddef
990 n += Closure()
991 echo 'result: ' .. n
992 enddef
993
994 def g:FuncWithArgs(text: string, nr: number, ...items: list<number>)
995 echo text .. nr
996 for it in items
997 echo it
998 endfor
999 echo "done"
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001000 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001001
1002 def g:FuncWithDict()
1003 var d = {
1004 a: 1,
1005 b: 2,
1006 }
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001007 # comment
1008 def Inner()
1009 eval 1
1010 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001011 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001012
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001013 def g:FuncComment()
1014 # comment
1015 echo "first"
1016 .. "one"
1017 # comment
1018 echo "second"
1019 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001020
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001021 def g:FuncForLoop()
1022 eval 1
1023 for i in [11, 22, 33]
1024 eval i
1025 endfor
1026 echo "done"
1027 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001028
1029 def g:FuncWithSplitLine()
1030 eval 1
1031 | eval 2
1032 enddef
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001033 END
1034 call writefile(file, 'Xtest.vim')
1035
1036 let buf = RunVimInTerminal('-S Xtest.vim', {})
1037
1038 call RunDbgCmd(buf,
1039 \ ':debug call Func()',
1040 \ ['cmd: call Func()'])
1041 call RunDbgCmd(buf, 'next', ['result: 3'])
1042 call term_sendkeys(buf, "\r")
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001043 call RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001044
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001045 call RunDbgCmd(buf,
1046 \ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)',
1047 \ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001048 call RunDbgCmd(buf, 'step', ['line 1: echo text .. nr'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001049 call RunDbgCmd(buf, 'echo text', ['asdf'])
1050 call RunDbgCmd(buf, 'echo nr', ['42'])
1051 call RunDbgCmd(buf, 'echo items', ['[1, 2, 3]'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001052 call RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001053 call RunDbgCmd(buf, 'echo it', ['1'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001054 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
1055 call RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor'])
1056 call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001057 call RunDbgCmd(buf, 'echo it', ['2'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001058 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
1059 call RunDbgCmd(buf, 'step', ['2', 'function FuncWithArgs', 'line 4: endfor'])
1060 call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001061 call RunDbgCmd(buf, 'echo it', ['3'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001062 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
1063 call RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor'])
1064 call RunDbgCmd(buf, 'step', ['line 5: echo "done"'])
1065 call RunDbgCmd(buf, 'cont')
1066
1067 call RunDbgCmd(buf,
1068 \ ':debug call FuncWithDict()',
1069 \ ['cmd: call FuncWithDict()'])
1070 call RunDbgCmd(buf, 'step', ['line 1: var d = { a: 1, b: 2, }'])
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001071 call RunDbgCmd(buf, 'step', ['line 6: def Inner()'])
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001072 call RunDbgCmd(buf, 'cont')
1073
1074 call RunDbgCmd(buf, ':breakadd func 1 FuncComment')
1075 call RunDbgCmd(buf, ':call FuncComment()', ['function FuncComment', 'line 2: echo "first" .. "one"'])
1076 call RunDbgCmd(buf, ':breakadd func 3 FuncComment')
1077 call RunDbgCmd(buf, 'cont', ['function FuncComment', 'line 5: echo "second"'])
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001078 call RunDbgCmd(buf, 'cont')
1079
1080 call RunDbgCmd(buf, ':breakadd func 2 FuncForLoop')
1081 call RunDbgCmd(buf, ':call FuncForLoop()', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
1082 call RunDbgCmd(buf, 'echo i', ['11'])
1083 call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 3: eval i'])
1084 call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 4: endfor'])
1085 call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
1086 call RunDbgCmd(buf, 'echo i', ['22'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001087
Bram Moolenaar303215d2021-07-07 20:10:43 +02001088 call RunDbgCmd(buf, 'breakdel *')
1089 call RunDbgCmd(buf, 'cont')
1090
1091 call RunDbgCmd(buf, ':breakadd func FuncWithSplitLine')
1092 call RunDbgCmd(buf, ':call FuncWithSplitLine()', ['function FuncWithSplitLine', 'line 1: eval 1 | eval 2'])
1093
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001094 call RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001095 call StopVimInTerminal(buf)
1096 call delete('Xtest.vim')
1097endfunc
1098
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001099func Test_debug_def_function_with_lambda()
1100 CheckCWD
1101 let lines =<< trim END
1102 vim9script
1103 def g:Func()
1104 var s = 'a'
1105 ['b']->map((_, v) => s)
1106 echo "done"
1107 enddef
1108 breakadd func 2 g:Func
1109 END
1110 call writefile(lines, 'XtestLambda.vim')
1111
1112 let buf = RunVimInTerminal('-S XtestLambda.vim', {})
1113
1114 call RunDbgCmd(buf,
1115 \ ':call g:Func()',
1116 \ ['function Func', 'line 2: [''b'']->map((_, v) => s)'])
1117 call RunDbgCmd(buf,
1118 \ 'next',
1119 \ ['function Func', 'line 3: echo "done"'])
1120
1121 call RunDbgCmd(buf, 'cont')
1122 call StopVimInTerminal(buf)
1123 call delete('XtestLambda.vim')
1124endfunc
1125
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001126func Test_debug_backtrace_level()
1127 CheckCWD
1128 let lines =<< trim END
1129 let s:file1_var = 'file1'
1130 let g:global_var = 'global'
1131
1132 func s:File1Func( arg )
1133 let s:file1_var .= a:arg
1134 let local_var = s:file1_var .. ' test1'
1135 let g:global_var .= local_var
1136 source Xtest2.vim
1137 endfunc
1138
1139 call s:File1Func( 'arg1' )
1140 END
1141 call writefile(lines, 'Xtest1.vim')
1142
1143 let lines =<< trim END
1144 let s:file2_var = 'file2'
1145
1146 func s:File2Func( arg )
1147 let s:file2_var .= a:arg
1148 let local_var = s:file2_var .. ' test2'
1149 let g:global_var .= local_var
1150 endfunc
1151
1152 call s:File2Func( 'arg2' )
1153 END
1154 call writefile(lines, 'Xtest2.vim')
1155
1156 let file1 = getcwd() .. '/Xtest1.vim'
1157 let file2 = getcwd() .. '/Xtest2.vim'
1158
1159 " set a breakpoint and source file1.vim
1160 let buf = RunVimInTerminal(
1161 \ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim',
Bram Moolenaar18dc3552020-11-22 14:24:00 +01001162 \ #{wait_for_ruler: 0})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001163
1164 call CheckDbgOutput(buf, [
1165 \ 'Breakpoint in "' .. file1 .. '" line 1',
1166 \ 'Entering Debug mode. Type "cont" to continue.',
1167 \ 'command line..script ' .. file1,
1168 \ 'line 1: let s:file1_var = ''file1'''
Bram Moolenaar18dc3552020-11-22 14:24:00 +01001169 \ ], #{msec: 5000})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001170
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01001171 " step through the initial declarations
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001172 call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] )
1173 call RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] )
1174 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1175 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1176 call RunDbgCmd(buf, 'echo global_var', [ 'global' ] )
1177
1178 " step in to the first function
1179 call RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] )
1180 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] )
1181 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1182 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1183 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1184 call RunDbgCmd(buf,
1185 \'echo global_var',
1186 \[ 'E121: Undefined variable: global_var' ] )
1187 call RunDbgCmd(buf,
1188 \'echo local_var',
1189 \[ 'E121: Undefined variable: local_var' ] )
1190 call RunDbgCmd(buf,
1191 \'echo l:local_var',
1192 \[ 'E121: Undefined variable: l:local_var' ] )
1193
1194 " backtrace up
1195 call RunDbgCmd(buf, 'backtrace', [
1196 \ '\V>backtrace',
1197 \ '\V 2 command line',
1198 \ '\V 1 script ' .. file1 .. '[11]',
1199 \ '\V->0 function <SNR>\.\*_File1Func',
1200 \ '\Vline 1: let s:file1_var .= a:arg',
1201 \ ],
1202 \ #{ match: 'pattern' } )
1203 call RunDbgCmd(buf, 'up', [ '>up' ] )
1204
1205 call RunDbgCmd(buf, 'backtrace', [
1206 \ '\V>backtrace',
1207 \ '\V 2 command line',
1208 \ '\V->1 script ' .. file1 .. '[11]',
1209 \ '\V 0 function <SNR>\.\*_File1Func',
1210 \ '\Vline 1: let s:file1_var .= a:arg',
1211 \ ],
1212 \ #{ match: 'pattern' } )
1213
1214 " Expression evaluation in the script frame (not the function frame)
1215 " FIXME: Unexpected in this scope (a: should not be visibnle)
1216 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1217 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1218 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1219 " FIXME: Unexpected in this scope (global should be found)
1220 call RunDbgCmd(buf,
1221 \'echo global_var',
1222 \[ 'E121: Undefined variable: global_var' ] )
1223 call RunDbgCmd(buf,
1224 \'echo local_var',
1225 \[ 'E121: Undefined variable: local_var' ] )
1226 call RunDbgCmd(buf,
1227 \'echo l:local_var',
1228 \[ 'E121: Undefined variable: l:local_var' ] )
1229
1230
1231 " step while backtraced jumps to the latest frame
1232 call RunDbgCmd(buf, 'step', [
1233 \ 'line 2: let local_var = s:file1_var .. '' test1''' ] )
1234 call RunDbgCmd(buf, 'backtrace', [
1235 \ '\V>backtrace',
1236 \ '\V 2 command line',
1237 \ '\V 1 script ' .. file1 .. '[11]',
1238 \ '\V->0 function <SNR>\.\*_File1Func',
1239 \ '\Vline 2: let local_var = s:file1_var .. '' test1''',
1240 \ ],
1241 \ #{ match: 'pattern' } )
1242
1243 call RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] )
1244 call RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] )
1245 call RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] )
1246
1247 call RunDbgCmd(buf, 'step', [ 'line 4: source Xtest2.vim' ] )
1248 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file2_var = ''file2''' ] )
1249 call RunDbgCmd(buf, 'backtrace', [
1250 \ '\V>backtrace',
1251 \ '\V 3 command line',
1252 \ '\V 2 script ' .. file1 .. '[11]',
1253 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1254 \ '\V->0 script ' .. file2,
1255 \ '\Vline 1: let s:file2_var = ''file2''',
1256 \ ],
1257 \ #{ match: 'pattern' } )
1258
1259 " Expression evaluation in the script frame file2 (not the function frame)
1260 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1261 call RunDbgCmd(buf,
1262 \ 'echo s:file1_var',
1263 \ [ 'E121: Undefined variable: s:file1_var' ] )
1264 call RunDbgCmd(buf, 'echo g:global_var', [ 'globalfile1arg1 test1' ] )
1265 call RunDbgCmd(buf, 'echo global_var', [ 'globalfile1arg1 test1' ] )
1266 call RunDbgCmd(buf,
1267 \'echo local_var',
1268 \[ 'E121: Undefined variable: local_var' ] )
1269 call RunDbgCmd(buf,
1270 \'echo l:local_var',
1271 \[ 'E121: Undefined variable: l:local_var' ] )
1272 call RunDbgCmd(buf,
1273 \ 'echo s:file2_var',
1274 \ [ 'E121: Undefined variable: s:file2_var' ] )
1275
1276 call RunDbgCmd(buf, 'step', [ 'line 3: func s:File2Func( arg )' ] )
1277 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1278
1279 " Up the stack to the other script context
1280 call RunDbgCmd(buf, 'up')
1281 call RunDbgCmd(buf, 'backtrace', [
1282 \ '\V>backtrace',
1283 \ '\V 3 command line',
1284 \ '\V 2 script ' .. file1 .. '[11]',
1285 \ '\V->1 function <SNR>\.\*_File1Func[4]',
1286 \ '\V 0 script ' .. file2,
1287 \ '\Vline 3: func s:File2Func( arg )',
1288 \ ],
1289 \ #{ match: 'pattern' } )
1290 " FIXME: Unexpected. Should see the a: and l: dicts from File1Func
1291 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1292 call RunDbgCmd(buf,
1293 \ 'echo l:local_var',
1294 \ [ 'E121: Undefined variable: l:local_var' ] )
1295
1296 call RunDbgCmd(buf, 'up')
1297 call RunDbgCmd(buf, 'backtrace', [
1298 \ '\V>backtrace',
1299 \ '\V 3 command line',
1300 \ '\V->2 script ' .. file1 .. '[11]',
1301 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1302 \ '\V 0 script ' .. file2,
1303 \ '\Vline 3: func s:File2Func( arg )',
1304 \ ],
1305 \ #{ match: 'pattern' } )
1306
1307 " FIXME: Unexpected (wrong script vars are used)
1308 call RunDbgCmd(buf,
1309 \ 'echo s:file1_var',
1310 \ [ 'E121: Undefined variable: s:file1_var' ] )
1311 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1312
Bram Moolenaare99d4222021-06-13 14:01:26 +02001313 call RunDbgCmd(buf, 'cont')
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001314 call StopVimInTerminal(buf)
1315 call delete('Xtest1.vim')
1316 call delete('Xtest2.vim')
1317endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001318
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001319" Test for setting a breakpoint on a :endif where the :if condition is false
1320" and then quit the script. This should generate an interrupt.
1321func Test_breakpt_endif_intr()
1322 func F()
1323 let g:Xpath ..= 'a'
1324 if v:false
1325 let g:Xpath ..= 'b'
1326 endif
1327 invalid_command
1328 endfunc
1329
1330 let g:Xpath = ''
1331 breakadd func 4 F
1332 try
1333 let caught_intr = 0
1334 debuggreedy
1335 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001336 catch /^Vim:Interrupt$/
1337 call assert_match('\.F, line 4', v:throwpoint)
1338 let caught_intr = 1
1339 endtry
1340 0debuggreedy
1341 call assert_equal(1, caught_intr)
1342 call assert_equal('a', g:Xpath)
1343 breakdel *
1344 delfunc F
1345endfunc
1346
1347" Test for setting a breakpoint on a :else where the :if condition is false
1348" and then quit the script. This should generate an interrupt.
1349func Test_breakpt_else_intr()
1350 func F()
1351 let g:Xpath ..= 'a'
1352 if v:false
1353 let g:Xpath ..= 'b'
1354 else
1355 invalid_command
1356 endif
1357 invalid_command
1358 endfunc
1359
1360 let g:Xpath = ''
1361 breakadd func 4 F
1362 try
1363 let caught_intr = 0
1364 debuggreedy
1365 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001366 catch /^Vim:Interrupt$/
1367 call assert_match('\.F, line 4', v:throwpoint)
1368 let caught_intr = 1
1369 endtry
1370 0debuggreedy
1371 call assert_equal(1, caught_intr)
1372 call assert_equal('a', g:Xpath)
1373 breakdel *
1374 delfunc F
1375endfunc
1376
1377" Test for setting a breakpoint on a :endwhile where the :while condition is
1378" false and then quit the script. This should generate an interrupt.
1379func Test_breakpt_endwhile_intr()
1380 func F()
1381 let g:Xpath ..= 'a'
1382 while v:false
1383 let g:Xpath ..= 'b'
1384 endwhile
1385 invalid_command
1386 endfunc
1387
1388 let g:Xpath = ''
1389 breakadd func 4 F
1390 try
1391 let caught_intr = 0
1392 debuggreedy
1393 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001394 catch /^Vim:Interrupt$/
1395 call assert_match('\.F, line 4', v:throwpoint)
1396 let caught_intr = 1
1397 endtry
1398 0debuggreedy
1399 call assert_equal(1, caught_intr)
1400 call assert_equal('a', g:Xpath)
1401 breakdel *
1402 delfunc F
1403endfunc
1404
Bram Moolenaar16c62322020-08-13 19:20:04 +02001405" Test for setting a breakpoint on a script local function
1406func Test_breakpt_scriptlocal_func()
1407 let g:Xpath = ''
1408 func s:G()
1409 let g:Xpath ..= 'a'
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001410 endfunc
1411
Bram Moolenaar16c62322020-08-13 19:20:04 +02001412 let funcname = expand("<SID>") .. "G"
1413 exe "breakadd func 1 " .. funcname
1414 debuggreedy
1415 redir => output
1416 call feedkeys(":call " .. funcname .. "()\<CR>c\<CR>", "xt")
1417 redir END
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001418 0debuggreedy
Bram Moolenaar16c62322020-08-13 19:20:04 +02001419 call assert_match('Breakpoint in "' .. funcname .. '" line 1', output)
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001420 call assert_equal('a', g:Xpath)
1421 breakdel *
Bram Moolenaar16c62322020-08-13 19:20:04 +02001422 exe "delfunc " .. funcname
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001423endfunc
1424
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001425" vim: shiftwidth=2 sts=2 expandtab