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