blob: fb2700754c67d4edc83cc7d18f708b313a740ca6 [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 Moolenaar113bf062019-04-17 16:54:05 +0200342endfunc
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200343
344func Test_Backtrace_Through_Source()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200345 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200346 let file1 =<< trim END
347 func SourceAnotherFile()
348 source Xtest2.vim
349 endfunc
350
351 func CallAFunction()
352 call SourceAnotherFile()
353 call File2Function()
354 endfunc
355
356 func GlobalFunction()
357 call CallAFunction()
358 endfunc
359 END
360 call writefile(file1, 'Xtest1.vim')
361
362 let file2 =<< trim END
363 func DoAThing()
364 echo "DoAThing"
365 endfunc
366
367 func File2Function()
368 call DoAThing()
369 endfunc
370
371 call File2Function()
372 END
373 call writefile(file2, 'Xtest2.vim')
374
375 let buf = RunVimInTerminal('-S Xtest1.vim', {})
376
377 call RunDbgCmd(buf,
378 \ ':debug call GlobalFunction()',
379 \ ['cmd: call GlobalFunction()'])
380 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
381
382 call RunDbgCmd(buf, 'backtrace', ['>backtrace',
383 \ '->0 function GlobalFunction',
384 \ 'line 1: call CallAFunction()'])
385
386 call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
387 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
388
389 call RunDbgCmd(buf, 'backtrace', ['>backtrace',
390 \ ' 2 function GlobalFunction[1]',
391 \ ' 1 CallAFunction[1]',
392 \ '->0 SourceAnotherFile',
393 \ 'line 1: source Xtest2.vim'])
394
395 " Step into the 'source' command. Note that we print the full trace all the
396 " way though the source command.
397 call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
398 call RunDbgCmd(buf, 'backtrace', [
399 \ '>backtrace',
400 \ ' 3 function GlobalFunction[1]',
401 \ ' 2 CallAFunction[1]',
402 \ ' 1 SourceAnotherFile[1]',
403 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
404 \ 'line 1: func DoAThing()'])
405
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200406 call RunDbgCmd( buf, 'up' )
407 call RunDbgCmd( buf, 'backtrace', [
408 \ '>backtrace',
409 \ ' 3 function GlobalFunction[1]',
410 \ ' 2 CallAFunction[1]',
411 \ '->1 SourceAnotherFile[1]',
412 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
413 \ 'line 1: func DoAThing()' ] )
414
415 call RunDbgCmd( buf, 'up' )
416 call RunDbgCmd( buf, 'backtrace', [
417 \ '>backtrace',
418 \ ' 3 function GlobalFunction[1]',
419 \ '->2 CallAFunction[1]',
420 \ ' 1 SourceAnotherFile[1]',
421 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
422 \ 'line 1: func DoAThing()' ] )
423
424 call RunDbgCmd( buf, 'up' )
425 call RunDbgCmd( buf, 'backtrace', [
426 \ '>backtrace',
427 \ '->3 function GlobalFunction[1]',
428 \ ' 2 CallAFunction[1]',
429 \ ' 1 SourceAnotherFile[1]',
430 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
431 \ 'line 1: func DoAThing()' ] )
432
433 call RunDbgCmd( buf, 'up', [ 'frame at highest level: 3' ] )
434 call RunDbgCmd( buf, 'backtrace', [
435 \ '>backtrace',
436 \ '->3 function GlobalFunction[1]',
437 \ ' 2 CallAFunction[1]',
438 \ ' 1 SourceAnotherFile[1]',
439 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
440 \ 'line 1: func DoAThing()' ] )
441
442 call RunDbgCmd( buf, 'down' )
443 call RunDbgCmd( buf, 'backtrace', [
444 \ '>backtrace',
445 \ ' 3 function GlobalFunction[1]',
446 \ '->2 CallAFunction[1]',
447 \ ' 1 SourceAnotherFile[1]',
448 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
449 \ 'line 1: func DoAThing()' ] )
450
451 call RunDbgCmd( buf, 'down' )
452 call RunDbgCmd( buf, 'backtrace', [
453 \ '>backtrace',
454 \ ' 3 function GlobalFunction[1]',
455 \ ' 2 CallAFunction[1]',
456 \ '->1 SourceAnotherFile[1]',
457 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
458 \ 'line 1: func DoAThing()' ] )
459
460 call RunDbgCmd( buf, 'down' )
461 call RunDbgCmd( buf, 'backtrace', [
462 \ '>backtrace',
463 \ ' 3 function GlobalFunction[1]',
464 \ ' 2 CallAFunction[1]',
465 \ ' 1 SourceAnotherFile[1]',
466 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
467 \ 'line 1: func DoAThing()' ] )
468
469 call RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
470
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200471 " step until we have another meaninfgul trace
472 call RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
473 call RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
474 call RunDbgCmd(buf, 'backtrace', [
475 \ '>backtrace',
476 \ ' 3 function GlobalFunction[1]',
477 \ ' 2 CallAFunction[1]',
478 \ ' 1 SourceAnotherFile[1]',
479 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
480 \ 'line 9: call File2Function()'])
481
482 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
483 call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
484 call RunDbgCmd(buf, 'backtrace', [
485 \ '>backtrace',
486 \ ' 5 function GlobalFunction[1]',
487 \ ' 4 CallAFunction[1]',
488 \ ' 3 SourceAnotherFile[1]',
489 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
490 \ ' 1 function File2Function[1]',
491 \ '->0 DoAThing',
492 \ 'line 1: echo "DoAThing"'])
493
494 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
495 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
496 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
497 call RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
498 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
499 call RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
500 call RunDbgCmd(buf, 'backtrace', [
501 \ '>backtrace',
502 \ ' 1 function GlobalFunction[1]',
503 \ '->0 CallAFunction',
504 \ 'line 2: call File2Function()'])
505
506 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
507 call RunDbgCmd(buf, 'backtrace', [
508 \ '>backtrace',
509 \ ' 2 function GlobalFunction[1]',
510 \ ' 1 CallAFunction[2]',
511 \ '->0 File2Function',
512 \ 'line 1: call DoAThing()'])
513
514 call StopVimInTerminal(buf)
515 call delete('Xtest1.vim')
516 call delete('Xtest2.vim')
517endfunc
518
519func Test_Backtrace_Autocmd()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200520 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200521 let file1 =<< trim END
522 func SourceAnotherFile()
523 source Xtest2.vim
524 endfunc
525
526 func CallAFunction()
527 call SourceAnotherFile()
528 call File2Function()
529 endfunc
530
531 func GlobalFunction()
532 call CallAFunction()
533 endfunc
534
535 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
536 END
537 call writefile(file1, 'Xtest1.vim')
538
539 let file2 =<< trim END
540 func DoAThing()
541 echo "DoAThing"
542 endfunc
543
544 func File2Function()
545 call DoAThing()
546 endfunc
547
548 call File2Function()
549 END
550 call writefile(file2, 'Xtest2.vim')
551
552 let buf = RunVimInTerminal('-S Xtest1.vim', {})
553
554 call RunDbgCmd(buf,
555 \ ':debug doautocmd User TestGlobalFunction',
556 \ ['cmd: doautocmd User TestGlobalFunction'])
557 call RunDbgCmd(buf, 'step', ['cmd: call GlobalFunction() | echo "Done"'])
558
559 " At this point the ontly thing in the stack is the autocommand
560 call RunDbgCmd(buf, 'backtrace', [
561 \ '>backtrace',
562 \ '->0 User Autocommands for "TestGlobalFunction"',
563 \ 'cmd: call GlobalFunction() | echo "Done"'])
564
565 " And now we're back into the call stack
566 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
567 call RunDbgCmd(buf, 'backtrace', [
568 \ '>backtrace',
569 \ ' 1 User Autocommands for "TestGlobalFunction"',
570 \ '->0 function GlobalFunction',
571 \ 'line 1: call CallAFunction()'])
572
573 call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
574 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
575
576 call RunDbgCmd(buf, 'backtrace', [
577 \ '>backtrace',
578 \ ' 3 User Autocommands for "TestGlobalFunction"',
579 \ ' 2 function GlobalFunction[1]',
580 \ ' 1 CallAFunction[1]',
581 \ '->0 SourceAnotherFile',
582 \ 'line 1: source Xtest2.vim'])
583
584 " Step into the 'source' command. Note that we print the full trace all the
585 " way though the source command.
586 call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
587 call RunDbgCmd(buf, 'backtrace', [
588 \ '>backtrace',
589 \ ' 4 User Autocommands for "TestGlobalFunction"',
590 \ ' 3 function GlobalFunction[1]',
591 \ ' 2 CallAFunction[1]',
592 \ ' 1 SourceAnotherFile[1]',
593 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
594 \ 'line 1: func DoAThing()'])
595
596 " step until we have another meaninfgul trace
597 call RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
598 call RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
599 call RunDbgCmd(buf, 'backtrace', [
600 \ '>backtrace',
601 \ ' 4 User Autocommands for "TestGlobalFunction"',
602 \ ' 3 function GlobalFunction[1]',
603 \ ' 2 CallAFunction[1]',
604 \ ' 1 SourceAnotherFile[1]',
605 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
606 \ 'line 9: call File2Function()'])
607
608 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
609 call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
610 call RunDbgCmd(buf, 'backtrace', [
611 \ '>backtrace',
612 \ ' 6 User Autocommands for "TestGlobalFunction"',
613 \ ' 5 function GlobalFunction[1]',
614 \ ' 4 CallAFunction[1]',
615 \ ' 3 SourceAnotherFile[1]',
616 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
617 \ ' 1 function File2Function[1]',
618 \ '->0 DoAThing',
619 \ 'line 1: echo "DoAThing"'])
620
621 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
622 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
623 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
624 call RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
625 call RunDbgCmd(buf, 'step', ['line 1: End of function'])
626 call RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
627 call RunDbgCmd(buf, 'backtrace', [
628 \ '>backtrace',
629 \ ' 2 User Autocommands for "TestGlobalFunction"',
630 \ ' 1 function GlobalFunction[1]',
631 \ '->0 CallAFunction',
632 \ 'line 2: call File2Function()'])
633
634 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
635 call RunDbgCmd(buf, 'backtrace', [
636 \ '>backtrace',
637 \ ' 3 User Autocommands for "TestGlobalFunction"',
638 \ ' 2 function GlobalFunction[1]',
639 \ ' 1 CallAFunction[2]',
640 \ '->0 File2Function',
641 \ 'line 1: call DoAThing()'])
642
643
644 " Now unwind so that we get back to the original autocommand (and the second
645 " cmd echo "Done")
646 call RunDbgCmd(buf, 'finish', ['line 1: End of function'])
647 call RunDbgCmd(buf, 'backtrace', [
648 \ '>backtrace',
649 \ ' 3 User Autocommands for "TestGlobalFunction"',
650 \ ' 2 function GlobalFunction[1]',
651 \ ' 1 CallAFunction[2]',
652 \ '->0 File2Function',
653 \ 'line 1: End of function'])
654
655 call RunDbgCmd(buf, 'finish', ['line 2: End of function'])
656 call RunDbgCmd(buf, 'backtrace', [
657 \ '>backtrace',
658 \ ' 2 User Autocommands for "TestGlobalFunction"',
659 \ ' 1 function GlobalFunction[1]',
660 \ '->0 CallAFunction',
661 \ 'line 2: End of function'])
662
663 call RunDbgCmd(buf, 'finish', ['line 1: End of function'])
664 call RunDbgCmd(buf, 'backtrace', [
665 \ '>backtrace',
666 \ ' 1 User Autocommands for "TestGlobalFunction"',
667 \ '->0 function GlobalFunction',
668 \ 'line 1: End of function'])
669
670 call RunDbgCmd(buf, 'step', ['cmd: echo "Done"'])
671 call RunDbgCmd(buf, 'backtrace', [
672 \ '>backtrace',
673 \ '->0 User Autocommands for "TestGlobalFunction"',
674 \ 'cmd: echo "Done"'])
675
676 call StopVimInTerminal(buf)
677 call delete('Xtest1.vim')
678 call delete('Xtest2.vim')
679endfunc
680
681func Test_Backtrace_CmdLine()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200682 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200683 let file1 =<< trim END
684 func SourceAnotherFile()
685 source Xtest2.vim
686 endfunc
687
688 func CallAFunction()
689 call SourceAnotherFile()
690 call File2Function()
691 endfunc
692
693 func GlobalFunction()
694 call CallAFunction()
695 endfunc
696
697 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
698 END
699 call writefile(file1, 'Xtest1.vim')
700
701 let file2 =<< trim END
702 func DoAThing()
703 echo "DoAThing"
704 endfunc
705
706 func File2Function()
707 call DoAThing()
708 endfunc
709
710 call File2Function()
711 END
712 call writefile(file2, 'Xtest2.vim')
713
714 let buf = RunVimInTerminal(
715 \ '-S Xtest1.vim -c "debug call GlobalFunction()"',
716 \ {'wait_for_ruler': 0})
717
718 " Need to wait for the vim-in-terminal to be ready
719 call CheckDbgOutput(buf, ['command line',
720 \ 'cmd: call GlobalFunction()'])
721
722 " At this point the ontly thing in the stack is the cmdline
723 call RunDbgCmd(buf, 'backtrace', [
724 \ '>backtrace',
725 \ '->0 command line',
726 \ 'cmd: call GlobalFunction()'])
727
728 " And now we're back into the call stack
729 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
730 call RunDbgCmd(buf, 'backtrace', [
731 \ '>backtrace',
732 \ ' 1 command line',
733 \ '->0 function GlobalFunction',
734 \ 'line 1: call CallAFunction()'])
735
736 call StopVimInTerminal(buf)
737 call delete('Xtest1.vim')
738 call delete('Xtest2.vim')
739endfunc
740
741func Test_Backtrace_DefFunction()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200742 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200743 let file1 =<< trim END
744 vim9script
745 import File2Function from './Xtest2.vim'
746
747 def SourceAnotherFile()
748 source Xtest2.vim
749 enddef
750
751 def CallAFunction()
752 SourceAnotherFile()
753 File2Function()
754 enddef
755
756 def g:GlobalFunction()
757 CallAFunction()
758 enddef
759
760 defcompile
761 END
762 call writefile(file1, 'Xtest1.vim')
763
764 let file2 =<< trim END
765 vim9script
766
767 def DoAThing(): number
768 let a = 100 * 2
769 a += 3
770 return a
771 enddef
772
773 export def File2Function()
774 DoAThing()
775 enddef
776
777 defcompile
778 File2Function()
779 END
780 call writefile(file2, 'Xtest2.vim')
781
782 let buf = RunVimInTerminal('-S Xtest1.vim', {})
783
784 call RunDbgCmd(buf,
785 \ ':debug call GlobalFunction()',
786 \ ['cmd: call GlobalFunction()'])
787
788 " FIXME: Vim9 lines are not debugged!
789 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
790
791 " But they do appear in the backtrace
792 call RunDbgCmd(buf, 'backtrace', [
793 \ '\V>backtrace',
794 \ '\V 2 function GlobalFunction[1]',
795 \ '\V 1 <SNR>\.\*_CallAFunction[1]',
796 \ '\V->0 <SNR>\.\*_SourceAnotherFile',
797 \ '\Vline 1: source Xtest2.vim'],
798 \ #{match: 'pattern'})
799
800
801 call RunDbgCmd(buf, 'step', ['line 1: vim9script'])
802 call RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number'])
803 call RunDbgCmd(buf, 'step', ['line 9: export def File2Function()'])
804 call RunDbgCmd(buf, 'step', ['line 9: def File2Function()'])
805 call RunDbgCmd(buf, 'step', ['line 13: defcompile'])
806 call RunDbgCmd(buf, 'step', ['line 14: File2Function()'])
807 call RunDbgCmd(buf, 'backtrace', [
808 \ '\V>backtrace',
809 \ '\V 3 function GlobalFunction[1]',
810 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
811 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
812 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
813 \ '\Vline 14: File2Function()'],
814 \ #{match: 'pattern'})
815
816 " Don't step into compiled functions...
817 call RunDbgCmd(buf, 'step', ['line 15: End of sourced file'])
818 call RunDbgCmd(buf, 'backtrace', [
819 \ '\V>backtrace',
820 \ '\V 3 function GlobalFunction[1]',
821 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
822 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
823 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
824 \ '\Vline 15: End of sourced file'],
825 \ #{match: 'pattern'})
826
827
828 call StopVimInTerminal(buf)
829 call delete('Xtest1.vim')
830 call delete('Xtest2.vim')
831endfunc
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200832
833func Test_debug_backtrace_level()
834 CheckCWD
835 let lines =<< trim END
836 let s:file1_var = 'file1'
837 let g:global_var = 'global'
838
839 func s:File1Func( arg )
840 let s:file1_var .= a:arg
841 let local_var = s:file1_var .. ' test1'
842 let g:global_var .= local_var
843 source Xtest2.vim
844 endfunc
845
846 call s:File1Func( 'arg1' )
847 END
848 call writefile(lines, 'Xtest1.vim')
849
850 let lines =<< trim END
851 let s:file2_var = 'file2'
852
853 func s:File2Func( arg )
854 let s:file2_var .= a:arg
855 let local_var = s:file2_var .. ' test2'
856 let g:global_var .= local_var
857 endfunc
858
859 call s:File2Func( 'arg2' )
860 END
861 call writefile(lines, 'Xtest2.vim')
862
863 let file1 = getcwd() .. '/Xtest1.vim'
864 let file2 = getcwd() .. '/Xtest2.vim'
865
866 " set a breakpoint and source file1.vim
867 let buf = RunVimInTerminal(
868 \ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim',
869 \ #{ wait_for_ruler: 0 } )
870
871 call CheckDbgOutput(buf, [
872 \ 'Breakpoint in "' .. file1 .. '" line 1',
873 \ 'Entering Debug mode. Type "cont" to continue.',
874 \ 'command line..script ' .. file1,
875 \ 'line 1: let s:file1_var = ''file1'''
876 \ ])
877
878 " step throught the initial declarations
879 call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] )
880 call RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] )
881 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
882 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
883 call RunDbgCmd(buf, 'echo global_var', [ 'global' ] )
884
885 " step in to the first function
886 call RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] )
887 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] )
888 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
889 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
890 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
891 call RunDbgCmd(buf,
892 \'echo global_var',
893 \[ 'E121: Undefined variable: global_var' ] )
894 call RunDbgCmd(buf,
895 \'echo local_var',
896 \[ 'E121: Undefined variable: local_var' ] )
897 call RunDbgCmd(buf,
898 \'echo l:local_var',
899 \[ 'E121: Undefined variable: l:local_var' ] )
900
901 " backtrace up
902 call RunDbgCmd(buf, 'backtrace', [
903 \ '\V>backtrace',
904 \ '\V 2 command line',
905 \ '\V 1 script ' .. file1 .. '[11]',
906 \ '\V->0 function <SNR>\.\*_File1Func',
907 \ '\Vline 1: let s:file1_var .= a:arg',
908 \ ],
909 \ #{ match: 'pattern' } )
910 call RunDbgCmd(buf, 'up', [ '>up' ] )
911
912 call RunDbgCmd(buf, 'backtrace', [
913 \ '\V>backtrace',
914 \ '\V 2 command line',
915 \ '\V->1 script ' .. file1 .. '[11]',
916 \ '\V 0 function <SNR>\.\*_File1Func',
917 \ '\Vline 1: let s:file1_var .= a:arg',
918 \ ],
919 \ #{ match: 'pattern' } )
920
921 " Expression evaluation in the script frame (not the function frame)
922 " FIXME: Unexpected in this scope (a: should not be visibnle)
923 call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
924 call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
925 call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
926 " FIXME: Unexpected in this scope (global should be found)
927 call RunDbgCmd(buf,
928 \'echo global_var',
929 \[ 'E121: Undefined variable: global_var' ] )
930 call RunDbgCmd(buf,
931 \'echo local_var',
932 \[ 'E121: Undefined variable: local_var' ] )
933 call RunDbgCmd(buf,
934 \'echo l:local_var',
935 \[ 'E121: Undefined variable: l:local_var' ] )
936
937
938 " step while backtraced jumps to the latest frame
939 call RunDbgCmd(buf, 'step', [
940 \ 'line 2: let local_var = s:file1_var .. '' test1''' ] )
941 call RunDbgCmd(buf, 'backtrace', [
942 \ '\V>backtrace',
943 \ '\V 2 command line',
944 \ '\V 1 script ' .. file1 .. '[11]',
945 \ '\V->0 function <SNR>\.\*_File1Func',
946 \ '\Vline 2: let local_var = s:file1_var .. '' test1''',
947 \ ],
948 \ #{ match: 'pattern' } )
949
950 call RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] )
951 call RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] )
952 call RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] )
953
954 call RunDbgCmd(buf, 'step', [ 'line 4: source Xtest2.vim' ] )
955 call RunDbgCmd(buf, 'step', [ 'line 1: let s:file2_var = ''file2''' ] )
956 call RunDbgCmd(buf, 'backtrace', [
957 \ '\V>backtrace',
958 \ '\V 3 command line',
959 \ '\V 2 script ' .. file1 .. '[11]',
960 \ '\V 1 function <SNR>\.\*_File1Func[4]',
961 \ '\V->0 script ' .. file2,
962 \ '\Vline 1: let s:file2_var = ''file2''',
963 \ ],
964 \ #{ match: 'pattern' } )
965
966 " Expression evaluation in the script frame file2 (not the function frame)
967 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
968 call RunDbgCmd(buf,
969 \ 'echo s:file1_var',
970 \ [ 'E121: Undefined variable: s:file1_var' ] )
971 call RunDbgCmd(buf, 'echo g:global_var', [ 'globalfile1arg1 test1' ] )
972 call RunDbgCmd(buf, 'echo global_var', [ 'globalfile1arg1 test1' ] )
973 call RunDbgCmd(buf,
974 \'echo local_var',
975 \[ 'E121: Undefined variable: local_var' ] )
976 call RunDbgCmd(buf,
977 \'echo l:local_var',
978 \[ 'E121: Undefined variable: l:local_var' ] )
979 call RunDbgCmd(buf,
980 \ 'echo s:file2_var',
981 \ [ 'E121: Undefined variable: s:file2_var' ] )
982
983 call RunDbgCmd(buf, 'step', [ 'line 3: func s:File2Func( arg )' ] )
984 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
985
986 " Up the stack to the other script context
987 call RunDbgCmd(buf, 'up')
988 call RunDbgCmd(buf, 'backtrace', [
989 \ '\V>backtrace',
990 \ '\V 3 command line',
991 \ '\V 2 script ' .. file1 .. '[11]',
992 \ '\V->1 function <SNR>\.\*_File1Func[4]',
993 \ '\V 0 script ' .. file2,
994 \ '\Vline 3: func s:File2Func( arg )',
995 \ ],
996 \ #{ match: 'pattern' } )
997 " FIXME: Unexpected. Should see the a: and l: dicts from File1Func
998 call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
999 call RunDbgCmd(buf,
1000 \ 'echo l:local_var',
1001 \ [ 'E121: Undefined variable: l:local_var' ] )
1002
1003 call RunDbgCmd(buf, 'up')
1004 call RunDbgCmd(buf, 'backtrace', [
1005 \ '\V>backtrace',
1006 \ '\V 3 command line',
1007 \ '\V->2 script ' .. file1 .. '[11]',
1008 \ '\V 1 function <SNR>\.\*_File1Func[4]',
1009 \ '\V 0 script ' .. file2,
1010 \ '\Vline 3: func s:File2Func( arg )',
1011 \ ],
1012 \ #{ match: 'pattern' } )
1013
1014 " FIXME: Unexpected (wrong script vars are used)
1015 call RunDbgCmd(buf,
1016 \ 'echo s:file1_var',
1017 \ [ 'E121: Undefined variable: s:file1_var' ] )
1018 call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
1019
1020 call StopVimInTerminal(buf)
1021 call delete('Xtest1.vim')
1022 call delete('Xtest2.vim')
1023endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001024
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001025" Test for setting a breakpoint on a :endif where the :if condition is false
1026" and then quit the script. This should generate an interrupt.
1027func Test_breakpt_endif_intr()
1028 func F()
1029 let g:Xpath ..= 'a'
1030 if v:false
1031 let g:Xpath ..= 'b'
1032 endif
1033 invalid_command
1034 endfunc
1035
1036 let g:Xpath = ''
1037 breakadd func 4 F
1038 try
1039 let caught_intr = 0
1040 debuggreedy
1041 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001042 catch /^Vim:Interrupt$/
1043 call assert_match('\.F, line 4', v:throwpoint)
1044 let caught_intr = 1
1045 endtry
1046 0debuggreedy
1047 call assert_equal(1, caught_intr)
1048 call assert_equal('a', g:Xpath)
1049 breakdel *
1050 delfunc F
1051endfunc
1052
1053" Test for setting a breakpoint on a :else where the :if condition is false
1054" and then quit the script. This should generate an interrupt.
1055func Test_breakpt_else_intr()
1056 func F()
1057 let g:Xpath ..= 'a'
1058 if v:false
1059 let g:Xpath ..= 'b'
1060 else
1061 invalid_command
1062 endif
1063 invalid_command
1064 endfunc
1065
1066 let g:Xpath = ''
1067 breakadd func 4 F
1068 try
1069 let caught_intr = 0
1070 debuggreedy
1071 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001072 catch /^Vim:Interrupt$/
1073 call assert_match('\.F, line 4', v:throwpoint)
1074 let caught_intr = 1
1075 endtry
1076 0debuggreedy
1077 call assert_equal(1, caught_intr)
1078 call assert_equal('a', g:Xpath)
1079 breakdel *
1080 delfunc F
1081endfunc
1082
1083" Test for setting a breakpoint on a :endwhile where the :while condition is
1084" false and then quit the script. This should generate an interrupt.
1085func Test_breakpt_endwhile_intr()
1086 func F()
1087 let g:Xpath ..= 'a'
1088 while v:false
1089 let g:Xpath ..= 'b'
1090 endwhile
1091 invalid_command
1092 endfunc
1093
1094 let g:Xpath = ''
1095 breakadd func 4 F
1096 try
1097 let caught_intr = 0
1098 debuggreedy
1099 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001100 catch /^Vim:Interrupt$/
1101 call assert_match('\.F, line 4', v:throwpoint)
1102 let caught_intr = 1
1103 endtry
1104 0debuggreedy
1105 call assert_equal(1, caught_intr)
1106 call assert_equal('a', g:Xpath)
1107 breakdel *
1108 delfunc F
1109endfunc
1110
Bram Moolenaar16c62322020-08-13 19:20:04 +02001111" Test for setting a breakpoint on a script local function
1112func Test_breakpt_scriptlocal_func()
1113 let g:Xpath = ''
1114 func s:G()
1115 let g:Xpath ..= 'a'
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001116 endfunc
1117
Bram Moolenaar16c62322020-08-13 19:20:04 +02001118 let funcname = expand("<SID>") .. "G"
1119 exe "breakadd func 1 " .. funcname
1120 debuggreedy
1121 redir => output
1122 call feedkeys(":call " .. funcname .. "()\<CR>c\<CR>", "xt")
1123 redir END
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001124 0debuggreedy
Bram Moolenaar16c62322020-08-13 19:20:04 +02001125 call assert_match('Breakpoint in "' .. funcname .. '" line 1', output)
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001126 call assert_equal('a', g:Xpath)
1127 breakdel *
Bram Moolenaar16c62322020-08-13 19:20:04 +02001128 exe "delfunc " .. funcname
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001129endfunc
1130
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001131" vim: shiftwidth=2 sts=2 expandtab