blob: 3b02241205b14d6c92604ac4387c8fd52ed90d45 [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 Moolenaar6ca6ca42020-07-27 19:47:07 +020020func CheckDbgOutput(buf, lines, options = {})
21 " Verify the expected output
22 let lnum = 20 - len(a:lines)
23 for l in a:lines
24 if get(a:options, 'match', 'equal') ==# 'pattern'
25 call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, 200)
26 else
27 call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, 200)
28 endif
29 let lnum += 1
30 endfor
31endfunc
32
Bram Moolenaar113bf062019-04-17 16:54:05 +020033" Run a Vim debugger command
34" If the expected output argument is supplied, then check for it.
35func RunDbgCmd(buf, cmd, ...)
36 call term_sendkeys(a:buf, a:cmd . "\r")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +020037 call TermWait(a:buf)
Bram Moolenaar113bf062019-04-17 16:54:05 +020038
39 if a:0 != 0
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020040 let options = #{match: 'equal'}
41 if a:0 > 1
42 call extend(options, a:2)
43 endif
44 call CheckDbgOutput(a:buf, a:1, options)
Bram Moolenaar113bf062019-04-17 16:54:05 +020045 endif
46endfunc
47
48" Debugger tests
49func Test_Debugger()
Bram Moolenaar113bf062019-04-17 16:54:05 +020050 " Create a Vim script with some functions
Bram Moolenaare7eb9272019-06-24 00:58:07 +020051 let lines =<< trim END
52 func Foo()
53 let var1 = 1
54 let var2 = Bar(var1) + 9
55 return var2
56 endfunc
57 func Bar(var)
58 let var1 = 2 + a:var
59 let var2 = Bazz(var1) + 4
60 return var2
61 endfunc
62 func Bazz(var)
63 try
64 let var1 = 3 + a:var
65 let var3 = "another var"
66 let var3 = "value2"
67 catch
68 let var4 = "exception"
69 endtry
70 return var1
71 endfunc
72 END
73 call writefile(lines, 'Xtest.vim')
Bram Moolenaar113bf062019-04-17 16:54:05 +020074
75 " Start Vim in a terminal
76 let buf = RunVimInTerminal('-S Xtest.vim', {})
77
78 " Start the Vim debugger
Bram Moolenaarddd33082019-06-03 23:07:25 +020079 call RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()'])
Bram Moolenaar113bf062019-04-17 16:54:05 +020080
81 " Create a few stack frames by stepping through functions
Bram Moolenaarddd33082019-06-03 23:07:25 +020082 call RunDbgCmd(buf, 'step', ['line 1: let var1 = 1'])
83 call RunDbgCmd(buf, 'step', ['line 2: let var2 = Bar(var1) + 9'])
84 call RunDbgCmd(buf, 'step', ['line 1: let var1 = 2 + a:var'])
85 call RunDbgCmd(buf, 'step', ['line 2: let var2 = Bazz(var1) + 4'])
86 call RunDbgCmd(buf, 'step', ['line 1: try'])
87 call RunDbgCmd(buf, 'step', ['line 2: let var1 = 3 + a:var'])
88 call RunDbgCmd(buf, 'step', ['line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +020089
90 " check backtrace
91 call RunDbgCmd(buf, 'backtrace', [
92 \ ' 2 function Foo[2]',
93 \ ' 1 Bar[2]',
94 \ '->0 Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +020095 \ 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +020096
97 " Check variables in different stack frames
98 call RunDbgCmd(buf, 'echo var1', ['6'])
99
100 call RunDbgCmd(buf, 'up')
101 call RunDbgCmd(buf, 'back', [
102 \ ' 2 function Foo[2]',
103 \ '->1 Bar[2]',
104 \ ' 0 Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200105 \ 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200106 call RunDbgCmd(buf, 'echo var1', ['3'])
107
108 call RunDbgCmd(buf, 'u')
109 call RunDbgCmd(buf, 'bt', [
110 \ '->2 function Foo[2]',
111 \ ' 1 Bar[2]',
112 \ ' 0 Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200113 \ 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200114 call RunDbgCmd(buf, 'echo var1', ['1'])
115
116 " Undefined variables
117 call RunDbgCmd(buf, 'step')
118 call RunDbgCmd(buf, 'frame 2')
119 call RunDbgCmd(buf, 'echo var3', [
120 \ 'Error detected while processing function Foo[2]..Bar[2]..Bazz:',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200121 \ 'line 4:',
Bram Moolenaar113bf062019-04-17 16:54:05 +0200122 \ 'E121: Undefined variable: var3'])
123
124 " var3 is defined in this level with some other value
125 call RunDbgCmd(buf, 'fr 0')
126 call RunDbgCmd(buf, 'echo var3', ['another var'])
127
128 call RunDbgCmd(buf, 'step')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200129 call RunDbgCmd(buf, '')
130 call RunDbgCmd(buf, '')
131 call RunDbgCmd(buf, '')
132 call RunDbgCmd(buf, '')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200133 call RunDbgCmd(buf, 'step', [
134 \ 'function Foo[2]..Bar',
135 \ 'line 3: End of function'])
136 call RunDbgCmd(buf, 'up')
137
138 " Undefined var2
139 call RunDbgCmd(buf, 'echo var2', [
140 \ 'Error detected while processing function Foo[2]..Bar:',
141 \ 'line 3:',
142 \ 'E121: Undefined variable: var2'])
143
144 " Var2 is defined with 10
145 call RunDbgCmd(buf, 'down')
146 call RunDbgCmd(buf, 'echo var2', ['10'])
147
148 " Backtrace movements
149 call RunDbgCmd(buf, 'b', [
150 \ ' 1 function Foo[2]',
151 \ '->0 Bar',
152 \ 'line 3: End of function'])
153
154 " next command cannot go down, we are on bottom
155 call RunDbgCmd(buf, 'down', ['frame is zero'])
156 call RunDbgCmd(buf, 'up')
157
158 " next command cannot go up, we are on top
159 call RunDbgCmd(buf, 'up', ['frame at highest level: 1'])
160 call RunDbgCmd(buf, 'where', [
161 \ '->1 function Foo[2]',
162 \ ' 0 Bar',
163 \ 'line 3: End of function'])
164
165 " fil is not frame or finish, it is file
166 call RunDbgCmd(buf, 'fil', ['"[No Name]" --No lines in buffer--'])
167
168 " relative backtrace movement
169 call RunDbgCmd(buf, 'fr -1')
170 call RunDbgCmd(buf, 'frame', [
171 \ ' 1 function Foo[2]',
172 \ '->0 Bar',
173 \ 'line 3: End of function'])
174
175 call RunDbgCmd(buf, 'fr +1')
176 call RunDbgCmd(buf, 'fram', [
177 \ '->1 function Foo[2]',
178 \ ' 0 Bar',
179 \ 'line 3: End of function'])
180
181 " go beyond limits does not crash
182 call RunDbgCmd(buf, 'fr 100', ['frame at highest level: 1'])
183 call RunDbgCmd(buf, 'fra', [
184 \ '->1 function Foo[2]',
185 \ ' 0 Bar',
186 \ 'line 3: End of function'])
187
188 call RunDbgCmd(buf, 'frame -40', ['frame is zero'])
189 call RunDbgCmd(buf, 'fram', [
190 \ ' 1 function Foo[2]',
191 \ '->0 Bar',
192 \ 'line 3: End of function'])
193
194 " final result 19
195 call RunDbgCmd(buf, 'cont', ['19'])
196
197 " breakpoints tests
198
199 " Start a debug session, so that reading the last line from the terminal
200 " works properly.
201 call RunDbgCmd(buf, ':debug echo Foo()')
202
203 " No breakpoints
204 call RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
205
206 " Place some breakpoints
207 call RunDbgCmd(buf, 'breaka func Bar')
208 call RunDbgCmd(buf, 'breaklis', [' 1 func Bar line 1'])
209 call RunDbgCmd(buf, 'breakadd func 3 Bazz')
210 call RunDbgCmd(buf, 'breaklist', [' 1 func Bar line 1',
211 \ ' 2 func Bazz line 3'])
212
213 " Check whether the breakpoints are hit
214 call RunDbgCmd(buf, 'cont', [
215 \ 'Breakpoint in "Bar" line 1',
216 \ 'function Foo[2]..Bar',
217 \ 'line 1: let var1 = 2 + a:var'])
218 call RunDbgCmd(buf, 'cont', [
219 \ 'Breakpoint in "Bazz" line 3',
220 \ 'function Foo[2]..Bar[2]..Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200221 \ 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200222
223 " Delete the breakpoints
224 call RunDbgCmd(buf, 'breakd 1')
225 call RunDbgCmd(buf, 'breakli', [' 2 func Bazz line 3'])
226 call RunDbgCmd(buf, 'breakdel func 3 Bazz')
227 call RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
228
229 call RunDbgCmd(buf, 'cont')
230
231 " Make sure the breakpoints are removed
232 call RunDbgCmd(buf, ':echo Foo()', ['19'])
233
234 " Delete a non-existing breakpoint
235 call RunDbgCmd(buf, ':breakdel 2', ['E161: Breakpoint not found: 2'])
236
237 " Expression breakpoint
238 call RunDbgCmd(buf, ':breakadd func 2 Bazz')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200239 call RunDbgCmd(buf, ':echo Bazz(1)', [
240 \ 'Entering Debug mode. Type "cont" to continue.',
241 \ 'function Bazz',
242 \ 'line 2: let var1 = 3 + a:var'])
243 call RunDbgCmd(buf, 'step')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200244 call RunDbgCmd(buf, 'step')
245 call RunDbgCmd(buf, 'breaka expr var3')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200246 call RunDbgCmd(buf, 'breakl', [' 3 func Bazz line 2',
247 \ ' 4 expr var3'])
248 call RunDbgCmd(buf, 'cont', ['Breakpoint in "Bazz" line 5',
Bram Moolenaar113bf062019-04-17 16:54:05 +0200249 \ 'Oldval = "''another var''"',
250 \ 'Newval = "''value2''"',
251 \ 'function Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200252 \ 'line 5: catch'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200253
254 call RunDbgCmd(buf, 'breakdel *')
255 call RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
256
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200257 " Check for error cases
258 call RunDbgCmd(buf, 'breakadd abcd', [
259 \ 'Error detected while processing function Bazz:',
260 \ 'line 5:',
261 \ 'E475: Invalid argument: abcd'])
262 call RunDbgCmd(buf, 'breakadd func', ['E475: Invalid argument: func'])
263 call RunDbgCmd(buf, 'breakadd func 2', ['E475: Invalid argument: func 2'])
264 call RunDbgCmd(buf, 'breaka func a()', ['E475: Invalid argument: func a()'])
265 call RunDbgCmd(buf, 'breakd abcd', ['E475: Invalid argument: abcd'])
266 call RunDbgCmd(buf, 'breakd func', ['E475: Invalid argument: func'])
267 call RunDbgCmd(buf, 'breakd func a()', ['E475: Invalid argument: func a()'])
268 call RunDbgCmd(buf, 'breakd func a', ['E161: Breakpoint not found: func a'])
269 call RunDbgCmd(buf, 'breakd expr', ['E475: Invalid argument: expr'])
270 call RunDbgCmd(buf, 'breakd expr x', [
271 \ 'E121: Undefined variable: x',
272 \ 'E161: Breakpoint not found: expr x'])
273
Bram Moolenaar113bf062019-04-17 16:54:05 +0200274 " finish the current function
275 call RunDbgCmd(buf, 'finish', [
276 \ 'function Bazz',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200277 \ 'line 8: End of function'])
278 call RunDbgCmd(buf, 'cont')
279
280 " Test for :next
281 call RunDbgCmd(buf, ':debug echo Bar(1)')
282 call RunDbgCmd(buf, 'step')
283 call RunDbgCmd(buf, 'next')
284 call RunDbgCmd(buf, '', [
285 \ 'function Bar',
286 \ 'line 3: return var2'])
287 call RunDbgCmd(buf, 'c')
288
289 " Test for :interrupt
290 call RunDbgCmd(buf, ':debug echo Bazz(1)')
291 call RunDbgCmd(buf, 'step')
292 call RunDbgCmd(buf, 'step')
293 call RunDbgCmd(buf, 'interrupt', [
294 \ 'Exception thrown: Vim:Interrupt',
295 \ 'function Bazz',
296 \ 'line 5: catch'])
297 call RunDbgCmd(buf, 'c')
298
299 " Test for :quit
300 call RunDbgCmd(buf, ':debug echo Foo()')
301 call RunDbgCmd(buf, 'breakdel *')
302 call RunDbgCmd(buf, 'breakadd func 3 Foo')
303 call RunDbgCmd(buf, 'breakadd func 3 Bazz')
304 call RunDbgCmd(buf, 'cont', [
305 \ 'Breakpoint in "Bazz" line 3',
306 \ 'function Foo[2]..Bar[2]..Bazz',
307 \ 'line 3: let var3 = "another var"'])
308 call RunDbgCmd(buf, 'quit', [
309 \ 'Breakpoint in "Foo" line 3',
310 \ 'function Foo',
311 \ 'line 3: return var2'])
312 call RunDbgCmd(buf, 'breakdel *')
313 call RunDbgCmd(buf, 'quit')
314 call RunDbgCmd(buf, 'enew! | only!')
315
316 call StopVimInTerminal(buf)
317
318 " Tests for :breakadd file and :breakadd here
319 " Breakpoints should be set before sourcing the file
320
Bram Moolenaare7eb9272019-06-24 00:58:07 +0200321 let lines =<< trim END
322 let var1 = 10
323 let var2 = 20
324 let var3 = 30
325 let var4 = 40
326 END
327 call writefile(lines, 'Xtest.vim')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200328
329 " Start Vim in a terminal
330 let buf = RunVimInTerminal('Xtest.vim', {})
331 call RunDbgCmd(buf, ':breakadd file 2 Xtest.vim')
332 call RunDbgCmd(buf, ':4 | breakadd here')
333 call RunDbgCmd(buf, ':source Xtest.vim', ['line 2: let var2 = 20'])
334 call RunDbgCmd(buf, 'cont', ['line 4: let var4 = 40'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200335 call RunDbgCmd(buf, 'cont')
336
337 call StopVimInTerminal(buf)
338
339 call delete('Xtest.vim')
Bram Moolenaar16c62322020-08-13 19:20:04 +0200340 %bw!
341 call assert_fails('breakadd here', 'E32:')
Bram Moolenaar531be472020-09-23 22:38:05 +0200342 call assert_fails('breakadd file Xtest.vim /\)/', 'E55:')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200343endfunc
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200344
345func Test_Backtrace_Through_Source()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200346 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200347 let file1 =<< trim END
348 func SourceAnotherFile()
349 source Xtest2.vim
350 endfunc
351
352 func CallAFunction()
353 call SourceAnotherFile()
354 call File2Function()
355 endfunc
356
357 func GlobalFunction()
358 call CallAFunction()
359 endfunc
360 END
361 call writefile(file1, 'Xtest1.vim')
362
363 let file2 =<< trim END
364 func DoAThing()
365 echo "DoAThing"
366 endfunc
367
368 func File2Function()
369 call DoAThing()
370 endfunc
371
372 call File2Function()
373 END
374 call writefile(file2, 'Xtest2.vim')
375
376 let buf = RunVimInTerminal('-S Xtest1.vim', {})
377
378 call RunDbgCmd(buf,
379 \ ':debug call GlobalFunction()',
380 \ ['cmd: call GlobalFunction()'])
381 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
382
383 call RunDbgCmd(buf, 'backtrace', ['>backtrace',
384 \ '->0 function GlobalFunction',
385 \ 'line 1: call CallAFunction()'])
386
387 call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
388 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
389
390 call RunDbgCmd(buf, 'backtrace', ['>backtrace',
391 \ ' 2 function GlobalFunction[1]',
392 \ ' 1 CallAFunction[1]',
393 \ '->0 SourceAnotherFile',
394 \ 'line 1: source Xtest2.vim'])
395
396 " Step into the 'source' command. Note that we print the full trace all the
397 " way though the source command.
398 call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
399 call RunDbgCmd(buf, 'backtrace', [
400 \ '>backtrace',
401 \ ' 3 function GlobalFunction[1]',
402 \ ' 2 CallAFunction[1]',
403 \ ' 1 SourceAnotherFile[1]',
404 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
405 \ 'line 1: func DoAThing()'])
406
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200407 call RunDbgCmd( buf, 'up' )
408 call RunDbgCmd( buf, 'backtrace', [
409 \ '>backtrace',
410 \ ' 3 function GlobalFunction[1]',
411 \ ' 2 CallAFunction[1]',
412 \ '->1 SourceAnotherFile[1]',
413 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
414 \ 'line 1: func DoAThing()' ] )
415
416 call RunDbgCmd( buf, 'up' )
417 call RunDbgCmd( buf, 'backtrace', [
418 \ '>backtrace',
419 \ ' 3 function GlobalFunction[1]',
420 \ '->2 CallAFunction[1]',
421 \ ' 1 SourceAnotherFile[1]',
422 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
423 \ 'line 1: func DoAThing()' ] )
424
425 call RunDbgCmd( buf, 'up' )
426 call RunDbgCmd( buf, 'backtrace', [
427 \ '>backtrace',
428 \ '->3 function GlobalFunction[1]',
429 \ ' 2 CallAFunction[1]',
430 \ ' 1 SourceAnotherFile[1]',
431 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
432 \ 'line 1: func DoAThing()' ] )
433
434 call RunDbgCmd( buf, 'up', [ 'frame at highest level: 3' ] )
435 call RunDbgCmd( buf, 'backtrace', [
436 \ '>backtrace',
437 \ '->3 function GlobalFunction[1]',
438 \ ' 2 CallAFunction[1]',
439 \ ' 1 SourceAnotherFile[1]',
440 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
441 \ 'line 1: func DoAThing()' ] )
442
443 call RunDbgCmd( buf, 'down' )
444 call RunDbgCmd( buf, 'backtrace', [
445 \ '>backtrace',
446 \ ' 3 function GlobalFunction[1]',
447 \ '->2 CallAFunction[1]',
448 \ ' 1 SourceAnotherFile[1]',
449 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
450 \ 'line 1: func DoAThing()' ] )
451
452 call RunDbgCmd( buf, 'down' )
453 call RunDbgCmd( buf, 'backtrace', [
454 \ '>backtrace',
455 \ ' 3 function GlobalFunction[1]',
456 \ ' 2 CallAFunction[1]',
457 \ '->1 SourceAnotherFile[1]',
458 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
459 \ 'line 1: func DoAThing()' ] )
460
461 call RunDbgCmd( buf, 'down' )
462 call RunDbgCmd( buf, 'backtrace', [
463 \ '>backtrace',
464 \ ' 3 function GlobalFunction[1]',
465 \ ' 2 CallAFunction[1]',
466 \ ' 1 SourceAnotherFile[1]',
467 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
468 \ 'line 1: func DoAThing()' ] )
469
470 call RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
471
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200472 " step until we have another meaninfgul trace
473 call RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
474 call RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
475 call RunDbgCmd(buf, 'backtrace', [
476 \ '>backtrace',
477 \ ' 3 function GlobalFunction[1]',
478 \ ' 2 CallAFunction[1]',
479 \ ' 1 SourceAnotherFile[1]',
480 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
481 \ 'line 9: call File2Function()'])
482
483 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
484 call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
485 call RunDbgCmd(buf, 'backtrace', [
486 \ '>backtrace',
487 \ ' 5 function GlobalFunction[1]',
488 \ ' 4 CallAFunction[1]',
489 \ ' 3 SourceAnotherFile[1]',
490 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
491 \ ' 1 function File2Function[1]',
492 \ '->0 DoAThing',
493 \ 'line 1: echo "DoAThing"'])
494
495 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
496 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
497 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
498 call RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
499 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
500 call RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
501 call RunDbgCmd(buf, 'backtrace', [
502 \ '>backtrace',
503 \ ' 1 function GlobalFunction[1]',
504 \ '->0 CallAFunction',
505 \ 'line 2: call File2Function()'])
506
507 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
508 call RunDbgCmd(buf, 'backtrace', [
509 \ '>backtrace',
510 \ ' 2 function GlobalFunction[1]',
511 \ ' 1 CallAFunction[2]',
512 \ '->0 File2Function',
513 \ 'line 1: call DoAThing()'])
514
515 call StopVimInTerminal(buf)
516 call delete('Xtest1.vim')
517 call delete('Xtest2.vim')
518endfunc
519
520func Test_Backtrace_Autocmd()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200521 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200522 let file1 =<< trim END
523 func SourceAnotherFile()
524 source Xtest2.vim
525 endfunc
526
527 func CallAFunction()
528 call SourceAnotherFile()
529 call File2Function()
530 endfunc
531
532 func GlobalFunction()
533 call CallAFunction()
534 endfunc
535
536 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
537 END
538 call writefile(file1, 'Xtest1.vim')
539
540 let file2 =<< trim END
541 func DoAThing()
542 echo "DoAThing"
543 endfunc
544
545 func File2Function()
546 call DoAThing()
547 endfunc
548
549 call File2Function()
550 END
551 call writefile(file2, 'Xtest2.vim')
552
553 let buf = RunVimInTerminal('-S Xtest1.vim', {})
554
555 call RunDbgCmd(buf,
556 \ ':debug doautocmd User TestGlobalFunction',
557 \ ['cmd: doautocmd User TestGlobalFunction'])
558 call RunDbgCmd(buf, 'step', ['cmd: call GlobalFunction() | echo "Done"'])
559
560 " At this point the ontly thing in the stack is the autocommand
561 call RunDbgCmd(buf, 'backtrace', [
562 \ '>backtrace',
563 \ '->0 User Autocommands for "TestGlobalFunction"',
564 \ 'cmd: call GlobalFunction() | echo "Done"'])
565
566 " And now we're back into the call stack
567 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
568 call RunDbgCmd(buf, 'backtrace', [
569 \ '>backtrace',
570 \ ' 1 User Autocommands for "TestGlobalFunction"',
571 \ '->0 function GlobalFunction',
572 \ 'line 1: call CallAFunction()'])
573
574 call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
575 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
576
577 call RunDbgCmd(buf, 'backtrace', [
578 \ '>backtrace',
579 \ ' 3 User Autocommands for "TestGlobalFunction"',
580 \ ' 2 function GlobalFunction[1]',
581 \ ' 1 CallAFunction[1]',
582 \ '->0 SourceAnotherFile',
583 \ 'line 1: source Xtest2.vim'])
584
585 " Step into the 'source' command. Note that we print the full trace all the
586 " way though the source command.
587 call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
588 call RunDbgCmd(buf, 'backtrace', [
589 \ '>backtrace',
590 \ ' 4 User Autocommands for "TestGlobalFunction"',
591 \ ' 3 function GlobalFunction[1]',
592 \ ' 2 CallAFunction[1]',
593 \ ' 1 SourceAnotherFile[1]',
594 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
595 \ 'line 1: func DoAThing()'])
596
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200597 call RunDbgCmd( buf, 'up' )
598 call RunDbgCmd( buf, 'backtrace', [
599 \ '>backtrace',
600 \ ' 4 User Autocommands for "TestGlobalFunction"',
601 \ ' 3 function GlobalFunction[1]',
602 \ ' 2 CallAFunction[1]',
603 \ '->1 SourceAnotherFile[1]',
604 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
605 \ 'line 1: func DoAThing()' ] )
606
607 call RunDbgCmd( buf, 'up' )
608 call RunDbgCmd( buf, 'backtrace', [
609 \ '>backtrace',
610 \ ' 4 User Autocommands for "TestGlobalFunction"',
611 \ ' 3 function GlobalFunction[1]',
612 \ '->2 CallAFunction[1]',
613 \ ' 1 SourceAnotherFile[1]',
614 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
615 \ 'line 1: func DoAThing()' ] )
616
617 call RunDbgCmd( buf, 'up' )
618 call RunDbgCmd( buf, 'backtrace', [
619 \ '>backtrace',
620 \ ' 4 User Autocommands for "TestGlobalFunction"',
621 \ '->3 function GlobalFunction[1]',
622 \ ' 2 CallAFunction[1]',
623 \ ' 1 SourceAnotherFile[1]',
624 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
625 \ 'line 1: func DoAThing()' ] )
626
627 call RunDbgCmd( buf, 'up' )
628 call RunDbgCmd( buf, 'backtrace', [
629 \ '>backtrace',
630 \ '->4 User Autocommands for "TestGlobalFunction"',
631 \ ' 3 function GlobalFunction[1]',
632 \ ' 2 CallAFunction[1]',
633 \ ' 1 SourceAnotherFile[1]',
634 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
635 \ 'line 1: func DoAThing()' ] )
636
637 call RunDbgCmd( buf, 'up', [ 'frame at highest level: 4' ] )
638 call RunDbgCmd( buf, 'backtrace', [
639 \ '>backtrace',
640 \ '->4 User Autocommands for "TestGlobalFunction"',
641 \ ' 3 function GlobalFunction[1]',
642 \ ' 2 CallAFunction[1]',
643 \ ' 1 SourceAnotherFile[1]',
644 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
645 \ 'line 1: func DoAThing()' ] )
646
647 call RunDbgCmd( buf, 'down' )
648 call RunDbgCmd( buf, 'backtrace', [
649 \ '>backtrace',
650 \ ' 4 User Autocommands for "TestGlobalFunction"',
651 \ '->3 function GlobalFunction[1]',
652 \ ' 2 CallAFunction[1]',
653 \ ' 1 SourceAnotherFile[1]',
654 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
655 \ 'line 1: func DoAThing()' ] )
656
657
658 call RunDbgCmd( buf, 'down' )
659 call RunDbgCmd( buf, 'backtrace', [
660 \ '>backtrace',
661 \ ' 4 User Autocommands for "TestGlobalFunction"',
662 \ ' 3 function GlobalFunction[1]',
663 \ '->2 CallAFunction[1]',
664 \ ' 1 SourceAnotherFile[1]',
665 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
666 \ 'line 1: func DoAThing()' ] )
667
668 call RunDbgCmd( buf, 'down' )
669 call RunDbgCmd( buf, 'backtrace', [
670 \ '>backtrace',
671 \ ' 4 User Autocommands for "TestGlobalFunction"',
672 \ ' 3 function GlobalFunction[1]',
673 \ ' 2 CallAFunction[1]',
674 \ '->1 SourceAnotherFile[1]',
675 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
676 \ 'line 1: func DoAThing()' ] )
677
678 call RunDbgCmd( buf, 'down' )
679 call RunDbgCmd( buf, 'backtrace', [
680 \ '>backtrace',
681 \ ' 4 User Autocommands for "TestGlobalFunction"',
682 \ ' 3 function GlobalFunction[1]',
683 \ ' 2 CallAFunction[1]',
684 \ ' 1 SourceAnotherFile[1]',
685 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
686 \ 'line 1: func DoAThing()' ] )
687
688 call RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
689
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200690 " step until we have another meaninfgul trace
691 call RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
692 call RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
693 call RunDbgCmd(buf, 'backtrace', [
694 \ '>backtrace',
695 \ ' 4 User Autocommands for "TestGlobalFunction"',
696 \ ' 3 function GlobalFunction[1]',
697 \ ' 2 CallAFunction[1]',
698 \ ' 1 SourceAnotherFile[1]',
699 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
700 \ 'line 9: call File2Function()'])
701
702 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
703 call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
704 call RunDbgCmd(buf, 'backtrace', [
705 \ '>backtrace',
706 \ ' 6 User Autocommands for "TestGlobalFunction"',
707 \ ' 5 function GlobalFunction[1]',
708 \ ' 4 CallAFunction[1]',
709 \ ' 3 SourceAnotherFile[1]',
710 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
711 \ ' 1 function File2Function[1]',
712 \ '->0 DoAThing',
713 \ 'line 1: echo "DoAThing"'])
714
715 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
716 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
717 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
718 call RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
719 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
720 call RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
721 call RunDbgCmd(buf, 'backtrace', [
722 \ '>backtrace',
723 \ ' 2 User Autocommands for "TestGlobalFunction"',
724 \ ' 1 function GlobalFunction[1]',
725 \ '->0 CallAFunction',
726 \ 'line 2: call File2Function()'])
727
728 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
729 call RunDbgCmd(buf, 'backtrace', [
730 \ '>backtrace',
731 \ ' 3 User Autocommands for "TestGlobalFunction"',
732 \ ' 2 function GlobalFunction[1]',
733 \ ' 1 CallAFunction[2]',
734 \ '->0 File2Function',
735 \ 'line 1: call DoAThing()'])
736
737
738 " Now unwind so that we get back to the original autocommand (and the second
739 " cmd echo "Done")
740 call RunDbgCmd(buf, 'finish', ['line 1: End of function'])
741 call RunDbgCmd(buf, 'backtrace', [
742 \ '>backtrace',
743 \ ' 3 User Autocommands for "TestGlobalFunction"',
744 \ ' 2 function GlobalFunction[1]',
745 \ ' 1 CallAFunction[2]',
746 \ '->0 File2Function',
747 \ 'line 1: End of function'])
748
749 call RunDbgCmd(buf, 'finish', ['line 2: End of function'])
750 call RunDbgCmd(buf, 'backtrace', [
751 \ '>backtrace',
752 \ ' 2 User Autocommands for "TestGlobalFunction"',
753 \ ' 1 function GlobalFunction[1]',
754 \ '->0 CallAFunction',
755 \ 'line 2: End of function'])
756
757 call RunDbgCmd(buf, 'finish', ['line 1: End of function'])
758 call RunDbgCmd(buf, 'backtrace', [
759 \ '>backtrace',
760 \ ' 1 User Autocommands for "TestGlobalFunction"',
761 \ '->0 function GlobalFunction',
762 \ 'line 1: End of function'])
763
764 call RunDbgCmd(buf, 'step', ['cmd: echo "Done"'])
765 call RunDbgCmd(buf, 'backtrace', [
766 \ '>backtrace',
767 \ '->0 User Autocommands for "TestGlobalFunction"',
768 \ 'cmd: echo "Done"'])
769
770 call StopVimInTerminal(buf)
771 call delete('Xtest1.vim')
772 call delete('Xtest2.vim')
773endfunc
774
775func Test_Backtrace_CmdLine()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200776 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200777 let file1 =<< trim END
778 func SourceAnotherFile()
779 source Xtest2.vim
780 endfunc
781
782 func CallAFunction()
783 call SourceAnotherFile()
784 call File2Function()
785 endfunc
786
787 func GlobalFunction()
788 call CallAFunction()
789 endfunc
790
791 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
792 END
793 call writefile(file1, 'Xtest1.vim')
794
795 let file2 =<< trim END
796 func DoAThing()
797 echo "DoAThing"
798 endfunc
799
800 func File2Function()
801 call DoAThing()
802 endfunc
803
804 call File2Function()
805 END
806 call writefile(file2, 'Xtest2.vim')
807
808 let buf = RunVimInTerminal(
809 \ '-S Xtest1.vim -c "debug call GlobalFunction()"',
810 \ {'wait_for_ruler': 0})
811
812 " Need to wait for the vim-in-terminal to be ready
813 call CheckDbgOutput(buf, ['command line',
814 \ 'cmd: call GlobalFunction()'])
815
816 " At this point the ontly thing in the stack is the cmdline
817 call RunDbgCmd(buf, 'backtrace', [
818 \ '>backtrace',
819 \ '->0 command line',
820 \ 'cmd: call GlobalFunction()'])
821
822 " And now we're back into the call stack
823 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
824 call RunDbgCmd(buf, 'backtrace', [
825 \ '>backtrace',
826 \ ' 1 command line',
827 \ '->0 function GlobalFunction',
828 \ 'line 1: call CallAFunction()'])
829
830 call StopVimInTerminal(buf)
831 call delete('Xtest1.vim')
832 call delete('Xtest2.vim')
833endfunc
834
835func Test_Backtrace_DefFunction()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200836 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200837 let file1 =<< trim END
838 vim9script
839 import File2Function from './Xtest2.vim'
840
841 def SourceAnotherFile()
842 source Xtest2.vim
843 enddef
844
845 def CallAFunction()
846 SourceAnotherFile()
847 File2Function()
848 enddef
849
850 def g:GlobalFunction()
851 CallAFunction()
852 enddef
853
854 defcompile
855 END
856 call writefile(file1, 'Xtest1.vim')
857
858 let file2 =<< trim END
859 vim9script
860
861 def DoAThing(): number
Bram Moolenaar1bdae402020-10-03 14:14:56 +0200862 var a = 100 * 2
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200863 a += 3
864 return a
865 enddef
866
867 export def File2Function()
868 DoAThing()
869 enddef
870
871 defcompile
872 File2Function()
873 END
874 call writefile(file2, 'Xtest2.vim')
875
876 let buf = RunVimInTerminal('-S Xtest1.vim', {})
877
878 call RunDbgCmd(buf,
879 \ ':debug call GlobalFunction()',
880 \ ['cmd: call GlobalFunction()'])
881
882 " FIXME: Vim9 lines are not debugged!
883 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
884
885 " But they do appear in the backtrace
886 call RunDbgCmd(buf, 'backtrace', [
887 \ '\V>backtrace',
888 \ '\V 2 function GlobalFunction[1]',
889 \ '\V 1 <SNR>\.\*_CallAFunction[1]',
890 \ '\V->0 <SNR>\.\*_SourceAnotherFile',
891 \ '\Vline 1: source Xtest2.vim'],
892 \ #{match: 'pattern'})
893
894
895 call RunDbgCmd(buf, 'step', ['line 1: vim9script'])
896 call RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number'])
897 call RunDbgCmd(buf, 'step', ['line 9: export def File2Function()'])
898 call RunDbgCmd(buf, 'step', ['line 9: def File2Function()'])
899 call RunDbgCmd(buf, 'step', ['line 13: defcompile'])
900 call RunDbgCmd(buf, 'step', ['line 14: File2Function()'])
901 call RunDbgCmd(buf, 'backtrace', [
902 \ '\V>backtrace',
903 \ '\V 3 function GlobalFunction[1]',
904 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
905 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
906 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
907 \ '\Vline 14: File2Function()'],
908 \ #{match: 'pattern'})
909
910 " Don't step into compiled functions...
911 call RunDbgCmd(buf, 'step', ['line 15: End of sourced file'])
912 call RunDbgCmd(buf, 'backtrace', [
913 \ '\V>backtrace',
914 \ '\V 3 function GlobalFunction[1]',
915 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
916 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
917 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
918 \ '\Vline 15: End of sourced file'],
919 \ #{match: 'pattern'})
920
921
922 call StopVimInTerminal(buf)
923 call delete('Xtest1.vim')
924 call delete('Xtest2.vim')
925endfunc
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200926
927func Test_debug_backtrace_level()
928 CheckCWD
929 let lines =<< trim END
930 let s:file1_var = 'file1'
931 let g:global_var = 'global'
932
933 func s:File1Func( arg )
934 let s:file1_var .= a:arg
935 let local_var = s:file1_var .. ' test1'
936 let g:global_var .= local_var
937 source Xtest2.vim
938 endfunc
939
940 call s:File1Func( 'arg1' )
941 END
942 call writefile(lines, 'Xtest1.vim')
943
944 let lines =<< trim END
945 let s:file2_var = 'file2'
946
947 func s:File2Func( arg )
948 let s:file2_var .= a:arg
949 let local_var = s:file2_var .. ' test2'
950 let g:global_var .= local_var
951 endfunc
952
953 call s:File2Func( 'arg2' )
954 END
955 call writefile(lines, 'Xtest2.vim')
956
957 let file1 = getcwd() .. '/Xtest1.vim'
958 let file2 = getcwd() .. '/Xtest2.vim'
959
960 " set a breakpoint and source file1.vim
961 let buf = RunVimInTerminal(
962 \ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim',
963 \ #{ wait_for_ruler: 0 } )
964
965 call CheckDbgOutput(buf, [
966 \ 'Breakpoint in "' .. file1 .. '" line 1',
967 \ 'Entering Debug mode. Type "cont" to continue.',
968 \ 'command line..script ' .. file1,
969 \ 'line 1: let s:file1_var = ''file1'''
970 \ ])
971
972 " step throught the initial declarations
973 call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] )
974 call RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] )
975 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
976 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
977 call RunDbgCmd(buf, 'echo global_var', [ 'global' ] )
978
979 " step in to the first function
980 call RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] )
981 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] )
982 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
983 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
984 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
985 call RunDbgCmd(buf,
986 \'echo global_var',
987 \[ 'E121: Undefined variable: global_var' ] )
988 call RunDbgCmd(buf,
989 \'echo local_var',
990 \[ 'E121: Undefined variable: local_var' ] )
991 call RunDbgCmd(buf,
992 \'echo l:local_var',
993 \[ 'E121: Undefined variable: l:local_var' ] )
994
995 " backtrace up
996 call RunDbgCmd(buf, 'backtrace', [
997 \ '\V>backtrace',
998 \ '\V 2 command line',
999 \ '\V 1 script ' .. file1 .. '[11]',
1000 \ '\V->0 function <SNR>\.\*_File1Func',
1001 \ '\Vline 1: let s:file1_var .= a:arg',
1002 \ ],
1003 \ #{ match: 'pattern' } )
1004 call RunDbgCmd(buf, 'up', [ '>up' ] )
1005
1006 call RunDbgCmd(buf, 'backtrace', [
1007 \ '\V>backtrace',
1008 \ '\V 2 command line',
1009 \ '\V->1 script ' .. file1 .. '[11]',
1010 \ '\V 0 function <SNR>\.\*_File1Func',
1011 \ '\Vline 1: let s:file1_var .= a:arg',
1012 \ ],
1013 \ #{ match: 'pattern' } )
1014
1015 " Expression evaluation in the script frame (not the function frame)
1016 " FIXME: Unexpected in this scope (a: should not be visibnle)
1017 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1018 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1019 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1020 " FIXME: Unexpected in this scope (global should be found)
1021 call RunDbgCmd(buf,
1022 \'echo global_var',
1023 \[ 'E121: Undefined variable: global_var' ] )
1024 call RunDbgCmd(buf,
1025 \'echo local_var',
1026 \[ 'E121: Undefined variable: local_var' ] )
1027 call RunDbgCmd(buf,
1028 \'echo l:local_var',
1029 \[ 'E121: Undefined variable: l:local_var' ] )
1030
1031
1032 " step while backtraced jumps to the latest frame
1033 call RunDbgCmd(buf, 'step', [
1034 \ 'line 2: let local_var = s:file1_var .. '' test1''' ] )
1035 call RunDbgCmd(buf, 'backtrace', [
1036 \ '\V>backtrace',
1037 \ '\V 2 command line',
1038 \ '\V 1 script ' .. file1 .. '[11]',
1039 \ '\V->0 function <SNR>\.\*_File1Func',
1040 \ '\Vline 2: let local_var = s:file1_var .. '' test1''',
1041 \ ],
1042 \ #{ match: 'pattern' } )
1043
1044 call RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] )
1045 call RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] )
1046 call RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] )
1047
1048 call RunDbgCmd(buf, 'step', [ 'line 4: source Xtest2.vim' ] )
1049 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file2_var = ''file2''' ] )
1050 call RunDbgCmd(buf, 'backtrace', [
1051 \ '\V>backtrace',
1052 \ '\V 3 command line',
1053 \ '\V 2 script ' .. file1 .. '[11]',
1054 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1055 \ '\V->0 script ' .. file2,
1056 \ '\Vline 1: let s:file2_var = ''file2''',
1057 \ ],
1058 \ #{ match: 'pattern' } )
1059
1060 " Expression evaluation in the script frame file2 (not the function frame)
1061 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1062 call RunDbgCmd(buf,
1063 \ 'echo s:file1_var',
1064 \ [ 'E121: Undefined variable: s:file1_var' ] )
1065 call RunDbgCmd(buf, 'echo g:global_var', [ 'globalfile1arg1 test1' ] )
1066 call RunDbgCmd(buf, 'echo global_var', [ 'globalfile1arg1 test1' ] )
1067 call RunDbgCmd(buf,
1068 \'echo local_var',
1069 \[ 'E121: Undefined variable: local_var' ] )
1070 call RunDbgCmd(buf,
1071 \'echo l:local_var',
1072 \[ 'E121: Undefined variable: l:local_var' ] )
1073 call RunDbgCmd(buf,
1074 \ 'echo s:file2_var',
1075 \ [ 'E121: Undefined variable: s:file2_var' ] )
1076
1077 call RunDbgCmd(buf, 'step', [ 'line 3: func s:File2Func( arg )' ] )
1078 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1079
1080 " Up the stack to the other script context
1081 call RunDbgCmd(buf, 'up')
1082 call RunDbgCmd(buf, 'backtrace', [
1083 \ '\V>backtrace',
1084 \ '\V 3 command line',
1085 \ '\V 2 script ' .. file1 .. '[11]',
1086 \ '\V->1 function <SNR>\.\*_File1Func[4]',
1087 \ '\V 0 script ' .. file2,
1088 \ '\Vline 3: func s:File2Func( arg )',
1089 \ ],
1090 \ #{ match: 'pattern' } )
1091 " FIXME: Unexpected. Should see the a: and l: dicts from File1Func
1092 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1093 call RunDbgCmd(buf,
1094 \ 'echo l:local_var',
1095 \ [ 'E121: Undefined variable: l:local_var' ] )
1096
1097 call RunDbgCmd(buf, 'up')
1098 call RunDbgCmd(buf, 'backtrace', [
1099 \ '\V>backtrace',
1100 \ '\V 3 command line',
1101 \ '\V->2 script ' .. file1 .. '[11]',
1102 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1103 \ '\V 0 script ' .. file2,
1104 \ '\Vline 3: func s:File2Func( arg )',
1105 \ ],
1106 \ #{ match: 'pattern' } )
1107
1108 " FIXME: Unexpected (wrong script vars are used)
1109 call RunDbgCmd(buf,
1110 \ 'echo s:file1_var',
1111 \ [ 'E121: Undefined variable: s:file1_var' ] )
1112 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1113
1114 call StopVimInTerminal(buf)
1115 call delete('Xtest1.vim')
1116 call delete('Xtest2.vim')
1117endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001118
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001119" Test for setting a breakpoint on a :endif where the :if condition is false
1120" and then quit the script. This should generate an interrupt.
1121func Test_breakpt_endif_intr()
1122 func F()
1123 let g:Xpath ..= 'a'
1124 if v:false
1125 let g:Xpath ..= 'b'
1126 endif
1127 invalid_command
1128 endfunc
1129
1130 let g:Xpath = ''
1131 breakadd func 4 F
1132 try
1133 let caught_intr = 0
1134 debuggreedy
1135 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001136 catch /^Vim:Interrupt$/
1137 call assert_match('\.F, line 4', v:throwpoint)
1138 let caught_intr = 1
1139 endtry
1140 0debuggreedy
1141 call assert_equal(1, caught_intr)
1142 call assert_equal('a', g:Xpath)
1143 breakdel *
1144 delfunc F
1145endfunc
1146
1147" Test for setting a breakpoint on a :else where the :if condition is false
1148" and then quit the script. This should generate an interrupt.
1149func Test_breakpt_else_intr()
1150 func F()
1151 let g:Xpath ..= 'a'
1152 if v:false
1153 let g:Xpath ..= 'b'
1154 else
1155 invalid_command
1156 endif
1157 invalid_command
1158 endfunc
1159
1160 let g:Xpath = ''
1161 breakadd func 4 F
1162 try
1163 let caught_intr = 0
1164 debuggreedy
1165 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001166 catch /^Vim:Interrupt$/
1167 call assert_match('\.F, line 4', v:throwpoint)
1168 let caught_intr = 1
1169 endtry
1170 0debuggreedy
1171 call assert_equal(1, caught_intr)
1172 call assert_equal('a', g:Xpath)
1173 breakdel *
1174 delfunc F
1175endfunc
1176
1177" Test for setting a breakpoint on a :endwhile where the :while condition is
1178" false and then quit the script. This should generate an interrupt.
1179func Test_breakpt_endwhile_intr()
1180 func F()
1181 let g:Xpath ..= 'a'
1182 while v:false
1183 let g:Xpath ..= 'b'
1184 endwhile
1185 invalid_command
1186 endfunc
1187
1188 let g:Xpath = ''
1189 breakadd func 4 F
1190 try
1191 let caught_intr = 0
1192 debuggreedy
1193 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001194 catch /^Vim:Interrupt$/
1195 call assert_match('\.F, line 4', v:throwpoint)
1196 let caught_intr = 1
1197 endtry
1198 0debuggreedy
1199 call assert_equal(1, caught_intr)
1200 call assert_equal('a', g:Xpath)
1201 breakdel *
1202 delfunc F
1203endfunc
1204
Bram Moolenaar16c62322020-08-13 19:20:04 +02001205" Test for setting a breakpoint on a script local function
1206func Test_breakpt_scriptlocal_func()
1207 let g:Xpath = ''
1208 func s:G()
1209 let g:Xpath ..= 'a'
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001210 endfunc
1211
Bram Moolenaar16c62322020-08-13 19:20:04 +02001212 let funcname = expand("<SID>") .. "G"
1213 exe "breakadd func 1 " .. funcname
1214 debuggreedy
1215 redir => output
1216 call feedkeys(":call " .. funcname .. "()\<CR>c\<CR>", "xt")
1217 redir END
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001218 0debuggreedy
Bram Moolenaar16c62322020-08-13 19:20:04 +02001219 call assert_match('Breakpoint in "' .. funcname .. '" line 1', output)
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001220 call assert_equal('a', g:Xpath)
1221 breakdel *
Bram Moolenaar16c62322020-08-13 19:20:04 +02001222 exe "delfunc " .. funcname
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001223endfunc
1224
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001225" vim: shiftwidth=2 sts=2 expandtab