blob: 264420998e58a3cd14a730751e0e8a86f3a7bef8 [file] [log] [blame]
Bram Moolenaar113bf062019-04-17 16:54:05 +02001" Tests for the Vim script debug commands
2
Christian Brabandteb380b92025-07-07 20:53:55 +02003source util/screendump.vim
Bram Moolenaar113bf062019-04-17 16:54:05 +02004
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02005CheckRunVimInTerminal
6
7func CheckCWD()
8 " Check that the longer lines don't wrap due to the length of the script name
Yee Cheng Chin3acfbb42025-01-25 15:14:06 +01009 " in cwd. Need to subtract by 1 since Vim will still wrap the message if it
10 " just fits.
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +020011 let script_len = len( getcwd() .. '/Xtest1.vim' )
12 let longest_line = len( 'Breakpoint in "" line 1' )
Yee Cheng Chin3acfbb42025-01-25 15:14:06 +010013 if script_len > ( 75 - longest_line - 1 )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +020014 throw 'Skipped: Your CWD has too many characters'
15 endif
16endfunc
17command! -nargs=0 -bar CheckCWD call CheckCWD()
18
Bram Moolenaar18dc3552020-11-22 14:24:00 +010019" "options" argument can contain:
20" 'msec' - time to wait for a match
21" 'match' - "pattern" to use "lines" as pattern instead of text
Bram Moolenaarbf630112023-05-19 21:41:02 +010022def s:CheckDbgOutput(buf: number, lines: list<string>, options = {})
23 # Verify the expected output
24 var lnum = 20 - len(lines)
25 var msec = get(options, 'msec', 1000)
26 for l in lines
27 if get(options, 'match', 'equal') ==# 'pattern'
28 g:WaitForAssert(() => assert_match(l, term_getline(buf, lnum)), msec)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020029 else
Bram Moolenaarbf630112023-05-19 21:41:02 +010030 g:WaitForAssert(() => assert_equal(l, term_getline(buf, lnum)), msec)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020031 endif
Bram Moolenaarbf630112023-05-19 21:41:02 +010032 lnum += 1
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020033 endfor
Bram Moolenaarbf630112023-05-19 21:41:02 +010034enddef
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020035
Bram Moolenaar113bf062019-04-17 16:54:05 +020036" Run a Vim debugger command
37" If the expected output argument is supplied, then check for it.
Bram Moolenaarbf630112023-05-19 21:41:02 +010038def s:RunDbgCmd(buf: number, cmd: string, ...extra: list<any>)
39 term_sendkeys(buf, cmd .. "\r")
40 g:TermWait(buf)
Bram Moolenaar113bf062019-04-17 16:54:05 +020041
Bram Moolenaarbf630112023-05-19 21:41:02 +010042 if len(extra) > 0
43 var options = {match: 'equal'}
44 if len(extra) > 1
45 extend(options, extra[1])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +020046 endif
Bram Moolenaarbf630112023-05-19 21:41:02 +010047 s:CheckDbgOutput(buf, extra[0], options)
Bram Moolenaar113bf062019-04-17 16:54:05 +020048 endif
Bram Moolenaarbf630112023-05-19 21:41:02 +010049enddef
Bram Moolenaar113bf062019-04-17 16:54:05 +020050
51" Debugger tests
Bram Moolenaarbf630112023-05-19 21:41:02 +010052def Test_Debugger()
53 # Create a Vim script with some functions
54 var lines =<< trim END
Bram Moolenaare7eb9272019-06-24 00:58:07 +020055 func Foo()
56 let var1 = 1
57 let var2 = Bar(var1) + 9
58 return var2
59 endfunc
60 func Bar(var)
61 let var1 = 2 + a:var
62 let var2 = Bazz(var1) + 4
63 return var2
64 endfunc
65 func Bazz(var)
66 try
67 let var1 = 3 + a:var
68 let var3 = "another var"
69 let var3 = "value2"
70 catch
71 let var4 = "exception"
72 endtry
73 return var1
74 endfunc
Bram Moolenaare406ff82022-03-10 20:47:43 +000075 def Vim9Func()
76 for cmd in ['confirm', 'xxxxxxx']
77 for _ in [1, 2]
78 echo cmd
79 endfor
80 endfor
81 enddef
Bram Moolenaare7eb9272019-06-24 00:58:07 +020082 END
Bram Moolenaarbf630112023-05-19 21:41:02 +010083 writefile(lines, 'XtestDebug.vim', 'D')
Bram Moolenaar113bf062019-04-17 16:54:05 +020084
Bram Moolenaarbf630112023-05-19 21:41:02 +010085 # Start Vim in a terminal
86 var buf = g:RunVimInTerminal('-S XtestDebug.vim', {})
Bram Moolenaar113bf062019-04-17 16:54:05 +020087
Bram Moolenaarbf630112023-05-19 21:41:02 +010088 # Start the Vim debugger
89 s:RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()'])
Bram Moolenaar113bf062019-04-17 16:54:05 +020090
Bram Moolenaarbf630112023-05-19 21:41:02 +010091 # Create a few stack frames by stepping through functions
92 s:RunDbgCmd(buf, 'step', ['line 1: let var1 = 1'])
93 s:RunDbgCmd(buf, 'step', ['line 2: let var2 = Bar(var1) + 9'])
94 s:RunDbgCmd(buf, 'step', ['line 1: let var1 = 2 + a:var'])
95 s:RunDbgCmd(buf, 'step', ['line 2: let var2 = Bazz(var1) + 4'])
96 s:RunDbgCmd(buf, 'step', ['line 1: try'])
97 s:RunDbgCmd(buf, 'step', ['line 2: let var1 = 3 + a:var'])
98 s:RunDbgCmd(buf, 'step', ['line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +020099
Bram Moolenaarbf630112023-05-19 21:41:02 +0100100 # check backtrace
101 s:RunDbgCmd(buf, 'backtrace', [
102 ' 2 function Foo[2]',
103 ' 1 Bar[2]',
104 '->0 Bazz',
105 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200106
Bram Moolenaarbf630112023-05-19 21:41:02 +0100107 # Check variables in different stack frames
108 s:RunDbgCmd(buf, 'echo var1', ['6'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200109
Bram Moolenaarbf630112023-05-19 21:41:02 +0100110 s:RunDbgCmd(buf, 'up')
111 s:RunDbgCmd(buf, 'back', [
112 ' 2 function Foo[2]',
113 '->1 Bar[2]',
114 ' 0 Bazz',
115 'line 3: let var3 = "another var"'])
116 s:RunDbgCmd(buf, 'echo var1', ['3'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200117
Bram Moolenaarbf630112023-05-19 21:41:02 +0100118 s:RunDbgCmd(buf, 'u')
119 s:RunDbgCmd(buf, 'bt', [
120 '->2 function Foo[2]',
121 ' 1 Bar[2]',
122 ' 0 Bazz',
123 'line 3: let var3 = "another var"'])
124 s:RunDbgCmd(buf, 'echo var1', ['1'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200125
Bram Moolenaarbf630112023-05-19 21:41:02 +0100126 # Undefined variables
127 s:RunDbgCmd(buf, 'step')
128 s:RunDbgCmd(buf, 'frame 2')
129 s:RunDbgCmd(buf, 'echo var3', [
130 'Error detected while processing function Foo[2]..Bar[2]..Bazz:',
131 'line 4:',
132 'E121: Undefined variable: var3'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200133
Bram Moolenaarbf630112023-05-19 21:41:02 +0100134 # var3 is defined in this level with some other value
135 s:RunDbgCmd(buf, 'fr 0')
136 s:RunDbgCmd(buf, 'echo var3', ['another var'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200137
Bram Moolenaarbf630112023-05-19 21:41:02 +0100138 s:RunDbgCmd(buf, 'step')
139 s:RunDbgCmd(buf, '')
140 s:RunDbgCmd(buf, '')
141 s:RunDbgCmd(buf, '')
142 s:RunDbgCmd(buf, '')
143 s:RunDbgCmd(buf, 'step', [
144 'function Foo[2]..Bar',
145 'line 3: End of function'])
146 s:RunDbgCmd(buf, 'up')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200147
Bram Moolenaarbf630112023-05-19 21:41:02 +0100148 # Undefined var2
149 s:RunDbgCmd(buf, 'echo var2', [
150 'Error detected while processing function Foo[2]..Bar:',
151 'line 3:',
152 'E121: Undefined variable: var2'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200153
Bram Moolenaarbf630112023-05-19 21:41:02 +0100154 # Var2 is defined with 10
155 s:RunDbgCmd(buf, 'down')
156 s:RunDbgCmd(buf, 'echo var2', ['10'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200157
Bram Moolenaarbf630112023-05-19 21:41:02 +0100158 # Backtrace movements
159 s:RunDbgCmd(buf, 'b', [
160 ' 1 function Foo[2]',
161 '->0 Bar',
162 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200163
Bram Moolenaarbf630112023-05-19 21:41:02 +0100164 # next command cannot go down, we are on bottom
165 s:RunDbgCmd(buf, 'down', ['frame is zero'])
166 s:RunDbgCmd(buf, 'up')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200167
Bram Moolenaarbf630112023-05-19 21:41:02 +0100168 # next command cannot go up, we are on top
169 s:RunDbgCmd(buf, 'up', ['frame at highest level: 1'])
170 s:RunDbgCmd(buf, 'where', [
171 '->1 function Foo[2]',
172 ' 0 Bar',
173 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200174
Bram Moolenaarbf630112023-05-19 21:41:02 +0100175 # fil is not frame or finish, it is file
176 s:RunDbgCmd(buf, 'fil', ['"[No Name]" --No lines in buffer--'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200177
Bram Moolenaarbf630112023-05-19 21:41:02 +0100178 # relative backtrace movement
179 s:RunDbgCmd(buf, 'fr -1')
180 s:RunDbgCmd(buf, 'frame', [
181 ' 1 function Foo[2]',
182 '->0 Bar',
183 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200184
Bram Moolenaarbf630112023-05-19 21:41:02 +0100185 s:RunDbgCmd(buf, 'fr +1')
186 s:RunDbgCmd(buf, 'fram', [
187 '->1 function Foo[2]',
188 ' 0 Bar',
189 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200190
Bram Moolenaarbf630112023-05-19 21:41:02 +0100191 # go beyond limits does not crash
192 s:RunDbgCmd(buf, 'fr 100', ['frame at highest level: 1'])
193 s:RunDbgCmd(buf, 'fra', [
194 '->1 function Foo[2]',
195 ' 0 Bar',
196 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200197
Bram Moolenaarbf630112023-05-19 21:41:02 +0100198 s:RunDbgCmd(buf, 'frame -40', ['frame is zero'])
199 s:RunDbgCmd(buf, 'fram', [
200 ' 1 function Foo[2]',
201 '->0 Bar',
202 'line 3: End of function'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200203
Bram Moolenaarbf630112023-05-19 21:41:02 +0100204 # final result 19
205 s:RunDbgCmd(buf, 'cont', ['19'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200206
Bram Moolenaarbf630112023-05-19 21:41:02 +0100207 # breakpoints tests
Bram Moolenaar113bf062019-04-17 16:54:05 +0200208
Bram Moolenaarbf630112023-05-19 21:41:02 +0100209 # Start a debug session, so that reading the last line from the terminal
210 # works properly.
211 s:RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200212
Bram Moolenaarbf630112023-05-19 21:41:02 +0100213 # No breakpoints
214 s:RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200215
Bram Moolenaarbf630112023-05-19 21:41:02 +0100216 # Place some breakpoints
217 s:RunDbgCmd(buf, 'breaka func Bar')
218 s:RunDbgCmd(buf, 'breaklis', [' 1 func Bar line 1'])
219 s:RunDbgCmd(buf, 'breakadd func 3 Bazz')
220 s:RunDbgCmd(buf, 'breaklist', [' 1 func Bar line 1',
221 ' 2 func Bazz line 3'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200222
Bram Moolenaarbf630112023-05-19 21:41:02 +0100223 # Check whether the breakpoints are hit
224 s:RunDbgCmd(buf, 'cont', [
225 'Breakpoint in "Bar" line 1',
226 'function Foo[2]..Bar',
227 'line 1: let var1 = 2 + a:var'])
228 s:RunDbgCmd(buf, 'cont', [
229 'Breakpoint in "Bazz" line 3',
230 'function Foo[2]..Bar[2]..Bazz',
231 'line 3: let var3 = "another var"'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200232
Bram Moolenaarbf630112023-05-19 21:41:02 +0100233 # Delete the breakpoints
234 s:RunDbgCmd(buf, 'breakd 1')
235 s:RunDbgCmd(buf, 'breakli', [' 2 func Bazz line 3'])
236 s:RunDbgCmd(buf, 'breakdel func 3 Bazz')
237 s:RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200238
Bram Moolenaarbf630112023-05-19 21:41:02 +0100239 s:RunDbgCmd(buf, 'cont')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200240
Bram Moolenaarbf630112023-05-19 21:41:02 +0100241 # Make sure the breakpoints are removed
242 s:RunDbgCmd(buf, ':echo Foo()', ['19'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200243
Bram Moolenaarbf630112023-05-19 21:41:02 +0100244 # Delete a non-existing breakpoint
245 s:RunDbgCmd(buf, ':breakdel 2', ['E161: Breakpoint not found: 2'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200246
Bram Moolenaarbf630112023-05-19 21:41:02 +0100247 # Expression breakpoint
248 s:RunDbgCmd(buf, ':breakadd func 2 Bazz')
249 s:RunDbgCmd(buf, ':echo Bazz(1)', [
250 'Entering Debug mode. Type "cont" to continue.',
251 'function Bazz',
252 'line 2: let var1 = 3 + a:var'])
253 s:RunDbgCmd(buf, 'step')
254 s:RunDbgCmd(buf, 'step')
255 s:RunDbgCmd(buf, 'breaka expr var3')
256 s:RunDbgCmd(buf, 'breakl', [' 3 func Bazz line 2',
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200257 \ ' 4 expr var3'])
Bram Moolenaarbf630112023-05-19 21:41:02 +0100258 s:RunDbgCmd(buf, 'cont', ['Breakpoint in "Bazz" line 5',
259 'Oldval = "''another var''"',
260 'Newval = "''value2''"',
261 'function Bazz',
262 'line 5: catch'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200263
Bram Moolenaarbf630112023-05-19 21:41:02 +0100264 s:RunDbgCmd(buf, 'breakdel *')
265 s:RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
Bram Moolenaar113bf062019-04-17 16:54:05 +0200266
Bram Moolenaarbf630112023-05-19 21:41:02 +0100267 # Check for error cases
268 s:RunDbgCmd(buf, 'breakadd abcd', [
269 'Error detected while processing function Bazz:',
270 'line 5:',
271 'E475: Invalid argument: abcd'])
272 s:RunDbgCmd(buf, 'breakadd func', ['E475: Invalid argument: func'])
273 s:RunDbgCmd(buf, 'breakadd func 2', ['E475: Invalid argument: func 2'])
274 s:RunDbgCmd(buf, 'breaka func a()', ['E475: Invalid argument: func a()'])
275 s:RunDbgCmd(buf, 'breakd abcd', ['E475: Invalid argument: abcd'])
276 s:RunDbgCmd(buf, 'breakd func', ['E475: Invalid argument: func'])
277 s:RunDbgCmd(buf, 'breakd func a()', ['E475: Invalid argument: func a()'])
278 s:RunDbgCmd(buf, 'breakd func a', ['E161: Breakpoint not found: func a'])
279 s:RunDbgCmd(buf, 'breakd expr', ['E475: Invalid argument: expr'])
280 s:RunDbgCmd(buf, 'breakd expr x', ['E161: Breakpoint not found: expr x'])
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200281
Bram Moolenaarbf630112023-05-19 21:41:02 +0100282 # finish the current function
283 s:RunDbgCmd(buf, 'finish', [
284 'function Bazz',
285 'line 8: End of function'])
286 s:RunDbgCmd(buf, 'cont')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200287
Bram Moolenaarbf630112023-05-19 21:41:02 +0100288 # Test for :next
289 s:RunDbgCmd(buf, ':debug echo Bar(1)')
290 s:RunDbgCmd(buf, 'step')
291 s:RunDbgCmd(buf, 'next')
292 s:RunDbgCmd(buf, '', [
293 'function Bar',
294 'line 3: return var2'])
295 s:RunDbgCmd(buf, 'c')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200296
Bram Moolenaarbf630112023-05-19 21:41:02 +0100297 # Test for :interrupt
298 s:RunDbgCmd(buf, ':debug echo Bazz(1)')
299 s:RunDbgCmd(buf, 'step')
300 s:RunDbgCmd(buf, 'step')
301 s:RunDbgCmd(buf, 'interrupt', [
302 'Exception thrown: Vim:Interrupt',
303 'function Bazz',
304 'line 5: catch'])
305 s:RunDbgCmd(buf, 'c')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200306
Bram Moolenaarbf630112023-05-19 21:41:02 +0100307 # Test showing local variable in :def function
308 s:RunDbgCmd(buf, ':breakadd func 2 Vim9Func')
309 s:RunDbgCmd(buf, ':call Vim9Func()', ['line 2: for _ in [1, 2]'])
310 s:RunDbgCmd(buf, 'next', ['line 2: for _ in [1, 2]'])
311 s:RunDbgCmd(buf, 'echo cmd', ['confirm'])
312 s:RunDbgCmd(buf, 'breakdel *')
313 s:RunDbgCmd(buf, 'cont')
Bram Moolenaare406ff82022-03-10 20:47:43 +0000314
Bram Moolenaarbf630112023-05-19 21:41:02 +0100315 # Test for :quit
316 s:RunDbgCmd(buf, ':debug echo Foo()')
317 s:RunDbgCmd(buf, 'breakdel *')
318 s:RunDbgCmd(buf, 'breakadd func 3 Foo')
319 s:RunDbgCmd(buf, 'breakadd func 3 Bazz')
320 s:RunDbgCmd(buf, 'cont', [
321 'Breakpoint in "Bazz" line 3',
322 'function Foo[2]..Bar[2]..Bazz',
323 'line 3: let var3 = "another var"'])
324 s:RunDbgCmd(buf, 'quit', [
325 'Breakpoint in "Foo" line 3',
326 'function Foo',
327 'line 3: return var2'])
328 s:RunDbgCmd(buf, 'breakdel *')
329 s:RunDbgCmd(buf, 'quit')
330 s:RunDbgCmd(buf, 'enew! | only!')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200331
Bram Moolenaarbf630112023-05-19 21:41:02 +0100332 g:StopVimInTerminal(buf)
333enddef
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200334
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200335func Test_Debugger_breakadd()
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200336 " Tests for :breakadd file and :breakadd here
337 " Breakpoints should be set before sourcing the file
338
Bram Moolenaare7eb9272019-06-24 00:58:07 +0200339 let lines =<< trim END
340 let var1 = 10
341 let var2 = 20
342 let var3 = 30
343 let var4 = 40
344 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100345 call writefile(lines, 'XdebugBreakadd.vim', 'D')
Bram Moolenaar0fdd9432019-04-20 22:28:48 +0200346
347 " Start Vim in a terminal
Bram Moolenaar59173412022-09-20 22:01:33 +0100348 let buf = RunVimInTerminal('XdebugBreakadd.vim', {})
Bram Moolenaarbf630112023-05-19 21:41:02 +0100349 call s:RunDbgCmd(buf, ':breakadd file 2 XdebugBreakadd.vim')
350 call s:RunDbgCmd(buf, ':4 | breakadd here')
351 call s:RunDbgCmd(buf, ':source XdebugBreakadd.vim', ['line 2: let var2 = 20'])
352 call s:RunDbgCmd(buf, 'cont', ['line 4: let var4 = 40'])
353 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200354
355 call StopVimInTerminal(buf)
356
Bram Moolenaar16c62322020-08-13 19:20:04 +0200357 %bw!
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200358
Bram Moolenaar16c62322020-08-13 19:20:04 +0200359 call assert_fails('breakadd here', 'E32:')
Bram Moolenaar531be472020-09-23 22:38:05 +0200360 call assert_fails('breakadd file Xtest.vim /\)/', 'E55:')
Bram Moolenaar113bf062019-04-17 16:54:05 +0200361endfunc
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200362
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100363" Test for expression breakpoint set using ":breakadd expr <expr>"
364func Test_Debugger_breakadd_expr()
James McCoydb7a88d2022-08-03 16:13:27 +0100365 CheckCWD
366
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100367 let lines =<< trim END
368 let g:Xtest_var += 1
369 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100370 call writefile(lines, 'XdebugBreakExpr.vim', 'D')
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100371
372 " Start Vim in a terminal
Bram Moolenaar59173412022-09-20 22:01:33 +0100373 let buf = RunVimInTerminal('XdebugBreakExpr.vim', {})
Bram Moolenaarbf630112023-05-19 21:41:02 +0100374 call s:RunDbgCmd(buf, ':let g:Xtest_var = 10')
375 call s:RunDbgCmd(buf, ':breakadd expr g:Xtest_var')
376 call s:RunDbgCmd(buf, ':source %')
Bram Moolenaar59173412022-09-20 22:01:33 +0100377 let expected =<< trim eval END
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100378 Oldval = "10"
379 Newval = "11"
Bram Moolenaar59173412022-09-20 22:01:33 +0100380 {fnamemodify('XdebugBreakExpr.vim', ':p')}
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100381 line 1: let g:Xtest_var += 1
382 END
Bram Moolenaarbf630112023-05-19 21:41:02 +0100383 call s:RunDbgCmd(buf, ':source %', expected)
384 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar59173412022-09-20 22:01:33 +0100385 let expected =<< trim eval END
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100386 Oldval = "11"
387 Newval = "12"
Bram Moolenaar59173412022-09-20 22:01:33 +0100388 {fnamemodify('XdebugBreakExpr.vim', ':p')}
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100389 line 1: let g:Xtest_var += 1
390 END
Bram Moolenaarbf630112023-05-19 21:41:02 +0100391 call s:RunDbgCmd(buf, ':source %', expected)
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100392
393 call StopVimInTerminal(buf)
Yegappan Lakshmanan885de442022-04-23 10:51:14 +0100394endfunc
395
396def Test_Debugger_breakadd_vim9_expr()
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200397 var lines =<< trim END
398 vim9script
399 func g:EarlyFunc()
400 endfunc
401 breakadd expr DoesNotExist()
402 func g:LaterFunc()
403 endfunc
404 breakdel *
405 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100406 writefile(lines, 'XdebugBreak9expr.vim', 'D')
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200407
408 # Start Vim in a terminal
Bram Moolenaar59173412022-09-20 22:01:33 +0100409 var buf = g:RunVimInTerminal('-S XdebugBreak9expr.vim', {wait_for_ruler: 0})
Bram Moolenaare366ed42022-06-19 20:13:56 +0100410 call g:TermWait(buf, g:RunningWithValgrind() ? 1000 : 50)
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200411
412 # Despite the failure the functions are defined
Bram Moolenaarbf630112023-05-19 21:41:02 +0100413 s:RunDbgCmd(buf, ':function g:EarlyFunc',
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200414 ['function EarlyFunc()', 'endfunction'], {match: 'pattern'})
Bram Moolenaarbf630112023-05-19 21:41:02 +0100415 s:RunDbgCmd(buf, ':function g:LaterFunc',
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200416 ['function LaterFunc()', 'endfunction'], {match: 'pattern'})
417
Bram Moolenaar62aec932022-01-29 21:45:34 +0000418 call g:StopVimInTerminal(buf)
Bram Moolenaar072f1c62021-09-08 20:40:34 +0200419enddef
420
Bram Moolenaar112bed02021-11-23 22:16:34 +0000421def Test_Debugger_break_at_return()
422 var lines =<< trim END
423 vim9script
424 def g:GetNum(): number
425 return 1
426 + 2
427 + 3
428 enddef
429 breakadd func GetNum
430 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100431 writefile(lines, 'XdebugBreakRet.vim', 'D')
Bram Moolenaar112bed02021-11-23 22:16:34 +0000432
433 # Start Vim in a terminal
Bram Moolenaar59173412022-09-20 22:01:33 +0100434 var buf = g:RunVimInTerminal('-S XdebugBreakRet.vim', {wait_for_ruler: 0})
Bram Moolenaare366ed42022-06-19 20:13:56 +0100435 call g:TermWait(buf, g:RunningWithValgrind() ? 1000 : 50)
Bram Moolenaar112bed02021-11-23 22:16:34 +0000436
Bram Moolenaarbf630112023-05-19 21:41:02 +0100437 s:RunDbgCmd(buf, ':call GetNum()',
Bram Moolenaar112bed02021-11-23 22:16:34 +0000438 ['line 1: return 1 + 2 + 3'], {match: 'pattern'})
439
Bram Moolenaar62aec932022-01-29 21:45:34 +0000440 call g:StopVimInTerminal(buf)
Bram Moolenaar112bed02021-11-23 22:16:34 +0000441enddef
442
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200443func Test_Backtrace_Through_Source()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200444 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200445 let file1 =<< trim END
446 func SourceAnotherFile()
447 source Xtest2.vim
448 endfunc
449
450 func CallAFunction()
451 call SourceAnotherFile()
452 call File2Function()
453 endfunc
454
455 func GlobalFunction()
456 call CallAFunction()
457 endfunc
458 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100459 call writefile(file1, 'Xtest1.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200460
461 let file2 =<< trim END
462 func DoAThing()
463 echo "DoAThing"
464 endfunc
465
466 func File2Function()
467 call DoAThing()
468 endfunc
469
470 call File2Function()
471 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100472 call writefile(file2, 'Xtest2.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200473
474 let buf = RunVimInTerminal('-S Xtest1.vim', {})
475
Bram Moolenaarbf630112023-05-19 21:41:02 +0100476 call s:RunDbgCmd(buf,
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200477 \ ':debug call GlobalFunction()',
478 \ ['cmd: call GlobalFunction()'])
Bram Moolenaarbf630112023-05-19 21:41:02 +0100479 call s:RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200480
Bram Moolenaarbf630112023-05-19 21:41:02 +0100481 call s:RunDbgCmd(buf, 'backtrace', ['>backtrace',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200482 \ '->0 function GlobalFunction',
483 \ 'line 1: call CallAFunction()'])
484
Bram Moolenaarbf630112023-05-19 21:41:02 +0100485 call s:RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
486 call s:RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200487
Bram Moolenaarbf630112023-05-19 21:41:02 +0100488 call s:RunDbgCmd(buf, 'backtrace', ['>backtrace',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200489 \ ' 2 function GlobalFunction[1]',
490 \ ' 1 CallAFunction[1]',
491 \ '->0 SourceAnotherFile',
492 \ 'line 1: source Xtest2.vim'])
493
494 " Step into the 'source' command. Note that we print the full trace all the
495 " way though the source command.
Bram Moolenaarbf630112023-05-19 21:41:02 +0100496 call s:RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
497 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200498 \ '>backtrace',
499 \ ' 3 function GlobalFunction[1]',
500 \ ' 2 CallAFunction[1]',
501 \ ' 1 SourceAnotherFile[1]',
502 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
503 \ 'line 1: func DoAThing()'])
504
Bram Moolenaarbf630112023-05-19 21:41:02 +0100505 call s:RunDbgCmd( buf, 'up' )
506 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200507 \ '>backtrace',
508 \ ' 3 function GlobalFunction[1]',
509 \ ' 2 CallAFunction[1]',
510 \ '->1 SourceAnotherFile[1]',
511 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
512 \ 'line 1: func DoAThing()' ] )
513
Bram Moolenaarbf630112023-05-19 21:41:02 +0100514 call s:RunDbgCmd( buf, 'up' )
515 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200516 \ '>backtrace',
517 \ ' 3 function GlobalFunction[1]',
518 \ '->2 CallAFunction[1]',
519 \ ' 1 SourceAnotherFile[1]',
520 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
521 \ 'line 1: func DoAThing()' ] )
522
Bram Moolenaarbf630112023-05-19 21:41:02 +0100523 call s:RunDbgCmd( buf, 'up' )
524 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200525 \ '>backtrace',
526 \ '->3 function GlobalFunction[1]',
527 \ ' 2 CallAFunction[1]',
528 \ ' 1 SourceAnotherFile[1]',
529 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
530 \ 'line 1: func DoAThing()' ] )
531
Bram Moolenaarbf630112023-05-19 21:41:02 +0100532 call s:RunDbgCmd( buf, 'up', [ 'frame at highest level: 3' ] )
533 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200534 \ '>backtrace',
535 \ '->3 function GlobalFunction[1]',
536 \ ' 2 CallAFunction[1]',
537 \ ' 1 SourceAnotherFile[1]',
538 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
539 \ 'line 1: func DoAThing()' ] )
540
Bram Moolenaarbf630112023-05-19 21:41:02 +0100541 call s:RunDbgCmd( buf, 'down' )
542 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200543 \ '>backtrace',
544 \ ' 3 function GlobalFunction[1]',
545 \ '->2 CallAFunction[1]',
546 \ ' 1 SourceAnotherFile[1]',
547 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
548 \ 'line 1: func DoAThing()' ] )
549
Bram Moolenaarbf630112023-05-19 21:41:02 +0100550 call s:RunDbgCmd( buf, 'down' )
551 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200552 \ '>backtrace',
553 \ ' 3 function GlobalFunction[1]',
554 \ ' 2 CallAFunction[1]',
555 \ '->1 SourceAnotherFile[1]',
556 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
557 \ 'line 1: func DoAThing()' ] )
558
Bram Moolenaarbf630112023-05-19 21:41:02 +0100559 call s:RunDbgCmd( buf, 'down' )
560 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200561 \ '>backtrace',
562 \ ' 3 function GlobalFunction[1]',
563 \ ' 2 CallAFunction[1]',
564 \ ' 1 SourceAnotherFile[1]',
565 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
566 \ 'line 1: func DoAThing()' ] )
567
Bram Moolenaarbf630112023-05-19 21:41:02 +0100568 call s:RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200569
Dominique Pelle923dce22021-11-21 11:36:04 +0000570 " step until we have another meaningful trace
Bram Moolenaarbf630112023-05-19 21:41:02 +0100571 call s:RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
572 call s:RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
573 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200574 \ '>backtrace',
575 \ ' 3 function GlobalFunction[1]',
576 \ ' 2 CallAFunction[1]',
577 \ ' 1 SourceAnotherFile[1]',
578 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
579 \ 'line 9: call File2Function()'])
580
Bram Moolenaarbf630112023-05-19 21:41:02 +0100581 call s:RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
582 call s:RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
583 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200584 \ '>backtrace',
585 \ ' 5 function GlobalFunction[1]',
586 \ ' 4 CallAFunction[1]',
587 \ ' 3 SourceAnotherFile[1]',
588 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
589 \ ' 1 function File2Function[1]',
590 \ '->0 DoAThing',
591 \ 'line 1: echo "DoAThing"'])
592
593 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
Bram Moolenaarbf630112023-05-19 21:41:02 +0100594 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
595 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
596 call s:RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
597 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
598 call s:RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
599 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200600 \ '>backtrace',
601 \ ' 1 function GlobalFunction[1]',
602 \ '->0 CallAFunction',
603 \ 'line 2: call File2Function()'])
604
Bram Moolenaarbf630112023-05-19 21:41:02 +0100605 call s:RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
606 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200607 \ '>backtrace',
608 \ ' 2 function GlobalFunction[1]',
609 \ ' 1 CallAFunction[2]',
610 \ '->0 File2Function',
611 \ 'line 1: call DoAThing()'])
612
613 call StopVimInTerminal(buf)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200614endfunc
615
616func Test_Backtrace_Autocmd()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200617 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200618 let file1 =<< trim END
619 func SourceAnotherFile()
620 source Xtest2.vim
621 endfunc
622
623 func CallAFunction()
624 call SourceAnotherFile()
625 call File2Function()
626 endfunc
627
628 func GlobalFunction()
629 call CallAFunction()
630 endfunc
631
632 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
633 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100634 call writefile(file1, 'Xtest1.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200635
636 let file2 =<< trim END
637 func DoAThing()
638 echo "DoAThing"
639 endfunc
640
641 func File2Function()
642 call DoAThing()
643 endfunc
644
645 call File2Function()
646 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100647 call writefile(file2, 'Xtest2.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200648
649 let buf = RunVimInTerminal('-S Xtest1.vim', {})
650
Bram Moolenaarbf630112023-05-19 21:41:02 +0100651 call s:RunDbgCmd(buf,
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200652 \ ':debug doautocmd User TestGlobalFunction',
653 \ ['cmd: doautocmd User TestGlobalFunction'])
Bram Moolenaarbf630112023-05-19 21:41:02 +0100654 call s:RunDbgCmd(buf, 'step', ['cmd: call GlobalFunction() | echo "Done"'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200655
Dominique Pelle923dce22021-11-21 11:36:04 +0000656 " At this point the only thing in the stack is the autocommand
Bram Moolenaarbf630112023-05-19 21:41:02 +0100657 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200658 \ '>backtrace',
659 \ '->0 User Autocommands for "TestGlobalFunction"',
660 \ 'cmd: call GlobalFunction() | echo "Done"'])
661
662 " And now we're back into the call stack
Bram Moolenaarbf630112023-05-19 21:41:02 +0100663 call s:RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
664 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200665 \ '>backtrace',
666 \ ' 1 User Autocommands for "TestGlobalFunction"',
667 \ '->0 function GlobalFunction',
668 \ 'line 1: call CallAFunction()'])
669
Bram Moolenaarbf630112023-05-19 21:41:02 +0100670 call s:RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()'])
671 call s:RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200672
Bram Moolenaarbf630112023-05-19 21:41:02 +0100673 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200674 \ '>backtrace',
675 \ ' 3 User Autocommands for "TestGlobalFunction"',
676 \ ' 2 function GlobalFunction[1]',
677 \ ' 1 CallAFunction[1]',
678 \ '->0 SourceAnotherFile',
679 \ 'line 1: source Xtest2.vim'])
680
681 " Step into the 'source' command. Note that we print the full trace all the
682 " way though the source command.
Bram Moolenaarbf630112023-05-19 21:41:02 +0100683 call s:RunDbgCmd(buf, 'step', ['line 1: func DoAThing()'])
684 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200685 \ '>backtrace',
686 \ ' 4 User Autocommands for "TestGlobalFunction"',
687 \ ' 3 function GlobalFunction[1]',
688 \ ' 2 CallAFunction[1]',
689 \ ' 1 SourceAnotherFile[1]',
690 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
691 \ 'line 1: func DoAThing()'])
692
Bram Moolenaarbf630112023-05-19 21:41:02 +0100693 call s:RunDbgCmd( buf, 'up' )
694 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200695 \ '>backtrace',
696 \ ' 4 User Autocommands for "TestGlobalFunction"',
697 \ ' 3 function GlobalFunction[1]',
698 \ ' 2 CallAFunction[1]',
699 \ '->1 SourceAnotherFile[1]',
700 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
701 \ 'line 1: func DoAThing()' ] )
702
Bram Moolenaarbf630112023-05-19 21:41:02 +0100703 call s:RunDbgCmd( buf, 'up' )
704 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200705 \ '>backtrace',
706 \ ' 4 User Autocommands for "TestGlobalFunction"',
707 \ ' 3 function GlobalFunction[1]',
708 \ '->2 CallAFunction[1]',
709 \ ' 1 SourceAnotherFile[1]',
710 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
711 \ 'line 1: func DoAThing()' ] )
712
Bram Moolenaarbf630112023-05-19 21:41:02 +0100713 call s:RunDbgCmd( buf, 'up' )
714 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200715 \ '>backtrace',
716 \ ' 4 User Autocommands for "TestGlobalFunction"',
717 \ '->3 function GlobalFunction[1]',
718 \ ' 2 CallAFunction[1]',
719 \ ' 1 SourceAnotherFile[1]',
720 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
721 \ 'line 1: func DoAThing()' ] )
722
Bram Moolenaarbf630112023-05-19 21:41:02 +0100723 call s:RunDbgCmd( buf, 'up' )
724 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200725 \ '>backtrace',
726 \ '->4 User Autocommands for "TestGlobalFunction"',
727 \ ' 3 function GlobalFunction[1]',
728 \ ' 2 CallAFunction[1]',
729 \ ' 1 SourceAnotherFile[1]',
730 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
731 \ 'line 1: func DoAThing()' ] )
732
Bram Moolenaarbf630112023-05-19 21:41:02 +0100733 call s:RunDbgCmd( buf, 'up', [ 'frame at highest level: 4' ] )
734 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200735 \ '>backtrace',
736 \ '->4 User Autocommands for "TestGlobalFunction"',
737 \ ' 3 function GlobalFunction[1]',
738 \ ' 2 CallAFunction[1]',
739 \ ' 1 SourceAnotherFile[1]',
740 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
741 \ 'line 1: func DoAThing()' ] )
742
Bram Moolenaarbf630112023-05-19 21:41:02 +0100743 call s:RunDbgCmd( buf, 'down' )
744 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200745 \ '>backtrace',
746 \ ' 4 User Autocommands for "TestGlobalFunction"',
747 \ '->3 function GlobalFunction[1]',
748 \ ' 2 CallAFunction[1]',
749 \ ' 1 SourceAnotherFile[1]',
750 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
751 \ 'line 1: func DoAThing()' ] )
752
753
Bram Moolenaarbf630112023-05-19 21:41:02 +0100754 call s:RunDbgCmd( buf, 'down' )
755 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200756 \ '>backtrace',
757 \ ' 4 User Autocommands for "TestGlobalFunction"',
758 \ ' 3 function GlobalFunction[1]',
759 \ '->2 CallAFunction[1]',
760 \ ' 1 SourceAnotherFile[1]',
761 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
762 \ 'line 1: func DoAThing()' ] )
763
Bram Moolenaarbf630112023-05-19 21:41:02 +0100764 call s:RunDbgCmd( buf, 'down' )
765 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200766 \ '>backtrace',
767 \ ' 4 User Autocommands for "TestGlobalFunction"',
768 \ ' 3 function GlobalFunction[1]',
769 \ ' 2 CallAFunction[1]',
770 \ '->1 SourceAnotherFile[1]',
771 \ ' 0 script ' .. getcwd() .. '/Xtest2.vim',
772 \ 'line 1: func DoAThing()' ] )
773
Bram Moolenaarbf630112023-05-19 21:41:02 +0100774 call s:RunDbgCmd( buf, 'down' )
775 call s:RunDbgCmd( buf, 'backtrace', [
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200776 \ '>backtrace',
777 \ ' 4 User Autocommands for "TestGlobalFunction"',
778 \ ' 3 function GlobalFunction[1]',
779 \ ' 2 CallAFunction[1]',
780 \ ' 1 SourceAnotherFile[1]',
781 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
782 \ 'line 1: func DoAThing()' ] )
783
Bram Moolenaarbf630112023-05-19 21:41:02 +0100784 call s:RunDbgCmd( buf, 'down', [ 'frame is zero' ] )
Bram Moolenaarc63b72b2020-08-22 16:04:52 +0200785
Dominique Pelle923dce22021-11-21 11:36:04 +0000786 " step until we have another meaningful trace
Bram Moolenaarbf630112023-05-19 21:41:02 +0100787 call s:RunDbgCmd(buf, 'step', ['line 5: func File2Function()'])
788 call s:RunDbgCmd(buf, 'step', ['line 9: call File2Function()'])
789 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200790 \ '>backtrace',
791 \ ' 4 User Autocommands for "TestGlobalFunction"',
792 \ ' 3 function GlobalFunction[1]',
793 \ ' 2 CallAFunction[1]',
794 \ ' 1 SourceAnotherFile[1]',
795 \ '->0 script ' .. getcwd() .. '/Xtest2.vim',
796 \ 'line 9: call File2Function()'])
797
Bram Moolenaarbf630112023-05-19 21:41:02 +0100798 call s:RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
799 call s:RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"'])
800 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200801 \ '>backtrace',
802 \ ' 6 User Autocommands for "TestGlobalFunction"',
803 \ ' 5 function GlobalFunction[1]',
804 \ ' 4 CallAFunction[1]',
805 \ ' 3 SourceAnotherFile[1]',
806 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]',
807 \ ' 1 function File2Function[1]',
808 \ '->0 DoAThing',
809 \ 'line 1: echo "DoAThing"'])
810
811 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim
Bram Moolenaarbf630112023-05-19 21:41:02 +0100812 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
813 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
814 call s:RunDbgCmd(buf, 'step', ['line 10: End of sourced file'])
815 call s:RunDbgCmd(buf, 'step', ['line 1: End of function'])
816 call s:RunDbgCmd(buf, 'step', ['line 2: call File2Function()'])
817 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200818 \ '>backtrace',
819 \ ' 2 User Autocommands for "TestGlobalFunction"',
820 \ ' 1 function GlobalFunction[1]',
821 \ '->0 CallAFunction',
822 \ 'line 2: call File2Function()'])
823
Bram Moolenaarbf630112023-05-19 21:41:02 +0100824 call s:RunDbgCmd(buf, 'step', ['line 1: call DoAThing()'])
825 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200826 \ '>backtrace',
827 \ ' 3 User Autocommands for "TestGlobalFunction"',
828 \ ' 2 function GlobalFunction[1]',
829 \ ' 1 CallAFunction[2]',
830 \ '->0 File2Function',
831 \ 'line 1: call DoAThing()'])
832
833
834 " Now unwind so that we get back to the original autocommand (and the second
835 " cmd echo "Done")
Bram Moolenaarbf630112023-05-19 21:41:02 +0100836 call s:RunDbgCmd(buf, 'finish', ['line 1: End of function'])
837 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200838 \ '>backtrace',
839 \ ' 3 User Autocommands for "TestGlobalFunction"',
840 \ ' 2 function GlobalFunction[1]',
841 \ ' 1 CallAFunction[2]',
842 \ '->0 File2Function',
843 \ 'line 1: End of function'])
844
Bram Moolenaarbf630112023-05-19 21:41:02 +0100845 call s:RunDbgCmd(buf, 'finish', ['line 2: End of function'])
846 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200847 \ '>backtrace',
848 \ ' 2 User Autocommands for "TestGlobalFunction"',
849 \ ' 1 function GlobalFunction[1]',
850 \ '->0 CallAFunction',
851 \ 'line 2: End of function'])
852
Bram Moolenaarbf630112023-05-19 21:41:02 +0100853 call s:RunDbgCmd(buf, 'finish', ['line 1: End of function'])
854 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200855 \ '>backtrace',
856 \ ' 1 User Autocommands for "TestGlobalFunction"',
857 \ '->0 function GlobalFunction',
858 \ 'line 1: End of function'])
859
Bram Moolenaarbf630112023-05-19 21:41:02 +0100860 call s:RunDbgCmd(buf, 'step', ['cmd: echo "Done"'])
861 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200862 \ '>backtrace',
863 \ '->0 User Autocommands for "TestGlobalFunction"',
864 \ 'cmd: echo "Done"'])
865
866 call StopVimInTerminal(buf)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200867endfunc
868
869func Test_Backtrace_CmdLine()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200870 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200871 let file1 =<< trim END
872 func SourceAnotherFile()
873 source Xtest2.vim
874 endfunc
875
876 func CallAFunction()
877 call SourceAnotherFile()
878 call File2Function()
879 endfunc
880
881 func GlobalFunction()
882 call CallAFunction()
883 endfunc
884
885 au User TestGlobalFunction :call GlobalFunction() | echo "Done"
886 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100887 call writefile(file1, 'Xtest1.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200888
889 let file2 =<< trim END
890 func DoAThing()
891 echo "DoAThing"
892 endfunc
893
894 func File2Function()
895 call DoAThing()
896 endfunc
897
898 call File2Function()
899 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100900 call writefile(file2, 'Xtest2.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200901
902 let buf = RunVimInTerminal(
903 \ '-S Xtest1.vim -c "debug call GlobalFunction()"',
904 \ {'wait_for_ruler': 0})
905
Bram Moolenaar18dc3552020-11-22 14:24:00 +0100906 " Need to wait for the vim-in-terminal to be ready.
907 " With valgrind this can take quite long.
Bram Moolenaarbf630112023-05-19 21:41:02 +0100908 call s:CheckDbgOutput(buf, ['command line',
Bram Moolenaar18dc3552020-11-22 14:24:00 +0100909 \ 'cmd: call GlobalFunction()'], #{msec: 5000})
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200910
Dominique Pelle923dce22021-11-21 11:36:04 +0000911 " At this point the only thing in the stack is the cmdline
Bram Moolenaarbf630112023-05-19 21:41:02 +0100912 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200913 \ '>backtrace',
914 \ '->0 command line',
915 \ 'cmd: call GlobalFunction()'])
916
917 " And now we're back into the call stack
Bram Moolenaarbf630112023-05-19 21:41:02 +0100918 call s:RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()'])
919 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200920 \ '>backtrace',
921 \ ' 1 command line',
922 \ '->0 function GlobalFunction',
923 \ 'line 1: call CallAFunction()'])
924
925 call StopVimInTerminal(buf)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200926endfunc
927
928func Test_Backtrace_DefFunction()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +0200929 CheckCWD
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200930 let file1 =<< trim END
931 vim9script
Bram Moolenaar84c62d52022-01-06 21:31:19 +0000932 import './Xtest2.vim' as imp
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200933
934 def SourceAnotherFile()
935 source Xtest2.vim
936 enddef
937
938 def CallAFunction()
939 SourceAnotherFile()
Bram Moolenaar84c62d52022-01-06 21:31:19 +0000940 imp.File2Function()
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200941 enddef
942
943 def g:GlobalFunction()
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200944 var some = "some var"
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200945 CallAFunction()
946 enddef
947
948 defcompile
949 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100950 call writefile(file1, 'Xtest1.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200951
952 let file2 =<< trim END
953 vim9script
954
955 def DoAThing(): number
Bram Moolenaar1bdae402020-10-03 14:14:56 +0200956 var a = 100 * 2
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200957 a += 3
958 return a
959 enddef
960
961 export def File2Function()
962 DoAThing()
963 enddef
964
965 defcompile
966 File2Function()
967 END
Bram Moolenaar59173412022-09-20 22:01:33 +0100968 call writefile(file2, 'Xtest2.vim', 'D')
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200969
970 let buf = RunVimInTerminal('-S Xtest1.vim', {})
971
Bram Moolenaarbf630112023-05-19 21:41:02 +0100972 call s:RunDbgCmd(buf,
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200973 \ ':debug call GlobalFunction()',
974 \ ['cmd: call GlobalFunction()'])
975
Bram Moolenaarbf630112023-05-19 21:41:02 +0100976 call s:RunDbgCmd(buf, 'step', ['line 1: var some = "some var"'])
977 call s:RunDbgCmd(buf, 'step', ['line 2: CallAFunction()'])
978 call s:RunDbgCmd(buf, 'echo some', ['some var'])
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200979
Bram Moolenaarbf630112023-05-19 21:41:02 +0100980 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200981 \ '\V>backtrace',
Bram Moolenaare99d4222021-06-13 14:01:26 +0200982 \ '\V->0 function GlobalFunction',
Bram Moolenaar4cea5362021-06-16 22:24:40 +0200983 \ '\Vline 2: CallAFunction()',
Bram Moolenaare99d4222021-06-13 14:01:26 +0200984 \ ],
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200985 \ #{match: 'pattern'})
986
Bram Moolenaarbf630112023-05-19 21:41:02 +0100987 call s:RunDbgCmd(buf, 'step', ['line 1: SourceAnotherFile()'])
988 call s:RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000989 " Repeated line, because we first are in the compiled function before the
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200990 " EXEC and then in do_cmdline() before the :source command.
Bram Moolenaarbf630112023-05-19 21:41:02 +0100991 call s:RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
992 call s:RunDbgCmd(buf, 'step', ['line 1: vim9script'])
993 call s:RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number'])
994 call s:RunDbgCmd(buf, 'step', ['line 9: export def File2Function()'])
995 call s:RunDbgCmd(buf, 'step', ['line 13: defcompile'])
996 call s:RunDbgCmd(buf, 'step', ['line 14: File2Function()'])
997 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +0200998 \ '\V>backtrace',
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200999 \ '\V 3 function GlobalFunction[2]',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001000 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
1001 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
1002 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
1003 \ '\Vline 14: File2Function()'],
1004 \ #{match: 'pattern'})
1005
1006 " Don't step into compiled functions...
Bram Moolenaarbf630112023-05-19 21:41:02 +01001007 call s:RunDbgCmd(buf, 'next', ['line 15: End of sourced file'])
1008 call s:RunDbgCmd(buf, 'backtrace', [
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001009 \ '\V>backtrace',
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001010 \ '\V 3 function GlobalFunction[2]',
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001011 \ '\V 2 <SNR>\.\*_CallAFunction[1]',
1012 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]',
1013 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim',
1014 \ '\Vline 15: End of sourced file'],
1015 \ #{match: 'pattern'})
1016
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001017 call StopVimInTerminal(buf)
Bram Moolenaar6ca6ca42020-07-27 19:47:07 +02001018endfunc
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001019
Bram Moolenaar26a44842021-09-02 18:49:06 +02001020func Test_DefFunction_expr()
1021 CheckCWD
1022 let file3 =<< trim END
1023 vim9script
1024 g:someVar = "foo"
1025 def g:ChangeVar()
1026 g:someVar = "bar"
1027 echo "changed"
1028 enddef
1029 defcompile
1030 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001031 call writefile(file3, 'Xtest3.vim', 'D')
Bram Moolenaar26a44842021-09-02 18:49:06 +02001032 let buf = RunVimInTerminal('-S Xtest3.vim', {})
1033
Bram Moolenaarbf630112023-05-19 21:41:02 +01001034 call s:RunDbgCmd(buf, ':breakadd expr g:someVar')
1035 call s:RunDbgCmd(buf, ':call g:ChangeVar()', ['Oldval = "''foo''"', 'Newval = "''bar''"', 'function ChangeVar', 'line 2: echo "changed"'])
Bram Moolenaar26a44842021-09-02 18:49:06 +02001036
1037 call StopVimInTerminal(buf)
Bram Moolenaar26a44842021-09-02 18:49:06 +02001038endfunc
1039
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001040func Test_debug_def_and_legacy_function()
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001041 CheckCWD
1042 let file =<< trim END
1043 vim9script
1044 def g:SomeFunc()
1045 echo "here"
1046 echo "and"
1047 echo "there"
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001048 breakadd func 2 LocalFunc
1049 LocalFunc()
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001050 enddef
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001051
1052 def LocalFunc()
1053 echo "first"
1054 echo "second"
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001055 breakadd func LegacyFunc
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001056 LegacyFunc()
1057 enddef
1058
1059 func LegacyFunc()
1060 echo "legone"
1061 echo "legtwo"
1062 endfunc
1063
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001064 breakadd func 2 g:SomeFunc
1065 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001066 call writefile(file, 'XtestDebug.vim', 'D')
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001067
1068 let buf = RunVimInTerminal('-S XtestDebug.vim', {})
1069
Bram Moolenaarbf630112023-05-19 21:41:02 +01001070 call s:RunDbgCmd(buf,':call SomeFunc()', ['line 2: echo "and"'])
1071 call s:RunDbgCmd(buf,'next', ['line 3: echo "there"'])
1072 call s:RunDbgCmd(buf,'next', ['line 4: breakadd func 2 LocalFunc'])
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001073
1074 " continue, next breakpoint is in LocalFunc()
Bram Moolenaarbf630112023-05-19 21:41:02 +01001075 call s:RunDbgCmd(buf,'cont', ['line 2: echo "second"'])
Bram Moolenaar2ac4b252021-06-20 20:09:42 +02001076
1077 " continue, next breakpoint is in LegacyFunc()
Bram Moolenaarbf630112023-05-19 21:41:02 +01001078 call s:RunDbgCmd(buf,'cont', ['line 1: echo "legone"'])
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001079
Bram Moolenaarbf630112023-05-19 21:41:02 +01001080 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001081
1082 call StopVimInTerminal(buf)
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001083endfunc
1084
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001085func Test_debug_def_function()
1086 CheckCWD
1087 let file =<< trim END
1088 vim9script
1089 def g:Func()
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001090 var n: number
1091 def Closure(): number
1092 return n + 3
1093 enddef
1094 n += Closure()
1095 echo 'result: ' .. n
1096 enddef
1097
1098 def g:FuncWithArgs(text: string, nr: number, ...items: list<number>)
1099 echo text .. nr
1100 for it in items
1101 echo it
1102 endfor
1103 echo "done"
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001104 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001105
1106 def g:FuncWithDict()
1107 var d = {
1108 a: 1,
1109 b: 2,
1110 }
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001111 # comment
1112 def Inner()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001113 eval 1 + 2
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001114 enddef
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001115 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001116
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001117 def g:FuncComment()
1118 # comment
1119 echo "first"
1120 .. "one"
1121 # comment
1122 echo "second"
1123 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001124
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001125 def g:FuncForLoop()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001126 eval 1 + 2
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001127 for i in [11, 22, 33]
Bram Moolenaar31e21762021-07-10 20:43:59 +02001128 eval i + 2
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001129 endfor
1130 echo "done"
1131 enddef
Bram Moolenaar303215d2021-07-07 20:10:43 +02001132
1133 def g:FuncWithSplitLine()
Bram Moolenaar31e21762021-07-10 20:43:59 +02001134 eval 1 + 2
1135 | eval 2 + 3
Bram Moolenaar303215d2021-07-07 20:10:43 +02001136 enddef
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001137 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001138 call writefile(file, 'Xtest.vim', 'D')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001139
1140 let buf = RunVimInTerminal('-S Xtest.vim', {})
1141
Bram Moolenaarbf630112023-05-19 21:41:02 +01001142 call s:RunDbgCmd(buf,
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001143 \ ':debug call Func()',
1144 \ ['cmd: call Func()'])
Bram Moolenaarbf630112023-05-19 21:41:02 +01001145 call s:RunDbgCmd(buf, 'next', ['result: 3'])
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001146 call term_sendkeys(buf, "\r")
Bram Moolenaarbf630112023-05-19 21:41:02 +01001147 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001148
Bram Moolenaarbf630112023-05-19 21:41:02 +01001149 call s:RunDbgCmd(buf,
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001150 \ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)',
1151 \ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)'])
Bram Moolenaarbf630112023-05-19 21:41:02 +01001152 call s:RunDbgCmd(buf, 'step', ['line 1: echo text .. nr'])
1153 call s:RunDbgCmd(buf, 'echo text', ['asdf'])
1154 call s:RunDbgCmd(buf, 'echo nr', ['42'])
1155 call s:RunDbgCmd(buf, 'echo items', ['[1, 2, 3]'])
1156 call s:RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items'])
1157 call s:RunDbgCmd(buf, 'step', ['function FuncWithArgs', 'line 2: for it in items'])
1158 call s:RunDbgCmd(buf, 'echo it', ['0'])
1159 call s:RunDbgCmd(buf, 'step', ['line 3: echo it'])
1160 call s:RunDbgCmd(buf, 'echo it', ['1'])
1161 call s:RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor'])
1162 call s:RunDbgCmd(buf, 'step', ['line 2: for it in items'])
1163 call s:RunDbgCmd(buf, 'echo it', ['1'])
1164 call s:RunDbgCmd(buf, 'step', ['line 3: echo it'])
1165 call s:RunDbgCmd(buf, 'step', ['2', 'function FuncWithArgs', 'line 4: endfor'])
1166 call s:RunDbgCmd(buf, 'step', ['line 2: for it in items'])
1167 call s:RunDbgCmd(buf, 'echo it', ['2'])
1168 call s:RunDbgCmd(buf, 'step', ['line 3: echo it'])
1169 call s:RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor'])
1170 call s:RunDbgCmd(buf, 'step', ['line 2: for it in items'])
1171 call s:RunDbgCmd(buf, 'step', ['line 5: echo "done"'])
1172 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001173
Bram Moolenaarbf630112023-05-19 21:41:02 +01001174 call s:RunDbgCmd(buf,
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001175 \ ':debug call FuncWithDict()',
1176 \ ['cmd: call FuncWithDict()'])
Bram Moolenaarbf630112023-05-19 21:41:02 +01001177 call s:RunDbgCmd(buf, 'step', ['line 1: var d = { a: 1, b: 2, }'])
1178 call s:RunDbgCmd(buf, 'step', ['line 6: def Inner()'])
1179 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001180
Bram Moolenaarbf630112023-05-19 21:41:02 +01001181 call s:RunDbgCmd(buf, ':breakadd func 1 FuncComment')
1182 call s:RunDbgCmd(buf, ':call FuncComment()', ['function FuncComment', 'line 2: echo "first" .. "one"'])
1183 call s:RunDbgCmd(buf, ':breakadd func 3 FuncComment')
1184 call s:RunDbgCmd(buf, 'cont', ['function FuncComment', 'line 5: echo "second"'])
1185 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar6fc01612021-07-03 13:36:31 +02001186
Bram Moolenaarbf630112023-05-19 21:41:02 +01001187 call s:RunDbgCmd(buf, ':breakadd func 2 FuncForLoop')
1188 call s:RunDbgCmd(buf, ':call FuncForLoop()', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
1189 call s:RunDbgCmd(buf, 'step', ['line 2: for i in [11, 22, 33]'])
1190 call s:RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 3: eval i + 2'])
1191 call s:RunDbgCmd(buf, 'echo i', ['11'])
1192 call s:RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 4: endfor'])
1193 call s:RunDbgCmd(buf, 'next', ['function FuncForLoop', 'line 2: for i in [11, 22, 33]'])
1194 call s:RunDbgCmd(buf, 'next', ['line 3: eval i + 2'])
1195 call s:RunDbgCmd(buf, 'echo i', ['22'])
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001196
Bram Moolenaarbf630112023-05-19 21:41:02 +01001197 call s:RunDbgCmd(buf, 'breakdel *')
1198 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar303215d2021-07-07 20:10:43 +02001199
Bram Moolenaarbf630112023-05-19 21:41:02 +01001200 call s:RunDbgCmd(buf, ':breakadd func FuncWithSplitLine')
1201 call s:RunDbgCmd(buf, ':call FuncWithSplitLine()', ['function FuncWithSplitLine', 'line 1: eval 1 + 2 | eval 2 + 3'])
Bram Moolenaar303215d2021-07-07 20:10:43 +02001202
Bram Moolenaarbf630112023-05-19 21:41:02 +01001203 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001204 call StopVimInTerminal(buf)
Bram Moolenaar968a5b62021-06-15 19:32:40 +02001205endfunc
1206
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001207func Test_debug_def_function_with_lambda()
1208 CheckCWD
1209 let lines =<< trim END
1210 vim9script
1211 def g:Func()
1212 var s = 'a'
1213 ['b']->map((_, v) => s)
1214 echo "done"
1215 enddef
1216 breakadd func 2 g:Func
1217 END
Bram Moolenaar59173412022-09-20 22:01:33 +01001218 call writefile(lines, 'XtestLambda.vim', 'D')
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001219
1220 let buf = RunVimInTerminal('-S XtestLambda.vim', {})
1221
Bram Moolenaarbf630112023-05-19 21:41:02 +01001222 call s:RunDbgCmd(buf,
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001223 \ ':call g:Func()',
1224 \ ['function Func', 'line 2: [''b'']->map((_, v) => s)'])
Bram Moolenaarbf630112023-05-19 21:41:02 +01001225 call s:RunDbgCmd(buf,
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001226 \ 'next',
1227 \ ['function Func', 'line 3: echo "done"'])
1228
Bram Moolenaarbf630112023-05-19 21:41:02 +01001229 call s:RunDbgCmd(buf, 'cont')
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001230 call StopVimInTerminal(buf)
Bram Moolenaar17d868b2021-06-27 16:29:53 +02001231endfunc
1232
Bram Moolenaarbf630112023-05-19 21:41:02 +01001233def Test_debug_backtrace_level()
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001234 CheckCWD
Bram Moolenaarbf630112023-05-19 21:41:02 +01001235 var lines =<< trim END
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001236 let s:file1_var = 'file1'
1237 let g:global_var = 'global'
1238
1239 func s:File1Func( arg )
1240 let s:file1_var .= a:arg
1241 let local_var = s:file1_var .. ' test1'
1242 let g:global_var .= local_var
1243 source Xtest2.vim
1244 endfunc
1245
1246 call s:File1Func( 'arg1' )
1247 END
Bram Moolenaarbf630112023-05-19 21:41:02 +01001248 writefile(lines, 'Xtest1.vim', 'D')
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001249
Bram Moolenaarbf630112023-05-19 21:41:02 +01001250 lines =<< trim END
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001251 let s:file2_var = 'file2'
1252
1253 func s:File2Func( arg )
1254 let s:file2_var .= a:arg
1255 let local_var = s:file2_var .. ' test2'
1256 let g:global_var .= local_var
1257 endfunc
1258
1259 call s:File2Func( 'arg2' )
1260 END
Bram Moolenaarbf630112023-05-19 21:41:02 +01001261 writefile(lines, 'Xtest2.vim', 'D')
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001262
Bram Moolenaarbf630112023-05-19 21:41:02 +01001263 var file1 = getcwd() .. '/Xtest1.vim'
1264 var file2 = getcwd() .. '/Xtest2.vim'
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001265
Bram Moolenaarbf630112023-05-19 21:41:02 +01001266 # set a breakpoint and source file1.vim
1267 var buf = g:RunVimInTerminal(
1268 '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim',
1269 {wait_for_ruler: 0})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001270
Bram Moolenaarbf630112023-05-19 21:41:02 +01001271 s:CheckDbgOutput(buf, [
1272 'Breakpoint in "' .. file1 .. '" line 1',
1273 'Entering Debug mode. Type "cont" to continue.',
1274 'command line..script ' .. file1,
1275 'line 1: let s:file1_var = ''file1'''
1276 ], {msec: 5000})
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001277
Bram Moolenaarbf630112023-05-19 21:41:02 +01001278 # step through the initial declarations
1279 s:RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] )
1280 s:RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] )
1281 s:RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1282 s:RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1283 s:RunDbgCmd(buf, 'echo global_var', [ 'global' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001284
Bram Moolenaarbf630112023-05-19 21:41:02 +01001285 # step in to the first function
1286 s:RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] )
1287 s:RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] )
1288 s:RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1289 s:RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1290 s:RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1291 s:RunDbgCmd(buf,
1292 'echo global_var',
1293 [ 'E121: Undefined variable: global_var' ] )
1294 s:RunDbgCmd(buf,
1295 'echo local_var',
1296 [ 'E121: Undefined variable: local_var' ] )
1297 s:RunDbgCmd(buf,
1298 'echo l:local_var',
1299 [ 'E121: Undefined variable: l:local_var' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001300
Bram Moolenaarbf630112023-05-19 21:41:02 +01001301 # backtrace up
1302 s:RunDbgCmd(buf, 'backtrace', [
1303 '\V>backtrace',
1304 '\V 2 command line',
1305 '\V 1 script ' .. file1 .. '[11]',
1306 '\V->0 function <SNR>\.\*_File1Func',
1307 '\Vline 1: let s:file1_var .= a:arg',
1308 ],
1309 { match: 'pattern' } )
1310 s:RunDbgCmd(buf, 'up', [ '>up' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001311
Bram Moolenaarbf630112023-05-19 21:41:02 +01001312 s:RunDbgCmd(buf, 'backtrace', [
1313 '\V>backtrace',
1314 '\V 2 command line',
1315 '\V->1 script ' .. file1 .. '[11]',
1316 '\V 0 function <SNR>\.\*_File1Func',
1317 '\Vline 1: let s:file1_var .= a:arg',
1318 ],
1319 { match: 'pattern' } )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001320
Bram Moolenaarbf630112023-05-19 21:41:02 +01001321 # Expression evaluation in the script frame (not the function frame)
1322 # FIXME: Unexpected in this scope (a: should not be visible)
1323 s:RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] )
1324 s:RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] )
1325 s:RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] )
1326 # FIXME: Unexpected in this scope (global should be found)
1327 s:RunDbgCmd(buf,
1328 'echo global_var',
1329 [ 'E121: Undefined variable: global_var' ] )
1330 s:RunDbgCmd(buf,
1331 'echo local_var',
1332 [ 'E121: Undefined variable: local_var' ] )
1333 s:RunDbgCmd(buf,
1334 'echo l:local_var',
1335 [ 'E121: Undefined variable: l:local_var' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001336
1337
Bram Moolenaarbf630112023-05-19 21:41:02 +01001338 # step while backtraced jumps to the latest frame
1339 s:RunDbgCmd(buf, 'step', [
1340 'line 2: let local_var = s:file1_var .. '' test1''' ] )
1341 s:RunDbgCmd(buf, 'backtrace', [
1342 '\V>backtrace',
1343 '\V 2 command line',
1344 '\V 1 script ' .. file1 .. '[11]',
1345 '\V->0 function <SNR>\.\*_File1Func',
1346 '\Vline 2: let local_var = s:file1_var .. '' test1''',
1347 ],
1348 { match: 'pattern' } )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001349
Bram Moolenaarbf630112023-05-19 21:41:02 +01001350 s:RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] )
1351 s:RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] )
1352 s:RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001353
Bram Moolenaarbf630112023-05-19 21:41:02 +01001354 s:RunDbgCmd(buf, 'step', [ 'line 4: source Xtest2.vim' ] )
1355 s:RunDbgCmd(buf, 'step', [ 'line 1: let s:file2_var = ''file2''' ] )
1356 s:RunDbgCmd(buf, 'backtrace', [
1357 '\V>backtrace',
1358 '\V 3 command line',
1359 '\V 2 script ' .. file1 .. '[11]',
1360 '\V 1 function <SNR>\.\*_File1Func[4]',
1361 '\V->0 script ' .. file2,
1362 '\Vline 1: let s:file2_var = ''file2''',
1363 ],
1364 { match: 'pattern' } )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001365
Bram Moolenaarbf630112023-05-19 21:41:02 +01001366 # Expression evaluation in the script frame file2 (not the function frame)
1367 s:RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1368 s:RunDbgCmd(buf,
1369 'echo s:file1_var',
1370 [ 'E121: Undefined variable: s:file1_var' ] )
1371 s:RunDbgCmd(buf, 'echo g:global_var', [ 'globalfile1arg1 test1' ] )
1372 s:RunDbgCmd(buf, 'echo global_var', [ 'globalfile1arg1 test1' ] )
1373 s:RunDbgCmd(buf,
1374 'echo local_var',
1375 [ 'E121: Undefined variable: local_var' ] )
1376 s:RunDbgCmd(buf,
1377 'echo l:local_var',
1378 [ 'E121: Undefined variable: l:local_var' ] )
1379 s:RunDbgCmd(buf,
1380 'echo s:file2_var',
1381 [ 'E121: Undefined variable: s:file2_var' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001382
Bram Moolenaarbf630112023-05-19 21:41:02 +01001383 s:RunDbgCmd(buf, 'step', [ 'line 3: func s:File2Func( arg )' ] )
1384 s:RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001385
Bram Moolenaarbf630112023-05-19 21:41:02 +01001386 # Up the stack to the other script context
1387 s:RunDbgCmd(buf, 'up')
1388 s:RunDbgCmd(buf, 'backtrace', [
1389 '\V>backtrace',
1390 '\V 3 command line',
1391 '\V 2 script ' .. file1 .. '[11]',
1392 '\V->1 function <SNR>\.\*_File1Func[4]',
1393 '\V 0 script ' .. file2,
1394 '\Vline 3: func s:File2Func( arg )',
1395 ],
1396 { match: 'pattern' } )
1397 # FIXME: Unexpected. Should see the a: and l: dicts from File1Func
1398 s:RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] )
1399 s:RunDbgCmd(buf,
1400 'echo l:local_var',
1401 [ 'E121: Undefined variable: l:local_var' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001402
Bram Moolenaarbf630112023-05-19 21:41:02 +01001403 s:RunDbgCmd(buf, 'up')
1404 s:RunDbgCmd(buf, 'backtrace', [
1405 '\V>backtrace',
1406 '\V 3 command line',
1407 '\V->2 script ' .. file1 .. '[11]',
1408 '\V 1 function <SNR>\.\*_File1Func[4]',
1409 '\V 0 script ' .. file2,
1410 '\Vline 3: func s:File2Func( arg )',
1411 ],
1412 { match: 'pattern' } )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001413
Bram Moolenaarbf630112023-05-19 21:41:02 +01001414 # FIXME: Unexpected (wrong script vars are used)
1415 s:RunDbgCmd(buf,
1416 'echo s:file1_var',
1417 [ 'E121: Undefined variable: s:file1_var' ] )
1418 s:RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] )
Bram Moolenaarb7f4fa52020-08-08 14:41:52 +02001419
Bram Moolenaarbf630112023-05-19 21:41:02 +01001420 s:RunDbgCmd(buf, 'cont')
1421 g:StopVimInTerminal(buf)
1422enddef
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001423
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001424" Test for setting a breakpoint on a :endif where the :if condition is false
1425" and then quit the script. This should generate an interrupt.
1426func Test_breakpt_endif_intr()
1427 func F()
1428 let g:Xpath ..= 'a'
1429 if v:false
1430 let g:Xpath ..= 'b'
1431 endif
1432 invalid_command
1433 endfunc
1434
1435 let g:Xpath = ''
1436 breakadd func 4 F
1437 try
1438 let caught_intr = 0
1439 debuggreedy
1440 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001441 catch /^Vim:Interrupt$/
1442 call assert_match('\.F, line 4', v:throwpoint)
1443 let caught_intr = 1
1444 endtry
1445 0debuggreedy
1446 call assert_equal(1, caught_intr)
1447 call assert_equal('a', g:Xpath)
1448 breakdel *
1449 delfunc F
1450endfunc
1451
1452" Test for setting a breakpoint on a :else where the :if condition is false
1453" and then quit the script. This should generate an interrupt.
1454func Test_breakpt_else_intr()
1455 func F()
1456 let g:Xpath ..= 'a'
1457 if v:false
1458 let g:Xpath ..= 'b'
1459 else
1460 invalid_command
1461 endif
1462 invalid_command
1463 endfunc
1464
1465 let g:Xpath = ''
1466 breakadd func 4 F
1467 try
1468 let caught_intr = 0
1469 debuggreedy
1470 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001471 catch /^Vim:Interrupt$/
1472 call assert_match('\.F, line 4', v:throwpoint)
1473 let caught_intr = 1
1474 endtry
1475 0debuggreedy
1476 call assert_equal(1, caught_intr)
1477 call assert_equal('a', g:Xpath)
1478 breakdel *
1479 delfunc F
1480endfunc
1481
1482" Test for setting a breakpoint on a :endwhile where the :while condition is
1483" false and then quit the script. This should generate an interrupt.
1484func Test_breakpt_endwhile_intr()
1485 func F()
1486 let g:Xpath ..= 'a'
1487 while v:false
1488 let g:Xpath ..= 'b'
1489 endwhile
1490 invalid_command
1491 endfunc
1492
1493 let g:Xpath = ''
1494 breakadd func 4 F
1495 try
1496 let caught_intr = 0
1497 debuggreedy
1498 call feedkeys(":call F()\<CR>quit\<CR>", "xt")
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001499 catch /^Vim:Interrupt$/
1500 call assert_match('\.F, line 4', v:throwpoint)
1501 let caught_intr = 1
1502 endtry
1503 0debuggreedy
1504 call assert_equal(1, caught_intr)
1505 call assert_equal('a', g:Xpath)
1506 breakdel *
1507 delfunc F
1508endfunc
1509
Bram Moolenaar16c62322020-08-13 19:20:04 +02001510" Test for setting a breakpoint on a script local function
1511func Test_breakpt_scriptlocal_func()
1512 let g:Xpath = ''
1513 func s:G()
1514 let g:Xpath ..= 'a'
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001515 endfunc
1516
Bram Moolenaar16c62322020-08-13 19:20:04 +02001517 let funcname = expand("<SID>") .. "G"
1518 exe "breakadd func 1 " .. funcname
1519 debuggreedy
1520 redir => output
1521 call feedkeys(":call " .. funcname .. "()\<CR>c\<CR>", "xt")
1522 redir END
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001523 0debuggreedy
Bram Moolenaar16c62322020-08-13 19:20:04 +02001524 call assert_match('Breakpoint in "' .. funcname .. '" line 1', output)
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001525 call assert_equal('a', g:Xpath)
1526 breakdel *
Bram Moolenaar16c62322020-08-13 19:20:04 +02001527 exe "delfunc " .. funcname
Bram Moolenaar7ac616c2020-08-12 22:22:09 +02001528endfunc
1529
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001530" vim: shiftwidth=2 sts=2 expandtab