1#!./perl 2 3BEGIN { 4 chdir 't' if -d 't'; 5 @INC = '../lib'; 6 require './test.pl'; 7} 8 9use strict; 10use warnings; 11use Config; 12 13delete $ENV{PERLDB_OPTS}; 14 15BEGIN { 16 if (! -c "/dev/null") { 17 print "1..0 # Skip: no /dev/null\n"; 18 exit 0; 19 } 20 21 my $dev_tty = '/dev/tty'; 22 $dev_tty = 'TT:' if ($^O eq 'VMS'); 23 if (! -c $dev_tty) { 24 print "1..0 # Skip: no $dev_tty\n"; 25 exit 0; 26 } 27 if ($ENV{PERL5DB}) { 28 print "1..0 # Skip: \$ENV{PERL5DB} is already set to '$ENV{PERL5DB}'\n"; 29 exit 0; 30 } 31 $ENV{PERL_RL} = 'Perl'; # Suppress system Term::ReadLine::Gnu 32} 33 34my $rc_filename = '.perldb'; 35 36sub rc { 37 open my $rc_fh, '>', $rc_filename 38 or die $!; 39 print {$rc_fh} @_; 40 close ($rc_fh); 41 42 # overly permissive perms gives "Must not source insecure rcfile" 43 # and hangs at the DB(1> prompt 44 chmod 0644, $rc_filename; 45} 46 47sub _slurp 48{ 49 my $filename = shift; 50 51 open my $in, '<', $filename 52 or die "Cannot open '$filename' for slurping - $!"; 53 54 local $/; 55 my $contents = <$in>; 56 57 close($in); 58 59 return $contents; 60} 61 62my $out_fn = 'db.out'; 63 64sub _out_contents 65{ 66 return _slurp($out_fn); 67} 68 69 70# Test for Proxy constants 71{ 72 rc( 73 <<'EOF', 74 75&parse_options("NonStop=0 ReadLine=0 TTY=db.out"); 76 77sub afterinit { 78 push(@DB::typeahead, 79 'm main->s1', 80 'q', 81 ); 82} 83 84EOF 85 ); 86 87 my $output = runperl(switches => [ '-d' ], stderr => 1, progfile => '../lib/perl5db/t/proxy-constants'); 88 is($output, "", "proxy constant subroutines"); 89} 90 91# [perl #66110] Call a subroutine inside a regex 92{ 93 local $ENV{PERLDB_OPTS} = "ReadLine=0 NonStop=1"; 94 my $output = runperl(switches => [ '-d' ], stderr => 1, progfile => '../lib/perl5db/t/rt-66110'); 95 like($output, qr/\bAll tests successful\.$/, "[perl #66110]"); 96} 97# [ perl #116769] Frame=2 98{ 99 local $ENV{PERLDB_OPTS} = "frame=2 nonstop"; 100 my $output = runperl( switches => [ '-d' ], prog => 'print qq{success\n}' ); 101 is( $?, 0, '[perl #116769] frame=2 does not crash debugger, exit == 0' ); 102 is( $output, "success\n" , '[perl #116769] code is run' ); 103} 104# [ perl #116771] autotrace 105{ 106 local $ENV{PERLDB_OPTS} = "autotrace nonstop"; 107 my $output = runperl( switches => [ '-d' ], prog => 'print qq{success\n}' ); 108 is( $?, 0, '[perl #116771] autotrace does not crash debugger, exit == 0' ); 109 is( $output, "success\n" , '[perl #116771] code is run' ); 110} 111# [ perl #41461] Frame=2 noTTY 112{ 113 local $ENV{PERLDB_OPTS} = "frame=2 noTTY nonstop"; 114 rc(''); 115 my $output = runperl( switches => [ '-d' ], prog => 'print qq{success\n}' ); 116 is( $?, 0, '[perl #41461] frame=2 noTTY does not crash debugger, exit == 0' ); 117 is( $output, "success\n" , '[perl #41461] code is run' ); 118} 119 120package DebugWrap; 121 122sub new { 123 my $class = shift; 124 125 my $self = bless {}, $class; 126 127 $self->_init(@_); 128 129 return $self; 130} 131 132sub _cmds { 133 my $self = shift; 134 135 if (@_) { 136 $self->{_cmds} = shift; 137 } 138 139 return $self->{_cmds}; 140} 141 142sub _prog { 143 my $self = shift; 144 145 if (@_) { 146 $self->{_prog} = shift; 147 } 148 149 return $self->{_prog}; 150} 151 152sub _output { 153 my $self = shift; 154 155 if (@_) { 156 $self->{_output} = shift; 157 } 158 159 return $self->{_output}; 160} 161 162sub _include_t 163{ 164 my $self = shift; 165 166 if (@_) 167 { 168 $self->{_include_t} = shift; 169 } 170 171 return $self->{_include_t}; 172} 173 174sub _stderr_val 175{ 176 my $self = shift; 177 178 if (@_) 179 { 180 $self->{_stderr_val} = shift; 181 } 182 183 return $self->{_stderr_val}; 184} 185 186sub field 187{ 188 my $self = shift; 189 190 if (@_) 191 { 192 $self->{field} = shift; 193 } 194 195 return $self->{field}; 196} 197 198sub _switches 199{ 200 my $self = shift; 201 202 if (@_) 203 { 204 $self->{_switches} = shift; 205 } 206 207 return $self->{_switches}; 208} 209 210sub _contents 211{ 212 my $self = shift; 213 214 if (@_) 215 { 216 $self->{_contents} = shift; 217 } 218 219 return $self->{_contents}; 220} 221 222# object for prog temporary file 223sub _tempprog 224{ 225 my $self = shift; 226 227 if (@_) 228 { 229 $self->{_tempprog} = shift; 230 } 231 232 return $self->{_tempprog}; 233} 234 235sub _init 236{ 237 my ($self, $args) = @_; 238 239 my $cmds = $args->{cmds}; 240 241 if (ref($cmds) ne 'ARRAY') { 242 die "cmds must be an array of commands."; 243 } 244 245 $self->_cmds($cmds); 246 247 my $prog = $args->{prog}; 248 249 if (ref($prog) eq 'SCALAR') { 250 use File::Temp; 251 my $fh = File::Temp->new; 252 $self->_tempprog($fh); 253 print $fh $$prog; 254 $prog = $fh->filename; 255 } 256 elsif (ref($prog) ne '' or !defined($prog)) { 257 die "prog should be a path to a program file."; 258 } 259 260 $self->_prog($prog); 261 262 $self->_include_t($args->{include_t} ? 1 : 0); 263 264 $self->_stderr_val(exists($args->{stderr}) ? $args->{stderr} : 1); 265 266 if (exists($args->{switches})) 267 { 268 $self->_switches($args->{switches}); 269 } 270 271 $self->_run(); 272 273 return; 274} 275 276sub _quote 277{ 278 my ($self, $str) = @_; 279 280 $str =~ s/(["\@\$\\])/\\$1/g; 281 $str =~ s/\n/\\n/g; 282 $str =~ s/\r/\\r/g; 283 284 return qq{"$str"}; 285} 286 287sub _run { 288 my $self = shift; 289 290 my $rc = qq{&parse_options("NonStop=0 TTY=db.out");\n}; 291 292 $rc .= join('', 293 map { "$_\n"} 294 (q#sub afterinit {#, 295 q#push (@DB::typeahead,#, 296 (map { $self->_quote($_) . "," } @{$self->_cmds()}), 297 q#);#, 298 q#}#, 299 ) 300 ); 301 302 # I guess two objects like that cannot be used at the same time. 303 # Oh well. 304 ::rc($rc); 305 306 my $output = 307 ::runperl( 308 switches => 309 [ 310 ($self->_switches ? (@{$self->_switches()}) : ('-d')), 311 ($self->_include_t ? ('-I', '../lib/perl5db/t') : ()) 312 ], 313 (defined($self->_stderr_val()) 314 ? (stderr => $self->_stderr_val()) 315 : () 316 ), 317 progfile => $self->_prog() 318 ); 319 320 $self->_output($output); 321 322 $self->_contents(::_out_contents()); 323 324 return; 325} 326 327sub get_output 328{ 329 return shift->_output(); 330} 331 332sub output_like { 333 my ($self, $re, $msg) = @_; 334 335 local $::Level = $::Level + 1; 336 ::like($self->_output(), $re, $msg); 337} 338 339sub output_unlike { 340 my ($self, $re, $msg) = @_; 341 342 local $::Level = $::Level + 1; 343 ::unlike($self->_output(), $re, $msg); 344} 345 346sub get_contents { 347 return shift->_contents(); 348} 349 350sub contents_like { 351 my ($self, $re, $msg) = @_; 352 353 local $::Level = $::Level + 1; 354 ::like($self->_contents(), $re, $msg); 355} 356 357sub contents_unlike { 358 my ($self, $re, $msg) = @_; 359 360 local $::Level = $::Level + 1; 361 ::unlike($self->_contents(), $re, $msg); 362} 363 364=head1 NAME 365 366DebugWrap - wrapper to execute code under the debugger and examine the 367results. 368 369=head1 SYNOPSIS 370 371 my $wrapper = DebugWrap->new( 372 { 373 cmds => 374 [ 375 # list of commands supplied to the debugger 376 ], 377 prog => 'filename_of_code_to_debug.pl', 378 # and some optional arguments 379 } 380 ); 381 382 my $wrapper = DebugWrap->new( 383 { 384 cmds => 385 [ 386 # list of commands supplied to the debugger 387 ], 388 prog => \<<'EOS', 389 # perl code to debug 390 EOS 391 # and some optional arguments 392 } 393 ); 394 395 # test the output from the program being debugged 396 $wrapper->output_like(qr/.../, "describe the test"); 397 $wrapper->output_unlike(qr/.../, "describe the test"); 398 my $output = $wrapper->get_output; # for more sophisticated checks 399 400 # test the output from the debugger 401 $wrapper->contents_like(qr/.../, "describe the test"); 402 $wrapper->contents_unlike(qr/.../, "describe the test"); 403 my $contents = $wrapper->get_contents; # for more sophisticated checks 404 405=head1 DESCRIPTION 406 407DebugWrap is a simple class used when testing the Perl debugger that 408executes a set of debugger commands against a program under the 409debugger and provides some simple methods to examine the results. 410 411It is not installed to your system. 412 413=head2 Creating a DebugWrap object 414 415The constructor new() accepts a hash of arguments, with the following 416possible members: 417 418=over 419 420=item cmds 421 422An array of commands to execute, one command per element. Required. 423 424=item prog 425 426Either the name of a perl program to test under the debugger, or a 427reference to a scalar containing the text of the program to test. 428Required. 429 430=item stderr 431 432If this is a true value capture standard error, which is the default. 433Optional. 434 435=item include_t 436 437Add F<lib/perl5db/t> to the perl search path, as with C<-I> 438 439=item switches 440 441An arrayref of switches to supply to perl. This should include the 442C<-d> switch needed to invoke the debugger. If C<switches> is not 443supplied then C<-d> only is supplied. The C<-I> for C<include_t> is 444added after these switches. 445 446=back 447 448=head2 Other methods 449 450The other methods intended for test usage are: 451 452=over 453 454=item $wrapper->get_contents 455 456Fetch the debugger output from the debugger run. This does not 457include the output from the program under test. 458 459=item $wrapper->contents_like($re, $test_name) 460 461Test that the debugger output matches the given regular expression 462object (as with qr//). 463 464Equivalent to: 465 466 like($wrapper->get_contents, $re, $test_name); 467 468=item $wrapper->contents_unlike($re, $test_name) 469 470Test that the debugger output does not match the given regular 471expression object (as with qr//). 472 473Equivalent to: 474 475 unlike($wrapper->get_contents, $re, $test_name); 476 477=item $wrapper->get_output 478 479Fetch the program output from the debugger run. This does not include 480the output from the debugger itself, it does include the output 481generated by C<valgrind> or ASAN, assuming you haven't disabled 482capturing stderr. 483 484=item $wrapper->output_like($re, $test_name); 485 486Test that the program output matches the given regular expression 487object (as with qr//). 488 489Equivalent to: 490 491 like($wrapper->get_output, $re, $test_name); 492 493=item $wrapper->output_unlike($re, $test_name); 494 495Test that the program output does not match the given regular 496expression object (as with qr//). 497 498Equivalent to: 499 500 unlike($wrapper->get_output, $re, $test_name); 501 502=back 503 504=cut 505 506package main; 507 508{ 509 local $ENV{PERLDB_OPTS} = "ReadLine=0"; 510 my $target = '../lib/perl5db/t/eval-line-bug'; 511 my $wrapper = DebugWrap->new( 512 { 513 cmds => 514 [ 515 'b 23', 516 'n', 517 'n', 518 'n', 519 'c', # line 23 520 'n', 521 "p \@{'main::_<$target'}", 522 'q', 523 ], 524 prog => $target, 525 } 526 ); 527 $wrapper->contents_like( 528 qr/sub factorial/, 529 'The ${main::_<filename} variable in the debugger was not destroyed', 530 ); 531} 532 533sub _calc_generic_wrapper 534{ 535 my $args = shift; 536 537 my $extra_opts = delete($args->{extra_opts}); 538 $extra_opts ||= ''; 539 local $ENV{PERLDB_OPTS} = "ReadLine=0" . $extra_opts; 540 return DebugWrap->new( 541 { 542 cmds => delete($args->{cmds}), 543 prog => delete($args->{prog}), 544 %$args, 545 } 546 ); 547} 548 549sub _calc_new_var_wrapper 550{ 551 my ($args) = @_; 552 return _calc_generic_wrapper( 553 { 554 cmds => 555 [ 556 'b 23', 557 'c', 558 '$new_var = "Foo"', 559 'x "new_var = <$new_var>\\n"', 560 'q', 561 ], 562 %$args, 563 } 564 ); 565} 566 567sub _calc_threads_wrapper 568{ 569 my $args = shift; 570 571 return _calc_new_var_wrapper( 572 { 573 switches => [ '-dt', ], 574 stderr => 1, 575 %$args 576 } 577 ); 578} 579 580{ 581 _calc_new_var_wrapper({ prog => '../lib/perl5db/t/eval-line-bug'}) 582 ->contents_like( 583 qr/new_var = <Foo>/, 584 "no strict 'vars' in evaluated lines.", 585 ); 586} 587 588{ 589 _calc_new_var_wrapper( 590 { 591 prog => '../lib/perl5db/t/lvalue-bug', 592 stderr => undef(), 593 }, 594 )->output_like( 595 qr/foo is defined/, 596 'lvalue subs work in the debugger', 597 ); 598} 599 600{ 601 _calc_new_var_wrapper( 602 { 603 prog => '../lib/perl5db/t/symbol-table-bug', 604 extra_opts => "NonStop=1", 605 stderr => undef(), 606 } 607 )->output_like( 608 qr/Undefined symbols 0/, 609 'there are no undefined values in the symbol table', 610 ); 611} 612 613SKIP: 614{ 615 if ( $Config{usethreads} ) { 616 skip('This perl has threads, skipping non-threaded debugger tests'); 617 } 618 else { 619 my $error = 'This Perl not built to support threads'; 620 _calc_threads_wrapper( 621 { 622 prog => '../lib/perl5db/t/eval-line-bug', 623 } 624 )->output_like( 625 qr/\Q$error\E/, 626 'Perl debugger correctly complains that it was not built with threads', 627 ); 628 } 629} 630 631SKIP: 632{ 633 if ( $Config{usethreads} ) { 634 _calc_threads_wrapper( 635 { 636 prog => '../lib/perl5db/t/symbol-table-bug', 637 } 638 )->output_like( 639 qr/Undefined symbols 0/, 640 'there are no undefined values in the symbol table when running with thread support', 641 ); 642 } 643 else { 644 skip("This perl is not threaded, skipping threaded debugger tests"); 645 } 646} 647 648# Test [perl #61222] 649{ 650 local $ENV{PERLDB_OPTS}; 651 my $wrapper = DebugWrap->new( 652 { 653 cmds => 654 [ 655 'm Pie', 656 'q', 657 ], 658 prog => '../lib/perl5db/t/rt-61222', 659 } 660 ); 661 662 $wrapper->contents_unlike(qr/INCORRECT/, "[perl #61222]"); 663} 664 665sub _calc_trace_wrapper 666{ 667 my ($args) = @_; 668 669 return _calc_generic_wrapper( 670 { 671 cmds => 672 [ 673 't 2', 674 'c', 675 'q', 676 ], 677 %$args, 678 } 679 ); 680} 681 682# [perl 104168] level option for tracing 683{ 684 my $wrapper = _calc_trace_wrapper({ prog => '../lib/perl5db/t/rt-104168' }); 685 $wrapper->contents_like(qr/level 2/, "[perl #104168] - level 2 appears"); 686 $wrapper->contents_unlike(qr/baz/, "[perl #104168] - no 'baz'"); 687} 688 689# taint tests 690if (!exists($Config{taint_support}) || $Config{taint_support}) 691{ 692 my $wrapper = _calc_trace_wrapper( 693 { 694 prog => '../lib/perl5db/t/taint', 695 extra_opts => ' NonStop=1', 696 switches => [ '-d', '-T', ], 697 } 698 ); 699 700 my $output = $wrapper->get_output(); 701 chomp $output if $^O eq 'VMS'; # newline guaranteed at EOF 702 is($output, '[$^X][done]', "taint"); 703} 704 705# Testing that we can set a line in the middle of the file. 706{ 707 my $wrapper = DebugWrap->new( 708 { 709 cmds => 710 [ 711 'b ../lib/perl5db/t/MyModule.pm:12', 712 'c', 713 q/do { use IO::Handle; STDOUT->autoflush(1); print "Var=$var\n"; }/, 714 'c', 715 'q', 716 ], 717 include_t => 1, 718 prog => '../lib/perl5db/t/filename-line-breakpoint' 719 } 720 ); 721 722 $wrapper->output_like(qr/ 723 ^Var=Bar$ 724 .* 725 ^In\ MyModule\.$ 726 .* 727 ^In\ Main\ File\.$ 728 .* 729 /msx, 730 "Can set breakpoint in a line in the middle of the file."); 731} 732 733# Testing that we can set a breakpoint 734{ 735 my $wrapper = DebugWrap->new( 736 { 737 prog => '../lib/perl5db/t/breakpoint-bug', 738 cmds => 739 [ 740 'b 6', 741 'c', 742 q/do { use IO::Handle; STDOUT->autoflush(1); print "X={$x}\n"; }/, 743 'c', 744 'q', 745 ], 746 }, 747 ); 748 749 $wrapper->output_like( 750 qr/X=\{Two\}/msx, 751 "Can set breakpoint in a line." 752 ); 753} 754 755# Testing that we can disable a breakpoint at a numeric line. 756{ 757 my $wrapper = DebugWrap->new( 758 { 759 prog => '../lib/perl5db/t/disable-breakpoints-1', 760 cmds => 761 [ 762 'b 7', 763 'b 11', 764 'disable 7', 765 'c', 766 q/print "X={$x}\n";/, 767 'c', 768 'q', 769 ], 770 } 771 ); 772 773 $wrapper->output_like(qr/X=\{SecondVal\}/ms, 774 "Can set breakpoint in a line."); 775} 776 777# Testing that we can re-enable a breakpoint at a numeric line. 778{ 779 my $wrapper = DebugWrap->new( 780 { 781 prog => '../lib/perl5db/t/disable-breakpoints-2', 782 cmds => 783 [ 784 'b 8', 785 'b 24', 786 'disable 24', 787 'c', 788 'enable 24', 789 'c', 790 q/print "X={$x}\n";/, 791 'c', 792 'q', 793 ], 794 }, 795 ); 796 797 $wrapper->output_like( 798 qr/ 799 X=\{SecondValOneHundred\} 800 /msx, 801 "Can set breakpoint in a line." 802 ); 803} 804# clean up. 805 806# Disable and enable for breakpoints on outer files. 807{ 808 my $wrapper = DebugWrap->new( 809 { 810 cmds => 811 [ 812 'b 10', 813 'b ../lib/perl5db/t/EnableModule.pm:14', 814 'disable ../lib/perl5db/t/EnableModule.pm:14', 815 'c', 816 'enable ../lib/perl5db/t/EnableModule.pm:14', 817 'c', 818 q/print "X={$x}\n";/, 819 'c', 820 'q', 821 ], 822 prog => '../lib/perl5db/t/disable-breakpoints-3', 823 include_t => 1, 824 } 825 ); 826 827 $wrapper->output_like(qr/ 828 X=\{SecondValTwoHundred\} 829 /msx, 830 "Can set breakpoint in a line."); 831} 832 833# Testing that the prompt with the information appears. 834{ 835 my $wrapper = DebugWrap->new( 836 { 837 cmds => ['q'], 838 prog => '../lib/perl5db/t/disable-breakpoints-1', 839 } 840 ); 841 842 $wrapper->contents_like(qr/ 843 ^main::\([^\)]*\bdisable-breakpoints-1:2\):\n 844 2:\s+my\ \$x\ =\ "One";\n 845 /msx, 846 "Prompt should display the first line of code."); 847} 848 849# Testing that R (restart) and "B *" work. 850{ 851 my $wrapper = DebugWrap->new( 852 { 853 cmds => 854 [ 855 'b 13', 856 'c', 857 'B *', 858 'b 9', 859 'R', 860 'c', 861 q/print "X={$x};dummy={$dummy}\n";/, 862 'q', 863 ], 864 prog => '../lib/perl5db/t/disable-breakpoints-1', 865 } 866 ); 867 868 $wrapper->output_like(qr/ 869 X=\{FirstVal\};dummy=\{1\} 870 /msx, 871 "Restart and delete all breakpoints work properly."); 872} 873 874{ 875 my $wrapper = DebugWrap->new( 876 { 877 cmds => 878 [ 879 'c 15', 880 q/print "X={$x}\n";/, 881 'c', 882 'q', 883 ], 884 prog => '../lib/perl5db/t/disable-breakpoints-1', 885 } 886 ); 887 888 $wrapper->output_like(qr/ 889 X=\{ThirdVal\} 890 /msx, 891 "'c line_num' is working properly."); 892} 893 894{ 895 my $wrapper = DebugWrap->new( 896 { 897 cmds => 898 [ 899 'n', 900 'n', 901 'b . $exp > 200', 902 'c', 903 q/print "Exp={$exp}\n";/, 904 'q', 905 ], 906 prog => '../lib/perl5db/t/break-on-dot', 907 } 908 ); 909 910 $wrapper->output_like(qr/ 911 Exp=\{256\} 912 /msx, 913 "'b .' is working correctly."); 914} 915 916# Testing that the prompt with the information appears inside a subroutine call. 917# See https://rt.perl.org/rt3/Ticket/Display.html?id=104820 918{ 919 my $wrapper = DebugWrap->new( 920 { 921 cmds => 922 [ 923 'c back', 924 'q', 925 ], 926 prog => '../lib/perl5db/t/with-subroutine', 927 } 928 ); 929 930 $wrapper->contents_like( 931 qr/ 932 ^main::back\([^\)\n]*\bwith-subroutine:15\):[\ \t]*\n 933 ^15:\s*print\ "hello\ back\\n"; 934 /msx, 935 "Prompt should display the line of code inside a subroutine."); 936} 937 938# Checking that the p command works. 939{ 940 my $wrapper = DebugWrap->new( 941 { 942 cmds => 943 [ 944 'p "<<<" . (4*6) . ">>>"', 945 'q', 946 ], 947 prog => '../lib/perl5db/t/with-subroutine', 948 } 949 ); 950 951 $wrapper->contents_like( 952 qr/<<<24>>>/, 953 "p command works."); 954} 955 956# Tests for x. 957{ 958 my $wrapper = DebugWrap->new( 959 { 960 cmds => 961 [ 962 q/x {500 => 600}/, 963 'q', 964 ], 965 prog => '../lib/perl5db/t/with-subroutine', 966 } 967 ); 968 969 $wrapper->contents_like( 970 # qr/^0\s+HASH\([^\)]+\)\n\s+500 => 600\n/, 971 qr/^0\s+HASH\([^\)]+\)\n\s+500 => 600\n/ms, 972 "x command test." 973 ); 974} 975 976# Tests for x with @_ 977{ 978 my $wrapper = DebugWrap->new( 979 { 980 cmds => 981 [ 982 'b 10', 983 'c', 984 'x @_', 985 'q', 986 ], 987 prog => '../lib/perl5db/t/test-passing-at-underscore-to-x-etc', 988 } 989 ); 990 991 $wrapper->contents_like( 992 # qr/^0\s+HASH\([^\)]+\)\n\s+500 => 600\n/, 993 qr/Arg1.*?Capsula.*GreekHumor.*Socrates/ms, 994 q/x command test with '@_'./, 995 ); 996} 997 998# Tests for mutating @_ 999{ 1000 my $wrapper = DebugWrap->new( 1001 { 1002 cmds => 1003 [ 1004 'b 10', 1005 'c', 1006 'shift(@_)', 1007 'print "\n\n\n(((" . join(",", @_) . ")))\n\n\n"', 1008 'q', 1009 ], 1010 prog => '../lib/perl5db/t/test-passing-at-underscore-to-x-etc', 1011 } 1012 ); 1013 1014 $wrapper->output_like( 1015 qr/^\(\(\(Capsula,GreekHumor,Socrates\)\)\)$/ms, 1016 q/Mutating '@_'./, 1017 ); 1018} 1019 1020# Tests for x with AutoTrace=1. 1021{ 1022 my $wrapper = DebugWrap->new( 1023 { 1024 cmds => 1025 [ 1026 'n', 1027 'o AutoTrace=1', 1028 # So it may fail. 1029 q/x "failure"/, 1030 q/x \$x/, 1031 'q', 1032 ], 1033 prog => '../lib/perl5db/t/with-subroutine', 1034 } 1035 ); 1036 1037 $wrapper->contents_like( 1038 # qr/^0\s+HASH\([^\)]+\)\n\s+500 => 600\n/, 1039 qr/^0\s+SCALAR\([^\)]+\)\n\s+-> 'hello world'\n/ms, 1040 "x after AutoTrace=1 command is working." 1041 ); 1042} 1043 1044# Tests for "T" (stack trace). 1045{ 1046 my $prog_fn = '../lib/perl5db/t/rt-104168'; 1047 my $wrapper = DebugWrap->new( 1048 { 1049 prog => $prog_fn, 1050 cmds => 1051 [ 1052 'c baz', 1053 'T', 1054 'q', 1055 ], 1056 } 1057 ); 1058 my $re_text = join('', 1059 map { 1060 sprintf( 1061 "%s = %s\\(\\) called from file " . 1062 "'" . quotemeta($prog_fn) . "' line %s\\n", 1063 (map { quotemeta($_) } @$_) 1064 ) 1065 } 1066 ( 1067 ['.', 'main::baz', 14,], 1068 ['.', 'main::bar', 9,], 1069 ['.', 'main::foo', 6], 1070 ) 1071 ); 1072 $wrapper->contents_like( 1073 # qr/^0\s+HASH\([^\)]+\)\n\s+500 => 600\n/, 1074 qr/^$re_text/ms, 1075 "T command test." 1076 ); 1077} 1078 1079# Test for s. 1080{ 1081 my $wrapper = DebugWrap->new( 1082 { 1083 cmds => 1084 [ 1085 'b 9', 1086 'c', 1087 's', 1088 q/print "X={$x};dummy={$dummy}\n";/, 1089 'q', 1090 ], 1091 prog => '../lib/perl5db/t/disable-breakpoints-1' 1092 } 1093 ); 1094 1095 $wrapper->output_like(qr/ 1096 X=\{SecondVal\};dummy=\{1\} 1097 /msx, 1098 'test for s - single step', 1099 ); 1100} 1101 1102{ 1103 my $wrapper = DebugWrap->new( 1104 { 1105 cmds => 1106 [ 1107 'n', 1108 'n', 1109 'b . $exp > 200', 1110 'c', 1111 q/print "Exp={$exp}\n";/, 1112 'q', 1113 ], 1114 prog => '../lib/perl5db/t/break-on-dot' 1115 } 1116 ); 1117 1118 $wrapper->output_like(qr/ 1119 Exp=\{256\} 1120 /msx, 1121 "'b .' is working correctly."); 1122} 1123 1124{ 1125 my $prog_fn = '../lib/perl5db/t/rt-104168'; 1126 my $wrapper = DebugWrap->new( 1127 { 1128 cmds => 1129 [ 1130 's', 1131 'q', 1132 ], 1133 prog => $prog_fn, 1134 } 1135 ); 1136 1137 $wrapper->contents_like( 1138 qr/ 1139 ^main::foo\([^\)\n]*\brt-104168:9\):[\ \t]*\n 1140 ^9:\s*bar\(\); 1141 /msx, 1142 'Test for the s command.', 1143 ); 1144} 1145 1146{ 1147 my $wrapper = DebugWrap->new( 1148 { 1149 cmds => 1150 [ 1151 's uncalled_subroutine()', 1152 'c', 1153 'q', 1154 ], 1155 1156 prog => '../lib/perl5db/t/uncalled-subroutine'} 1157 ); 1158 1159 $wrapper->output_like( 1160 qr/<1,2,3,4,5>\n/, 1161 'uncalled_subroutine was called after s EXPR()', 1162 ); 1163} 1164 1165{ 1166 my $wrapper = DebugWrap->new( 1167 { 1168 cmds => 1169 [ 1170 'n uncalled_subroutine()', 1171 'c', 1172 'q', 1173 ], 1174 prog => '../lib/perl5db/t/uncalled-subroutine', 1175 } 1176 ); 1177 1178 $wrapper->output_like( 1179 qr/<1,2,3,4,5>\n/, 1180 'uncalled_subroutine was called after n EXPR()', 1181 ); 1182} 1183 1184{ 1185 my $wrapper = DebugWrap->new( 1186 { 1187 cmds => 1188 [ 1189 'b fact', 1190 'c', 1191 'c', 1192 'c', 1193 'n', 1194 'print "<$n>"', 1195 'q', 1196 ], 1197 prog => '../lib/perl5db/t/fact', 1198 } 1199 ); 1200 1201 $wrapper->output_like( 1202 qr/<3>/, 1203 'b subroutine works fine', 1204 ); 1205} 1206 1207# Test for n with lvalue subs 1208DebugWrap->new({ 1209 cmds => 1210 [ 1211 'n', 'print "<$x>\n"', 1212 'n', 'print "<$x>\n"', 1213 'q', 1214 ], 1215 prog => '../lib/perl5db/t/lsub-n', 1216})->output_like( 1217 qr/<1>\n<11>\n/, 1218 'n steps over lvalue subs', 1219); 1220 1221# Test for 'M' (module list). 1222{ 1223 my $wrapper = DebugWrap->new( 1224 { 1225 cmds => 1226 [ 1227 'M', 1228 'q', 1229 ], 1230 prog => '../lib/perl5db/t/load-modules' 1231 } 1232 ); 1233 1234 $wrapper->contents_like( 1235 qr[Scalar/Util\.pm], 1236 'M (module list) works fine', 1237 ); 1238} 1239 1240{ 1241 my $wrapper = DebugWrap->new( 1242 { 1243 cmds => 1244 [ 1245 'b 14', 1246 'c', 1247 '$flag = 1;', 1248 'r', 1249 'print "Var=$var\n";', 1250 'q', 1251 ], 1252 prog => '../lib/perl5db/t/test-r-statement', 1253 } 1254 ); 1255 1256 $wrapper->output_like( 1257 qr/ 1258 ^Foo$ 1259 .*? 1260 ^Bar$ 1261 .*? 1262 ^Var=Test$ 1263 /msx, 1264 'r statement is working properly.', 1265 ); 1266} 1267 1268{ 1269 my $wrapper = DebugWrap->new( 1270 { 1271 cmds => 1272 [ 1273 'l', 1274 'q', 1275 ], 1276 prog => '../lib/perl5db/t/test-l-statement-1', 1277 } 1278 ); 1279 1280 $wrapper->contents_like( 1281 qr/ 1282 ^1==>\s+\$x\ =\ 1;\n 1283 2:\s+print\ "1\\n";\n 1284 3\s*\n 1285 4:\s+\$x\ =\ 2;\n 1286 5:\s+print\ "2\\n";\n 1287 /msx, 1288 'l statement is working properly (test No. 1).', 1289 ); 1290} 1291 1292{ 1293 my $wrapper = DebugWrap->new( 1294 { 1295 cmds => 1296 [ 1297 'l', 1298 q/# After l 1/, 1299 'l', 1300 q/# After l 2/, 1301 '-', 1302 q/# After -/, 1303 'q', 1304 ], 1305 prog => '../lib/perl5db/t/test-l-statement-1', 1306 } 1307 ); 1308 1309 my $first_l_out = qr/ 1310 1==>\s+\$x\ =\ 1;\n 1311 2:\s+print\ "1\\n";\n 1312 3\s*\n 1313 4:\s+\$x\ =\ 2;\n 1314 5:\s+print\ "2\\n";\n 1315 6\s*\n 1316 7:\s+\$x\ =\ 3;\n 1317 8:\s+print\ "3\\n";\n 1318 9\s*\n 1319 10:\s+\$x\ =\ 4;\n 1320 /msx; 1321 1322 my $second_l_out = qr/ 1323 11:\s+print\ "4\\n";\n 1324 12\s*\n 1325 13:\s+\$x\ =\ 5;\n 1326 14:\s+print\ "5\\n";\n 1327 15\s*\n 1328 16:\s+\$x\ =\ 6;\n 1329 17:\s+print\ "6\\n";\n 1330 18\s*\n 1331 19:\s+\$x\ =\ 7;\n 1332 20:\s+print\ "7\\n";\n 1333 /msx; 1334 $wrapper->contents_like( 1335 qr/ 1336 ^$first_l_out 1337 [^\n]*?DB<\d+>\ \#\ After\ l\ 1\n 1338 [\ \t]*\n 1339 [^\n]*?DB<\d+>\ l\s*\n 1340 $second_l_out 1341 [^\n]*?DB<\d+>\ \#\ After\ l\ 2\n 1342 [\ \t]*\n 1343 [^\n]*?DB<\d+>\ -\s*\n 1344 $first_l_out 1345 [^\n]*?DB<\d+>\ \#\ After\ -\n 1346 /msx, 1347 'l followed by l and then followed by -', 1348 ); 1349} 1350 1351{ 1352 my $wrapper = DebugWrap->new( 1353 { 1354 cmds => 1355 [ 1356 'v', 1357 'q', 1358 ], 1359 prog => '../lib/perl5db/t/test-l-statement-1', 1360 } 1361 ); 1362 $wrapper->contents_like( 1363 qr/ 1364 1==>\s+\$x\ =\ 1;\n 1365 2:\s+print\ "1\\n";\n 1366 3\s+\n 1367 4:\s+\$x\ =\ 2;\n 1368 5:\s+print\ "2\\n";\n 1369 6\s*\n 1370 7:\s+\$x\ =\ 3;\n 1371 /msx, 1372 "test plain v" 1373 ); 1374} 1375 1376{ 1377 my $wrapper = DebugWrap->new( 1378 { 1379 cmds => 1380 [ 1381 'v 10', 1382 'q', 1383 ], 1384 prog => '../lib/perl5db/t/test-l-statement-1', 1385 } 1386 ); 1387 1388 $wrapper->contents_like( 1389 qr/ 1390 7:\s+\$x\ =\ 3;\n 1391 8:\s+print\ "3\\n";\n 1392 9\s*\n 1393 10:\s+\$x\ =\ 4;\n 1394 11:\s+print\ "4\\n";\n 1395 12\s*\n 1396 13:\s+\$x\ =\ 5;\n 1397 14:\s+print\ "5\\n";\n 1398 15\s*\n 1399 16:\s+\$x\ =\ 6;\n 1400 /msx, 1401 "test v with line" 1402 ); 1403} 1404 1405{ 1406 my $wrapper = DebugWrap->new( 1407 { 1408 cmds => 1409 [ 1410 'l fact', 1411 'q', 1412 ], 1413 prog => '../lib/perl5db/t/test-l-statement-2', 1414 } 1415 ); 1416 1417 my $first_l_out = qr/ 1418 6\s+sub\ fact\ \{\n 1419 7:\s+my\ \$n\ =\ shift;\n 1420 8:\s+if\ \(\$n\ >\ 1\)\ \{\n 1421 9:\s+return\ \$n\ \*\ fact\(\$n\ -\ 1\); 1422 /msx; 1423 1424 $wrapper->contents_like( 1425 qr/ 1426 DB<1>\s+l\ fact\n 1427 $first_l_out 1428 /msx, 1429 'l subroutine_name', 1430 ); 1431} 1432 1433{ 1434 my $wrapper = DebugWrap->new( 1435 { 1436 cmds => 1437 [ 1438 'b fact', 1439 'c', 1440 # Repeat several times to avoid @typeahead problems. 1441 '.', 1442 '.', 1443 '.', 1444 '.', 1445 'q', 1446 ], 1447 prog => '../lib/perl5db/t/test-l-statement-2', 1448 } 1449 ); 1450 1451 my $line_out = qr / 1452 ^main::fact\([^\n]*?:7\):\n 1453 ^7:\s+my\ \$n\ =\ shift;\n 1454 /msx; 1455 1456 $wrapper->contents_like( 1457 qr/ 1458 $line_out 1459 auto\(-\d+\)\s+DB<\d+>\s+\.\n 1460 $line_out 1461 /msx, 1462 'Test the "." command', 1463 ); 1464} 1465 1466# Testing that the f command works. 1467{ 1468 my $wrapper = DebugWrap->new( 1469 { 1470 cmds => 1471 [ 1472 'f ../lib/perl5db/t/MyModule.pm', 1473 'b 12', 1474 'c', 1475 q/do { use IO::Handle; STDOUT->autoflush(1); print "Var=$var\n"; }/, 1476 'c', 1477 'q', 1478 ], 1479 include_t => 1, 1480 prog => '../lib/perl5db/t/filename-line-breakpoint' 1481 } 1482 ); 1483 1484 $wrapper->output_like(qr/ 1485 ^Var=Bar$ 1486 .* 1487 ^In\ MyModule\.$ 1488 .* 1489 ^In\ Main\ File\.$ 1490 .* 1491 /msx, 1492 "f command is working.", 1493 ); 1494} 1495 1496# We broke the /pattern/ command because apparently the CORE::eval-s inside 1497# lib/perl5db.pl cannot handle lexical variable properly. So we now fix this 1498# bug. 1499# 1500# TODO : 1501# 1502# 1. Go over the rest of the "eval"s in lib/perl5db.t and see if they cause 1503# problems. 1504{ 1505 my $wrapper = DebugWrap->new( 1506 { 1507 cmds => 1508 [ 1509 '/for/', 1510 'q', 1511 ], 1512 prog => '../lib/perl5db/t/eval-line-bug', 1513 } 1514 ); 1515 1516 $wrapper->contents_like( 1517 qr/12: \s* for\ my\ \$q\ \(1\ \.\.\ 10\)\ \{/msx, 1518 "/pat/ command is working and found a match.", 1519 ); 1520} 1521 1522{ 1523 my $wrapper = DebugWrap->new( 1524 { 1525 cmds => 1526 [ 1527 'b 22', 1528 'c', 1529 '?for?', 1530 'q', 1531 ], 1532 prog => '../lib/perl5db/t/eval-line-bug', 1533 } 1534 ); 1535 1536 $wrapper->contents_like( 1537 qr/12: \s* for\ my\ \$q\ \(1\ \.\.\ 10\)\ \{/msx, 1538 "?pat? command is working and found a match.", 1539 ); 1540} 1541 1542# Test the L command. 1543{ 1544 my $wrapper = DebugWrap->new( 1545 { 1546 cmds => 1547 [ 1548 'b 6', 1549 'b 13 ($q == 5)', 1550 'L', 1551 'q', 1552 ], 1553 prog => '../lib/perl5db/t/eval-line-bug', 1554 } 1555 ); 1556 1557 $wrapper->contents_like( 1558 qr# 1559 ^\S*?eval-line-bug:\n 1560 \s*6:\s*my\ \$i\ =\ 5;\n 1561 \s*break\ if\ \(1\)\n 1562 \s*13:\s*\$i\ \+=\ \$q;\n 1563 \s*break\ if\ \(\(\$q\ ==\ 5\)\)\n 1564 #msx, 1565 "L command is listing breakpoints", 1566 ); 1567} 1568 1569# Test the L command for watch expressions. 1570{ 1571 my $wrapper = DebugWrap->new( 1572 { 1573 cmds => 1574 [ 1575 'w (5+6)', 1576 'L', 1577 'q', 1578 ], 1579 prog => '../lib/perl5db/t/eval-line-bug', 1580 } 1581 ); 1582 1583 $wrapper->contents_like( 1584 qr# 1585 ^Watch-expressions:\n 1586 \s*\(5\+6\)\n 1587 #msx, 1588 "L command is listing watch expressions", 1589 ); 1590} 1591 1592{ 1593 my $wrapper = DebugWrap->new( 1594 { 1595 cmds => 1596 [ 1597 'w (5+6)', 1598 'w (11*23)', 1599 'W (5+6)', 1600 'L', 1601 'q', 1602 ], 1603 prog => '../lib/perl5db/t/eval-line-bug', 1604 } 1605 ); 1606 1607 $wrapper->contents_like( 1608 qr# 1609 ^Watch-expressions:\n 1610 \s*\(11\*23\)\n 1611 ^auto\( 1612 #msx, 1613 "L command is not listing deleted watch expressions", 1614 ); 1615} 1616 1617# Test the L command. 1618{ 1619 my $wrapper = DebugWrap->new( 1620 { 1621 cmds => 1622 [ 1623 'b 6', 1624 'a 13 print $i', 1625 'L', 1626 'q', 1627 ], 1628 prog => '../lib/perl5db/t/eval-line-bug', 1629 } 1630 ); 1631 1632 $wrapper->contents_like( 1633 qr# 1634 ^\S*?eval-line-bug:\n 1635 \s*6:\s*my\ \$i\ =\ 5;\n 1636 \s*break\ if\ \(1\)\n 1637 \s*13:\s*\$i\ \+=\ \$q;\n 1638 \s*action:\s+print\ \$i\n 1639 #msx, 1640 "L command is listing actions and breakpoints", 1641 ); 1642} 1643 1644{ 1645 my $wrapper = DebugWrap->new( 1646 { 1647 cmds => 1648 [ 1649 'S', 1650 'q', 1651 ], 1652 prog => '../lib/perl5db/t/rt-104168', 1653 } 1654 ); 1655 1656 $wrapper->contents_like( 1657 qr# 1658 ^main::bar\n 1659 main::baz\n 1660 main::foo\n 1661 #msx, 1662 "S command - 1", 1663 ); 1664} 1665 1666{ 1667 my $wrapper = DebugWrap->new( 1668 { 1669 cmds => 1670 [ 1671 'S ^main::ba', 1672 'q', 1673 ], 1674 prog => '../lib/perl5db/t/rt-104168', 1675 } 1676 ); 1677 1678 $wrapper->contents_like( 1679 qr# 1680 ^main::bar\n 1681 main::baz\n 1682 auto\( 1683 #msx, 1684 "S command with regex", 1685 ); 1686} 1687 1688{ 1689 my $wrapper = DebugWrap->new( 1690 { 1691 cmds => 1692 [ 1693 'S !^main::ba', 1694 'q', 1695 ], 1696 prog => '../lib/perl5db/t/rt-104168', 1697 } 1698 ); 1699 1700 $wrapper->contents_unlike( 1701 qr# 1702 ^main::ba 1703 #msx, 1704 "S command with negative regex", 1705 ); 1706 1707 $wrapper->contents_like( 1708 qr# 1709 ^main::foo\n 1710 #msx, 1711 "S command with negative regex - what it still matches", 1712 ); 1713} 1714 1715# Test the 'a' command. 1716{ 1717 my $wrapper = DebugWrap->new( 1718 { 1719 cmds => 1720 [ 1721 'a 13 print "\nVar<Q>=$q\n"', 1722 'c', 1723 'q', 1724 ], 1725 prog => '../lib/perl5db/t/eval-line-bug', 1726 } 1727 ); 1728 1729 my $nl = $^O eq 'VMS' ? "" : "\\\n"; 1730 $wrapper->output_like(qr# 1731 \nVar<Q>=1$nl 1732 \nVar<Q>=2$nl 1733 \nVar<Q>=3 1734 #msx, 1735 "a command is working", 1736 ); 1737} 1738 1739# Test the 'a' command with no line number. 1740{ 1741 my $wrapper = DebugWrap->new( 1742 { 1743 cmds => 1744 [ 1745 'n', 1746 q/a print "Hello " . (3 * 4) . "\n";/, 1747 'c', 1748 'q', 1749 ], 1750 prog => '../lib/perl5db/t/test-a-statement-1', 1751 } 1752 ); 1753 1754 $wrapper->output_like(qr# 1755 (?:^Hello\ 12\n.*?){4} 1756 #msx, 1757 "a command with no line number is working", 1758 ); 1759} 1760 1761# Test the 'A' command 1762{ 1763 my $wrapper = DebugWrap->new( 1764 { 1765 cmds => 1766 [ 1767 'a 13 print "\nVar<Q>=$q\n"', 1768 'A 13', 1769 'c', 1770 'q', 1771 ], 1772 prog => '../lib/perl5db/t/eval-line-bug', 1773 } 1774 ); 1775 1776 $wrapper->output_like( 1777 qr#\A\z#msx, # The empty string. 1778 "A command (for removing actions) is working", 1779 ); 1780} 1781 1782# Test the 'A *' command 1783{ 1784 my $wrapper = DebugWrap->new( 1785 { 1786 cmds => 1787 [ 1788 'a 6 print "\nFail!\n"', 1789 'a 13 print "\nVar<Q>=$q\n"', 1790 'A *', 1791 'c', 1792 'q', 1793 ], 1794 prog => '../lib/perl5db/t/eval-line-bug', 1795 } 1796 ); 1797 1798 $wrapper->output_like( 1799 qr#\A\z#msx, # The empty string. 1800 "'A *' command (for removing all actions) is working", 1801 ); 1802} 1803 1804{ 1805 my $wrapper = DebugWrap->new( 1806 { 1807 cmds => 1808 [ 1809 'n', 1810 'w $foo', 1811 'c', 1812 'print "\nIDX=<$idx>\n"', 1813 'q', 1814 ], 1815 prog => '../lib/perl5db/t/test-w-statement-1', 1816 } 1817 ); 1818 1819 1820 $wrapper->contents_like(qr# 1821 \$foo\ changed:\n 1822 \s+old\ value:\s+'1'\n 1823 \s+new\ value:\s+'2'\n 1824 #msx, 1825 'w command - watchpoint changed', 1826 ); 1827 $wrapper->output_like(qr# 1828 \nIDX=<20>\n 1829 #msx, 1830 "w command - correct output from IDX", 1831 ); 1832} 1833 1834{ 1835 my $wrapper = DebugWrap->new( 1836 { 1837 cmds => 1838 [ 1839 'n', 1840 'w $foo', 1841 'W $foo', 1842 'c', 1843 'print "\nIDX=<$idx>\n"', 1844 'q', 1845 ], 1846 prog => '../lib/perl5db/t/test-w-statement-1', 1847 } 1848 ); 1849 1850 $wrapper->contents_unlike(qr# 1851 \$foo\ changed: 1852 #msx, 1853 'W command - watchpoint was deleted', 1854 ); 1855 1856 $wrapper->output_like(qr# 1857 \nIDX=<>\n 1858 #msx, 1859 "W command - stopped at end.", 1860 ); 1861} 1862 1863# Test the W * command. 1864{ 1865 my $wrapper = DebugWrap->new( 1866 { 1867 cmds => 1868 [ 1869 'n', 1870 'w $foo', 1871 'w ($foo*$foo)', 1872 'W *', 1873 'c', 1874 'print "\nIDX=<$idx>\n"', 1875 'q', 1876 ], 1877 prog => '../lib/perl5db/t/test-w-statement-1', 1878 } 1879 ); 1880 1881 $wrapper->contents_unlike(qr# 1882 \$foo\ changed: 1883 #msx, 1884 '"W *" command - watchpoint was deleted', 1885 ); 1886 1887 $wrapper->output_like(qr# 1888 \nIDX=<>\n 1889 #msx, 1890 '"W *" command - stopped at end.', 1891 ); 1892} 1893 1894# Test the 'o' command (without further arguments). 1895{ 1896 my $wrapper = DebugWrap->new( 1897 { 1898 cmds => 1899 [ 1900 'o', 1901 'q', 1902 ], 1903 prog => '../lib/perl5db/t/test-w-statement-1', 1904 } 1905 ); 1906 1907 $wrapper->contents_like(qr# 1908 ^\s*warnLevel\ =\ '1'\n 1909 #msx, 1910 q#"o" command (without arguments) displays warnLevel#, 1911 ); 1912 1913 $wrapper->contents_like(qr# 1914 ^\s*signalLevel\ =\ '1'\n 1915 #msx, 1916 q#"o" command (without arguments) displays signalLevel#, 1917 ); 1918 1919 $wrapper->contents_like(qr# 1920 ^\s*dieLevel\ =\ '1'\n 1921 #msx, 1922 q#"o" command (without arguments) displays dieLevel#, 1923 ); 1924 1925 $wrapper->contents_like(qr# 1926 ^\s*hashDepth\ =\ 'N/A'\n 1927 #msx, 1928 q#"o" command (without arguments) displays hashDepth#, 1929 ); 1930} 1931 1932# Test the 'o' query command. 1933{ 1934 my $wrapper = DebugWrap->new( 1935 { 1936 cmds => 1937 [ 1938 'o hashDepth? signalLevel?', 1939 'q', 1940 ], 1941 prog => '../lib/perl5db/t/test-w-statement-1', 1942 } 1943 ); 1944 1945 $wrapper->contents_unlike(qr#warnLevel#, 1946 q#"o" query command does not display warnLevel#, 1947 ); 1948 1949 $wrapper->contents_like(qr# 1950 ^\s*signalLevel\ =\ '1'\n 1951 #msx, 1952 q#"o" query command displays signalLevel#, 1953 ); 1954 1955 $wrapper->contents_unlike(qr#dieLevel#, 1956 q#"o" query command does not display dieLevel#, 1957 ); 1958 1959 $wrapper->contents_like(qr# 1960 ^\s*hashDepth\ =\ 'N/A'\n 1961 #msx, 1962 q#"o" query command displays hashDepth#, 1963 ); 1964} 1965 1966# Test the 'o' set command. 1967{ 1968 my $wrapper = DebugWrap->new( 1969 { 1970 cmds => 1971 [ 1972 'o signalLevel=0', 1973 'o', 1974 'q', 1975 ], 1976 prog => '../lib/perl5db/t/test-w-statement-1', 1977 } 1978 ); 1979 1980 $wrapper->contents_like(qr/ 1981 ^\s*(signalLevel\ =\ '0'\n) 1982 .*? 1983 ^\s*\1 1984 /msx, 1985 q#o set command works#, 1986 ); 1987 1988 $wrapper->contents_like(qr# 1989 ^\s*hashDepth\ =\ 'N/A'\n 1990 #msx, 1991 q#o set command - hashDepth#, 1992 ); 1993} 1994 1995# Test the '<' and "< ?" commands. 1996{ 1997 my $wrapper = DebugWrap->new( 1998 { 1999 cmds => 2000 [ 2001 q/< print "\nX=<$x>\n"/, 2002 q/b 7/, 2003 q/< ?/, 2004 'c', 2005 'q', 2006 ], 2007 prog => '../lib/perl5db/t/disable-breakpoints-1', 2008 } 2009 ); 2010 2011 $wrapper->contents_like(qr/ 2012 ^pre-perl\ commands:\n 2013 \s*<\ --\ print\ "\\nX=<\$x>\\n"\n 2014 /msx, 2015 q#Test < and < ? commands - contents.#, 2016 ); 2017 2018 $wrapper->output_like(qr# 2019 ^X=<FirstVal>\n 2020 #msx, 2021 q#Test < and < ? commands - output.#, 2022 ); 2023} 2024 2025# Test the '< *' command. 2026{ 2027 my $wrapper = DebugWrap->new( 2028 { 2029 cmds => 2030 [ 2031 q/< print "\nX=<$x>\n"/, 2032 q/b 7/, 2033 q/< */, 2034 'c', 2035 'q', 2036 ], 2037 prog => '../lib/perl5db/t/disable-breakpoints-1', 2038 } 2039 ); 2040 2041 $wrapper->output_unlike(qr/FirstVal/, 2042 q#Test the '< *' command.#, 2043 ); 2044} 2045 2046# Test the '>' and "> ?" commands. 2047{ 2048 my $wrapper = DebugWrap->new( 2049 { 2050 cmds => 2051 [ 2052 q/$::foo = 500;/, 2053 q/> print "\nFOO=<$::foo>\n"/, 2054 q/b 7/, 2055 q/> ?/, 2056 'c', 2057 'q', 2058 ], 2059 prog => '../lib/perl5db/t/disable-breakpoints-1', 2060 } 2061 ); 2062 2063 $wrapper->contents_like(qr/ 2064 ^post-perl\ commands:\n 2065 \s*>\ --\ print\ "\\nFOO=<\$::foo>\\n"\n 2066 /msx, 2067 q#Test > and > ? commands - contents.#, 2068 ); 2069 2070 $wrapper->output_like(qr# 2071 ^FOO=<500>\n 2072 #msx, 2073 q#Test > and > ? commands - output.#, 2074 ); 2075} 2076 2077# Test the '> *' command. 2078{ 2079 my $wrapper = DebugWrap->new( 2080 { 2081 cmds => 2082 [ 2083 q/> print "\nFOO=<$::foo>\n"/, 2084 q/b 7/, 2085 q/> */, 2086 'c', 2087 'q', 2088 ], 2089 prog => '../lib/perl5db/t/disable-breakpoints-1', 2090 } 2091 ); 2092 2093 $wrapper->output_unlike(qr/FOO=/, 2094 q#Test the '> *' command.#, 2095 ); 2096} 2097 2098# Test the < and > commands together 2099{ 2100 my $wrapper = DebugWrap->new( 2101 { 2102 cmds => 2103 [ 2104 q/$::lorem = 0;/, 2105 q/< $::lorem += 10;/, 2106 q/> print "\nLOREM=<$::lorem>\n"/, 2107 q/b 7/, 2108 q/b 5/, 2109 'c', 2110 'c', 2111 'q', 2112 ], 2113 prog => '../lib/perl5db/t/disable-breakpoints-1', 2114 } 2115 ); 2116 2117 $wrapper->output_like(qr# 2118 ^LOREM=<10>\n 2119 #msx, 2120 q#Test < and > commands. #, 2121 ); 2122} 2123 2124# Test the { ? and { [command] commands. 2125{ 2126 my $wrapper = DebugWrap->new( 2127 { 2128 cmds => 2129 [ 2130 '{ ?', 2131 '{ l', 2132 '{ ?', 2133 q/b 5/, 2134 q/c/, 2135 q/q/, 2136 ], 2137 prog => '../lib/perl5db/t/disable-breakpoints-1', 2138 } 2139 ); 2140 2141 $wrapper->contents_like(qr# 2142 ^No\ pre-debugger\ actions\.\n 2143 .*? 2144 ^pre-debugger\ commands:\n 2145 \s+\{\ --\ l\n 2146 .*? 2147 ^5==>b\s+\$x\ =\ "FirstVal";\n 2148 6\s*\n 2149 7:\s+\$dummy\+\+;\n 2150 8\s*\n 2151 9:\s+\$x\ =\ "SecondVal";\n 2152 2153 #msx, 2154 'Test the pre-prompt debugger commands', 2155 ); 2156} 2157 2158# Test the { * command. 2159{ 2160 my $wrapper = DebugWrap->new( 2161 { 2162 cmds => 2163 [ 2164 '{ q', 2165 '{ *', 2166 q/b 5/, 2167 q/c/, 2168 q/print (("One" x 5), "\n");/, 2169 q/q/, 2170 ], 2171 prog => '../lib/perl5db/t/disable-breakpoints-1', 2172 } 2173 ); 2174 2175 $wrapper->contents_like(qr# 2176 ^All\ \{\ actions\ cleared\.\n 2177 #msx, 2178 'Test the { * command', 2179 ); 2180 2181 $wrapper->output_like(qr/OneOneOneOneOne/, 2182 '{ * test - output is OK.', 2183 ); 2184} 2185 2186# Test the ! command. 2187{ 2188 my $wrapper = DebugWrap->new( 2189 { 2190 cmds => 2191 [ 2192 'l 3-5', 2193 '!', 2194 'q', 2195 ], 2196 prog => '../lib/perl5db/t/disable-breakpoints-1', 2197 } 2198 ); 2199 2200 $wrapper->contents_like(qr# 2201 (^3:\s+my\ \$dummy\ =\ 0;\n 2202 4\s*\n 2203 5:\s+\$x\ =\ "FirstVal";)\n 2204 .*? 2205 ^l\ 3-5\n 2206 \1 2207 #msx, 2208 'Test the ! command (along with l 3-5)', 2209 ); 2210} 2211 2212# Test the ! -number command. 2213{ 2214 my $wrapper = DebugWrap->new( 2215 { 2216 cmds => 2217 [ 2218 'l 3-5', 2219 'l 2', 2220 '! -1', 2221 'q', 2222 ], 2223 prog => '../lib/perl5db/t/disable-breakpoints-1', 2224 } 2225 ); 2226 2227 $wrapper->contents_like(qr# 2228 (^3:\s+my\ \$dummy\ =\ 0;\n 2229 4\s*\n 2230 5:\s+\$x\ =\ "FirstVal";)\n 2231 .*? 2232 ^2==\>\s+my\ \$x\ =\ "One";\n 2233 .*? 2234 ^l\ 3-5\n 2235 \1 2236 #msx, 2237 'Test the ! -n command (along with l)', 2238 ); 2239} 2240 2241# Test the 'source' command. 2242{ 2243 my $wrapper = DebugWrap->new( 2244 { 2245 cmds => 2246 [ 2247 'source ../lib/perl5db/t/source-cmd-test.perldb', 2248 # If we have a 'q' here, then the typeahead will override the 2249 # input, and so it won't be reached - solution: 2250 # put a q inside the .perldb commands. 2251 # ( This may be a bug or a misfeature. ) 2252 ], 2253 prog => '../lib/perl5db/t/disable-breakpoints-1', 2254 } 2255 ); 2256 2257 $wrapper->contents_like(qr# 2258 ^3:\s+my\ \$dummy\ =\ 0;\n 2259 4\s*\n 2260 5:\s+\$x\ =\ "FirstVal";\n 2261 6\s*\n 2262 7:\s+\$dummy\+\+;\n 2263 8\s*\n 2264 9:\s+\$x\ =\ "SecondVal";\n 2265 10\s*\n 2266 #msx, 2267 'Test the source command (along with l)', 2268 ); 2269} 2270 2271# Test the 'source' command being traversed from withing typeahead. 2272{ 2273 my $wrapper = DebugWrap->new( 2274 { 2275 cmds => 2276 [ 2277 'source ../lib/perl5db/t/source-cmd-test-no-q.perldb', 2278 'q', 2279 ], 2280 prog => '../lib/perl5db/t/disable-breakpoints-1', 2281 } 2282 ); 2283 2284 $wrapper->contents_like(qr# 2285 ^3:\s+my\ \$dummy\ =\ 0;\n 2286 4\s*\n 2287 5:\s+\$x\ =\ "FirstVal";\n 2288 6\s*\n 2289 7:\s+\$dummy\+\+;\n 2290 8\s*\n 2291 9:\s+\$x\ =\ "SecondVal";\n 2292 10\s*\n 2293 #msx, 2294 'Test the source command inside a typeahead', 2295 ); 2296} 2297 2298# Test the 'H -number' command. 2299{ 2300 my $wrapper = DebugWrap->new( 2301 { 2302 cmds => 2303 [ 2304 'l 1-10', 2305 'l 5-10', 2306 'x "Hello World"', 2307 'l 1-5', 2308 'b 3', 2309 'x (20+4)', 2310 'H -7', 2311 'q', 2312 ], 2313 prog => '../lib/perl5db/t/disable-breakpoints-1', 2314 } 2315 ); 2316 2317 $wrapper->contents_like(qr# 2318 ^\d+:\s+H\ -7\n 2319 \d+:\s+x\ \(20\+4\)\n 2320 \d+:\s+b\ 3\n 2321 \d+:\s+l\ 1-5\n 2322 \d+:\s+x\ "Hello\ World"\n 2323 \d+:\s+l\ 5-10\n 2324 \d+:\s+l\ 1-10\n 2325 #msx, 2326 'Test the H -num command', 2327 ); 2328} 2329 2330# Add a test for H (without arguments) 2331{ 2332 my $wrapper = DebugWrap->new( 2333 { 2334 cmds => 2335 [ 2336 'l 1-10', 2337 'l 5-10', 2338 'x "Hello World"', 2339 'l 1-5', 2340 'b 3', 2341 'x (20+4)', 2342 'H', 2343 'q', 2344 ], 2345 prog => '../lib/perl5db/t/disable-breakpoints-1', 2346 } 2347 ); 2348 2349 $wrapper->contents_like(qr# 2350 ^\d+:\s+x\ \(20\+4\)\n 2351 \d+:\s+b\ 3\n 2352 \d+:\s+l\ 1-5\n 2353 \d+:\s+x\ "Hello\ World"\n 2354 \d+:\s+l\ 5-10\n 2355 \d+:\s+l\ 1-10\n 2356 #msx, 2357 'Test the H command (without a number.)', 2358 ); 2359} 2360 2361{ 2362 my $wrapper = DebugWrap->new( 2363 { 2364 cmds => 2365 [ 2366 '= quit q', 2367 '= foobar l', 2368 '= .hello print "hellox\n"', 2369 '= -goodbye print "goodbyex\n"', 2370 'foobar', 2371 '.hello', 2372 '-goodbye', 2373 'quit', 2374 ], 2375 prog => '../lib/perl5db/t/test-l-statement-1', 2376 } 2377 ); 2378 2379 $wrapper->contents_like( 2380 qr/ 2381 ^1==>\s+\$x\ =\ 1;\n 2382 2:\s+print\ "1\\n";\n 2383 3\s*\n 2384 4:\s+\$x\ =\ 2;\n 2385 5:\s+print\ "2\\n";\n 2386 /msx, 2387 'Test the = (command alias) command.', 2388 ); 2389 $wrapper->output_like(qr/hellox.*goodbyex/xs, 2390 "check . and - can start alias name"); 2391} 2392 2393# Test the m statement. 2394{ 2395 my $wrapper = DebugWrap->new( 2396 { 2397 cmds => 2398 [ 2399 'm main', 2400 'q', 2401 ], 2402 prog => '../lib/perl5db/t/disable-breakpoints-1', 2403 } 2404 ); 2405 2406 $wrapper->contents_like(qr# 2407 ^via\ UNIVERSAL:\ DOES$ 2408 #msx, 2409 "Test m for main - 1", 2410 ); 2411 2412 $wrapper->contents_like(qr# 2413 ^via\ UNIVERSAL:\ can$ 2414 #msx, 2415 "Test m for main - 2", 2416 ); 2417} 2418 2419# Test the m statement. 2420{ 2421 my $wrapper = DebugWrap->new( 2422 { 2423 cmds => 2424 [ 2425 'b 41', 2426 'c', 2427 'm $obj', 2428 'q', 2429 ], 2430 prog => '../lib/perl5db/t/test-m-statement-1', 2431 } 2432 ); 2433 2434 $wrapper->contents_like(qr#^greet$#ms, 2435 "Test m for obj - 1", 2436 ); 2437 2438 $wrapper->contents_like(qr#^via UNIVERSAL: can$#ms, 2439 "Test m for obj - 1", 2440 ); 2441} 2442 2443# Test the M command. 2444{ 2445 my $wrapper = DebugWrap->new( 2446 { 2447 cmds => 2448 [ 2449 'M', 2450 'q', 2451 ], 2452 prog => '../lib/perl5db/t/test-m-statement-1', 2453 } 2454 ); 2455 2456 $wrapper->contents_like(qr# 2457 ^'strict\.pm'\ =>\ '\d+\.\d+\ from 2458 #msx, 2459 "Test M", 2460 ); 2461 2462} 2463 2464# Test the recallCommand option. 2465{ 2466 my $wrapper = DebugWrap->new( 2467 { 2468 cmds => 2469 [ 2470 'o recallCommand=%', 2471 'l 3-5', 2472 'l 2', 2473 '% -1', 2474 'q', 2475 ], 2476 prog => '../lib/perl5db/t/disable-breakpoints-1', 2477 } 2478 ); 2479 2480 $wrapper->contents_like(qr# 2481 (^3:\s+my\ \$dummy\ =\ 0;\n 2482 4\s*\n 2483 5:\s+\$x\ =\ "FirstVal";)\n 2484 .*? 2485 ^2==\>\s+my\ \$x\ =\ "One";\n 2486 .*? 2487 ^l\ 3-5\n 2488 \1 2489 #msx, 2490 'Test the o recallCommand option', 2491 ); 2492} 2493 2494# Test the dieLevel option 2495{ 2496 my $wrapper = DebugWrap->new( 2497 { 2498 cmds => 2499 [ 2500 q/o dieLevel='1'/, 2501 q/c/, 2502 'q', 2503 ], 2504 prog => '../lib/perl5db/t/test-dieLevel-option-1', 2505 } 2506 ); 2507 2508 $wrapper->output_like(qr# 2509 ^This\ program\ dies\.\ at\ \S+\ line\ 18\N*\.\n 2510 .*? 2511 ^\s+main::baz\(\)\ called\ at\ \S+\ line\ 13\n 2512 \s+main::bar\(\)\ called\ at\ \S+\ line\ 7\n 2513 \s+main::foo\(\)\ called\ at\ \S+\ line\ 21\n 2514 #msx, 2515 'Test the o dieLevel option', 2516 ); 2517} 2518 2519# Test the warnLevel option 2520{ 2521 my $wrapper = DebugWrap->new( 2522 { 2523 cmds => 2524 [ 2525 q/o warnLevel='1'/, 2526 q/c/, 2527 'q', 2528 ], 2529 prog => '../lib/perl5db/t/test-warnLevel-option-1', 2530 } 2531 ); 2532 2533 $wrapper->contents_like(qr# 2534 ^This\ is\ not\ a\ warning\.\ at\ \S+\ line\ 18\N*\.\n 2535 .*? 2536 ^\s+main::baz\(\)\ called\ at\ \S+\ line\ 13\n 2537 \s+main::bar\(\)\ called\ at\ \S+\ line\ 25\n 2538 \s+main::myfunc\(\)\ called\ at\ \S+\ line\ 28\n 2539 #msx, 2540 'Test the o warnLevel option', 2541 ); 2542} 2543 2544# Test the t command 2545{ 2546 my $wrapper = DebugWrap->new( 2547 { 2548 cmds => 2549 [ 2550 't', 2551 'c', 2552 'q', 2553 ], 2554 prog => '../lib/perl5db/t/disable-breakpoints-1', 2555 } 2556 ); 2557 2558 $wrapper->contents_like(qr/ 2559 ^main::\([^:]+:15\):\n 2560 15:\s+\$dummy\+\+;\n 2561 main::\([^:]+:17\):\n 2562 17:\s+\$x\ =\ "FourthVal";\n 2563 /msx, 2564 'Test the t command (without a number.)', 2565 ); 2566} 2567 2568# Test the o AutoTrace command 2569{ 2570 my $wrapper = DebugWrap->new( 2571 { 2572 cmds => 2573 [ 2574 'o AutoTrace', 2575 'c', 2576 'q', 2577 ], 2578 prog => '../lib/perl5db/t/disable-breakpoints-1', 2579 } 2580 ); 2581 2582 $wrapper->contents_like(qr/ 2583 ^main::\([^:]+:15\):\n 2584 15:\s+\$dummy\+\+;\n 2585 main::\([^:]+:17\):\n 2586 17:\s+\$x\ =\ "FourthVal";\n 2587 /msx, 2588 'Test the o AutoTrace command', 2589 ); 2590} 2591 2592# Test the t command with function calls 2593{ 2594 my $wrapper = DebugWrap->new( 2595 { 2596 cmds => 2597 [ 2598 't', 2599 'b 18', 2600 'c', 2601 'x ["foo"]', 2602 'x ["bar"]', 2603 'q', 2604 ], 2605 prog => '../lib/perl5db/t/test-warnLevel-option-1', 2606 } 2607 ); 2608 2609 $wrapper->contents_like(qr/ 2610 ^main::\([^:]+:28\):\n 2611 28:\s+myfunc\(\);\n 2612 auto\(-\d+\)\s+DB<1>\s+t\n 2613 Trace\ =\ on\n 2614 auto\(-\d+\)\s+DB<1>\s+b\ 18\n 2615 auto\(-\d+\)\s+DB<2>\s+c\n 2616 main::myfunc\([^:]+:25\):\n 2617 25:\s+bar\(\);\n 2618 /msx, 2619 'Test the t command with function calls.', 2620 ); 2621} 2622 2623# Test the o AutoTrace command with function calls 2624{ 2625 my $wrapper = DebugWrap->new( 2626 { 2627 cmds => 2628 [ 2629 'o AutoTrace', 2630 'b 18', 2631 'c', 2632 'x ["foo"]', 2633 'x ["bar"]', 2634 'q', 2635 ], 2636 prog => '../lib/perl5db/t/test-warnLevel-option-1', 2637 } 2638 ); 2639 2640 $wrapper->contents_like(qr/ 2641 ^main::\([^:]+:28\):\n 2642 28:\s+myfunc\(\);\n 2643 auto\(-\d+\)\s+DB<1>\s+o\ AutoTrace\n 2644 \s+AutoTrace\s+=\s+'1'\n 2645 auto\(-\d+\)\s+DB<2>\s+b\ 18\n 2646 auto\(-\d+\)\s+DB<3>\s+c\n 2647 main::myfunc\([^:]+:25\):\n 2648 25:\s+bar\(\);\n 2649 /msx, 2650 'Test the o AutoTrace command with function calls.', 2651 ); 2652} 2653 2654# Test the final message. 2655{ 2656 my $wrapper = DebugWrap->new( 2657 { 2658 cmds => 2659 [ 2660 'c', 2661 'q', 2662 ], 2663 prog => '../lib/perl5db/t/test-warnLevel-option-1', 2664 } 2665 ); 2666 2667 $wrapper->contents_like(qr/ 2668 ^Debugged\ program\ terminated\. 2669 /msx, 2670 'Test the final "Debugged program terminated" message.', 2671 ); 2672} 2673 2674# Test the o inhibit_exit=0 command 2675{ 2676 my $wrapper = DebugWrap->new( 2677 { 2678 cmds => 2679 [ 2680 'o inhibit_exit=0', 2681 'n', 2682 'n', 2683 'n', 2684 'n', 2685 'q', 2686 ], 2687 prog => '../lib/perl5db/t/test-warnLevel-option-1', 2688 } 2689 ); 2690 2691 $wrapper->contents_unlike(qr/ 2692 ^Debugged\ program\ terminated\. 2693 /msx, 2694 'Test the o inhibit_exit=0 command.', 2695 ); 2696} 2697 2698# Test the o PrintRet=1 option 2699{ 2700 my $wrapper = DebugWrap->new( 2701 { 2702 cmds => 2703 [ 2704 'o PrintRet=1', 2705 'b 29', 2706 'c', 2707 q/$x = 's';/, 2708 'b 10', 2709 'c', 2710 'r', 2711 'q', 2712 ], 2713 prog => '../lib/perl5db/t/test-PrintRet-option-1', 2714 } 2715 ); 2716 2717 $wrapper->contents_like( 2718 qr/scalar context return from main::return_scalar: 20024/, 2719 "Test o PrintRet=1", 2720 ); 2721} 2722 2723# Test the o PrintRet=0 option 2724{ 2725 my $wrapper = DebugWrap->new( 2726 { 2727 cmds => 2728 [ 2729 'o PrintRet=0', 2730 'b 29', 2731 'c', 2732 q/$x = 's';/, 2733 'b 10', 2734 'c', 2735 'r', 2736 'q', 2737 ], 2738 prog => '../lib/perl5db/t/test-PrintRet-option-1', 2739 } 2740 ); 2741 2742 $wrapper->contents_unlike( 2743 qr/scalar context/, 2744 "Test o PrintRet=0", 2745 ); 2746} 2747 2748# Test the o PrintRet=1 option in list context 2749{ 2750 my $wrapper = DebugWrap->new( 2751 { 2752 cmds => 2753 [ 2754 'o PrintRet=1', 2755 'b 29', 2756 'c', 2757 q/$x = 'l';/, 2758 'b 17', 2759 'c', 2760 'r', 2761 'q', 2762 ], 2763 prog => '../lib/perl5db/t/test-PrintRet-option-1', 2764 } 2765 ); 2766 2767 $wrapper->contents_like( 2768 qr/list context return from main::return_list:\n0\s*'Foo'\n1\s*'Bar'\n2\s*'Baz'\n/, 2769 "Test o PrintRet=1 in list context", 2770 ); 2771} 2772 2773# Test the o PrintRet=0 option in list context 2774{ 2775 my $wrapper = DebugWrap->new( 2776 { 2777 cmds => 2778 [ 2779 'o PrintRet=0', 2780 'b 29', 2781 'c', 2782 q/$x = 'l';/, 2783 'b 17', 2784 'c', 2785 'r', 2786 'q', 2787 ], 2788 prog => '../lib/perl5db/t/test-PrintRet-option-1', 2789 } 2790 ); 2791 2792 $wrapper->contents_unlike( 2793 qr/list context/, 2794 "Test o PrintRet=0 in list context", 2795 ); 2796} 2797 2798# Test the o PrintRet=1 option in void context 2799{ 2800 my $wrapper = DebugWrap->new( 2801 { 2802 cmds => 2803 [ 2804 'o PrintRet=1', 2805 'b 29', 2806 'c', 2807 q/$x = 'v';/, 2808 'b 24', 2809 'c', 2810 'r', 2811 'q', 2812 ], 2813 prog => '../lib/perl5db/t/test-PrintRet-option-1', 2814 } 2815 ); 2816 2817 $wrapper->contents_like( 2818 qr/void context return from main::return_void/, 2819 "Test o PrintRet=1 in void context", 2820 ); 2821} 2822 2823# Test the o PrintRet=1 option in void context 2824{ 2825 my $wrapper = DebugWrap->new( 2826 { 2827 cmds => 2828 [ 2829 'o PrintRet=0', 2830 'b 29', 2831 'c', 2832 q/$x = 'v';/, 2833 'b 24', 2834 'c', 2835 'r', 2836 'q', 2837 ], 2838 prog => '../lib/perl5db/t/test-PrintRet-option-1', 2839 } 2840 ); 2841 2842 $wrapper->contents_unlike( 2843 qr/void context/, 2844 "Test o PrintRet=0 in void context", 2845 ); 2846} 2847 2848# Test the o frame option. 2849{ 2850 my $wrapper = DebugWrap->new( 2851 { 2852 cmds => 2853 [ 2854 # This is to avoid getting the "Debugger program terminated" 2855 # junk that interferes with the normal output. 2856 'o inhibit_exit=0', 2857 'b 10', 2858 'c', 2859 'o frame=255', 2860 'c', 2861 'q', 2862 ], 2863 prog => '../lib/perl5db/t/test-frame-option-1', 2864 } 2865 ); 2866 2867 $wrapper->contents_like( 2868 qr/ 2869 in\s*\.=main::my_other_func\(3,\ 1200\)\ from.*? 2870 out\s*\.=main::my_other_func\(3,\ 1200\)\ from 2871 /msx, 2872 "Test o PrintRet=0 in void context", 2873 ); 2874} 2875 2876{ # test t expr 2877 my $wrapper = DebugWrap->new( 2878 { 2879 cmds => 2880 [ 2881 # This is to avoid getting the "Debugger program terminated" 2882 # junk that interferes with the normal output. 2883 'o inhibit_exit=0', 2884 't fact(3)', 2885 'q', 2886 ], 2887 prog => '../lib/perl5db/t/fact', 2888 } 2889 ); 2890 2891 $wrapper->contents_like( 2892 qr/ 2893 (?:^main::fact.*return\ \$n\ \*\ fact\(\$n\ -\ 1\);.*) 2894 /msx, 2895 "Test t expr", 2896 ); 2897} 2898 2899# Test the w for lexical variables expression. 2900{ 2901 my $wrapper = DebugWrap->new( 2902 { 2903 cmds => 2904 [ 2905 # This is to avoid getting the "Debugger program terminated" 2906 # junk that interferes with the normal output. 2907 'w $exp', 2908 'n', 2909 'n', 2910 'n', 2911 'n', 2912 'q', 2913 ], 2914 prog => '../lib/perl5db/t/break-on-dot', 2915 } 2916 ); 2917 2918 $wrapper->contents_like( 2919 qr/ 2920\s+old\ value:\s+'1'\n 2921\s+new\ value:\s+'2'\n 2922 /msx, 2923 "Test w for lexical values.", 2924 ); 2925} 2926 2927# perl 5 RT #121509 regression bug. 2928# “perl debugger doesn't save starting dir to restart from” 2929# Thanks to Linda Walsh for reporting it. 2930{ 2931 use File::Temp qw/tempdir/; 2932 2933 my $temp_dir = tempdir( CLEANUP => 1 ); 2934 2935 local $ENV{__PERLDB_TEMP_DIR} = $temp_dir; 2936 my $wrapper = DebugWrap->new( 2937 { 2938 cmds => 2939 [ 2940 # This is to avoid getting the "Debugger program terminated" 2941 # junk that interferes with the normal output. 2942 'b _after_chdir', 2943 'c', 2944 'R', 2945 'b _finale', 2946 'c', 2947 'n', 2948 'n', 2949 'n', 2950 'n', 2951 'n', 2952 'n', 2953 'n', 2954 'n', 2955 'n', 2956 'n', 2957 'n', 2958 'n', 2959 'q', 2960 ], 2961 prog => '../lib/perl5db/t/rt-121509-restart-after-chdir', 2962 } 2963 ); 2964 2965 $wrapper->output_like( 2966 qr/ 2967In\ _finale\ No\ 1 2968 .*? 2969In\ _finale\ No\ 2 2970 .*? 2971In\ _finale\ No\ 3 2972 /msx, 2973 "Test that the debugger chdirs to the initial directory after a restart.", 2974 ); 2975} 2976# Test the perldoc command 2977# We don't actually run the program, but we need to provide one to the wrapper. 2978SKIP: 2979{ 2980 $^O eq "linux" 2981 or skip "man errors aren't especially portable", 1; 2982 -x '/usr/bin/man' 2983 or skip "man command seems to be missing", 1; 2984 local $ENV{LANG} = "C"; 2985 local $ENV{LC_MESSAGES} = "C"; 2986 local $ENV{LC_ALL} = "C"; 2987 my $wrapper = DebugWrap->new( 2988 { 2989 cmds => 2990 [ 2991 'perldoc perlrules', 2992 'q', 2993 ], 2994 prog => '../lib/perl5db/t/fact', 2995 } 2996 ); 2997 2998 $wrapper->output_like( 2999 qr/No (?:manual )?entry for perlrules/, 3000 'perldoc command works fine', 3001 ); 3002} 3003 3004# [perl #71678] debugger bug in evaluation of user actions ('a' command) 3005# Still evaluated after the script finishes. 3006{ 3007 my $wrapper = DebugWrap->new( 3008 { 3009 cmds => 3010 [ 3011 q#a 9 print " \$arg = $arg\n"#, 3012 'c 9', 3013 's', 3014 'q', 3015 ], 3016 prog => '../lib/perl5db/t/test-a-statement-2', 3017 switches => [ '-dw', ], 3018 stderr => 1, 3019 } 3020 ); 3021 3022 $wrapper->contents_unlike(qr/ 3023 Use\ of\ uninitialized\ value\ \$arg\ in\ concatenation\ [\S ]+\ or\ string\ at 3024 /msx, 3025 'Test that the a command does not emit warnings on program exit.', 3026 ); 3027} 3028 3029{ 3030 # GitHub #17901 3031 my $wrapper = DebugWrap->new( 3032 { 3033 cmds => 3034 [ 3035 'a 4 $s++', 3036 ('s') x 5, 3037 'x $s', 3038 'q' 3039 ], 3040 prog => '../lib/perl5db/t/test-a-statement-3', 3041 switches => [ '-d' ], 3042 stderr => 0, 3043 } 3044 ); 3045 $wrapper->contents_like( 3046 qr/^0 +2$/m, 3047 'Test that the a command runs only on the given lines.', 3048 ); 3049} 3050 3051{ 3052 # perl 5 RT #126735 regression bug. 3053 local $ENV{PERLDB_OPTS} = "NonStop=0 RemotePort=non-existent-host.tld:9001"; 3054 my $output = runperl( stdin => "q\n", stderr => 1, switches => [ '-d' ], prog => '../lib/perl5db/t/fact' ); 3055 like( 3056 $output, 3057 qr/^Unable to connect to remote host:/ms, 3058 'Tried to connect.', 3059 ); 3060 unlike( 3061 $output, 3062 qr/syntax error/, 3063 'Can quit from the debugger after a wrong RemotePort', 3064 ); 3065} 3066 3067{ 3068 # perl 5 RT #120174 - 'p' command 3069 my $wrapper = DebugWrap->new( 3070 { 3071 cmds => 3072 [ 3073 'b 2', 3074 'c', 3075 'p@abc', 3076 'q', 3077 ], 3078 prog => '../lib/perl5db/t/rt-120174', 3079 } 3080 ); 3081 3082 $wrapper->contents_like( 3083 qr/1234/, 3084 q/RT 120174: p command can be invoked without space after 'p'/, 3085 ); 3086} 3087 3088{ 3089 # perl 5 RT #120174 - 'x' command on array 3090 my $wrapper = DebugWrap->new( 3091 { 3092 cmds => 3093 [ 3094 'b 2', 3095 'c', 3096 'x@abc', 3097 'q', 3098 ], 3099 prog => '../lib/perl5db/t/rt-120174', 3100 } 3101 ); 3102 3103 $wrapper->contents_like( 3104 qr/0\s+1\n1\s+2\n2\s+3\n3\s+4/ms, 3105 q/RT 120174: x command can be invoked without space after 'x' before array/, 3106 ); 3107} 3108 3109{ 3110 # perl 5 RT #120174 - 'x' command on array ref 3111 my $wrapper = DebugWrap->new( 3112 { 3113 cmds => 3114 [ 3115 'b 2', 3116 'c', 3117 'x\@abc', 3118 'q', 3119 ], 3120 prog => '../lib/perl5db/t/rt-120174', 3121 } 3122 ); 3123 3124 $wrapper->contents_like( 3125 qr/\s+0\s+1\n\s+1\s+2\n\s+2\s+3\n\s+3\s+4/ms, 3126 q/RT 120174: x command can be invoked without space after 'x' before array ref/, 3127 ); 3128} 3129 3130{ 3131 # perl 5 RT #120174 - 'x' command on hash ref 3132 my $wrapper = DebugWrap->new( 3133 { 3134 cmds => 3135 [ 3136 'b 4', 3137 'c', 3138 'x\%xyz', 3139 'q', 3140 ], 3141 prog => '../lib/perl5db/t/rt-120174', 3142 } 3143 ); 3144 3145 $wrapper->contents_like( 3146 qr/\s+'alpha'\s+=>\s+'beta'\n\s+'gamma'\s+=>\s+'delta'/ms, 3147 q/RT 120174: x command can be invoked without space after 'x' before hash ref/, 3148 ); 3149} 3150 3151{ 3152 # gh #17660 3153 my $wrapper = DebugWrap->new( 3154 { 3155 cmds => 3156 [ 3157 'b 13', 3158 'c', 3159 'i Foo', 3160 'q', 3161 ], 3162 prog => '../lib/perl5db/t/gh-17660', 3163 } 3164 ); 3165 3166 $wrapper->output_unlike( 3167 qr/Undefined subroutine &mro::get_linear_isa/ms, 3168 q/mro needs to be loaded/, 3169 ); 3170 $wrapper->output_like( 3171 qr/Foo 1.000, Bar 2.000/, 3172 q/check for reasonable result/, 3173 ); 3174} 3175 3176{ 3177 # gh #17661 3178 my $wrapper = DebugWrap->new( 3179 { 3180 cmds => 3181 [ 3182 'c', 3183 'i $obj', 3184 'q', 3185 ], 3186 prog => '../lib/perl5db/t/gh-17661', 3187 } 3188 ); 3189 3190 $wrapper->output_like( 3191 qr/C5, C1, C2, C3, C4/, 3192 q/check for reasonable result/, 3193 ); 3194} 3195 3196{ 3197 # gh #17661 related - C<l $var> where $var is lexical 3198 my $wrapper = DebugWrap->new( 3199 { 3200 cmds => 3201 [ 3202 'c', 3203 'l $x', 3204 'l $y', 3205 'q', 3206 ], 3207 prog => '../lib/perl5db/t/gh-17661b', 3208 } 3209 ); 3210 3211 $wrapper->contents_like( 3212 qr/sub bar/, 3213 q/check bar was listed/, 3214 ); 3215 $wrapper->contents_like( 3216 qr/sub foo/, 3217 q/check foo was listed/, 3218 ); 3219} 3220 3221SKIP: 3222{ 3223 $Config{usethreads} 3224 or skip "need threads to test debugging threads", 1; 3225 my $wrapper = DebugWrap->new( 3226 { 3227 cmds => 3228 [ 3229 'c', 3230 'q', 3231 ], 3232 prog => '../lib/perl5db/t/rt-124203', 3233 } 3234 ); 3235 3236 $wrapper->output_like(qr/In the thread/, "[perl #124203] the thread ran"); 3237 3238 $wrapper->output_like(qr/Finished/, "[perl #124203] debugger didn't deadlock"); 3239 3240 $wrapper = DebugWrap->new( 3241 { 3242 cmds => 3243 [ 3244 'c', 3245 'q', 3246 ], 3247 prog => '../lib/perl5db/t/rt-124203b', 3248 } 3249 ); 3250 3251 $wrapper->output_like(qr/In the thread/, "[perl #124203] the thread ran (lvalue)"); 3252 3253 $wrapper->output_like(qr/Finished One/, "[perl #124203] debugger didn't deadlock (lvalue)"); 3254} 3255 3256{ 3257 # https://github.com/Perl/perl5/issues/19198 3258 # this isn't a debugger bug, but a bug in the way perl itself stores cop 3259 # information for lines 3260 my $wrapper = DebugWrap->new( 3261 { 3262 cmds => 3263 [ 3264 'b Test::AUTOLOAD', # this would crash on ASAN 3265 'c', # this would fail to stop at the breakpoint 3266 'q' 3267 ], 3268 prog => \<<'EOS', 3269package Test; 3270 3271sub AUTOLOAD { 3272 use vars '$AUTOLOAD'; 3273 my $sub = $AUTOLOAD; 3274 return 1; 3275} 3276 3277package main; 3278 3279 3280sub test 3281{ 3282 Test::test(); 3283} 3284 3285sub test_test 3286{ 3287 eval { test() }; 3288} 3289 3290test_test(); 3291EOS 3292 } 3293 ); 3294 $wrapper->output_unlike(qr/AddressSanitizer/, "[github #19198] no bad access"); 3295 $wrapper->contents_like(qr/^Test::AUTOLOAD\(.*?\):\s+\d+:\s+my \$sub = \$AUTOLOAD;/m, 3296 "[github #19198] check we stopped correctly"); 3297} 3298 3299{ 3300 # gh-21350: verify that nonsense linespecs are rejected #1 3301 my $wrapper = DebugWrap->new( 3302 { 3303 cmds => 3304 [ 3305 'l ...', 3306 'q', 3307 ], 3308 prog => '../lib/perl5db/t/gh-21350', 3309 } 3310 ); 3311 3312 $wrapper->contents_like( 3313 qr/Invalid line specification '...'/, 3314 q/gh-21350: multiple periods rejected/, 3315 ); 3316} 3317 3318{ 3319 # gh-21350: verify that nonsense linespecs are rejected #2 3320 my $wrapper = DebugWrap->new( 3321 { 3322 cmds => 3323 [ 3324 'l $', 3325 'q', 3326 ], 3327 prog => '../lib/perl5db/t/gh-21350', 3328 } 3329 ); 3330 3331 $wrapper->contents_like( 3332 qr/Invalid line specification '\$'/, 3333 q/gh-21350: $ rejected/, 3334 ); 3335} 3336 3337{ 3338 # gh-21350: verify that nonsense linespecs are rejected #3 3339 my $wrapper = DebugWrap->new( 3340 { 3341 cmds => 3342 [ 3343 'l 2.71828', 3344 'q', 3345 ], 3346 prog => '../lib/perl5db/t/gh-21350', 3347 } 3348 ); 3349 3350 $wrapper->contents_like( 3351 qr/Invalid line specification '2\.71828'/, 3352 q/gh-21350: floating-point rejected/, 3353 ); 3354} 3355 3356{ 3357 # gh-21350: verify that nonsense linespecs are rejected #4 3358 my $wrapper = DebugWrap->new( 3359 { 3360 cmds => 3361 [ 3362 'l 1.1.1.1', 3363 'q', 3364 ], 3365 prog => '../lib/perl5db/t/gh-21350', 3366 } 3367 ); 3368 3369 $wrapper->contents_like( 3370 qr/Invalid line specification '1\.1\.1\.1'/, 3371 q/gh-21350: IPv4 address rejected/, 3372 ); 3373} 3374 3375{ 3376 # gh-21350: verify that nonsense linespecs are rejected #5 3377 my $wrapper = DebugWrap->new( 3378 { 3379 cmds => 3380 [ 3381 'l -.', 3382 'q', 3383 ], 3384 prog => '../lib/perl5db/t/gh-21350', 3385 } 3386 ); 3387 3388 $wrapper->contents_like( 3389 qr/Invalid line specification '-\.'/, 3390 q/gh-21350: invalid partial range rejected/, 3391 ); 3392} 3393 3394{ 3395 # gh-21350: verify that nonsense linespecs are rejected #6 3396 my $wrapper = DebugWrap->new( 3397 { 3398 cmds => 3399 [ 3400 'l -$.', 3401 'q', 3402 ], 3403 prog => '../lib/perl5db/t/gh-21350', 3404 } 3405 ); 3406 3407 $wrapper->contents_like( 3408 qr/Invalid line specification '\-\$\.'/, 3409 q/gh-21350: formerly acceptable nonsense rejected/, 3410 ); 3411} 3412 3413{ 3414 # gh-21350: verify that nonsense linespecs are rejected #7 3415 my $wrapper = DebugWrap->new( 3416 { 3417 cmds => 3418 [ 3419 'l -12', 3420 'q', 3421 ], 3422 prog => '../lib/perl5db/t/gh-21350', 3423 } 3424 ); 3425 3426 $wrapper->contents_like( 3427 qr/Invalid line specification '-12'/, 3428 q/gh-21350: negative line number rejected/, 3429 ); 3430} 3431 3432{ 3433 # gh-21350: verify that nonsense linespecs are rejected #8 3434 my $wrapper = DebugWrap->new( 3435 { 3436 cmds => 3437 [ 3438 'l 17$', 3439 'q', 3440 ], 3441 prog => '../lib/perl5db/t/gh-21350', 3442 } 3443 ); 3444 3445 $wrapper->contents_like( 3446 qr/Invalid line specification '17\$'/, 3447 q/gh-21350: line number with trailing $ rejected/, 3448 ); 3449} 3450 3451{ 3452 # gh-21350: verify that nonsense linespecs are rejected #9 3453 my $wrapper = DebugWrap->new( 3454 { 3455 cmds => 3456 [ 3457 'l $2250$', 3458 'q', 3459 ], 3460 prog => '../lib/perl5db/t/gh-21350', 3461 } 3462 ); 3463 3464 $wrapper->contents_like( 3465 qr/Invalid line specification '\$2250\$'/, 3466 q/gh-21350: match variable with trailing $ rejected/, 3467 ); 3468} 3469 3470{ 3471 # https://github.com/Perl/perl5/issues/21564 3472 # not a debugger bug, but with the way the fix for #19198 was broken 3473 # this needs to be tested with a debugger of some sort (even a no-op 3474 # debugger) so test it here. 3475 my $wrapper = DebugWrap->new( 3476 { 3477 cmds => 3478 [ 3479 'c', # just run it, we check the output of the code 3480 'q' 3481 ], 3482 prog => \<<'EOS', 3483use v5.12; 3484no strict; 3485use B qw(svref_2object SVf_IOK); 3486my $sv = svref_2object(\(${"_<$0"}[3])); # the "use B;" line 3487say +($sv->FLAGS & SVf_IOK) ? "OK" : "FAIL"; 3488EOS 3489 } 3490 ); 3491 $wrapper->output_like(qr/\bOK\b/, "check the line is IOK"); 3492} 3493 3494done_testing(); 3495 3496END { 3497 1 while unlink ($rc_filename, $out_fn); 3498} 3499