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