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