1#!/usr/bin/python 2 3# Copyright 2016 Steven Watanabe 4# Distributed under the Boost Software License, Version 1.0. 5# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) 6 7# Test for the debugger 8 9import BoostBuild 10import TestCmd 11import re 12 13def split_stdin_stdout(text): 14 """stdin is all text after the prompt up to and including 15 the next newline. Everything else is stdout. stdout 16 may contain regular expressions enclosed in {{}}.""" 17 prompt = re.escape('(b2db) ') 18 pattern = re.compile('(?<=%s)(.*\n)' % prompt) 19 text = text.replace("{{bjam}}", "{{.*}}b2{{(?:\\.exe)?}}") 20 stdin = ''.join(re.findall(pattern, text)) 21 stdout = re.sub(pattern, '', text) 22 outside_pattern = re.compile(r'(?:\A|(?<=\}\}))(?:[^\{]|(?:\{(?!\{)))*(?:(?=\{\{)|\Z)') 23 24 def escape_line(line): 25 line = re.sub(outside_pattern, lambda m: re.escape(m.group(0)), line) 26 return re.sub(r'\{\{|\}\}', '', line) 27 28 stdout = '\n'.join([escape_line(line) for line in stdout.split('\n')]) 29 return (stdin,stdout) 30 31def run(tester, io): 32 (input,output) = split_stdin_stdout(io) 33 tester.run_build_system(stdin=input, stdout=output, match=TestCmd.match_re) 34 35def make_tester(): 36 return BoostBuild.Tester(["-dconsole"], pass_toolset=False, pass_d0=False, 37 use_test_config=False, ignore_toolset_requirements=False, match=TestCmd.match_re) 38 39def test_run(): 40 t = make_tester() 41 t.write("test.jam", """\ 42 UPDATE ; 43 """) 44 45 run(t, """\ 46(b2db) run -ftest.jam 47Starting program: {{bjam}} -ftest.jam 48Child {{\d+}} exited with status 0 49(b2db) quit 50""") 51 52 t.cleanup() 53 54def test_exit_status(): 55 t = make_tester() 56 t.write("test.jam", """\ 57 EXIT : 1 ; 58 """) 59 run(t, """\ 60(b2db) run -ftest.jam 61Starting program: {{bjam}} -ftest.jam 62 63Child {{\d+}} exited with status 1 64(b2db) quit 65""") 66 t.cleanup() 67 68def test_step(): 69 t = make_tester() 70 t.write("test.jam", """\ 71 rule g ( ) 72 { 73 a = 1 ; 74 b = 2 ; 75 } 76 rule f ( ) 77 { 78 g ; 79 c = 3 ; 80 } 81 f ; 82 """) 83 run(t, """\ 84(b2db) break f 85Breakpoint 1 set at f 86(b2db) run -ftest.jam 87Starting program: {{bjam}} -ftest.jam 88Breakpoint 1, f ( ) at test.jam:8 898 g ; 90(b2db) step 913 a = 1 ; 92(b2db) step 934 b = 2 ; 94(b2db) step 959 c = 3 ; 96(b2db) quit 97""") 98 t.cleanup() 99 100# Note: step doesn't need to worry about breakpoints, 101# as it always stops at the next line executed. 102 103def test_next(): 104 t = make_tester() 105 t.write("test.jam", """\ 106 rule g ( ) 107 { 108 a = 1 ; 109 } 110 rule f ( ) 111 { 112 g ; 113 b = 2 ; 114 c = 3 ; 115 } 116 rule h ( ) 117 { 118 f ; 119 g ; 120 } 121 h ; 122 d = 4 ; 123 """) 124 run(t, """\ 125(b2db) break f 126Breakpoint 1 set at f 127(b2db) run -ftest.jam 128Starting program: {{bjam}} -ftest.jam 129Breakpoint 1, f ( ) at test.jam:7 1307 g ; 131(b2db) next 1328 b = 2 ; 133(b2db) next 1349 c = 3 ; 135(b2db) next 13614 g ; 137(b2db) next 13817 d = 4 ; 139(b2db) quit 140""") 141 t.cleanup() 142 143def test_next_breakpoint(): 144 """next should stop if it encounters a breakpoint. 145 If the normal end point happens to be a breakpoint, 146 then it should be reported as normal stepping.""" 147 t = make_tester() 148 t.write("test.jam", """\ 149 rule f ( recurse ? ) 150 { 151 if $(recurse) { f ; } 152 a = 1 ; 153 } 154 rule g ( ) 155 { 156 b = 2 ; 157 } 158 f true ; 159 g ; 160 """) 161 run(t, """\ 162(b2db) break f 163Breakpoint 1 set at f 164(b2db) break g 165Breakpoint 2 set at g 166(b2db) break test.jam:4 167Breakpoint 3 set at test.jam:4 168(b2db) run -ftest.jam 169Starting program: {{bjam}} -ftest.jam 170Breakpoint 1, f ( true ) at test.jam:3 1713 if $(recurse) { f ; } 172(b2db) next 173Breakpoint 1, f ( ) at test.jam:3 1743 if $(recurse) { f ; } 175(b2db) next 1764 a = 1 ; 177(b2db) next 1784 a = 1 ; 179(b2db) next 18011 g ; 181(b2db) next 182Breakpoint 2, g ( ) at test.jam:8 1838 b = 2 ; 184(b2db) quit 185""") 186 t.cleanup() 187 188def test_finish(): 189 t = make_tester() 190 t.write("test.jam", """\ 191 rule f ( ) 192 { 193 a = 1 ; 194 } 195 rule g ( ) 196 { 197 f ; 198 b = 2 ; 199 i ; 200 } 201 rule h ( ) 202 { 203 g ; 204 i ; 205 } 206 rule i ( ) 207 { 208 c = 3 ; 209 } 210 h ; 211 d = 4 ; 212 """) 213 run(t, """\ 214(b2db) break f 215Breakpoint 1 set at f 216(b2db) run -ftest.jam 217Starting program: {{bjam}} -ftest.jam 218Breakpoint 1, f ( ) at test.jam:3 2193 a = 1 ; 220(b2db) finish 2218 b = 2 ; 222(b2db) finish 22314 i ; 224(b2db) finish 22521 d = 4 ; 226(b2db) quit 227""") 228 t.cleanup() 229 230def test_finish_breakpoints(): 231 """finish should stop when it reaches a breakpoint.""" 232 t = make_tester() 233 t.write("test.jam", """\ 234 rule f ( recurse * ) 235 { 236 if $(recurse) 237 { 238 a = [ f $(recurse[2-]) ] ; 239 } 240 } 241 rule g ( list * ) 242 { 243 for local v in $(list) 244 { 245 x = $(v) ; 246 } 247 } 248 f 1 2 ; 249 g 1 2 ; 250 """) 251 run(t, """\ 252(b2db) break test.jam:5 253Breakpoint 1 set at test.jam:5 254(b2db) break test.jam:12 255Breakpoint 2 set at test.jam:12 256(b2db) run -ftest.jam 257Starting program: {{bjam}} -ftest.jam 258Breakpoint 1, f ( 1 2 ) at test.jam:5 2595 a = [ f $(recurse[2-]) ] ; 260(b2db) finish 261Breakpoint 1, f ( 2 ) at test.jam:5 2625 a = [ f $(recurse[2-]) ] ; 263(b2db) finish 2645 a = [ f $(recurse[2-]) ] ; 265(b2db) finish 26616 g 1 2 ; 267(b2db) finish 268Breakpoint 2, g ( 1 2 ) at test.jam:12 26912 x = $(v) ; 270(b2db) finish 271Breakpoint 2, g ( 1 2 ) at test.jam:12 27212 x = $(v) ; 273(b2db) quit 274""") 275 t.cleanup() 276 277def test_continue_breakpoints(): 278 """continue should stop when it reaches a breakpoint""" 279 t = make_tester() 280 t.write("test.jam", """\ 281 rule f ( recurse * ) 282 { 283 if $(recurse) 284 { 285 a = [ f $(recurse[2-]) ] ; 286 } 287 } 288 rule g ( list * ) 289 { 290 for local v in $(list) 291 { 292 x = $(v) ; 293 } 294 } 295 f 1 2 ; 296 g 1 2 ; 297 """) 298 run(t, """\ 299(b2db) break test.jam:5 300Breakpoint 1 set at test.jam:5 301(b2db) break test.jam:12 302Breakpoint 2 set at test.jam:12 303(b2db) run -ftest.jam 304Starting program: {{bjam}} -ftest.jam 305Breakpoint 1, f ( 1 2 ) at test.jam:5 3065 a = [ f $(recurse[2-]) ] ; 307(b2db) continue 308Breakpoint 1, f ( 2 ) at test.jam:5 3095 a = [ f $(recurse[2-]) ] ; 310(b2db) continue 311Breakpoint 1, f ( 1 2 ) at test.jam:5 3125 a = [ f $(recurse[2-]) ] ; 313(b2db) continue 314Breakpoint 2, g ( 1 2 ) at test.jam:12 31512 x = $(v) ; 316(b2db) continue 317Breakpoint 2, g ( 1 2 ) at test.jam:12 31812 x = $(v) ; 319(b2db) quit 320""") 321 t.cleanup() 322 323def test_breakpoints(): 324 """Tests the interaction between the following commands: 325 break, clear, delete, disable, enable""" 326 t = make_tester() 327 t.write("test.jam", """\ 328 rule f ( ) 329 { 330 a = 1 ; 331 } 332 rule g ( ) 333 { 334 b = 2 ; 335 } 336 rule h ( ) 337 { 338 c = 3 ; 339 d = 4 ; 340 } 341 f ; 342 g ; 343 h ; 344 UPDATE ; 345 """) 346 run(t, """\ 347(b2db) break f 348Breakpoint 1 set at f 349(b2db) run -ftest.jam 350Starting program: {{bjam}} -ftest.jam 351Breakpoint 1, f ( ) at test.jam:3 3523 a = 1 ; 353(b2db) kill 354(b2db) break g 355Breakpoint 2 set at g 356(b2db) disable 1 357(b2db) run -ftest.jam 358Starting program: {{bjam}} -ftest.jam 359Breakpoint 2, g ( ) at test.jam:7 3607 b = 2 ; 361(b2db) kill 362(b2db) enable 1 363(b2db) run -ftest.jam 364Starting program: {{bjam}} -ftest.jam 365Breakpoint 1, f ( ) at test.jam:3 3663 a = 1 ; 367(b2db) kill 368(b2db) delete 1 369(b2db) run -ftest.jam 370Starting program: {{bjam}} -ftest.jam 371Breakpoint 2, g ( ) at test.jam:7 3727 b = 2 ; 373(b2db) kill 374(b2db) break test.jam:12 375Breakpoint 3 set at test.jam:12 376(b2db) clear g 377Deleted breakpoint 2 378(b2db) run -ftest.jam 379Starting program: {{bjam}} -ftest.jam 380Breakpoint 3, h ( ) at test.jam:12 38112 d = 4 ; 382(b2db) kill 383(b2db) clear test.jam:12 384Deleted breakpoint 3 385(b2db) run -ftest.jam 386Starting program: {{bjam}} -ftest.jam 387Child {{\d+}} exited with status 0 388(b2db) quit 389""") 390 t.cleanup() 391 392def test_breakpoints_running(): 393 """Tests that breakpoints can be added and modified 394 while the program is running.""" 395 t = make_tester() 396 t.write("test.jam", """\ 397 rule f ( ) 398 { 399 a = 1 ; 400 } 401 rule g ( ) 402 { 403 b = 2 ; 404 } 405 rule h ( ) 406 { 407 c = 3 ; 408 d = 4 ; 409 } 410 f ; 411 g ; 412 h ; 413 UPDATE ; 414 """) 415 run(t, """\ 416(b2db) break test.jam:14 417Breakpoint 1 set at test.jam:14 418(b2db) run -ftest.jam 419Starting program: {{bjam}} -ftest.jam 420Breakpoint 1, module scope at test.jam:14 42114 f ; 422(b2db) break f 423Breakpoint 2 set at f 424(b2db) continue 425Breakpoint 2, f ( ) at test.jam:3 4263 a = 1 ; 427(b2db) kill 428(b2db) run -ftest.jam 429Starting program: {{bjam}} -ftest.jam 430Breakpoint 1, module scope at test.jam:14 43114 f ; 432(b2db) break g 433Breakpoint 3 set at g 434(b2db) disable 2 435(b2db) continue 436Breakpoint 3, g ( ) at test.jam:7 4377 b = 2 ; 438(b2db) kill 439(b2db) run -ftest.jam 440Starting program: {{bjam}} -ftest.jam 441Breakpoint 1, module scope at test.jam:14 44214 f ; 443(b2db) enable 2 444(b2db) continue 445Breakpoint 2, f ( ) at test.jam:3 4463 a = 1 ; 447(b2db) kill 448(b2db) run -ftest.jam 449Starting program: {{bjam}} -ftest.jam 450Breakpoint 1, module scope at test.jam:14 45114 f ; 452(b2db) delete 2 453(b2db) continue 454Breakpoint 3, g ( ) at test.jam:7 4557 b = 2 ; 456(b2db) kill 457(b2db) run -ftest.jam 458Starting program: {{bjam}} -ftest.jam 459Breakpoint 1, module scope at test.jam:14 46014 f ; 461(b2db) break test.jam:12 462Breakpoint 4 set at test.jam:12 463(b2db) clear g 464Deleted breakpoint 3 465(b2db) continue 466Breakpoint 4, h ( ) at test.jam:12 46712 d = 4 ; 468(b2db) kill 469(b2db) run -ftest.jam 470Starting program: {{bjam}} -ftest.jam 471Breakpoint 1, module scope at test.jam:14 47214 f ; 473(b2db) clear test.jam:12 474Deleted breakpoint 4 475(b2db) continue 476Child {{\d+}} exited with status 0 477(b2db) quit 478""") 479 t.cleanup() 480 481def test_backtrace(): 482 t = make_tester() 483 t.write("test.jam", """\ 484 rule f ( x * : y * : z * ) 485 { 486 return $(x) ; 487 } 488 rule g ( x * : y * : z * ) 489 { 490 return [ f $(x) : $(y) : $(z) ] ; 491 } 492 g 1 : 2 : 3 ; 493 """) 494 run(t, """\ 495(b2db) break f 496Breakpoint 1 set at f 497(b2db) run -ftest.jam 498Starting program: {{bjam}} -ftest.jam 499Breakpoint 1, f ( 1 : 2 : 3 ) at test.jam:3 5003 return $(x) ; 501(b2db) backtrace 502#0 in f ( 1 : 2 : 3 ) at test.jam:3 503#1 in g ( 1 : 2 : 3 ) at test.jam:7 504#2 in module scope at test.jam:9 505(b2db) quit 506""") 507 t.cleanup() 508 509def test_print(): 510 t = make_tester() 511 t.write("test.jam", """\ 512 rule f ( args * ) 513 { 514 return $(args) ; 515 } 516 f x ; 517 f x y ; 518 """) 519 520 run(t, """\ 521(b2db) break f 522Breakpoint 1 set at f 523(b2db) run -ftest.jam 524Starting program: {{bjam}} -ftest.jam 525Breakpoint 1, f ( x ) at test.jam:3 5263 return $(args) ; 527(b2db) print $(args) 528x 529(b2db) continue 530Breakpoint 1, f ( x y ) at test.jam:3 5313 return $(args) ; 532(b2db) print $(args) 533x y 534(b2db) disable 1 535(b2db) print [ f z ] 536z 537(b2db) quit 538""") 539 540 t.cleanup() 541 542def test_run_running(): 543 t = make_tester() 544 t.write("test.jam", """\ 545 UPDATE ; 546 """) 547 548 run(t, """\ 549(b2db) break test.jam:1 550Breakpoint 1 set at test.jam:1 551(b2db) run -ftest.jam 552Starting program: {{bjam}} -ftest.jam 553Breakpoint 1, module scope at test.jam:1 5541 UPDATE ; 555(b2db) run -ftest.jam 556Child {{\d+}} exited with status 0 557Starting program: {{bjam}} -ftest.jam 558Breakpoint 1, module scope at test.jam:1 5591 UPDATE ; 560(b2db) quit 561""") 562 563 t.cleanup() 564 565def test_error_not_running(): 566 t = make_tester() 567 run(t, """\ 568(b2db) continue 569The program is not being run. 570(b2db) step 571The program is not being run. 572(b2db) next 573The program is not being run. 574(b2db) finish 575The program is not being run. 576(b2db) kill 577The program is not being run. 578(b2db) backtrace 579The program is not being run. 580(b2db) print 1 581The program is not being run. 582(b2db) quit 583""") 584 585 t.cleanup() 586 587def test_bad_arguments(): 588 t = make_tester() 589 t.write("test.jam", """\ 590 UPDATE ; 591 """) 592 593 run(t, """\ 594(b2db) break test.jam:1 595Breakpoint 1 set at test.jam:1 596(b2db) run -ftest.jam 597Starting program: {{bjam}} -ftest.jam 598Breakpoint 1, module scope at test.jam:1 5991 UPDATE ; 600(b2db) continue 1 601Too many arguments to continue. 602(b2db) step 1 603Too many arguments to step. 604(b2db) next 1 605Too many arguments to next. 606(b2db) finish 1 607Too many arguments to finish. 608(b2db) break 609Missing argument to break. 610(b2db) break x y 611Too many arguments to break. 612(b2db) disable 613Missing argument to disable. 614(b2db) disable 1 2 615Too many arguments to disable. 616(b2db) disable x 617Invalid breakpoint number x. 618(b2db) disable 2 619Unknown breakpoint 2. 620(b2db) enable 621Missing argument to enable. 622(b2db) enable 1 2 623Too many arguments to enable. 624(b2db) enable x 625Invalid breakpoint number x. 626(b2db) enable 2 627Unknown breakpoint 2. 628(b2db) delete 629Missing argument to delete. 630(b2db) delete 1 2 631Too many arguments to delete. 632(b2db) delete x 633Invalid breakpoint number x. 634(b2db) delete 2 635Unknown breakpoint 2. 636(b2db) clear 637Missing argument to clear. 638(b2db) clear test.jam:1 test.jam:1 639Too many arguments to clear. 640(b2db) clear test.jam:2 641No breakpoint at test.jam:2. 642(b2db) quit 643""") 644 645 t.cleanup() 646 647def test_unknown_command(): 648 t = make_tester() 649 run(t, """\ 650(b2db) xyzzy 651Unknown command: xyzzy 652(b2db) gnusto rezrov 653Unknown command: gnusto 654(b2db) quit 655""") 656 657 t.cleanup() 658 659test_run() 660test_exit_status() 661test_step() 662test_next() 663test_next_breakpoint() 664test_finish() 665test_finish_breakpoints() 666test_continue_breakpoints() 667test_breakpoints() 668test_breakpoints_running() 669test_backtrace() 670test_print() 671test_run_running() 672test_error_not_running() 673test_bad_arguments() 674test_unknown_command() 675