blob: 85ab6ea3936c4eac4dd094260a5fa57451991c4e [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 Moolenaar26a44842021-09-02 18:49:06 +0200935func Test_DefFunction_expr()
936 CheckCWD
937 let file3 =<< trim END
938 vim9script
939 g:someVar = "foo"
940 def g:ChangeVar()
941 g:someVar = "bar"
942 echo "changed"
943 enddef
944 defcompile
945 END
946 call writefile(file3, 'Xtest3.vim')
947 let buf = RunVimInTerminal('-S Xtest3.vim', {})
948
949 call RunDbgCmd(buf, ':breakadd expr g:someVar')
950 call RunDbgCmd(buf, ':call g:ChangeVar()', ['Oldval = "''foo''"', 'Newval = "''bar''"', 'function ChangeVar', 'line 2: echo "changed"'])
951
952 call StopVimInTerminal(buf)
953 call delete('Xtest3.vim')
954endfunc
955
Bram Moolenaar17d868b2021-06-27 16:29:53 +0200956func Test_debug_def_and_legacy_function()
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200957 CheckCWD
958 let file =<< trim END
959 vim9script
960 def g:SomeFunc()
961 echo "here"
962 echo "and"
963 echo "there"
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200964 breakadd func 2 LocalFunc
965 LocalFunc()
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200966 enddef
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200967
968 def LocalFunc()
969 echo "first"
970 echo "second"
Bram Moolenaar8cec9272021-06-23 20:20:53 +0200971 breakadd func LegacyFunc
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200972 LegacyFunc()
973 enddef
974
975 func LegacyFunc()
976 echo "legone"
977 echo "legtwo"
978 endfunc
979
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200980 breakadd func 2 g:SomeFunc
981 END
982 call writefile(file, 'XtestDebug.vim')
983
984 let buf = RunVimInTerminal('-S XtestDebug.vim', {})
985
986 call RunDbgCmd(buf,':call SomeFunc()', ['line 2: echo "and"'])
987 call RunDbgCmd(buf,'next', ['line 3: echo "there"'])
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200988 call RunDbgCmd(buf,'next', ['line 4: breakadd func 2 LocalFunc'])
989
990 " continue, next breakpoint is in LocalFunc()
991 call RunDbgCmd(buf,'cont', ['line 2: echo "second"'])
992
993 " continue, next breakpoint is in LegacyFunc()
994 call RunDbgCmd(buf,'cont', ['line 1: echo "legone"'])
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200995
996 call RunDbgCmd(buf, 'cont')
997
998 call StopVimInTerminal(buf)
Dominique Pelle6c72fd52021-07-04 12:30:06 +0200999 call delete('XtestDebug.vim')
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001000endfunc
1001
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001002func Test_debug_def_function()
1003 CheckCWD
1004 let file =<< trim END
1005 vim9script
1006 def g:Func()
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001007 var n: number
1008 def Closure(): number
1009 return n + 3
1010 enddef
1011 n += Closure()
1012 echo 'result: ' .. n
1013 enddef
1014
1015 def g:FuncWithArgs(text: string, nr: number, ...items: list<number>)
1016 echo text .. nr
1017 for it in items
1018 echo it
1019 endfor
1020 echo "done"
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001021 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001022
1023 def g:FuncWithDict()
1024 var d = {
1025 a: 1,
1026 b: 2,
1027 }
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001028 # comment
1029 def Inner()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001030 eval 1 + 2
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001031 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001032 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001033
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001034 def g:FuncComment()
1035 # comment
1036 echo "first"
1037 .. "one"
1038 # comment
1039 echo "second"
1040 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001041
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001042 def g:FuncForLoop()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001043 eval 1 + 2
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001044 for i in [11, 22, 33]
Bram Moolenaar31e21762021-07-10 20:43:59 +02001045 eval i + 2
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001046 endfor
1047 echo "done"
1048 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001049
1050 def g:FuncWithSplitLine()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001051 eval 1 + 2
1052 | eval 2 + 3
Bram Moolenaar303215d2021-07-07 20:10:43 +02001053 enddef
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001054 END
1055 call writefile(file, 'Xtest.vim')
1056
1057 let buf = RunVimInTerminal('-S Xtest.vim', {})
1058
1059 call RunDbgCmd(buf,
1060 \ ':debug call Func()',
1061 \ ['cmd: call Func()'])
1062 call RunDbgCmd(buf, 'next', ['result: 3'])
1063 call term_sendkeys(buf, "\r")
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001064 call RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001065
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001066 call RunDbgCmd(buf,
1067 \ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)',
1068 \ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001069 call RunDbgCmd(buf, 'step', ['line 1: echo text .. nr'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001070 call RunDbgCmd(buf, 'echo text', ['asdf'])
1071 call RunDbgCmd(buf, 'echo nr', ['42'])
1072 call RunDbgCmd(buf, 'echo items', ['[1, 2, 3]'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001073 call RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001074 call RunDbgCmd(buf, 'echo it', ['1'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001075 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
1076 call RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor'])
1077 call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001078 call RunDbgCmd(buf, 'echo it', ['2'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001079 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
1080 call RunDbgCmd(buf, 'step', ['2', 'function FuncWithArgs', 'line 4: endfor'])
1081 call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001082 call RunDbgCmd(buf, 'echo it', ['3'])
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001083 call RunDbgCmd(buf, 'step', ['line 3: echo it'])
1084 call RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor'])
1085 call RunDbgCmd(buf, 'step', ['line 5: echo "done"'])
1086 call RunDbgCmd(buf, 'cont')
1087
1088 call RunDbgCmd(buf,
1089 \ ':debug call FuncWithDict()',
1090 \ ['cmd: call FuncWithDict()'])
1091 call RunDbgCmd(buf, 'step', ['line 1: var d = { a: 1, b: 2, }'])
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001092 call RunDbgCmd(buf, 'step', ['line 6: def Inner()'])
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001093 call RunDbgCmd(buf, 'cont')
1094
1095 call RunDbgCmd(buf, ':breakadd func 1 FuncComment')
1096 call RunDbgCmd(buf, ':call FuncComment()', ['function FuncComment', 'line 2: echo "first" .. "one"'])
1097 call RunDbgCmd(buf, ':breakadd func 3 FuncComment')
1098 call RunDbgCmd(buf, 'cont', ['function FuncComment', 'line 5: echo "second"'])
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001099 call RunDbgCmd(buf, 'cont')
1100
1101 call RunDbgCmd(buf, ':breakadd func 2 FuncForLoop')
1102 call RunDbgCmd(buf, ':call FuncForLoop()', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
1103 call RunDbgCmd(buf, 'echo i', ['11'])
Bram Moolenaar31e21762021-07-10 20:43:59 +02001104 call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 3: eval i + 2'])
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001105 call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 4: endfor'])
1106 call RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
1107 call RunDbgCmd(buf, 'echo i', ['22'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001108
Bram Moolenaar303215d2021-07-07 20:10:43 +02001109 call RunDbgCmd(buf, 'breakdel *')
1110 call RunDbgCmd(buf, 'cont')
1111
1112 call RunDbgCmd(buf, ':breakadd func FuncWithSplitLine')
Bram Moolenaar31e21762021-07-10 20:43:59 +02001113 call RunDbgCmd(buf, ':call FuncWithSplitLine()', ['function FuncWithSplitLine', 'line 1: eval 1 + 2 | eval 2 + 3'])
Bram Moolenaar303215d2021-07-07 20:10:43 +02001114
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001115 call RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001116 call StopVimInTerminal(buf)
1117 call delete('Xtest.vim')
1118endfunc
1119
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001120func Test_debug_def_function_with_lambda()
1121 CheckCWD
1122 let lines =<< trim END
1123 vim9script
1124 def g:Func()
1125 var s = 'a'
1126 ['b']->map((_, v) => s)
1127 echo "done"
1128 enddef
1129 breakadd func 2 g:Func
1130 END
1131 call writefile(lines, 'XtestLambda.vim')
1132
1133 let buf = RunVimInTerminal('-S XtestLambda.vim', {})
1134
1135 call RunDbgCmd(buf,
1136 \ ':call g:Func()',
1137 \ ['function Func', 'line 2: [''b'']->map((_, v) => s)'])
1138 call RunDbgCmd(buf,
1139 \ 'next',
1140 \ ['function Func', 'line 3: echo "done"'])
1141
1142 call RunDbgCmd(buf, 'cont')
1143 call StopVimInTerminal(buf)
1144 call delete('XtestLambda.vim')
1145endfunc
1146
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001147func Test_debug_backtrace_level()
1148 CheckCWD
1149 let lines =<< trim END
1150 let s:file1_var = 'file1'
1151 let g:global_var = 'global'
1152
1153 func s:File1Func( arg )
1154 let s:file1_var .= a:arg
1155 let local_var = s:file1_var .. ' test1'
1156 let g:global_var .= local_var
1157 source Xtest2.vim
1158 endfunc
1159
1160 call s:File1Func( 'arg1' )
1161 END
1162 call writefile(lines, 'Xtest1.vim')
1163
1164 let lines =<< trim END
1165 let s:file2_var = 'file2'
1166
1167 func s:File2Func( arg )
1168 let s:file2_var .= a:arg
1169 let local_var = s:file2_var .. ' test2'
1170 let g:global_var .= local_var
1171 endfunc
1172
1173 call s:File2Func( 'arg2' )
1174 END
1175 call writefile(lines, 'Xtest2.vim')
1176
1177 let file1 = getcwd() .. '/Xtest1.vim'
1178 let file2 = getcwd() .. '/Xtest2.vim'
1179
1180 " set a breakpoint and source file1.vim
1181 let buf = RunVimInTerminal(
1182 \ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim',
Bram Moolenaar18dc3552020-11-22 14:24:00 +01001183 \ #{wait_for_ruler: 0})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001184
1185 call CheckDbgOutput(buf, [
1186 \ 'Breakpoint in "' .. file1 .. '" line 1',
1187 \ 'Entering Debug mode. Type "cont" to continue.',
1188 \ 'command line..script ' .. file1,
1189 \ 'line 1: let s:file1_var = ''file1'''
Bram Moolenaar18dc3552020-11-22 14:24:00 +01001190 \ ], #{msec: 5000})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001191
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01001192 " step through the initial declarations
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001193 call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] )
1194 call RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] )
1195 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1196 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1197 call RunDbgCmd(buf, 'echo global_var', [ 'global' ] )
1198
1199 " step in to the first function
1200 call RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] )
1201 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] )
1202 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1203 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1204 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1205 call RunDbgCmd(buf,
1206 \'echo global_var',
1207 \[ 'E121: Undefined variable: global_var' ] )
1208 call RunDbgCmd(buf,
1209 \'echo local_var',
1210 \[ 'E121: Undefined variable: local_var' ] )
1211 call RunDbgCmd(buf,
1212 \'echo l:local_var',
1213 \[ 'E121: Undefined variable: l:local_var' ] )
1214
1215 " backtrace up
1216 call RunDbgCmd(buf, 'backtrace', [
1217 \ '\V>backtrace',
1218 \ '\V 2 command line',
1219 \ '\V 1 script ' .. file1 .. '[11]',
1220 \ '\V->0 function <SNR>\.\*_File1Func',
1221 \ '\Vline 1: let s:file1_var .= a:arg',
1222 \ ],
1223 \ #{ match: 'pattern' } )
1224 call RunDbgCmd(buf, 'up', [ '>up' ] )
1225
1226 call RunDbgCmd(buf, 'backtrace', [
1227 \ '\V>backtrace',
1228 \ '\V 2 command line',
1229 \ '\V->1 script ' .. file1 .. '[11]',
1230 \ '\V 0 function <SNR>\.\*_File1Func',
1231 \ '\Vline 1: let s:file1_var .= a:arg',
1232 \ ],
1233 \ #{ match: 'pattern' } )
1234
1235 " Expression evaluation in the script frame (not the function frame)
1236 " FIXME: Unexpected in this scope (a: should not be visibnle)
1237 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1238 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1239 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1240 " FIXME: Unexpected in this scope (global should be found)
1241 call RunDbgCmd(buf,
1242 \'echo global_var',
1243 \[ 'E121: Undefined variable: global_var' ] )
1244 call RunDbgCmd(buf,
1245 \'echo local_var',
1246 \[ 'E121: Undefined variable: local_var' ] )
1247 call RunDbgCmd(buf,
1248 \'echo l:local_var',
1249 \[ 'E121: Undefined variable: l:local_var' ] )
1250
1251
1252 " step while backtraced jumps to the latest frame
1253 call RunDbgCmd(buf, 'step', [
1254 \ 'line 2: let local_var = s:file1_var .. '' test1''' ] )
1255 call RunDbgCmd(buf, 'backtrace', [
1256 \ '\V>backtrace',
1257 \ '\V 2 command line',
1258 \ '\V 1 script ' .. file1 .. '[11]',
1259 \ '\V->0 function <SNR>\.\*_File1Func',
1260 \ '\Vline 2: let local_var = s:file1_var .. '' test1''',
1261 \ ],
1262 \ #{ match: 'pattern' } )
1263
1264 call RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] )
1265 call RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] )
1266 call RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] )
1267
1268 call RunDbgCmd(buf, 'step', [ 'line 4: source Xtest2.vim' ] )
1269 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file2_var = ''file2''' ] )
1270 call RunDbgCmd(buf, 'backtrace', [
1271 \ '\V>backtrace',
1272 \ '\V 3 command line',
1273 \ '\V 2 script ' .. file1 .. '[11]',
1274 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1275 \ '\V->0 script ' .. file2,
1276 \ '\Vline 1: let s:file2_var = ''file2''',
1277 \ ],
1278 \ #{ match: 'pattern' } )
1279
1280 " Expression evaluation in the script frame file2 (not the function frame)
1281 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1282 call RunDbgCmd(buf,
1283 \ 'echo s:file1_var',
1284 \ [ 'E121: Undefined variable: s:file1_var' ] )
1285 call RunDbgCmd(buf, 'echo g:global_var', [ 'globalfile1arg1 test1' ] )
1286 call RunDbgCmd(buf, 'echo global_var', [ 'globalfile1arg1 test1' ] )
1287 call RunDbgCmd(buf,
1288 \'echo local_var',
1289 \[ 'E121: Undefined variable: local_var' ] )
1290 call RunDbgCmd(buf,
1291 \'echo l:local_var',
1292 \[ 'E121: Undefined variable: l:local_var' ] )
1293 call RunDbgCmd(buf,
1294 \ 'echo s:file2_var',
1295 \ [ 'E121: Undefined variable: s:file2_var' ] )
1296
1297 call RunDbgCmd(buf, 'step', [ 'line 3: func s:File2Func( arg )' ] )
1298 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1299
1300 " Up the stack to the other script context
1301 call RunDbgCmd(buf, 'up')
1302 call RunDbgCmd(buf, 'backtrace', [
1303 \ '\V>backtrace',
1304 \ '\V 3 command line',
1305 \ '\V 2 script ' .. file1 .. '[11]',
1306 \ '\V->1 function <SNR>\.\*_File1Func[4]',
1307 \ '\V 0 script ' .. file2,
1308 \ '\Vline 3: func s:File2Func( arg )',
1309 \ ],
1310 \ #{ match: 'pattern' } )
1311 " FIXME: Unexpected. Should see the a: and l: dicts from File1Func
1312 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1313 call RunDbgCmd(buf,
1314 \ 'echo l:local_var',
1315 \ [ 'E121: Undefined variable: l:local_var' ] )
1316
1317 call RunDbgCmd(buf, 'up')
1318 call RunDbgCmd(buf, 'backtrace', [
1319 \ '\V>backtrace',
1320 \ '\V 3 command line',
1321 \ '\V->2 script ' .. file1 .. '[11]',
1322 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1323 \ '\V 0 script ' .. file2,
1324 \ '\Vline 3: func s:File2Func( arg )',
1325 \ ],
1326 \ #{ match: 'pattern' } )
1327
1328 " FIXME: Unexpected (wrong script vars are used)
1329 call RunDbgCmd(buf,
1330 \ 'echo s:file1_var',
1331 \ [ 'E121: Undefined variable: s:file1_var' ] )
1332 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1333
Bram Moolenaare99d4222021-06-13 14:01:26 +02001334 call RunDbgCmd(buf, 'cont')
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001335 call StopVimInTerminal(buf)
1336 call delete('Xtest1.vim')
1337 call delete('Xtest2.vim')
1338endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001339
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001340" Test for setting a breakpoint on a :endif where the :if condition is false
1341" and then quit the script. This should generate an interrupt.
1342func Test_breakpt_endif_intr()
1343 func F()
1344 let g:Xpath ..= 'a'
1345 if v:false
1346 let g:Xpath ..= 'b'
1347 endif
1348 invalid_command
1349 endfunc
1350
1351 let g:Xpath = ''
1352 breakadd func 4 F
1353 try
1354 let caught_intr = 0
1355 debuggreedy
1356 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001357 catch /^Vim:Interrupt$/
1358 call assert_match('\.F, line 4', v:throwpoint)
1359 let caught_intr = 1
1360 endtry
1361 0debuggreedy
1362 call assert_equal(1, caught_intr)
1363 call assert_equal('a', g:Xpath)
1364 breakdel *
1365 delfunc F
1366endfunc
1367
1368" Test for setting a breakpoint on a :else where the :if condition is false
1369" and then quit the script. This should generate an interrupt.
1370func Test_breakpt_else_intr()
1371 func F()
1372 let g:Xpath ..= 'a'
1373 if v:false
1374 let g:Xpath ..= 'b'
1375 else
1376 invalid_command
1377 endif
1378 invalid_command
1379 endfunc
1380
1381 let g:Xpath = ''
1382 breakadd func 4 F
1383 try
1384 let caught_intr = 0
1385 debuggreedy
1386 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001387 catch /^Vim:Interrupt$/
1388 call assert_match('\.F, line 4', v:throwpoint)
1389 let caught_intr = 1
1390 endtry
1391 0debuggreedy
1392 call assert_equal(1, caught_intr)
1393 call assert_equal('a', g:Xpath)
1394 breakdel *
1395 delfunc F
1396endfunc
1397
1398" Test for setting a breakpoint on a :endwhile where the :while condition is
1399" false and then quit the script. This should generate an interrupt.
1400func Test_breakpt_endwhile_intr()
1401 func F()
1402 let g:Xpath ..= 'a'
1403 while v:false
1404 let g:Xpath ..= 'b'
1405 endwhile
1406 invalid_command
1407 endfunc
1408
1409 let g:Xpath = ''
1410 breakadd func 4 F
1411 try
1412 let caught_intr = 0
1413 debuggreedy
1414 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001415 catch /^Vim:Interrupt$/
1416 call assert_match('\.F, line 4', v:throwpoint)
1417 let caught_intr = 1
1418 endtry
1419 0debuggreedy
1420 call assert_equal(1, caught_intr)
1421 call assert_equal('a', g:Xpath)
1422 breakdel *
1423 delfunc F
1424endfunc
1425
Bram Moolenaar16c62322020-08-13 19:20:04 +02001426" Test for setting a breakpoint on a script local function
1427func Test_breakpt_scriptlocal_func()
1428 let g:Xpath = ''
1429 func s:G()
1430 let g:Xpath ..= 'a'
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001431 endfunc
1432
Bram Moolenaar16c62322020-08-13 19:20:04 +02001433 let funcname = expand("<SID>") .. "G"
1434 exe "breakadd func 1 " .. funcname
1435 debuggreedy
1436 redir => output
1437 call feedkeys(":call " .. funcname .. "()\<CR>c\<CR>", "xt")
1438 redir END
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001439 0debuggreedy
Bram Moolenaar16c62322020-08-13 19:20:04 +02001440 call assert_match('Breakpoint in "' .. funcname .. '" line 1', output)
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001441 call assert_equal('a', g:Xpath)
1442 breakdel *
Bram Moolenaar16c62322020-08-13 19:20:04 +02001443 exe "delfunc " .. funcname
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001444endfunc
1445
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001446" vim: shiftwidth=2 sts=2 expandtab