1" Tests for the Vim script debug commands 2 3source shared.vim 4source screendump.vim 5source check.vim 6 7func CheckDbgOutput(buf, lines, options = {}) 8 " Verify the expected output 9 let lnum = 20 - len(a:lines) 10 for l in a:lines 11 if get(a:options, 'match', 'equal') ==# 'pattern' 12 call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, 200) 13 else 14 call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, 200) 15 endif 16 let lnum += 1 17 endfor 18endfunc 19 20" Run a Vim debugger command 21" If the expected output argument is supplied, then check for it. 22func RunDbgCmd(buf, cmd, ...) 23 call term_sendkeys(a:buf, a:cmd . "\r") 24 call TermWait(a:buf) 25 26 if a:0 != 0 27 let options = #{match: 'equal'} 28 if a:0 > 1 29 call extend(options, a:2) 30 endif 31 call CheckDbgOutput(a:buf, a:1, options) 32 endif 33endfunc 34 35" Debugger tests 36func Test_Debugger() 37 CheckRunVimInTerminal 38 39 " Create a Vim script with some functions 40 let lines =<< trim END 41 func Foo() 42 let var1 = 1 43 let var2 = Bar(var1) + 9 44 return var2 45 endfunc 46 func Bar(var) 47 let var1 = 2 + a:var 48 let var2 = Bazz(var1) + 4 49 return var2 50 endfunc 51 func Bazz(var) 52 try 53 let var1 = 3 + a:var 54 let var3 = "another var" 55 let var3 = "value2" 56 catch 57 let var4 = "exception" 58 endtry 59 return var1 60 endfunc 61 END 62 call writefile(lines, 'Xtest.vim') 63 64 " Start Vim in a terminal 65 let buf = RunVimInTerminal('-S Xtest.vim', {}) 66 67 " Start the Vim debugger 68 call RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()']) 69 70 " Create a few stack frames by stepping through functions 71 call RunDbgCmd(buf, 'step', ['line 1: let var1 = 1']) 72 call RunDbgCmd(buf, 'step', ['line 2: let var2 = Bar(var1) + 9']) 73 call RunDbgCmd(buf, 'step', ['line 1: let var1 = 2 + a:var']) 74 call RunDbgCmd(buf, 'step', ['line 2: let var2 = Bazz(var1) + 4']) 75 call RunDbgCmd(buf, 'step', ['line 1: try']) 76 call RunDbgCmd(buf, 'step', ['line 2: let var1 = 3 + a:var']) 77 call RunDbgCmd(buf, 'step', ['line 3: let var3 = "another var"']) 78 79 " check backtrace 80 call RunDbgCmd(buf, 'backtrace', [ 81 \ ' 2 function Foo[2]', 82 \ ' 1 Bar[2]', 83 \ '->0 Bazz', 84 \ 'line 3: let var3 = "another var"']) 85 86 " Check variables in different stack frames 87 call RunDbgCmd(buf, 'echo var1', ['6']) 88 89 call RunDbgCmd(buf, 'up') 90 call RunDbgCmd(buf, 'back', [ 91 \ ' 2 function Foo[2]', 92 \ '->1 Bar[2]', 93 \ ' 0 Bazz', 94 \ 'line 3: let var3 = "another var"']) 95 call RunDbgCmd(buf, 'echo var1', ['3']) 96 97 call RunDbgCmd(buf, 'u') 98 call RunDbgCmd(buf, 'bt', [ 99 \ '->2 function Foo[2]', 100 \ ' 1 Bar[2]', 101 \ ' 0 Bazz', 102 \ 'line 3: let var3 = "another var"']) 103 call RunDbgCmd(buf, 'echo var1', ['1']) 104 105 " Undefined variables 106 call RunDbgCmd(buf, 'step') 107 call RunDbgCmd(buf, 'frame 2') 108 call RunDbgCmd(buf, 'echo var3', [ 109 \ 'Error detected while processing function Foo[2]..Bar[2]..Bazz:', 110 \ 'line 4:', 111 \ 'E121: Undefined variable: var3']) 112 113 " var3 is defined in this level with some other value 114 call RunDbgCmd(buf, 'fr 0') 115 call RunDbgCmd(buf, 'echo var3', ['another var']) 116 117 call RunDbgCmd(buf, 'step') 118 call RunDbgCmd(buf, '') 119 call RunDbgCmd(buf, '') 120 call RunDbgCmd(buf, '') 121 call RunDbgCmd(buf, '') 122 call RunDbgCmd(buf, 'step', [ 123 \ 'function Foo[2]..Bar', 124 \ 'line 3: End of function']) 125 call RunDbgCmd(buf, 'up') 126 127 " Undefined var2 128 call RunDbgCmd(buf, 'echo var2', [ 129 \ 'Error detected while processing function Foo[2]..Bar:', 130 \ 'line 3:', 131 \ 'E121: Undefined variable: var2']) 132 133 " Var2 is defined with 10 134 call RunDbgCmd(buf, 'down') 135 call RunDbgCmd(buf, 'echo var2', ['10']) 136 137 " Backtrace movements 138 call RunDbgCmd(buf, 'b', [ 139 \ ' 1 function Foo[2]', 140 \ '->0 Bar', 141 \ 'line 3: End of function']) 142 143 " next command cannot go down, we are on bottom 144 call RunDbgCmd(buf, 'down', ['frame is zero']) 145 call RunDbgCmd(buf, 'up') 146 147 " next command cannot go up, we are on top 148 call RunDbgCmd(buf, 'up', ['frame at highest level: 1']) 149 call RunDbgCmd(buf, 'where', [ 150 \ '->1 function Foo[2]', 151 \ ' 0 Bar', 152 \ 'line 3: End of function']) 153 154 " fil is not frame or finish, it is file 155 call RunDbgCmd(buf, 'fil', ['"[No Name]" --No lines in buffer--']) 156 157 " relative backtrace movement 158 call RunDbgCmd(buf, 'fr -1') 159 call RunDbgCmd(buf, 'frame', [ 160 \ ' 1 function Foo[2]', 161 \ '->0 Bar', 162 \ 'line 3: End of function']) 163 164 call RunDbgCmd(buf, 'fr +1') 165 call RunDbgCmd(buf, 'fram', [ 166 \ '->1 function Foo[2]', 167 \ ' 0 Bar', 168 \ 'line 3: End of function']) 169 170 " go beyond limits does not crash 171 call RunDbgCmd(buf, 'fr 100', ['frame at highest level: 1']) 172 call RunDbgCmd(buf, 'fra', [ 173 \ '->1 function Foo[2]', 174 \ ' 0 Bar', 175 \ 'line 3: End of function']) 176 177 call RunDbgCmd(buf, 'frame -40', ['frame is zero']) 178 call RunDbgCmd(buf, 'fram', [ 179 \ ' 1 function Foo[2]', 180 \ '->0 Bar', 181 \ 'line 3: End of function']) 182 183 " final result 19 184 call RunDbgCmd(buf, 'cont', ['19']) 185 186 " breakpoints tests 187 188 " Start a debug session, so that reading the last line from the terminal 189 " works properly. 190 call RunDbgCmd(buf, ':debug echo Foo()') 191 192 " No breakpoints 193 call RunDbgCmd(buf, 'breakl', ['No breakpoints defined']) 194 195 " Place some breakpoints 196 call RunDbgCmd(buf, 'breaka func Bar') 197 call RunDbgCmd(buf, 'breaklis', [' 1 func Bar line 1']) 198 call RunDbgCmd(buf, 'breakadd func 3 Bazz') 199 call RunDbgCmd(buf, 'breaklist', [' 1 func Bar line 1', 200 \ ' 2 func Bazz line 3']) 201 202 " Check whether the breakpoints are hit 203 call RunDbgCmd(buf, 'cont', [ 204 \ 'Breakpoint in "Bar" line 1', 205 \ 'function Foo[2]..Bar', 206 \ 'line 1: let var1 = 2 + a:var']) 207 call RunDbgCmd(buf, 'cont', [ 208 \ 'Breakpoint in "Bazz" line 3', 209 \ 'function Foo[2]..Bar[2]..Bazz', 210 \ 'line 3: let var3 = "another var"']) 211 212 " Delete the breakpoints 213 call RunDbgCmd(buf, 'breakd 1') 214 call RunDbgCmd(buf, 'breakli', [' 2 func Bazz line 3']) 215 call RunDbgCmd(buf, 'breakdel func 3 Bazz') 216 call RunDbgCmd(buf, 'breakl', ['No breakpoints defined']) 217 218 call RunDbgCmd(buf, 'cont') 219 220 " Make sure the breakpoints are removed 221 call RunDbgCmd(buf, ':echo Foo()', ['19']) 222 223 " Delete a non-existing breakpoint 224 call RunDbgCmd(buf, ':breakdel 2', ['E161: Breakpoint not found: 2']) 225 226 " Expression breakpoint 227 call RunDbgCmd(buf, ':breakadd func 2 Bazz') 228 call RunDbgCmd(buf, ':echo Bazz(1)', [ 229 \ 'Entering Debug mode. Type "cont" to continue.', 230 \ 'function Bazz', 231 \ 'line 2: let var1 = 3 + a:var']) 232 call RunDbgCmd(buf, 'step') 233 call RunDbgCmd(buf, 'step') 234 call RunDbgCmd(buf, 'breaka expr var3') 235 call RunDbgCmd(buf, 'breakl', [' 3 func Bazz line 2', 236 \ ' 4 expr var3']) 237 call RunDbgCmd(buf, 'cont', ['Breakpoint in "Bazz" line 5', 238 \ 'Oldval = "''another var''"', 239 \ 'Newval = "''value2''"', 240 \ 'function Bazz', 241 \ 'line 5: catch']) 242 243 call RunDbgCmd(buf, 'breakdel *') 244 call RunDbgCmd(buf, 'breakl', ['No breakpoints defined']) 245 246 " Check for error cases 247 call RunDbgCmd(buf, 'breakadd abcd', [ 248 \ 'Error detected while processing function Bazz:', 249 \ 'line 5:', 250 \ 'E475: Invalid argument: abcd']) 251 call RunDbgCmd(buf, 'breakadd func', ['E475: Invalid argument: func']) 252 call RunDbgCmd(buf, 'breakadd func 2', ['E475: Invalid argument: func 2']) 253 call RunDbgCmd(buf, 'breaka func a()', ['E475: Invalid argument: func a()']) 254 call RunDbgCmd(buf, 'breakd abcd', ['E475: Invalid argument: abcd']) 255 call RunDbgCmd(buf, 'breakd func', ['E475: Invalid argument: func']) 256 call RunDbgCmd(buf, 'breakd func a()', ['E475: Invalid argument: func a()']) 257 call RunDbgCmd(buf, 'breakd func a', ['E161: Breakpoint not found: func a']) 258 call RunDbgCmd(buf, 'breakd expr', ['E475: Invalid argument: expr']) 259 call RunDbgCmd(buf, 'breakd expr x', [ 260 \ 'E121: Undefined variable: x', 261 \ 'E161: Breakpoint not found: expr x']) 262 263 " finish the current function 264 call RunDbgCmd(buf, 'finish', [ 265 \ 'function Bazz', 266 \ 'line 8: End of function']) 267 call RunDbgCmd(buf, 'cont') 268 269 " Test for :next 270 call RunDbgCmd(buf, ':debug echo Bar(1)') 271 call RunDbgCmd(buf, 'step') 272 call RunDbgCmd(buf, 'next') 273 call RunDbgCmd(buf, '', [ 274 \ 'function Bar', 275 \ 'line 3: return var2']) 276 call RunDbgCmd(buf, 'c') 277 278 " Test for :interrupt 279 call RunDbgCmd(buf, ':debug echo Bazz(1)') 280 call RunDbgCmd(buf, 'step') 281 call RunDbgCmd(buf, 'step') 282 call RunDbgCmd(buf, 'interrupt', [ 283 \ 'Exception thrown: Vim:Interrupt', 284 \ 'function Bazz', 285 \ 'line 5: catch']) 286 call RunDbgCmd(buf, 'c') 287 288 " Test for :quit 289 call RunDbgCmd(buf, ':debug echo Foo()') 290 call RunDbgCmd(buf, 'breakdel *') 291 call RunDbgCmd(buf, 'breakadd func 3 Foo') 292 call RunDbgCmd(buf, 'breakadd func 3 Bazz') 293 call RunDbgCmd(buf, 'cont', [ 294 \ 'Breakpoint in "Bazz" line 3', 295 \ 'function Foo[2]..Bar[2]..Bazz', 296 \ 'line 3: let var3 = "another var"']) 297 call RunDbgCmd(buf, 'quit', [ 298 \ 'Breakpoint in "Foo" line 3', 299 \ 'function Foo', 300 \ 'line 3: return var2']) 301 call RunDbgCmd(buf, 'breakdel *') 302 call RunDbgCmd(buf, 'quit') 303 call RunDbgCmd(buf, 'enew! | only!') 304 305 call StopVimInTerminal(buf) 306 307 " Tests for :breakadd file and :breakadd here 308 " Breakpoints should be set before sourcing the file 309 310 let lines =<< trim END 311 let var1 = 10 312 let var2 = 20 313 let var3 = 30 314 let var4 = 40 315 END 316 call writefile(lines, 'Xtest.vim') 317 318 " Start Vim in a terminal 319 let buf = RunVimInTerminal('Xtest.vim', {}) 320 call RunDbgCmd(buf, ':breakadd file 2 Xtest.vim') 321 call RunDbgCmd(buf, ':4 | breakadd here') 322 call RunDbgCmd(buf, ':source Xtest.vim', ['line 2: let var2 = 20']) 323 call RunDbgCmd(buf, 'cont', ['line 4: let var4 = 40']) 324 call RunDbgCmd(buf, 'cont') 325 326 call StopVimInTerminal(buf) 327 328 call delete('Xtest.vim') 329endfunc 330 331func Test_Backtrace_Through_Source() 332 CheckRunVimInTerminal 333 334 let file1 =<< trim END 335 func SourceAnotherFile() 336 source Xtest2.vim 337 endfunc 338 339 func CallAFunction() 340 call SourceAnotherFile() 341 call File2Function() 342 endfunc 343 344 func GlobalFunction() 345 call CallAFunction() 346 endfunc 347 END 348 call writefile(file1, 'Xtest1.vim') 349 350 let file2 =<< trim END 351 func DoAThing() 352 echo "DoAThing" 353 endfunc 354 355 func File2Function() 356 call DoAThing() 357 endfunc 358 359 call File2Function() 360 END 361 call writefile(file2, 'Xtest2.vim') 362 363 let buf = RunVimInTerminal('-S Xtest1.vim', {}) 364 365 call RunDbgCmd(buf, 366 \ ':debug call GlobalFunction()', 367 \ ['cmd: call GlobalFunction()']) 368 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()']) 369 370 call RunDbgCmd(buf, 'backtrace', ['>backtrace', 371 \ '->0 function GlobalFunction', 372 \ 'line 1: call CallAFunction()']) 373 374 call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()']) 375 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim']) 376 377 call RunDbgCmd(buf, 'backtrace', ['>backtrace', 378 \ ' 2 function GlobalFunction[1]', 379 \ ' 1 CallAFunction[1]', 380 \ '->0 SourceAnotherFile', 381 \ 'line 1: source Xtest2.vim']) 382 383 " Step into the 'source' command. Note that we print the full trace all the 384 " way though the source command. 385 call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()']) 386 call RunDbgCmd(buf, 'backtrace', [ 387 \ '>backtrace', 388 \ ' 3 function GlobalFunction[1]', 389 \ ' 2 CallAFunction[1]', 390 \ ' 1 SourceAnotherFile[1]', 391 \ '->0 script ' .. getcwd() .. '/Xtest2.vim', 392 \ 'line 1: func DoAThing()']) 393 394 " step until we have another meaninfgul trace 395 call RunDbgCmd(buf, 'step', ['line 5: func File2Function()']) 396 call RunDbgCmd(buf, 'step', ['line 9: call File2Function()']) 397 call RunDbgCmd(buf, 'backtrace', [ 398 \ '>backtrace', 399 \ ' 3 function GlobalFunction[1]', 400 \ ' 2 CallAFunction[1]', 401 \ ' 1 SourceAnotherFile[1]', 402 \ '->0 script ' .. getcwd() .. '/Xtest2.vim', 403 \ 'line 9: call File2Function()']) 404 405 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) 406 call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"']) 407 call RunDbgCmd(buf, 'backtrace', [ 408 \ '>backtrace', 409 \ ' 5 function GlobalFunction[1]', 410 \ ' 4 CallAFunction[1]', 411 \ ' 3 SourceAnotherFile[1]', 412 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]', 413 \ ' 1 function File2Function[1]', 414 \ '->0 DoAThing', 415 \ 'line 1: echo "DoAThing"']) 416 417 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim 418 call RunDbgCmd(buf, 'step', ['line 1: End of function']) 419 call RunDbgCmd(buf, 'step', ['line 1: End of function']) 420 call RunDbgCmd(buf, 'step', ['line 10: End of sourced file']) 421 call RunDbgCmd(buf, 'step', ['line 1: End of function']) 422 call RunDbgCmd(buf, 'step', ['line 2: call File2Function()']) 423 call RunDbgCmd(buf, 'backtrace', [ 424 \ '>backtrace', 425 \ ' 1 function GlobalFunction[1]', 426 \ '->0 CallAFunction', 427 \ 'line 2: call File2Function()']) 428 429 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) 430 call RunDbgCmd(buf, 'backtrace', [ 431 \ '>backtrace', 432 \ ' 2 function GlobalFunction[1]', 433 \ ' 1 CallAFunction[2]', 434 \ '->0 File2Function', 435 \ 'line 1: call DoAThing()']) 436 437 call StopVimInTerminal(buf) 438 call delete('Xtest1.vim') 439 call delete('Xtest2.vim') 440endfunc 441 442func Test_Backtrace_Autocmd() 443 CheckRunVimInTerminal 444 445 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 459 au User TestGlobalFunction :call GlobalFunction() | echo "Done" 460 END 461 call writefile(file1, 'Xtest1.vim') 462 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 474 call writefile(file2, 'Xtest2.vim') 475 476 let buf = RunVimInTerminal('-S Xtest1.vim', {}) 477 478 call RunDbgCmd(buf, 479 \ ':debug doautocmd User TestGlobalFunction', 480 \ ['cmd: doautocmd User TestGlobalFunction']) 481 call RunDbgCmd(buf, 'step', ['cmd: call GlobalFunction() | echo "Done"']) 482 483 " At this point the ontly thing in the stack is the autocommand 484 call RunDbgCmd(buf, 'backtrace', [ 485 \ '>backtrace', 486 \ '->0 User Autocommands for "TestGlobalFunction"', 487 \ 'cmd: call GlobalFunction() | echo "Done"']) 488 489 " And now we're back into the call stack 490 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()']) 491 call RunDbgCmd(buf, 'backtrace', [ 492 \ '>backtrace', 493 \ ' 1 User Autocommands for "TestGlobalFunction"', 494 \ '->0 function GlobalFunction', 495 \ 'line 1: call CallAFunction()']) 496 497 call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()']) 498 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim']) 499 500 call RunDbgCmd(buf, 'backtrace', [ 501 \ '>backtrace', 502 \ ' 3 User Autocommands for "TestGlobalFunction"', 503 \ ' 2 function GlobalFunction[1]', 504 \ ' 1 CallAFunction[1]', 505 \ '->0 SourceAnotherFile', 506 \ 'line 1: source Xtest2.vim']) 507 508 " Step into the 'source' command. Note that we print the full trace all the 509 " way though the source command. 510 call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()']) 511 call RunDbgCmd(buf, 'backtrace', [ 512 \ '>backtrace', 513 \ ' 4 User Autocommands for "TestGlobalFunction"', 514 \ ' 3 function GlobalFunction[1]', 515 \ ' 2 CallAFunction[1]', 516 \ ' 1 SourceAnotherFile[1]', 517 \ '->0 script ' .. getcwd() .. '/Xtest2.vim', 518 \ 'line 1: func DoAThing()']) 519 520 " step until we have another meaninfgul trace 521 call RunDbgCmd(buf, 'step', ['line 5: func File2Function()']) 522 call RunDbgCmd(buf, 'step', ['line 9: call File2Function()']) 523 call RunDbgCmd(buf, 'backtrace', [ 524 \ '>backtrace', 525 \ ' 4 User Autocommands for "TestGlobalFunction"', 526 \ ' 3 function GlobalFunction[1]', 527 \ ' 2 CallAFunction[1]', 528 \ ' 1 SourceAnotherFile[1]', 529 \ '->0 script ' .. getcwd() .. '/Xtest2.vim', 530 \ 'line 9: call File2Function()']) 531 532 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) 533 call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"']) 534 call RunDbgCmd(buf, 'backtrace', [ 535 \ '>backtrace', 536 \ ' 6 User Autocommands for "TestGlobalFunction"', 537 \ ' 5 function GlobalFunction[1]', 538 \ ' 4 CallAFunction[1]', 539 \ ' 3 SourceAnotherFile[1]', 540 \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]', 541 \ ' 1 function File2Function[1]', 542 \ '->0 DoAThing', 543 \ 'line 1: echo "DoAThing"']) 544 545 " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim 546 call RunDbgCmd(buf, 'step', ['line 1: End of function']) 547 call RunDbgCmd(buf, 'step', ['line 1: End of function']) 548 call RunDbgCmd(buf, 'step', ['line 10: End of sourced file']) 549 call RunDbgCmd(buf, 'step', ['line 1: End of function']) 550 call RunDbgCmd(buf, 'step', ['line 2: call File2Function()']) 551 call RunDbgCmd(buf, 'backtrace', [ 552 \ '>backtrace', 553 \ ' 2 User Autocommands for "TestGlobalFunction"', 554 \ ' 1 function GlobalFunction[1]', 555 \ '->0 CallAFunction', 556 \ 'line 2: call File2Function()']) 557 558 call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) 559 call RunDbgCmd(buf, 'backtrace', [ 560 \ '>backtrace', 561 \ ' 3 User Autocommands for "TestGlobalFunction"', 562 \ ' 2 function GlobalFunction[1]', 563 \ ' 1 CallAFunction[2]', 564 \ '->0 File2Function', 565 \ 'line 1: call DoAThing()']) 566 567 568 " Now unwind so that we get back to the original autocommand (and the second 569 " cmd echo "Done") 570 call RunDbgCmd(buf, 'finish', ['line 1: End of function']) 571 call RunDbgCmd(buf, 'backtrace', [ 572 \ '>backtrace', 573 \ ' 3 User Autocommands for "TestGlobalFunction"', 574 \ ' 2 function GlobalFunction[1]', 575 \ ' 1 CallAFunction[2]', 576 \ '->0 File2Function', 577 \ 'line 1: End of function']) 578 579 call RunDbgCmd(buf, 'finish', ['line 2: End of function']) 580 call RunDbgCmd(buf, 'backtrace', [ 581 \ '>backtrace', 582 \ ' 2 User Autocommands for "TestGlobalFunction"', 583 \ ' 1 function GlobalFunction[1]', 584 \ '->0 CallAFunction', 585 \ 'line 2: End of function']) 586 587 call RunDbgCmd(buf, 'finish', ['line 1: End of function']) 588 call RunDbgCmd(buf, 'backtrace', [ 589 \ '>backtrace', 590 \ ' 1 User Autocommands for "TestGlobalFunction"', 591 \ '->0 function GlobalFunction', 592 \ 'line 1: End of function']) 593 594 call RunDbgCmd(buf, 'step', ['cmd: echo "Done"']) 595 call RunDbgCmd(buf, 'backtrace', [ 596 \ '>backtrace', 597 \ '->0 User Autocommands for "TestGlobalFunction"', 598 \ 'cmd: echo "Done"']) 599 600 call StopVimInTerminal(buf) 601 call delete('Xtest1.vim') 602 call delete('Xtest2.vim') 603endfunc 604 605func Test_Backtrace_CmdLine() 606 CheckRunVimInTerminal 607 608 let file1 =<< trim END 609 func SourceAnotherFile() 610 source Xtest2.vim 611 endfunc 612 613 func CallAFunction() 614 call SourceAnotherFile() 615 call File2Function() 616 endfunc 617 618 func GlobalFunction() 619 call CallAFunction() 620 endfunc 621 622 au User TestGlobalFunction :call GlobalFunction() | echo "Done" 623 END 624 call writefile(file1, 'Xtest1.vim') 625 626 let file2 =<< trim END 627 func DoAThing() 628 echo "DoAThing" 629 endfunc 630 631 func File2Function() 632 call DoAThing() 633 endfunc 634 635 call File2Function() 636 END 637 call writefile(file2, 'Xtest2.vim') 638 639 let buf = RunVimInTerminal( 640 \ '-S Xtest1.vim -c "debug call GlobalFunction()"', 641 \ {'wait_for_ruler': 0}) 642 643 " Need to wait for the vim-in-terminal to be ready 644 call CheckDbgOutput(buf, ['command line', 645 \ 'cmd: call GlobalFunction()']) 646 647 " At this point the ontly thing in the stack is the cmdline 648 call RunDbgCmd(buf, 'backtrace', [ 649 \ '>backtrace', 650 \ '->0 command line', 651 \ 'cmd: call GlobalFunction()']) 652 653 " And now we're back into the call stack 654 call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()']) 655 call RunDbgCmd(buf, 'backtrace', [ 656 \ '>backtrace', 657 \ ' 1 command line', 658 \ '->0 function GlobalFunction', 659 \ 'line 1: call CallAFunction()']) 660 661 call StopVimInTerminal(buf) 662 call delete('Xtest1.vim') 663 call delete('Xtest2.vim') 664endfunc 665 666func Test_Backtrace_DefFunction() 667 CheckRunVimInTerminal 668 669 let file1 =<< trim END 670 vim9script 671 import File2Function from './Xtest2.vim' 672 673 def SourceAnotherFile() 674 source Xtest2.vim 675 enddef 676 677 def CallAFunction() 678 SourceAnotherFile() 679 File2Function() 680 enddef 681 682 def g:GlobalFunction() 683 CallAFunction() 684 enddef 685 686 defcompile 687 END 688 call writefile(file1, 'Xtest1.vim') 689 690 let file2 =<< trim END 691 vim9script 692 693 def DoAThing(): number 694 let a = 100 * 2 695 a += 3 696 return a 697 enddef 698 699 export def File2Function() 700 DoAThing() 701 enddef 702 703 defcompile 704 File2Function() 705 END 706 call writefile(file2, 'Xtest2.vim') 707 708 let buf = RunVimInTerminal('-S Xtest1.vim', {}) 709 710 call RunDbgCmd(buf, 711 \ ':debug call GlobalFunction()', 712 \ ['cmd: call GlobalFunction()']) 713 714 " FIXME: Vim9 lines are not debugged! 715 call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim']) 716 717 " But they do appear in the backtrace 718 call RunDbgCmd(buf, 'backtrace', [ 719 \ '\V>backtrace', 720 \ '\V 2 function GlobalFunction[1]', 721 \ '\V 1 <SNR>\.\*_CallAFunction[1]', 722 \ '\V->0 <SNR>\.\*_SourceAnotherFile', 723 \ '\Vline 1: source Xtest2.vim'], 724 \ #{match: 'pattern'}) 725 726 727 call RunDbgCmd(buf, 'step', ['line 1: vim9script']) 728 call RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number']) 729 call RunDbgCmd(buf, 'step', ['line 9: export def File2Function()']) 730 call RunDbgCmd(buf, 'step', ['line 9: def File2Function()']) 731 call RunDbgCmd(buf, 'step', ['line 13: defcompile']) 732 call RunDbgCmd(buf, 'step', ['line 14: File2Function()']) 733 call RunDbgCmd(buf, 'backtrace', [ 734 \ '\V>backtrace', 735 \ '\V 3 function GlobalFunction[1]', 736 \ '\V 2 <SNR>\.\*_CallAFunction[1]', 737 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]', 738 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim', 739 \ '\Vline 14: File2Function()'], 740 \ #{match: 'pattern'}) 741 742 " Don't step into compiled functions... 743 call RunDbgCmd(buf, 'step', ['line 15: End of sourced file']) 744 call RunDbgCmd(buf, 'backtrace', [ 745 \ '\V>backtrace', 746 \ '\V 3 function GlobalFunction[1]', 747 \ '\V 2 <SNR>\.\*_CallAFunction[1]', 748 \ '\V 1 <SNR>\.\*_SourceAnotherFile[1]', 749 \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim', 750 \ '\Vline 15: End of sourced file'], 751 \ #{match: 'pattern'}) 752 753 754 call StopVimInTerminal(buf) 755 call delete('Xtest1.vim') 756 call delete('Xtest2.vim') 757endfunc 758