blob: 2fd68551f9e345a47c07a085988c3d968847ed91 [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
Yee Cheng Chin3acfbb42025-01-25 15:14:06 +010011 " in cwd. Need to subtract by 1 since Vim will still wrap the message if it
12 " just fits.
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +020013 let script_len = len( getcwd() .. '/Xtest1.vim' )
14 let longest_line = len( 'Breakpoint in "" line 1' )
Yee Cheng Chin3acfbb42025-01-25 15:14:06 +010015 if script_len > ( 75 - longest_line - 1 )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +020016 throw 'Skipped: Your CWD has too many characters'
17 endif
18endfunc
19command! -nargs=0 -bar CheckCWD call CheckCWD()
20
Bram Moolenaar18dc3552020-11-22 14:24:00 +010021" "options" argument can contain:
22" 'msec' - time to wait for a match
23" 'match' - "pattern" to use "lines" as pattern instead of text
Bram Moolenaarbf630112023-05-19 21:41:02 +010024def s:CheckDbgOutput(buf: number, lines: list<string>, options = {})
25 # Verify the expected output
26 var lnum = 20 - len(lines)
27 var msec = get(options, 'msec', 1000)
28 for l in lines
29 if get(options, 'match', 'equal') ==# 'pattern'
30 g:WaitForAssert(() => assert_match(l, term_getline(buf, lnum)), msec)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020031 else
Bram Moolenaarbf630112023-05-19 21:41:02 +010032 g:WaitForAssert(() => assert_equal(l, term_getline(buf, lnum)), msec)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020033 endif
Bram Moolenaarbf630112023-05-19 21:41:02 +010034 lnum += 1
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020035 endfor
Bram Moolenaarbf630112023-05-19 21:41:02 +010036enddef
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020037
Bram Moolenaar113bf062019-04-17 16:54:05 +020038" Run a Vim debugger command
39" If the expected output argument is supplied, then check for it.
Bram Moolenaarbf630112023-05-19 21:41:02 +010040def s:RunDbgCmd(buf: number, cmd: string, ...extra: list<any>)
41 term_sendkeys(buf, cmd .. "\r")
42 g:TermWait(buf)
Bram Moolenaar113bf062019-04-17 16:54:05 +020043
Bram Moolenaarbf630112023-05-19 21:41:02 +010044 if len(extra) > 0
45 var options = {match: 'equal'}
46 if len(extra) > 1
47 extend(options, extra[1])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020048 endif
Bram Moolenaarbf630112023-05-19 21:41:02 +010049 s:CheckDbgOutput(buf, extra[0], options)
Bram Moolenaar113bf062019-04-17 16:54:05 +020050 endif
Bram Moolenaarbf630112023-05-19 21:41:02 +010051enddef
Bram Moolenaar113bf062019-04-17 16:54:05 +020052
53" Debugger tests
Bram Moolenaarbf630112023-05-19 21:41:02 +010054def Test_Debugger()
55 # Create a Vim script with some functions
56 var lines =<< trim END
Bram Moolenaare7eb9272019-06-24 00:58:07 +020057 func Foo()
58 let var1 = 1
59 let var2 = Bar(var1) + 9
60 return var2
61 endfunc
62 func Bar(var)
63 let var1 = 2 + a:var
64 let var2 = Bazz(var1) + 4
65 return var2
66 endfunc
67 func Bazz(var)
68 try
69 let var1 = 3 + a:var
70 let var3 = "another var"
71 let var3 = "value2"
72 catch
73 let var4 = "exception"
74 endtry
75 return var1
76 endfunc
Bram Moolenaare406ff82022-03-10 20:47:43 +000077 def Vim9Func()
78 for cmd in ['confirm', 'xxxxxxx']
79 for _ in [1, 2]
80 echo cmd
81 endfor
82 endfor
83 enddef
Bram Moolenaare7eb9272019-06-24 00:58:07 +020084 END
Bram Moolenaarbf630112023-05-19 21:41:02 +010085 writefile(lines, 'XtestDebug.vim', 'D')
Bram Moolenaar113bf062019-04-17 16:54:05 +020086
Bram Moolenaarbf630112023-05-19 21:41:02 +010087 # Start Vim in a terminal
88 var buf = g:RunVimInTerminal('-S XtestDebug.vim', {})
Bram Moolenaar113bf062019-04-17 16:54:05 +020089
Bram Moolenaarbf630112023-05-19 21:41:02 +010090 # Start the Vim debugger
91 s:RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()'])
Bram Moolenaar113bf062019-04-17 16:54:05 +020092
Bram Moolenaarbf630112023-05-19 21:41:02 +010093 # Create a few stack frames by stepping through functions
94 s:RunDbgCmd(buf, 'step', ['line 1: let var1 = 1'])
95 s:RunDbgCmd(buf, 'step', ['line 2: let var2 = Bar(var1) + 9'])
96 s:RunDbgCmd(buf, 'step', ['line 1: let var1 = 2 + a:var'])
97 s:RunDbgCmd(buf, 'step', ['line 2: let var2 = Bazz(var1) + 4'])
98 s:RunDbgCmd(buf, 'step', ['line 1: try'])
99 s:RunDbgCmd(buf, 'step', ['line 2: let var1 = 3 + a:var'])
100 s:RunDbgCmd(buf, 'step', ['line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200101
Bram Moolenaarbf630112023-05-19 21:41:02 +0100102 # check backtrace
103 s:RunDbgCmd(buf, 'backtrace', [
104 ' 2 function Foo[2]',
105 ' 1 Bar[2]',
106 '->0 Bazz',
107 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200108
Bram Moolenaarbf630112023-05-19 21:41:02 +0100109 # Check variables in different stack frames
110 s:RunDbgCmd(buf, 'echo var1', ['6'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200111
Bram Moolenaarbf630112023-05-19 21:41:02 +0100112 s:RunDbgCmd(buf, 'up')
113 s:RunDbgCmd(buf, 'back', [
114 ' 2 function Foo[2]',
115 '->1 Bar[2]',
116 ' 0 Bazz',
117 'line 3: let var3 = "another var"'])
118 s:RunDbgCmd(buf, 'echo var1', ['3'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200119
Bram Moolenaarbf630112023-05-19 21:41:02 +0100120 s:RunDbgCmd(buf, 'u')
121 s:RunDbgCmd(buf, 'bt', [
122 '->2 function Foo[2]',
123 ' 1 Bar[2]',
124 ' 0 Bazz',
125 'line 3: let var3 = "another var"'])
126 s:RunDbgCmd(buf, 'echo var1', ['1'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200127
Bram Moolenaarbf630112023-05-19 21:41:02 +0100128 # Undefined variables
129 s:RunDbgCmd(buf, 'step')
130 s:RunDbgCmd(buf, 'frame 2')
131 s:RunDbgCmd(buf, 'echo var3', [
132 'Error detected while processing function Foo[2]..Bar[2]..Bazz:',
133 'line 4:',
134 'E121: Undefined variable: var3'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200135
Bram Moolenaarbf630112023-05-19 21:41:02 +0100136 # var3 is defined in this level with some other value
137 s:RunDbgCmd(buf, 'fr 0')
138 s:RunDbgCmd(buf, 'echo var3', ['another var'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200139
Bram Moolenaarbf630112023-05-19 21:41:02 +0100140 s:RunDbgCmd(buf, 'step')
141 s:RunDbgCmd(buf, '')
142 s:RunDbgCmd(buf, '')
143 s:RunDbgCmd(buf, '')
144 s:RunDbgCmd(buf, '')
145 s:RunDbgCmd(buf, 'step', [
146 'function Foo[2]..Bar',
147 'line 3: End of function'])
148 s:RunDbgCmd(buf, 'up')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200149
Bram Moolenaarbf630112023-05-19 21:41:02 +0100150 # Undefined var2
151 s:RunDbgCmd(buf, 'echo var2', [
152 'Error detected while processing function Foo[2]..Bar:',
153 'line 3:',
154 'E121: Undefined variable: var2'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200155
Bram Moolenaarbf630112023-05-19 21:41:02 +0100156 # Var2 is defined with 10
157 s:RunDbgCmd(buf, 'down')
158 s:RunDbgCmd(buf, 'echo var2', ['10'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200159
Bram Moolenaarbf630112023-05-19 21:41:02 +0100160 # Backtrace movements
161 s:RunDbgCmd(buf, 'b', [
162 ' 1 function Foo[2]',
163 '->0 Bar',
164 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200165
Bram Moolenaarbf630112023-05-19 21:41:02 +0100166 # next command cannot go down, we are on bottom
167 s:RunDbgCmd(buf, 'down', ['frame is zero'])
168 s:RunDbgCmd(buf, 'up')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200169
Bram Moolenaarbf630112023-05-19 21:41:02 +0100170 # next command cannot go up, we are on top
171 s:RunDbgCmd(buf, 'up', ['frame at highest level: 1'])
172 s:RunDbgCmd(buf, 'where', [
173 '->1 function Foo[2]',
174 ' 0 Bar',
175 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200176
Bram Moolenaarbf630112023-05-19 21:41:02 +0100177 # fil is not frame or finish, it is file
178 s:RunDbgCmd(buf, 'fil', ['"[No Name]" --No lines in buffer--'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200179
Bram Moolenaarbf630112023-05-19 21:41:02 +0100180 # relative backtrace movement
181 s:RunDbgCmd(buf, 'fr -1')
182 s:RunDbgCmd(buf, 'frame', [
183 ' 1 function Foo[2]',
184 '->0 Bar',
185 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200186
Bram Moolenaarbf630112023-05-19 21:41:02 +0100187 s:RunDbgCmd(buf, 'fr +1')
188 s:RunDbgCmd(buf, 'fram', [
189 '->1 function Foo[2]',
190 ' 0 Bar',
191 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200192
Bram Moolenaarbf630112023-05-19 21:41:02 +0100193 # go beyond limits does not crash
194 s:RunDbgCmd(buf, 'fr 100', ['frame at highest level: 1'])
195 s:RunDbgCmd(buf, 'fra', [
196 '->1 function Foo[2]',
197 ' 0 Bar',
198 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200199
Bram Moolenaarbf630112023-05-19 21:41:02 +0100200 s:RunDbgCmd(buf, 'frame -40', ['frame is zero'])
201 s:RunDbgCmd(buf, 'fram', [
202 ' 1 function Foo[2]',
203 '->0 Bar',
204 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200205
Bram Moolenaarbf630112023-05-19 21:41:02 +0100206 # final result 19
207 s:RunDbgCmd(buf, 'cont', ['19'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200208
Bram Moolenaarbf630112023-05-19 21:41:02 +0100209 # breakpoints tests
Bram Moolenaar113bf062019-04-17 16:54:05 +0200210
Bram Moolenaarbf630112023-05-19 21:41:02 +0100211 # Start a debug session, so that reading the last line from the terminal
212 # works properly.
213 s:RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200214
Bram Moolenaarbf630112023-05-19 21:41:02 +0100215 # No breakpoints
216 s:RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200217
Bram Moolenaarbf630112023-05-19 21:41:02 +0100218 # Place some breakpoints
219 s:RunDbgCmd(buf, 'breaka func Bar')
220 s:RunDbgCmd(buf, 'breaklis', [' 1 func Bar line 1'])
221 s:RunDbgCmd(buf, 'breakadd func 3 Bazz')
222 s:RunDbgCmd(buf, 'breaklist', [' 1 func Bar line 1',
223 ' 2 func Bazz line 3'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200224
Bram Moolenaarbf630112023-05-19 21:41:02 +0100225 # Check whether the breakpoints are hit
226 s:RunDbgCmd(buf, 'cont', [
227 'Breakpoint in "Bar" line 1',
228 'function Foo[2]..Bar',
229 'line 1: let var1 = 2 + a:var'])
230 s:RunDbgCmd(buf, 'cont', [
231 'Breakpoint in "Bazz" line 3',
232 'function Foo[2]..Bar[2]..Bazz',
233 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200234
Bram Moolenaarbf630112023-05-19 21:41:02 +0100235 # Delete the breakpoints
236 s:RunDbgCmd(buf, 'breakd 1')
237 s:RunDbgCmd(buf, 'breakli', [' 2 func Bazz line 3'])
238 s:RunDbgCmd(buf, 'breakdel func 3 Bazz')
239 s:RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200240
Bram Moolenaarbf630112023-05-19 21:41:02 +0100241 s:RunDbgCmd(buf, 'cont')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200242
Bram Moolenaarbf630112023-05-19 21:41:02 +0100243 # Make sure the breakpoints are removed
244 s:RunDbgCmd(buf, ':echo Foo()', ['19'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200245
Bram Moolenaarbf630112023-05-19 21:41:02 +0100246 # Delete a non-existing breakpoint
247 s:RunDbgCmd(buf, ':breakdel 2', ['E161: Breakpoint not found: 2'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200248
Bram Moolenaarbf630112023-05-19 21:41:02 +0100249 # Expression breakpoint
250 s:RunDbgCmd(buf, ':breakadd func 2 Bazz')
251 s:RunDbgCmd(buf, ':echo Bazz(1)', [
252 'Entering Debug mode. Type "cont" to continue.',
253 'function Bazz',
254 'line 2: let var1 = 3 + a:var'])
255 s:RunDbgCmd(buf, 'step')
256 s:RunDbgCmd(buf, 'step')
257 s:RunDbgCmd(buf, 'breaka expr var3')
258 s:RunDbgCmd(buf, 'breakl', [' 3 func Bazz line 2',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200259 \ ' 4 expr var3'])
Bram Moolenaarbf630112023-05-19 21:41:02 +0100260 s:RunDbgCmd(buf, 'cont', ['Breakpoint in "Bazz" line 5',
261 'Oldval = "''another var''"',
262 'Newval = "''value2''"',
263 'function Bazz',
264 'line 5: catch'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200265
Bram Moolenaarbf630112023-05-19 21:41:02 +0100266 s:RunDbgCmd(buf, 'breakdel *')
267 s:RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200268
Bram Moolenaarbf630112023-05-19 21:41:02 +0100269 # Check for error cases
270 s:RunDbgCmd(buf, 'breakadd abcd', [
271 'Error detected while processing function Bazz:',
272 'line 5:',
273 'E475: Invalid argument: abcd'])
274 s:RunDbgCmd(buf, 'breakadd func', ['E475: Invalid argument: func'])
275 s:RunDbgCmd(buf, 'breakadd func 2', ['E475: Invalid argument: func 2'])
276 s:RunDbgCmd(buf, 'breaka func a()', ['E475: Invalid argument: func a()'])
277 s:RunDbgCmd(buf, 'breakd abcd', ['E475: Invalid argument: abcd'])
278 s:RunDbgCmd(buf, 'breakd func', ['E475: Invalid argument: func'])
279 s:RunDbgCmd(buf, 'breakd func a()', ['E475: Invalid argument: func a()'])
280 s:RunDbgCmd(buf, 'breakd func a', ['E161: Breakpoint not found: func a'])
281 s:RunDbgCmd(buf, 'breakd expr', ['E475: Invalid argument: expr'])
282 s:RunDbgCmd(buf, 'breakd expr x', ['E161: Breakpoint not found: expr x'])
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200283
Bram Moolenaarbf630112023-05-19 21:41:02 +0100284 # finish the current function
285 s:RunDbgCmd(buf, 'finish', [
286 'function Bazz',
287 'line 8: End of function'])
288 s:RunDbgCmd(buf, 'cont')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200289
Bram Moolenaarbf630112023-05-19 21:41:02 +0100290 # Test for :next
291 s:RunDbgCmd(buf, ':debug echo Bar(1)')
292 s:RunDbgCmd(buf, 'step')
293 s:RunDbgCmd(buf, 'next')
294 s:RunDbgCmd(buf, '', [
295 'function Bar',
296 'line 3: return var2'])
297 s:RunDbgCmd(buf, 'c')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200298
Bram Moolenaarbf630112023-05-19 21:41:02 +0100299 # Test for :interrupt
300 s:RunDbgCmd(buf, ':debug echo Bazz(1)')
301 s:RunDbgCmd(buf, 'step')
302 s:RunDbgCmd(buf, 'step')
303 s:RunDbgCmd(buf, 'interrupt', [
304 'Exception thrown: Vim:Interrupt',
305 'function Bazz',
306 'line 5: catch'])
307 s:RunDbgCmd(buf, 'c')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200308
Bram Moolenaarbf630112023-05-19 21:41:02 +0100309 # Test showing local variable in :def function
310 s:RunDbgCmd(buf, ':breakadd func 2 Vim9Func')
311 s:RunDbgCmd(buf, ':call Vim9Func()', ['line 2: for _ in [1, 2]'])
312 s:RunDbgCmd(buf, 'next', ['line 2: for _ in [1, 2]'])
313 s:RunDbgCmd(buf, 'echo cmd', ['confirm'])
314 s:RunDbgCmd(buf, 'breakdel *')
315 s:RunDbgCmd(buf, 'cont')
Bram Moolenaare406ff82022-03-10 20:47:43 +0000316
Bram Moolenaarbf630112023-05-19 21:41:02 +0100317 # Test for :quit
318 s:RunDbgCmd(buf, ':debug echo Foo()')
319 s:RunDbgCmd(buf, 'breakdel *')
320 s:RunDbgCmd(buf, 'breakadd func 3 Foo')
321 s:RunDbgCmd(buf, 'breakadd func 3 Bazz')
322 s:RunDbgCmd(buf, 'cont', [
323 'Breakpoint in "Bazz" line 3',
324 'function Foo[2]..Bar[2]..Bazz',
325 'line 3: let var3 = "another var"'])
326 s:RunDbgCmd(buf, 'quit', [
327 'Breakpoint in "Foo" line 3',
328 'function Foo',
329 'line 3: return var2'])
330 s:RunDbgCmd(buf, 'breakdel *')
331 s:RunDbgCmd(buf, 'quit')
332 s:RunDbgCmd(buf, 'enew! | only!')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200333
Bram Moolenaarbf630112023-05-19 21:41:02 +0100334 g:StopVimInTerminal(buf)
335enddef
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200336
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200337func Test_Debugger_breakadd()
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200338 " Tests for :breakadd file and :breakadd here
339 " Breakpoints should be set before sourcing the file
340
Bram Moolenaare7eb9272019-06-24 00:58:07 +0200341 let lines =<< trim END
342 let var1 = 10
343 let var2 = 20
344 let var3 = 30
345 let var4 = 40
346 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100347 call writefile(lines, 'XdebugBreakadd.vim', 'D')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200348
349 " Start Vim in a terminal
Bram Moolenaar59173412022-09-20 22:01:33 +0100350 let buf = RunVimInTerminal('XdebugBreakadd.vim', {})
Bram Moolenaarbf630112023-05-19 21:41:02 +0100351 call s:RunDbgCmd(buf, ':breakadd file 2 XdebugBreakadd.vim')
352 call s:RunDbgCmd(buf, ':4 | breakadd here')
353 call s:RunDbgCmd(buf, ':source XdebugBreakadd.vim', ['line 2: let var2 = 20'])
354 call s:RunDbgCmd(buf, 'cont', ['line 4: let var4 = 40'])
355 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200356
357 call StopVimInTerminal(buf)
358
Bram Moolenaar16c62322020-08-13 19:20:04 +0200359 %bw!
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200360
Bram Moolenaar16c62322020-08-13 19:20:04 +0200361 call assert_fails('breakadd here', 'E32:')
Bram Moolenaar531be472020-09-23 22:38:05 +0200362 call assert_fails('breakadd file Xtest.vim /\)/', 'E55:')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200363endfunc
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200364
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100365" Test for expression breakpoint set using ":breakadd expr <expr>"
366func Test_Debugger_breakadd_expr()
James McCoydb7a88d2022-08-03 16:13:27 +0100367 CheckCWD
368
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100369 let lines =<< trim END
370 let g:Xtest_var += 1
371 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100372 call writefile(lines, 'XdebugBreakExpr.vim', 'D')
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100373
374 " Start Vim in a terminal
Bram Moolenaar59173412022-09-20 22:01:33 +0100375 let buf = RunVimInTerminal('XdebugBreakExpr.vim', {})
Bram Moolenaarbf630112023-05-19 21:41:02 +0100376 call s:RunDbgCmd(buf, ':let g:Xtest_var = 10')
377 call s:RunDbgCmd(buf, ':breakadd expr g:Xtest_var')
378 call s:RunDbgCmd(buf, ':source %')
Bram Moolenaar59173412022-09-20 22:01:33 +0100379 let expected =<< trim eval END
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100380 Oldval = "10"
381 Newval = "11"
Bram Moolenaar59173412022-09-20 22:01:33 +0100382 {fnamemodify('XdebugBreakExpr.vim', ':p')}
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100383 line 1: let g:Xtest_var += 1
384 END
Bram Moolenaarbf630112023-05-19 21:41:02 +0100385 call s:RunDbgCmd(buf, ':source %', expected)
386 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar59173412022-09-20 22:01:33 +0100387 let expected =<< trim eval END
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100388 Oldval = "11"
389 Newval = "12"
Bram Moolenaar59173412022-09-20 22:01:33 +0100390 {fnamemodify('XdebugBreakExpr.vim', ':p')}
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100391 line 1: let g:Xtest_var += 1
392 END
Bram Moolenaarbf630112023-05-19 21:41:02 +0100393 call s:RunDbgCmd(buf, ':source %', expected)
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100394
395 call StopVimInTerminal(buf)
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100396endfunc
397
398def Test_Debugger_breakadd_vim9_expr()
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200399 var lines =<< trim END
400 vim9script
401 func g:EarlyFunc()
402 endfunc
403 breakadd expr DoesNotExist()
404 func g:LaterFunc()
405 endfunc
406 breakdel *
407 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100408 writefile(lines, 'XdebugBreak9expr.vim', 'D')
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200409
410 # Start Vim in a terminal
Bram Moolenaar59173412022-09-20 22:01:33 +0100411 var buf = g:RunVimInTerminal('-S XdebugBreak9expr.vim', {wait_for_ruler: 0})
Bram Moolenaare366ed42022-06-19 20:13:56 +0100412 call g:TermWait(buf, g:RunningWithValgrind() ? 1000 : 50)
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200413
414 # Despite the failure the functions are defined
Bram Moolenaarbf630112023-05-19 21:41:02 +0100415 s:RunDbgCmd(buf, ':function g:EarlyFunc',
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200416 ['function EarlyFunc()', 'endfunction'], {match: 'pattern'})
Bram Moolenaarbf630112023-05-19 21:41:02 +0100417 s:RunDbgCmd(buf, ':function g:LaterFunc',
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200418 ['function LaterFunc()', 'endfunction'], {match: 'pattern'})
419
Bram Moolenaar62aec932022-01-29 21:45:34 +0000420 call g:StopVimInTerminal(buf)
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200421enddef
422
Bram Moolenaar112bed02021-11-23 22:16:34 +0000423def Test_Debugger_break_at_return()
424 var lines =<< trim END
425 vim9script
426 def g:GetNum(): number
427 return 1
428 + 2
429 + 3
430 enddef
431 breakadd func GetNum
432 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100433 writefile(lines, 'XdebugBreakRet.vim', 'D')
Bram Moolenaar112bed02021-11-23 22:16:34 +0000434
435 # Start Vim in a terminal
Bram Moolenaar59173412022-09-20 22:01:33 +0100436 var buf = g:RunVimInTerminal('-S XdebugBreakRet.vim', {wait_for_ruler: 0})
Bram Moolenaare366ed42022-06-19 20:13:56 +0100437 call g:TermWait(buf, g:RunningWithValgrind() ? 1000 : 50)
Bram Moolenaar112bed02021-11-23 22:16:34 +0000438
Bram Moolenaarbf630112023-05-19 21:41:02 +0100439 s:RunDbgCmd(buf, ':call GetNum()',
Bram Moolenaar112bed02021-11-23 22:16:34 +0000440 ['line 1: return 1 + 2 + 3'], {match: 'pattern'})
441
Bram Moolenaar62aec932022-01-29 21:45:34 +0000442 call g:StopVimInTerminal(buf)
Bram Moolenaar112bed02021-11-23 22:16:34 +0000443enddef
444
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200445func Test_Backtrace_Through_Source()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200446 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200447 let file1 =<< trim END
448 func SourceAnotherFile()
449 source Xtest2.vim
450 endfunc
451
452 func CallAFunction()
453 call SourceAnotherFile()
454 call File2Function()
455 endfunc
456
457 func GlobalFunction()
458 call CallAFunction()
459 endfunc
460 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100461 call writefile(file1, 'Xtest1.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200462
463 let file2 =<< trim END
464 func DoAThing()
465 echo "DoAThing"
466 endfunc
467
468 func File2Function()
469 call DoAThing()
470 endfunc
471
472 call File2Function()
473 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100474 call writefile(file2, 'Xtest2.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200475
476 let buf = RunVimInTerminal('-S Xtest1.vim', {})
477
Bram Moolenaarbf630112023-05-19 21:41:02 +0100478 call s:RunDbgCmd(buf,
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200479 \ ':debug call GlobalFunction()',
480 \ ['cmd: call GlobalFunction()'])
Bram Moolenaarbf630112023-05-19 21:41:02 +0100481 call s:RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200482
Bram Moolenaarbf630112023-05-19 21:41:02 +0100483 call s:RunDbgCmd(buf, 'backtrace', ['>backtrace',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200484 \ '->0 function GlobalFunction',
485 \ 'line 1: call CallAFunction()'])
486
Bram Moolenaarbf630112023-05-19 21:41:02 +0100487 call s:RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
488 call s:RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200489
Bram Moolenaarbf630112023-05-19 21:41:02 +0100490 call s:RunDbgCmd(buf, 'backtrace', ['>backtrace',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200491 \ ' 2 function GlobalFunction[1]',
492 \ ' 1 CallAFunction[1]',
493 \ '->0 SourceAnotherFile',
494 \ 'line 1: source Xtest2.vim'])
495
496 " Step into the 'source' command. Note that we print the full trace all the
497 " way though the source command.
Bram Moolenaarbf630112023-05-19 21:41:02 +0100498 call s:RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
499 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200500 \ '>backtrace',
501 \ ' 3 function GlobalFunction[1]',
502 \ ' 2 CallAFunction[1]',
503 \ ' 1 SourceAnotherFile[1]',
504 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
505 \ 'line 1: func DoAThing()'])
506
Bram Moolenaarbf630112023-05-19 21:41:02 +0100507 call s:RunDbgCmd( buf, 'up' )
508 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200509 \ '>backtrace',
510 \ ' 3 function GlobalFunction[1]',
511 \ ' 2 CallAFunction[1]',
512 \ '->1 SourceAnotherFile[1]',
513 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
514 \ 'line 1: func DoAThing()' ] )
515
Bram Moolenaarbf630112023-05-19 21:41:02 +0100516 call s:RunDbgCmd( buf, 'up' )
517 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200518 \ '>backtrace',
519 \ ' 3 function GlobalFunction[1]',
520 \ '->2 CallAFunction[1]',
521 \ ' 1 SourceAnotherFile[1]',
522 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
523 \ 'line 1: func DoAThing()' ] )
524
Bram Moolenaarbf630112023-05-19 21:41:02 +0100525 call s:RunDbgCmd( buf, 'up' )
526 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200527 \ '>backtrace',
528 \ '->3 function GlobalFunction[1]',
529 \ ' 2 CallAFunction[1]',
530 \ ' 1 SourceAnotherFile[1]',
531 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
532 \ 'line 1: func DoAThing()' ] )
533
Bram Moolenaarbf630112023-05-19 21:41:02 +0100534 call s:RunDbgCmd( buf, 'up', [ 'frame at highest level: 3' ] )
535 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200536 \ '>backtrace',
537 \ '->3 function GlobalFunction[1]',
538 \ ' 2 CallAFunction[1]',
539 \ ' 1 SourceAnotherFile[1]',
540 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
541 \ 'line 1: func DoAThing()' ] )
542
Bram Moolenaarbf630112023-05-19 21:41:02 +0100543 call s:RunDbgCmd( buf, 'down' )
544 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200545 \ '>backtrace',
546 \ ' 3 function GlobalFunction[1]',
547 \ '->2 CallAFunction[1]',
548 \ ' 1 SourceAnotherFile[1]',
549 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
550 \ 'line 1: func DoAThing()' ] )
551
Bram Moolenaarbf630112023-05-19 21:41:02 +0100552 call s:RunDbgCmd( buf, 'down' )
553 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200554 \ '>backtrace',
555 \ ' 3 function GlobalFunction[1]',
556 \ ' 2 CallAFunction[1]',
557 \ '->1 SourceAnotherFile[1]',
558 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
559 \ 'line 1: func DoAThing()' ] )
560
Bram Moolenaarbf630112023-05-19 21:41:02 +0100561 call s:RunDbgCmd( buf, 'down' )
562 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200563 \ '>backtrace',
564 \ ' 3 function GlobalFunction[1]',
565 \ ' 2 CallAFunction[1]',
566 \ ' 1 SourceAnotherFile[1]',
567 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
568 \ 'line 1: func DoAThing()' ] )
569
Bram Moolenaarbf630112023-05-19 21:41:02 +0100570 call s:RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200571
Dominique Pelle923dce22021-11-21 11:36:04 +0000572 " step until we have another meaningful trace
Bram Moolenaarbf630112023-05-19 21:41:02 +0100573 call s:RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
574 call s:RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
575 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200576 \ '>backtrace',
577 \ ' 3 function GlobalFunction[1]',
578 \ ' 2 CallAFunction[1]',
579 \ ' 1 SourceAnotherFile[1]',
580 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
581 \ 'line 9: call File2Function()'])
582
Bram Moolenaarbf630112023-05-19 21:41:02 +0100583 call s:RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
584 call s:RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
585 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200586 \ '>backtrace',
587 \ ' 5 function GlobalFunction[1]',
588 \ ' 4 CallAFunction[1]',
589 \ ' 3 SourceAnotherFile[1]',
590 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
591 \ ' 1 function File2Function[1]',
592 \ '->0 DoAThing',
593 \ 'line 1: echo "DoAThing"'])
594
595 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
Bram Moolenaarbf630112023-05-19 21:41:02 +0100596 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
597 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
598 call s:RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
599 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
600 call s:RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
601 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200602 \ '>backtrace',
603 \ ' 1 function GlobalFunction[1]',
604 \ '->0 CallAFunction',
605 \ 'line 2: call File2Function()'])
606
Bram Moolenaarbf630112023-05-19 21:41:02 +0100607 call s:RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
608 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200609 \ '>backtrace',
610 \ ' 2 function GlobalFunction[1]',
611 \ ' 1 CallAFunction[2]',
612 \ '->0 File2Function',
613 \ 'line 1: call DoAThing()'])
614
615 call StopVimInTerminal(buf)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200616endfunc
617
618func Test_Backtrace_Autocmd()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200619 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200620 let file1 =<< trim END
621 func SourceAnotherFile()
622 source Xtest2.vim
623 endfunc
624
625 func CallAFunction()
626 call SourceAnotherFile()
627 call File2Function()
628 endfunc
629
630 func GlobalFunction()
631 call CallAFunction()
632 endfunc
633
634 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
635 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100636 call writefile(file1, 'Xtest1.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200637
638 let file2 =<< trim END
639 func DoAThing()
640 echo "DoAThing"
641 endfunc
642
643 func File2Function()
644 call DoAThing()
645 endfunc
646
647 call File2Function()
648 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100649 call writefile(file2, 'Xtest2.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200650
651 let buf = RunVimInTerminal('-S Xtest1.vim', {})
652
Bram Moolenaarbf630112023-05-19 21:41:02 +0100653 call s:RunDbgCmd(buf,
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200654 \ ':debug doautocmd User TestGlobalFunction',
655 \ ['cmd: doautocmd User TestGlobalFunction'])
Bram Moolenaarbf630112023-05-19 21:41:02 +0100656 call s:RunDbgCmd(buf, 'step', ['cmd: call GlobalFunction() | echo "Done"'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200657
Dominique Pelle923dce22021-11-21 11:36:04 +0000658 " At this point the only thing in the stack is the autocommand
Bram Moolenaarbf630112023-05-19 21:41:02 +0100659 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200660 \ '>backtrace',
661 \ '->0 User Autocommands for "TestGlobalFunction"',
662 \ 'cmd: call GlobalFunction() | echo "Done"'])
663
664 " And now we're back into the call stack
Bram Moolenaarbf630112023-05-19 21:41:02 +0100665 call s:RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
666 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200667 \ '>backtrace',
668 \ ' 1 User Autocommands for "TestGlobalFunction"',
669 \ '->0 function GlobalFunction',
670 \ 'line 1: call CallAFunction()'])
671
Bram Moolenaarbf630112023-05-19 21:41:02 +0100672 call s:RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
673 call s:RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200674
Bram Moolenaarbf630112023-05-19 21:41:02 +0100675 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200676 \ '>backtrace',
677 \ ' 3 User Autocommands for "TestGlobalFunction"',
678 \ ' 2 function GlobalFunction[1]',
679 \ ' 1 CallAFunction[1]',
680 \ '->0 SourceAnotherFile',
681 \ 'line 1: source Xtest2.vim'])
682
683 " Step into the 'source' command. Note that we print the full trace all the
684 " way though the source command.
Bram Moolenaarbf630112023-05-19 21:41:02 +0100685 call s:RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
686 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200687 \ '>backtrace',
688 \ ' 4 User Autocommands for "TestGlobalFunction"',
689 \ ' 3 function GlobalFunction[1]',
690 \ ' 2 CallAFunction[1]',
691 \ ' 1 SourceAnotherFile[1]',
692 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
693 \ 'line 1: func DoAThing()'])
694
Bram Moolenaarbf630112023-05-19 21:41:02 +0100695 call s:RunDbgCmd( buf, 'up' )
696 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200697 \ '>backtrace',
698 \ ' 4 User Autocommands for "TestGlobalFunction"',
699 \ ' 3 function GlobalFunction[1]',
700 \ ' 2 CallAFunction[1]',
701 \ '->1 SourceAnotherFile[1]',
702 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
703 \ 'line 1: func DoAThing()' ] )
704
Bram Moolenaarbf630112023-05-19 21:41:02 +0100705 call s:RunDbgCmd( buf, 'up' )
706 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200707 \ '>backtrace',
708 \ ' 4 User Autocommands for "TestGlobalFunction"',
709 \ ' 3 function GlobalFunction[1]',
710 \ '->2 CallAFunction[1]',
711 \ ' 1 SourceAnotherFile[1]',
712 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
713 \ 'line 1: func DoAThing()' ] )
714
Bram Moolenaarbf630112023-05-19 21:41:02 +0100715 call s:RunDbgCmd( buf, 'up' )
716 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200717 \ '>backtrace',
718 \ ' 4 User Autocommands for "TestGlobalFunction"',
719 \ '->3 function GlobalFunction[1]',
720 \ ' 2 CallAFunction[1]',
721 \ ' 1 SourceAnotherFile[1]',
722 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
723 \ 'line 1: func DoAThing()' ] )
724
Bram Moolenaarbf630112023-05-19 21:41:02 +0100725 call s:RunDbgCmd( buf, 'up' )
726 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200727 \ '>backtrace',
728 \ '->4 User Autocommands for "TestGlobalFunction"',
729 \ ' 3 function GlobalFunction[1]',
730 \ ' 2 CallAFunction[1]',
731 \ ' 1 SourceAnotherFile[1]',
732 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
733 \ 'line 1: func DoAThing()' ] )
734
Bram Moolenaarbf630112023-05-19 21:41:02 +0100735 call s:RunDbgCmd( buf, 'up', [ 'frame at highest level: 4' ] )
736 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200737 \ '>backtrace',
738 \ '->4 User Autocommands for "TestGlobalFunction"',
739 \ ' 3 function GlobalFunction[1]',
740 \ ' 2 CallAFunction[1]',
741 \ ' 1 SourceAnotherFile[1]',
742 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
743 \ 'line 1: func DoAThing()' ] )
744
Bram Moolenaarbf630112023-05-19 21:41:02 +0100745 call s:RunDbgCmd( buf, 'down' )
746 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200747 \ '>backtrace',
748 \ ' 4 User Autocommands for "TestGlobalFunction"',
749 \ '->3 function GlobalFunction[1]',
750 \ ' 2 CallAFunction[1]',
751 \ ' 1 SourceAnotherFile[1]',
752 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
753 \ 'line 1: func DoAThing()' ] )
754
755
Bram Moolenaarbf630112023-05-19 21:41:02 +0100756 call s:RunDbgCmd( buf, 'down' )
757 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200758 \ '>backtrace',
759 \ ' 4 User Autocommands for "TestGlobalFunction"',
760 \ ' 3 function GlobalFunction[1]',
761 \ '->2 CallAFunction[1]',
762 \ ' 1 SourceAnotherFile[1]',
763 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
764 \ 'line 1: func DoAThing()' ] )
765
Bram Moolenaarbf630112023-05-19 21:41:02 +0100766 call s:RunDbgCmd( buf, 'down' )
767 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200768 \ '>backtrace',
769 \ ' 4 User Autocommands for "TestGlobalFunction"',
770 \ ' 3 function GlobalFunction[1]',
771 \ ' 2 CallAFunction[1]',
772 \ '->1 SourceAnotherFile[1]',
773 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
774 \ 'line 1: func DoAThing()' ] )
775
Bram Moolenaarbf630112023-05-19 21:41:02 +0100776 call s:RunDbgCmd( buf, 'down' )
777 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200778 \ '>backtrace',
779 \ ' 4 User Autocommands for "TestGlobalFunction"',
780 \ ' 3 function GlobalFunction[1]',
781 \ ' 2 CallAFunction[1]',
782 \ ' 1 SourceAnotherFile[1]',
783 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
784 \ 'line 1: func DoAThing()' ] )
785
Bram Moolenaarbf630112023-05-19 21:41:02 +0100786 call s:RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200787
Dominique Pelle923dce22021-11-21 11:36:04 +0000788 " step until we have another meaningful trace
Bram Moolenaarbf630112023-05-19 21:41:02 +0100789 call s:RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
790 call s:RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
791 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200792 \ '>backtrace',
793 \ ' 4 User Autocommands for "TestGlobalFunction"',
794 \ ' 3 function GlobalFunction[1]',
795 \ ' 2 CallAFunction[1]',
796 \ ' 1 SourceAnotherFile[1]',
797 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
798 \ 'line 9: call File2Function()'])
799
Bram Moolenaarbf630112023-05-19 21:41:02 +0100800 call s:RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
801 call s:RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
802 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200803 \ '>backtrace',
804 \ ' 6 User Autocommands for "TestGlobalFunction"',
805 \ ' 5 function GlobalFunction[1]',
806 \ ' 4 CallAFunction[1]',
807 \ ' 3 SourceAnotherFile[1]',
808 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
809 \ ' 1 function File2Function[1]',
810 \ '->0 DoAThing',
811 \ 'line 1: echo "DoAThing"'])
812
813 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
Bram Moolenaarbf630112023-05-19 21:41:02 +0100814 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
815 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
816 call s:RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
817 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
818 call s:RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
819 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200820 \ '>backtrace',
821 \ ' 2 User Autocommands for "TestGlobalFunction"',
822 \ ' 1 function GlobalFunction[1]',
823 \ '->0 CallAFunction',
824 \ 'line 2: call File2Function()'])
825
Bram Moolenaarbf630112023-05-19 21:41:02 +0100826 call s:RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
827 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200828 \ '>backtrace',
829 \ ' 3 User Autocommands for "TestGlobalFunction"',
830 \ ' 2 function GlobalFunction[1]',
831 \ ' 1 CallAFunction[2]',
832 \ '->0 File2Function',
833 \ 'line 1: call DoAThing()'])
834
835
836 " Now unwind so that we get back to the original autocommand (and the second
837 " cmd echo "Done")
Bram Moolenaarbf630112023-05-19 21:41:02 +0100838 call s:RunDbgCmd(buf, 'finish', ['line 1: End of function'])
839 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200840 \ '>backtrace',
841 \ ' 3 User Autocommands for "TestGlobalFunction"',
842 \ ' 2 function GlobalFunction[1]',
843 \ ' 1 CallAFunction[2]',
844 \ '->0 File2Function',
845 \ 'line 1: End of function'])
846
Bram Moolenaarbf630112023-05-19 21:41:02 +0100847 call s:RunDbgCmd(buf, 'finish', ['line 2: End of function'])
848 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200849 \ '>backtrace',
850 \ ' 2 User Autocommands for "TestGlobalFunction"',
851 \ ' 1 function GlobalFunction[1]',
852 \ '->0 CallAFunction',
853 \ 'line 2: End of function'])
854
Bram Moolenaarbf630112023-05-19 21:41:02 +0100855 call s:RunDbgCmd(buf, 'finish', ['line 1: End of function'])
856 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200857 \ '>backtrace',
858 \ ' 1 User Autocommands for "TestGlobalFunction"',
859 \ '->0 function GlobalFunction',
860 \ 'line 1: End of function'])
861
Bram Moolenaarbf630112023-05-19 21:41:02 +0100862 call s:RunDbgCmd(buf, 'step', ['cmd: echo "Done"'])
863 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200864 \ '>backtrace',
865 \ '->0 User Autocommands for "TestGlobalFunction"',
866 \ 'cmd: echo "Done"'])
867
868 call StopVimInTerminal(buf)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200869endfunc
870
871func Test_Backtrace_CmdLine()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200872 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200873 let file1 =<< trim END
874 func SourceAnotherFile()
875 source Xtest2.vim
876 endfunc
877
878 func CallAFunction()
879 call SourceAnotherFile()
880 call File2Function()
881 endfunc
882
883 func GlobalFunction()
884 call CallAFunction()
885 endfunc
886
887 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
888 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100889 call writefile(file1, 'Xtest1.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200890
891 let file2 =<< trim END
892 func DoAThing()
893 echo "DoAThing"
894 endfunc
895
896 func File2Function()
897 call DoAThing()
898 endfunc
899
900 call File2Function()
901 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100902 call writefile(file2, 'Xtest2.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200903
904 let buf = RunVimInTerminal(
905 \ '-S Xtest1.vim -c "debug call GlobalFunction()"',
906 \ {'wait_for_ruler': 0})
907
Bram Moolenaar18dc3552020-11-22 14:24:00 +0100908 " Need to wait for the vim-in-terminal to be ready.
909 " With valgrind this can take quite long.
Bram Moolenaarbf630112023-05-19 21:41:02 +0100910 call s:CheckDbgOutput(buf, ['command line',
Bram Moolenaar18dc3552020-11-22 14:24:00 +0100911 \ 'cmd: call GlobalFunction()'], #{msec: 5000})
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200912
Dominique Pelle923dce22021-11-21 11:36:04 +0000913 " At this point the only thing in the stack is the cmdline
Bram Moolenaarbf630112023-05-19 21:41:02 +0100914 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200915 \ '>backtrace',
916 \ '->0 command line',
917 \ 'cmd: call GlobalFunction()'])
918
919 " And now we're back into the call stack
Bram Moolenaarbf630112023-05-19 21:41:02 +0100920 call s:RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
921 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200922 \ '>backtrace',
923 \ ' 1 command line',
924 \ '->0 function GlobalFunction',
925 \ 'line 1: call CallAFunction()'])
926
927 call StopVimInTerminal(buf)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200928endfunc
929
930func Test_Backtrace_DefFunction()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200931 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200932 let file1 =<< trim END
933 vim9script
Bram Moolenaar84c62d52022-01-06 21:31:19 +0000934 import './Xtest2.vim' as imp
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200935
936 def SourceAnotherFile()
937 source Xtest2.vim
938 enddef
939
940 def CallAFunction()
941 SourceAnotherFile()
Bram Moolenaar84c62d52022-01-06 21:31:19 +0000942 imp.File2Function()
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200943 enddef
944
945 def g:GlobalFunction()
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200946 var some = "some var"
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200947 CallAFunction()
948 enddef
949
950 defcompile
951 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100952 call writefile(file1, 'Xtest1.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200953
954 let file2 =<< trim END
955 vim9script
956
957 def DoAThing(): number
Bram Moolenaar1bdae402020-10-03 14:14:56 +0200958 var a = 100 * 2
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200959 a += 3
960 return a
961 enddef
962
963 export def File2Function()
964 DoAThing()
965 enddef
966
967 defcompile
968 File2Function()
969 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100970 call writefile(file2, 'Xtest2.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200971
972 let buf = RunVimInTerminal('-S Xtest1.vim', {})
973
Bram Moolenaarbf630112023-05-19 21:41:02 +0100974 call s:RunDbgCmd(buf,
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200975 \ ':debug call GlobalFunction()',
976 \ ['cmd: call GlobalFunction()'])
977
Bram Moolenaarbf630112023-05-19 21:41:02 +0100978 call s:RunDbgCmd(buf, 'step', ['line 1: var some = "some var"'])
979 call s:RunDbgCmd(buf, 'step', ['line 2: CallAFunction()'])
980 call s:RunDbgCmd(buf, 'echo some', ['some var'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200981
Bram Moolenaarbf630112023-05-19 21:41:02 +0100982 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200983 \ '\V>backtrace',
Bram Moolenaare99d4222021-06-13 14:01:26 +0200984 \ '\V->0 function GlobalFunction',
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200985 \ '\Vline 2: CallAFunction()',
Bram Moolenaare99d4222021-06-13 14:01:26 +0200986 \ ],
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200987 \ #{match: 'pattern'})
988
Bram Moolenaarbf630112023-05-19 21:41:02 +0100989 call s:RunDbgCmd(buf, 'step', ['line 1: SourceAnotherFile()'])
990 call s:RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000991 " Repeated line, because we first are in the compiled function before the
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200992 " EXEC and then in do_cmdline() before the :source command.
Bram Moolenaarbf630112023-05-19 21:41:02 +0100993 call s:RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
994 call s:RunDbgCmd(buf, 'step', ['line 1: vim9script'])
995 call s:RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number'])
996 call s:RunDbgCmd(buf, 'step', ['line 9: export def File2Function()'])
997 call s:RunDbgCmd(buf, 'step', ['line 13: defcompile'])
998 call s:RunDbgCmd(buf, 'step', ['line 14: File2Function()'])
999 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001000 \ '\V>backtrace',
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001001 \ '\V 3 function GlobalFunction[2]',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001002 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
1003 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
1004 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
1005 \ '\Vline 14: File2Function()'],
1006 \ #{match: 'pattern'})
1007
1008 " Don't step into compiled functions...
Bram Moolenaarbf630112023-05-19 21:41:02 +01001009 call s:RunDbgCmd(buf, 'next', ['line 15: End of sourced file'])
1010 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001011 \ '\V>backtrace',
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001012 \ '\V 3 function GlobalFunction[2]',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001013 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
1014 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
1015 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
1016 \ '\Vline 15: End of sourced file'],
1017 \ #{match: 'pattern'})
1018
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001019 call StopVimInTerminal(buf)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001020endfunc
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001021
Bram Moolenaar26a44842021-09-02 18:49:06 +02001022func Test_DefFunction_expr()
1023 CheckCWD
1024 let file3 =<< trim END
1025 vim9script
1026 g:someVar = "foo"
1027 def g:ChangeVar()
1028 g:someVar = "bar"
1029 echo "changed"
1030 enddef
1031 defcompile
1032 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001033 call writefile(file3, 'Xtest3.vim', 'D')
Bram Moolenaar26a44842021-09-02 18:49:06 +02001034 let buf = RunVimInTerminal('-S Xtest3.vim', {})
1035
Bram Moolenaarbf630112023-05-19 21:41:02 +01001036 call s:RunDbgCmd(buf, ':breakadd expr g:someVar')
1037 call s:RunDbgCmd(buf, ':call g:ChangeVar()', ['Oldval = "''foo''"', 'Newval = "''bar''"', 'function ChangeVar', 'line 2: echo "changed"'])
Bram Moolenaar26a44842021-09-02 18:49:06 +02001038
1039 call StopVimInTerminal(buf)
Bram Moolenaar26a44842021-09-02 18:49:06 +02001040endfunc
1041
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001042func Test_debug_def_and_legacy_function()
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001043 CheckCWD
1044 let file =<< trim END
1045 vim9script
1046 def g:SomeFunc()
1047 echo "here"
1048 echo "and"
1049 echo "there"
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001050 breakadd func 2 LocalFunc
1051 LocalFunc()
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001052 enddef
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001053
1054 def LocalFunc()
1055 echo "first"
1056 echo "second"
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001057 breakadd func LegacyFunc
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001058 LegacyFunc()
1059 enddef
1060
1061 func LegacyFunc()
1062 echo "legone"
1063 echo "legtwo"
1064 endfunc
1065
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001066 breakadd func 2 g:SomeFunc
1067 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001068 call writefile(file, 'XtestDebug.vim', 'D')
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001069
1070 let buf = RunVimInTerminal('-S XtestDebug.vim', {})
1071
Bram Moolenaarbf630112023-05-19 21:41:02 +01001072 call s:RunDbgCmd(buf,':call SomeFunc()', ['line 2: echo "and"'])
1073 call s:RunDbgCmd(buf,'next', ['line 3: echo "there"'])
1074 call s:RunDbgCmd(buf,'next', ['line 4: breakadd func 2 LocalFunc'])
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001075
1076 " continue, next breakpoint is in LocalFunc()
Bram Moolenaarbf630112023-05-19 21:41:02 +01001077 call s:RunDbgCmd(buf,'cont', ['line 2: echo "second"'])
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001078
1079 " continue, next breakpoint is in LegacyFunc()
Bram Moolenaarbf630112023-05-19 21:41:02 +01001080 call s:RunDbgCmd(buf,'cont', ['line 1: echo "legone"'])
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001081
Bram Moolenaarbf630112023-05-19 21:41:02 +01001082 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001083
1084 call StopVimInTerminal(buf)
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001085endfunc
1086
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001087func Test_debug_def_function()
1088 CheckCWD
1089 let file =<< trim END
1090 vim9script
1091 def g:Func()
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001092 var n: number
1093 def Closure(): number
1094 return n + 3
1095 enddef
1096 n += Closure()
1097 echo 'result: ' .. n
1098 enddef
1099
1100 def g:FuncWithArgs(text: string, nr: number, ...items: list<number>)
1101 echo text .. nr
1102 for it in items
1103 echo it
1104 endfor
1105 echo "done"
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001106 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001107
1108 def g:FuncWithDict()
1109 var d = {
1110 a: 1,
1111 b: 2,
1112 }
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001113 # comment
1114 def Inner()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001115 eval 1 + 2
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001116 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001117 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001118
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001119 def g:FuncComment()
1120 # comment
1121 echo "first"
1122 .. "one"
1123 # comment
1124 echo "second"
1125 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001126
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001127 def g:FuncForLoop()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001128 eval 1 + 2
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001129 for i in [11, 22, 33]
Bram Moolenaar31e21762021-07-10 20:43:59 +02001130 eval i + 2
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001131 endfor
1132 echo "done"
1133 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001134
1135 def g:FuncWithSplitLine()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001136 eval 1 + 2
1137 | eval 2 + 3
Bram Moolenaar303215d2021-07-07 20:10:43 +02001138 enddef
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001139 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001140 call writefile(file, 'Xtest.vim', 'D')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001141
1142 let buf = RunVimInTerminal('-S Xtest.vim', {})
1143
Bram Moolenaarbf630112023-05-19 21:41:02 +01001144 call s:RunDbgCmd(buf,
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001145 \ ':debug call Func()',
1146 \ ['cmd: call Func()'])
Bram Moolenaarbf630112023-05-19 21:41:02 +01001147 call s:RunDbgCmd(buf, 'next', ['result: 3'])
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001148 call term_sendkeys(buf, "\r")
Bram Moolenaarbf630112023-05-19 21:41:02 +01001149 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001150
Bram Moolenaarbf630112023-05-19 21:41:02 +01001151 call s:RunDbgCmd(buf,
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001152 \ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)',
1153 \ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)'])
Bram Moolenaarbf630112023-05-19 21:41:02 +01001154 call s:RunDbgCmd(buf, 'step', ['line 1: echo text .. nr'])
1155 call s:RunDbgCmd(buf, 'echo text', ['asdf'])
1156 call s:RunDbgCmd(buf, 'echo nr', ['42'])
1157 call s:RunDbgCmd(buf, 'echo items', ['[1, 2, 3]'])
1158 call s:RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items'])
1159 call s:RunDbgCmd(buf, 'step', ['function FuncWithArgs', 'line 2: for it in items'])
1160 call s:RunDbgCmd(buf, 'echo it', ['0'])
1161 call s:RunDbgCmd(buf, 'step', ['line 3: echo it'])
1162 call s:RunDbgCmd(buf, 'echo it', ['1'])
1163 call s:RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor'])
1164 call s:RunDbgCmd(buf, 'step', ['line 2: for it in items'])
1165 call s:RunDbgCmd(buf, 'echo it', ['1'])
1166 call s:RunDbgCmd(buf, 'step', ['line 3: echo it'])
1167 call s:RunDbgCmd(buf, 'step', ['2', 'function FuncWithArgs', 'line 4: endfor'])
1168 call s:RunDbgCmd(buf, 'step', ['line 2: for it in items'])
1169 call s:RunDbgCmd(buf, 'echo it', ['2'])
1170 call s:RunDbgCmd(buf, 'step', ['line 3: echo it'])
1171 call s:RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor'])
1172 call s:RunDbgCmd(buf, 'step', ['line 2: for it in items'])
1173 call s:RunDbgCmd(buf, 'step', ['line 5: echo "done"'])
1174 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001175
Bram Moolenaarbf630112023-05-19 21:41:02 +01001176 call s:RunDbgCmd(buf,
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001177 \ ':debug call FuncWithDict()',
1178 \ ['cmd: call FuncWithDict()'])
Bram Moolenaarbf630112023-05-19 21:41:02 +01001179 call s:RunDbgCmd(buf, 'step', ['line 1: var d = { a: 1, b: 2, }'])
1180 call s:RunDbgCmd(buf, 'step', ['line 6: def Inner()'])
1181 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001182
Bram Moolenaarbf630112023-05-19 21:41:02 +01001183 call s:RunDbgCmd(buf, ':breakadd func 1 FuncComment')
1184 call s:RunDbgCmd(buf, ':call FuncComment()', ['function FuncComment', 'line 2: echo "first" .. "one"'])
1185 call s:RunDbgCmd(buf, ':breakadd func 3 FuncComment')
1186 call s:RunDbgCmd(buf, 'cont', ['function FuncComment', 'line 5: echo "second"'])
1187 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001188
Bram Moolenaarbf630112023-05-19 21:41:02 +01001189 call s:RunDbgCmd(buf, ':breakadd func 2 FuncForLoop')
1190 call s:RunDbgCmd(buf, ':call FuncForLoop()', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
1191 call s:RunDbgCmd(buf, 'step', ['line 2: for i in [11, 22, 33]'])
1192 call s:RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 3: eval i + 2'])
1193 call s:RunDbgCmd(buf, 'echo i', ['11'])
1194 call s:RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 4: endfor'])
1195 call s:RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
1196 call s:RunDbgCmd(buf, 'next', ['line 3: eval i + 2'])
1197 call s:RunDbgCmd(buf, 'echo i', ['22'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001198
Bram Moolenaarbf630112023-05-19 21:41:02 +01001199 call s:RunDbgCmd(buf, 'breakdel *')
1200 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar303215d2021-07-07 20:10:43 +02001201
Bram Moolenaarbf630112023-05-19 21:41:02 +01001202 call s:RunDbgCmd(buf, ':breakadd func FuncWithSplitLine')
1203 call s:RunDbgCmd(buf, ':call FuncWithSplitLine()', ['function FuncWithSplitLine', 'line 1: eval 1 + 2 | eval 2 + 3'])
Bram Moolenaar303215d2021-07-07 20:10:43 +02001204
Bram Moolenaarbf630112023-05-19 21:41:02 +01001205 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001206 call StopVimInTerminal(buf)
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001207endfunc
1208
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001209func Test_debug_def_function_with_lambda()
1210 CheckCWD
1211 let lines =<< trim END
1212 vim9script
1213 def g:Func()
1214 var s = 'a'
1215 ['b']->map((_, v) => s)
1216 echo "done"
1217 enddef
1218 breakadd func 2 g:Func
1219 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001220 call writefile(lines, 'XtestLambda.vim', 'D')
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001221
1222 let buf = RunVimInTerminal('-S XtestLambda.vim', {})
1223
Bram Moolenaarbf630112023-05-19 21:41:02 +01001224 call s:RunDbgCmd(buf,
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001225 \ ':call g:Func()',
1226 \ ['function Func', 'line 2: [''b'']->map((_, v) => s)'])
Bram Moolenaarbf630112023-05-19 21:41:02 +01001227 call s:RunDbgCmd(buf,
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001228 \ 'next',
1229 \ ['function Func', 'line 3: echo "done"'])
1230
Bram Moolenaarbf630112023-05-19 21:41:02 +01001231 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001232 call StopVimInTerminal(buf)
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001233endfunc
1234
Bram Moolenaarbf630112023-05-19 21:41:02 +01001235def Test_debug_backtrace_level()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001236 CheckCWD
Bram Moolenaarbf630112023-05-19 21:41:02 +01001237 var lines =<< trim END
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001238 let s:file1_var = 'file1'
1239 let g:global_var = 'global'
1240
1241 func s:File1Func( arg )
1242 let s:file1_var .= a:arg
1243 let local_var = s:file1_var .. ' test1'
1244 let g:global_var .= local_var
1245 source Xtest2.vim
1246 endfunc
1247
1248 call s:File1Func( 'arg1' )
1249 END
Bram Moolenaarbf630112023-05-19 21:41:02 +01001250 writefile(lines, 'Xtest1.vim', 'D')
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001251
Bram Moolenaarbf630112023-05-19 21:41:02 +01001252 lines =<< trim END
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001253 let s:file2_var = 'file2'
1254
1255 func s:File2Func( arg )
1256 let s:file2_var .= a:arg
1257 let local_var = s:file2_var .. ' test2'
1258 let g:global_var .= local_var
1259 endfunc
1260
1261 call s:File2Func( 'arg2' )
1262 END
Bram Moolenaarbf630112023-05-19 21:41:02 +01001263 writefile(lines, 'Xtest2.vim', 'D')
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001264
Bram Moolenaarbf630112023-05-19 21:41:02 +01001265 var file1 = getcwd() .. '/Xtest1.vim'
1266 var file2 = getcwd() .. '/Xtest2.vim'
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001267
Bram Moolenaarbf630112023-05-19 21:41:02 +01001268 # set a breakpoint and source file1.vim
1269 var buf = g:RunVimInTerminal(
1270 '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim',
1271 {wait_for_ruler: 0})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001272
Bram Moolenaarbf630112023-05-19 21:41:02 +01001273 s:CheckDbgOutput(buf, [
1274 'Breakpoint in "' .. file1 .. '" line 1',
1275 'Entering Debug mode. Type "cont" to continue.',
1276 'command line..script ' .. file1,
1277 'line 1: let s:file1_var = ''file1'''
1278 ], {msec: 5000})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001279
Bram Moolenaarbf630112023-05-19 21:41:02 +01001280 # step through the initial declarations
1281 s:RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] )
1282 s:RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] )
1283 s:RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1284 s:RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1285 s:RunDbgCmd(buf, 'echo global_var', [ 'global' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001286
Bram Moolenaarbf630112023-05-19 21:41:02 +01001287 # step in to the first function
1288 s:RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] )
1289 s:RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] )
1290 s:RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1291 s:RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1292 s:RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1293 s:RunDbgCmd(buf,
1294 'echo global_var',
1295 [ 'E121: Undefined variable: global_var' ] )
1296 s:RunDbgCmd(buf,
1297 'echo local_var',
1298 [ 'E121: Undefined variable: local_var' ] )
1299 s:RunDbgCmd(buf,
1300 'echo l:local_var',
1301 [ 'E121: Undefined variable: l:local_var' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001302
Bram Moolenaarbf630112023-05-19 21:41:02 +01001303 # backtrace up
1304 s:RunDbgCmd(buf, 'backtrace', [
1305 '\V>backtrace',
1306 '\V 2 command line',
1307 '\V 1 script ' .. file1 .. '[11]',
1308 '\V->0 function <SNR>\.\*_File1Func',
1309 '\Vline 1: let s:file1_var .= a:arg',
1310 ],
1311 { match: 'pattern' } )
1312 s:RunDbgCmd(buf, 'up', [ '>up' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001313
Bram Moolenaarbf630112023-05-19 21:41:02 +01001314 s:RunDbgCmd(buf, 'backtrace', [
1315 '\V>backtrace',
1316 '\V 2 command line',
1317 '\V->1 script ' .. file1 .. '[11]',
1318 '\V 0 function <SNR>\.\*_File1Func',
1319 '\Vline 1: let s:file1_var .= a:arg',
1320 ],
1321 { match: 'pattern' } )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001322
Bram Moolenaarbf630112023-05-19 21:41:02 +01001323 # Expression evaluation in the script frame (not the function frame)
1324 # FIXME: Unexpected in this scope (a: should not be visible)
1325 s:RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1326 s:RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1327 s:RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1328 # FIXME: Unexpected in this scope (global should be found)
1329 s:RunDbgCmd(buf,
1330 'echo global_var',
1331 [ 'E121: Undefined variable: global_var' ] )
1332 s:RunDbgCmd(buf,
1333 'echo local_var',
1334 [ 'E121: Undefined variable: local_var' ] )
1335 s:RunDbgCmd(buf,
1336 'echo l:local_var',
1337 [ 'E121: Undefined variable: l:local_var' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001338
1339
Bram Moolenaarbf630112023-05-19 21:41:02 +01001340 # step while backtraced jumps to the latest frame
1341 s:RunDbgCmd(buf, 'step', [
1342 'line 2: let local_var = s:file1_var .. '' test1''' ] )
1343 s:RunDbgCmd(buf, 'backtrace', [
1344 '\V>backtrace',
1345 '\V 2 command line',
1346 '\V 1 script ' .. file1 .. '[11]',
1347 '\V->0 function <SNR>\.\*_File1Func',
1348 '\Vline 2: let local_var = s:file1_var .. '' test1''',
1349 ],
1350 { match: 'pattern' } )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001351
Bram Moolenaarbf630112023-05-19 21:41:02 +01001352 s:RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] )
1353 s:RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] )
1354 s:RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001355
Bram Moolenaarbf630112023-05-19 21:41:02 +01001356 s:RunDbgCmd(buf, 'step', [ 'line 4: source Xtest2.vim' ] )
1357 s:RunDbgCmd(buf, 'step', [ 'line 1: let s:file2_var = ''file2''' ] )
1358 s:RunDbgCmd(buf, 'backtrace', [
1359 '\V>backtrace',
1360 '\V 3 command line',
1361 '\V 2 script ' .. file1 .. '[11]',
1362 '\V 1 function <SNR>\.\*_File1Func[4]',
1363 '\V->0 script ' .. file2,
1364 '\Vline 1: let s:file2_var = ''file2''',
1365 ],
1366 { match: 'pattern' } )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001367
Bram Moolenaarbf630112023-05-19 21:41:02 +01001368 # Expression evaluation in the script frame file2 (not the function frame)
1369 s:RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1370 s:RunDbgCmd(buf,
1371 'echo s:file1_var',
1372 [ 'E121: Undefined variable: s:file1_var' ] )
1373 s:RunDbgCmd(buf, 'echo g:global_var', [ 'globalfile1arg1 test1' ] )
1374 s:RunDbgCmd(buf, 'echo global_var', [ 'globalfile1arg1 test1' ] )
1375 s:RunDbgCmd(buf,
1376 'echo local_var',
1377 [ 'E121: Undefined variable: local_var' ] )
1378 s:RunDbgCmd(buf,
1379 'echo l:local_var',
1380 [ 'E121: Undefined variable: l:local_var' ] )
1381 s:RunDbgCmd(buf,
1382 'echo s:file2_var',
1383 [ 'E121: Undefined variable: s:file2_var' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001384
Bram Moolenaarbf630112023-05-19 21:41:02 +01001385 s:RunDbgCmd(buf, 'step', [ 'line 3: func s:File2Func( arg )' ] )
1386 s:RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001387
Bram Moolenaarbf630112023-05-19 21:41:02 +01001388 # Up the stack to the other script context
1389 s:RunDbgCmd(buf, 'up')
1390 s:RunDbgCmd(buf, 'backtrace', [
1391 '\V>backtrace',
1392 '\V 3 command line',
1393 '\V 2 script ' .. file1 .. '[11]',
1394 '\V->1 function <SNR>\.\*_File1Func[4]',
1395 '\V 0 script ' .. file2,
1396 '\Vline 3: func s:File2Func( arg )',
1397 ],
1398 { match: 'pattern' } )
1399 # FIXME: Unexpected. Should see the a: and l: dicts from File1Func
1400 s:RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1401 s:RunDbgCmd(buf,
1402 'echo l:local_var',
1403 [ 'E121: Undefined variable: l:local_var' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001404
Bram Moolenaarbf630112023-05-19 21:41:02 +01001405 s:RunDbgCmd(buf, 'up')
1406 s:RunDbgCmd(buf, 'backtrace', [
1407 '\V>backtrace',
1408 '\V 3 command line',
1409 '\V->2 script ' .. file1 .. '[11]',
1410 '\V 1 function <SNR>\.\*_File1Func[4]',
1411 '\V 0 script ' .. file2,
1412 '\Vline 3: func s:File2Func( arg )',
1413 ],
1414 { match: 'pattern' } )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001415
Bram Moolenaarbf630112023-05-19 21:41:02 +01001416 # FIXME: Unexpected (wrong script vars are used)
1417 s:RunDbgCmd(buf,
1418 'echo s:file1_var',
1419 [ 'E121: Undefined variable: s:file1_var' ] )
1420 s:RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001421
Bram Moolenaarbf630112023-05-19 21:41:02 +01001422 s:RunDbgCmd(buf, 'cont')
1423 g:StopVimInTerminal(buf)
1424enddef
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001425
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001426" Test for setting a breakpoint on a :endif where the :if condition is false
1427" and then quit the script. This should generate an interrupt.
1428func Test_breakpt_endif_intr()
1429 func F()
1430 let g:Xpath ..= 'a'
1431 if v:false
1432 let g:Xpath ..= 'b'
1433 endif
1434 invalid_command
1435 endfunc
1436
1437 let g:Xpath = ''
1438 breakadd func 4 F
1439 try
1440 let caught_intr = 0
1441 debuggreedy
1442 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001443 catch /^Vim:Interrupt$/
1444 call assert_match('\.F, line 4', v:throwpoint)
1445 let caught_intr = 1
1446 endtry
1447 0debuggreedy
1448 call assert_equal(1, caught_intr)
1449 call assert_equal('a', g:Xpath)
1450 breakdel *
1451 delfunc F
1452endfunc
1453
1454" Test for setting a breakpoint on a :else where the :if condition is false
1455" and then quit the script. This should generate an interrupt.
1456func Test_breakpt_else_intr()
1457 func F()
1458 let g:Xpath ..= 'a'
1459 if v:false
1460 let g:Xpath ..= 'b'
1461 else
1462 invalid_command
1463 endif
1464 invalid_command
1465 endfunc
1466
1467 let g:Xpath = ''
1468 breakadd func 4 F
1469 try
1470 let caught_intr = 0
1471 debuggreedy
1472 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001473 catch /^Vim:Interrupt$/
1474 call assert_match('\.F, line 4', v:throwpoint)
1475 let caught_intr = 1
1476 endtry
1477 0debuggreedy
1478 call assert_equal(1, caught_intr)
1479 call assert_equal('a', g:Xpath)
1480 breakdel *
1481 delfunc F
1482endfunc
1483
1484" Test for setting a breakpoint on a :endwhile where the :while condition is
1485" false and then quit the script. This should generate an interrupt.
1486func Test_breakpt_endwhile_intr()
1487 func F()
1488 let g:Xpath ..= 'a'
1489 while v:false
1490 let g:Xpath ..= 'b'
1491 endwhile
1492 invalid_command
1493 endfunc
1494
1495 let g:Xpath = ''
1496 breakadd func 4 F
1497 try
1498 let caught_intr = 0
1499 debuggreedy
1500 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001501 catch /^Vim:Interrupt$/
1502 call assert_match('\.F, line 4', v:throwpoint)
1503 let caught_intr = 1
1504 endtry
1505 0debuggreedy
1506 call assert_equal(1, caught_intr)
1507 call assert_equal('a', g:Xpath)
1508 breakdel *
1509 delfunc F
1510endfunc
1511
Bram Moolenaar16c62322020-08-13 19:20:04 +02001512" Test for setting a breakpoint on a script local function
1513func Test_breakpt_scriptlocal_func()
1514 let g:Xpath = ''
1515 func s:G()
1516 let g:Xpath ..= 'a'
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001517 endfunc
1518
Bram Moolenaar16c62322020-08-13 19:20:04 +02001519 let funcname = expand("<SID>") .. "G"
1520 exe "breakadd func 1 " .. funcname
1521 debuggreedy
1522 redir => output
1523 call feedkeys(":call " .. funcname .. "()\<CR>c\<CR>", "xt")
1524 redir END
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001525 0debuggreedy
Bram Moolenaar16c62322020-08-13 19:20:04 +02001526 call assert_match('Breakpoint in "' .. funcname .. '" line 1', output)
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001527 call assert_equal('a', g:Xpath)
1528 breakdel *
Bram Moolenaar16c62322020-08-13 19:20:04 +02001529 exe "delfunc " .. funcname
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001530endfunc
1531
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001532" vim: shiftwidth=2 sts=2 expandtab