xref: /openbsd/gnu/usr.bin/perl/lib/perl5db.t (revision 91f110e0)
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
13BEGIN {
14    if (! -c "/dev/null") {
15        print "1..0 # Skip: no /dev/null\n";
16        exit 0;
17    }
18
19    my $dev_tty = '/dev/tty';
20    $dev_tty = 'TT:' if ($^O eq 'VMS');
21    if (! -c $dev_tty) {
22        print "1..0 # Skip: no $dev_tty\n";
23        exit 0;
24    }
25    if ($ENV{PERL5DB}) {
26        print "1..0 # Skip: \$ENV{PERL5DB} is already set to '$ENV{PERL5DB}'\n";
27        exit 0;
28    }
29}
30
31plan(116);
32
33my $rc_filename = '.perldb';
34
35sub rc {
36    open my $rc_fh, '>', $rc_filename
37        or die $!;
38    print {$rc_fh} @_;
39    close ($rc_fh);
40
41    # overly permissive perms gives "Must not source insecure rcfile"
42    # and hangs at the DB(1> prompt
43    chmod 0644, $rc_filename;
44}
45
46sub _slurp
47{
48    my $filename = shift;
49
50    open my $in, '<', $filename
51        or die "Cannot open '$filename' for slurping - $!";
52
53    local $/;
54    my $contents = <$in>;
55
56    close($in);
57
58    return $contents;
59}
60
61my $out_fn = 'db.out';
62
63sub _out_contents
64{
65    return _slurp($out_fn);
66}
67
68
69# Test for Proxy constants
70{
71    rc(
72        <<'EOF',
73
74&parse_options("NonStop=0 ReadLine=0 TTY=db.out LineInfo=db.out");
75
76sub afterinit {
77    push(@DB::typeahead,
78        'm main->s1',
79        'q',
80    );
81}
82
83EOF
84    );
85
86    my $output = runperl(switches => [ '-d' ], stderr => 1, progfile => '../lib/perl5db/t/proxy-constants');
87    is($output, "", "proxy constant subroutines");
88}
89
90# [perl #66110] Call a subroutine inside a regex
91{
92    local $ENV{PERLDB_OPTS} = "ReadLine=0 NonStop=1";
93    my $output = runperl(switches => [ '-d' ], stderr => 1, progfile => '../lib/perl5db/t/rt-66110');
94    like($output, "All tests successful.", "[perl #66110]");
95}
96# [ perl #116769] Frame=2
97{
98    local $ENV{PERLDB_OPTS} = "frame=2 nonstop";
99    my $output = runperl( switches => [ '-d' ], prog => 'print q{success}' );
100    is( $?, 0, '[perl #116769] frame=2 does not crash debugger, exit == 0' );
101    like( $output, 'success' , '[perl #116769] code is run' );
102}
103# [ perl #116771] autotrace
104{
105    local $ENV{PERLDB_OPTS} = "autotrace nonstop";
106    my $output = runperl( switches => [ '-d' ], prog => 'print q{success}' );
107    is( $?, 0, '[perl #116771] autotrace does not crash debugger, exit == 0' );
108    like( $output, 'success' , '[perl #116771] code is run' );
109}
110
111{
112    rc(<<'EOF');
113&parse_options("NonStop=0 TTY=db.out LineInfo=db.out");
114
115sub afterinit {
116    push (@DB::typeahead,
117    't 2',
118    'c',
119    'q',
120    );
121
122}
123EOF
124}
125
126package DebugWrap;
127
128sub new {
129    my $class = shift;
130
131    my $self = bless {}, $class;
132
133    $self->_init(@_);
134
135    return $self;
136}
137
138sub _cmds {
139    my $self = shift;
140
141    if (@_) {
142        $self->{_cmds} = shift;
143    }
144
145    return $self->{_cmds};
146}
147
148sub _prog {
149    my $self = shift;
150
151    if (@_) {
152        $self->{_prog} = shift;
153    }
154
155    return $self->{_prog};
156}
157
158sub _output {
159    my $self = shift;
160
161    if (@_) {
162        $self->{_output} = shift;
163    }
164
165    return $self->{_output};
166}
167
168sub _include_t
169{
170    my $self = shift;
171
172    if (@_)
173    {
174        $self->{_include_t} = shift;
175    }
176
177    return $self->{_include_t};
178}
179
180sub _stderr_val
181{
182    my $self = shift;
183
184    if (@_)
185    {
186        $self->{_stderr_val} = shift;
187    }
188
189    return $self->{_stderr_val};
190}
191
192sub field
193{
194    my $self = shift;
195
196    if (@_)
197    {
198        $self->{field} = shift;
199    }
200
201    return $self->{field};
202}
203
204sub _switches
205{
206    my $self = shift;
207
208    if (@_)
209    {
210        $self->{_switches} = shift;
211    }
212
213    return $self->{_switches};
214}
215
216sub _contents
217{
218    my $self = shift;
219
220    if (@_)
221    {
222        $self->{_contents} = shift;
223    }
224
225    return $self->{_contents};
226}
227
228sub _init
229{
230    my ($self, $args) = @_;
231
232    my $cmds = $args->{cmds};
233
234    if (ref($cmds) ne 'ARRAY') {
235        die "cmds must be an array of commands.";
236    }
237
238    $self->_cmds($cmds);
239
240    my $prog = $args->{prog};
241
242    if (ref($prog) ne '' or !defined($prog)) {
243        die "prog should be a path to a program file.";
244    }
245
246    $self->_prog($prog);
247
248    $self->_include_t($args->{include_t} ? 1 : 0);
249
250    $self->_stderr_val(exists($args->{stderr}) ? $args->{stderr} : 1);
251
252    if (exists($args->{switches}))
253    {
254        $self->_switches($args->{switches});
255    }
256
257    $self->_run();
258
259    return;
260}
261
262sub _quote
263{
264    my ($self, $str) = @_;
265
266    $str =~ s/(["\@\$\\])/\\$1/g;
267    $str =~ s/\n/\\n/g;
268    $str =~ s/\r/\\r/g;
269
270    return qq{"$str"};
271}
272
273sub _run {
274    my $self = shift;
275
276    my $rc = qq{&parse_options("NonStop=0 TTY=db.out LineInfo=db.out");\n};
277
278    $rc .= join('',
279        map { "$_\n"}
280        (q#sub afterinit {#,
281         q#push (@DB::typeahead,#,
282         (map { $self->_quote($_) . "," } @{$self->_cmds()}),
283         q#);#,
284         q#}#,
285        )
286    );
287
288    # I guess two objects like that cannot be used at the same time.
289    # Oh well.
290    ::rc($rc);
291
292    my $output =
293        ::runperl(
294            switches =>
295            [
296                ($self->_switches ? (@{$self->_switches()}) : ('-d')),
297                ($self->_include_t ? ('-I', '../lib/perl5db/t') : ())
298            ],
299            (defined($self->_stderr_val())
300                ? (stderr => $self->_stderr_val())
301                : ()
302            ),
303            progfile => $self->_prog()
304        );
305
306    $self->_output($output);
307
308    $self->_contents(::_out_contents());
309
310    return;
311}
312
313sub get_output
314{
315    return shift->_output();
316}
317
318sub output_like {
319    my ($self, $re, $msg) = @_;
320
321    local $::Level = $::Level + 1;
322    ::like($self->_output(), $re, $msg);
323}
324
325sub output_unlike {
326    my ($self, $re, $msg) = @_;
327
328    local $::Level = $::Level + 1;
329    ::unlike($self->_output(), $re, $msg);
330}
331
332sub contents_like {
333    my ($self, $re, $msg) = @_;
334
335    local $::Level = $::Level + 1;
336    ::like($self->_contents(), $re, $msg);
337}
338
339sub contents_unlike {
340    my ($self, $re, $msg) = @_;
341
342    local $::Level = $::Level + 1;
343    ::unlike($self->_contents(), $re, $msg);
344}
345
346package main;
347
348{
349    local $ENV{PERLDB_OPTS} = "ReadLine=0";
350    my $target = '../lib/perl5db/t/eval-line-bug';
351    my $wrapper = DebugWrap->new(
352        {
353            cmds =>
354            [
355                'b 23',
356                'n',
357                'n',
358                'n',
359                'c', # line 23
360                'n',
361                "p \@{'main::_<$target'}",
362                'q',
363            ],
364            prog => $target,
365        }
366    );
367    $wrapper->contents_like(
368        qr/sub factorial/,
369        'The ${main::_<filename} variable in the debugger was not destroyed',
370    );
371}
372
373sub _calc_generic_wrapper
374{
375    my $args = shift;
376
377    my $extra_opts = delete($args->{extra_opts});
378    $extra_opts ||= '';
379    local $ENV{PERLDB_OPTS} = "ReadLine=0" . $extra_opts;
380    return DebugWrap->new(
381        {
382            cmds => delete($args->{cmds}),
383            prog => delete($args->{prog}),
384            %$args,
385        }
386    );
387}
388
389sub _calc_new_var_wrapper
390{
391    my ($args) = @_;
392    return _calc_generic_wrapper(
393        {
394            cmds =>
395            [
396                'b 23',
397                'c',
398                '$new_var = "Foo"',
399                'x "new_var = <$new_var>\\n"',
400                'q',
401            ],
402            %$args,
403        }
404    );
405}
406
407sub _calc_threads_wrapper
408{
409    my $args = shift;
410
411    return _calc_new_var_wrapper(
412        {
413            switches => [ '-dt', ],
414            stderr => 1,
415            %$args
416        }
417    );
418}
419
420{
421    _calc_new_var_wrapper({ prog => '../lib/perl5db/t/eval-line-bug'})
422        ->contents_like(
423            qr/new_var = <Foo>/,
424            "no strict 'vars' in evaluated lines.",
425        );
426}
427
428{
429    _calc_new_var_wrapper(
430        {
431            prog => '../lib/perl5db/t/lvalue-bug',
432            stderr => undef(),
433        },
434    )->output_like(
435            qr/foo is defined/,
436             'lvalue subs work in the debugger',
437         );
438}
439
440{
441    _calc_new_var_wrapper(
442        {
443            prog =>  '../lib/perl5db/t/symbol-table-bug',
444            extra_opts => "NonStop=1",
445            stderr => undef(),
446        }
447    )->output_like(
448        qr/Undefined symbols 0/,
449        'there are no undefined values in the symbol table',
450    );
451}
452
453SKIP:
454{
455    if ( $Config{usethreads} ) {
456        skip('This perl has threads, skipping non-threaded debugger tests');
457    }
458    else {
459        my $error = 'This Perl not built to support threads';
460        _calc_threads_wrapper(
461            {
462                prog => '../lib/perl5db/t/eval-line-bug',
463            }
464        )->output_like(
465            qr/\Q$error\E/,
466            'Perl debugger correctly complains that it was not built with threads',
467        );
468    }
469}
470
471SKIP:
472{
473    if ( $Config{usethreads} ) {
474        _calc_threads_wrapper(
475            {
476                prog =>  '../lib/perl5db/t/symbol-table-bug',
477            }
478        )->output_like(
479            qr/Undefined symbols 0/,
480            'there are no undefined values in the symbol table when running with thread support',
481        );
482    }
483    else {
484        skip("This perl is not threaded, skipping threaded debugger tests");
485    }
486}
487
488# Test [perl #61222]
489{
490    local $ENV{PERLDB_OPTS};
491    my $wrapper = DebugWrap->new(
492        {
493            cmds =>
494            [
495                'm Pie',
496                'q',
497            ],
498            prog => '../lib/perl5db/t/rt-61222',
499        }
500    );
501
502    $wrapper->contents_unlike(qr/INCORRECT/, "[perl #61222]");
503}
504
505sub _calc_trace_wrapper
506{
507    my ($args) = @_;
508
509    return _calc_generic_wrapper(
510        {
511            cmds =>
512            [
513                't 2',
514                'c',
515                'q',
516            ],
517            %$args,
518        }
519    );
520}
521
522# [perl 104168] level option for tracing
523{
524    my $wrapper = _calc_trace_wrapper({ prog =>  '../lib/perl5db/t/rt-104168' });
525    $wrapper->contents_like(qr/level 2/, "[perl #104168] - level 2 appears");
526    $wrapper->contents_unlike(qr/baz/, "[perl #104168] - no 'baz'");
527}
528
529# taint tests
530{
531    my $wrapper = _calc_trace_wrapper(
532        {
533            prog => '../lib/perl5db/t/taint',
534            extra_opts => ' NonStop=1',
535            switches => [ '-d', '-T', ],
536        }
537    );
538
539    my $output = $wrapper->get_output();
540    chomp $output if $^O eq 'VMS'; # newline guaranteed at EOF
541    is($output, '[$^X][done]', "taint");
542}
543
544# Testing that we can set a line in the middle of the file.
545{
546    my $wrapper = DebugWrap->new(
547        {
548            cmds =>
549            [
550                'b ../lib/perl5db/t/MyModule.pm:12',
551                'c',
552                q/do { use IO::Handle; STDOUT->autoflush(1); print "Var=$var\n"; }/,
553                'c',
554                'q',
555            ],
556            include_t => 1,
557            prog => '../lib/perl5db/t/filename-line-breakpoint'
558        }
559    );
560
561    $wrapper->output_like(qr/
562        ^Var=Bar$
563            .*
564        ^In\ MyModule\.$
565            .*
566        ^In\ Main\ File\.$
567            .*
568        /msx,
569        "Can set breakpoint in a line in the middle of the file.");
570}
571
572# Testing that we can set a breakpoint
573{
574    my $wrapper = DebugWrap->new(
575        {
576            prog => '../lib/perl5db/t/breakpoint-bug',
577            cmds =>
578            [
579                'b 6',
580                'c',
581                q/do { use IO::Handle; STDOUT->autoflush(1); print "X={$x}\n"; }/,
582                'c',
583                'q',
584            ],
585        },
586    );
587
588    $wrapper->output_like(
589        qr/X=\{Two\}/msx,
590        "Can set breakpoint in a line."
591    );
592}
593
594# Testing that we can disable a breakpoint at a numeric line.
595{
596    my $wrapper = DebugWrap->new(
597        {
598            prog =>  '../lib/perl5db/t/disable-breakpoints-1',
599            cmds =>
600            [
601                'b 7',
602                'b 11',
603                'disable 7',
604                'c',
605                q/print "X={$x}\n";/,
606                'c',
607                'q',
608            ],
609        }
610    );
611
612    $wrapper->output_like(qr/X=\{SecondVal\}/ms,
613        "Can set breakpoint in a line.");
614}
615
616# Testing that we can re-enable a breakpoint at a numeric line.
617{
618    my $wrapper = DebugWrap->new(
619        {
620            prog =>  '../lib/perl5db/t/disable-breakpoints-2',
621            cmds =>
622            [
623                'b 8',
624                'b 24',
625                'disable 24',
626                'c',
627                'enable 24',
628                'c',
629                q/print "X={$x}\n";/,
630                'c',
631                'q',
632            ],
633        },
634    );
635
636    $wrapper->output_like(
637        qr/
638        X=\{SecondValOneHundred\}
639        /msx,
640        "Can set breakpoint in a line."
641    );
642}
643# clean up.
644
645# Disable and enable for breakpoints on outer files.
646{
647    my $wrapper = DebugWrap->new(
648        {
649            cmds =>
650            [
651                'b 10',
652                'b ../lib/perl5db/t/EnableModule.pm:14',
653                'disable ../lib/perl5db/t/EnableModule.pm:14',
654                'c',
655                'enable ../lib/perl5db/t/EnableModule.pm:14',
656                'c',
657                q/print "X={$x}\n";/,
658                'c',
659                'q',
660            ],
661            prog =>  '../lib/perl5db/t/disable-breakpoints-3',
662            include_t => 1,
663        }
664    );
665
666    $wrapper->output_like(qr/
667        X=\{SecondValTwoHundred\}
668        /msx,
669        "Can set breakpoint in a line.");
670}
671
672# Testing that the prompt with the information appears.
673{
674    my $wrapper = DebugWrap->new(
675        {
676            cmds => ['q'],
677            prog => '../lib/perl5db/t/disable-breakpoints-1',
678        }
679    );
680
681    $wrapper->contents_like(qr/
682        ^main::\([^\)]*\bdisable-breakpoints-1:2\):\n
683        2:\s+my\ \$x\ =\ "One";\n
684        /msx,
685        "Prompt should display the first line of code.");
686}
687
688# Testing that R (restart) and "B *" work.
689{
690    my $wrapper = DebugWrap->new(
691        {
692            cmds =>
693            [
694                'b 13',
695                'c',
696                'B *',
697                'b 9',
698                'R',
699                'c',
700                q/print "X={$x};dummy={$dummy}\n";/,
701                'q',
702            ],
703            prog =>  '../lib/perl5db/t/disable-breakpoints-1',
704        }
705    );
706
707    $wrapper->output_like(qr/
708        X=\{FirstVal\};dummy=\{1\}
709        /msx,
710        "Restart and delete all breakpoints work properly.");
711}
712
713{
714    my $wrapper = DebugWrap->new(
715        {
716            cmds =>
717            [
718                'c 15',
719                q/print "X={$x}\n";/,
720                'c',
721                'q',
722            ],
723            prog =>  '../lib/perl5db/t/disable-breakpoints-1',
724        }
725    );
726
727    $wrapper->output_like(qr/
728        X=\{ThirdVal\}
729        /msx,
730        "'c line_num' is working properly.");
731}
732
733{
734    my $wrapper = DebugWrap->new(
735        {
736            cmds =>
737            [
738                'n',
739                'n',
740                'b . $exp > 200',
741                'c',
742                q/print "Exp={$exp}\n";/,
743                'q',
744            ],
745            prog => '../lib/perl5db/t/break-on-dot',
746        }
747    );
748
749    $wrapper->output_like(qr/
750        Exp=\{256\}
751        /msx,
752        "'b .' is working correctly.");
753}
754
755# Testing that the prompt with the information appears inside a subroutine call.
756# See https://rt.perl.org/rt3/Ticket/Display.html?id=104820
757{
758    my $wrapper = DebugWrap->new(
759        {
760            cmds =>
761            [
762                'c back',
763                'q',
764            ],
765            prog => '../lib/perl5db/t/with-subroutine',
766        }
767    );
768
769    $wrapper->contents_like(
770        qr/
771        ^main::back\([^\)\n]*\bwith-subroutine:15\):[\ \t]*\n
772        ^15:\s*print\ "hello\ back\\n";
773        /msx,
774        "Prompt should display the line of code inside a subroutine.");
775}
776
777# Checking that the p command works.
778{
779    my $wrapper = DebugWrap->new(
780        {
781            cmds =>
782            [
783                'p "<<<" . (4*6) . ">>>"',
784                'q',
785            ],
786            prog => '../lib/perl5db/t/with-subroutine',
787        }
788    );
789
790    $wrapper->contents_like(
791        qr/<<<24>>>/,
792        "p command works.");
793}
794
795# Tests for x.
796{
797    my $wrapper = DebugWrap->new(
798        {
799            cmds =>
800            [
801                q/x {500 => 600}/,
802                'q',
803            ],
804            prog => '../lib/perl5db/t/with-subroutine',
805        }
806    );
807
808    $wrapper->contents_like(
809        # qr/^0\s+HASH\([^\)]+\)\n\s+500 => 600\n/,
810        qr/^0\s+HASH\([^\)]+\)\n\s+500 => 600\n/ms,
811        "x command test."
812    );
813}
814
815# Tests for x with @_
816{
817    my $wrapper = DebugWrap->new(
818        {
819            cmds =>
820            [
821                'b 10',
822                'c',
823                'x @_',
824                'q',
825            ],
826            prog => '../lib/perl5db/t/test-passing-at-underscore-to-x-etc',
827        }
828    );
829
830    $wrapper->contents_like(
831        # qr/^0\s+HASH\([^\)]+\)\n\s+500 => 600\n/,
832        qr/Arg1.*?Capsula.*GreekHumor.*Socrates/ms,
833        q/x command test with '@_'./,
834    );
835}
836
837# Tests for mutating @_
838{
839    my $wrapper = DebugWrap->new(
840        {
841            cmds =>
842            [
843                'b 10',
844                'c',
845                'shift(@_)',
846                'print "\n\n\n(((" . join(",", @_) . ")))\n\n\n"',
847                'q',
848            ],
849            prog => '../lib/perl5db/t/test-passing-at-underscore-to-x-etc',
850        }
851    );
852
853    $wrapper->output_like(
854        qr/^\(\(\(Capsula,GreekHumor,Socrates\)\)\)$/ms,
855        q/Mutating '@_'./,
856    );
857}
858
859# Tests for x with AutoTrace=1.
860{
861    my $wrapper = DebugWrap->new(
862        {
863            cmds =>
864            [
865                'n',
866                'o AutoTrace=1',
867                # So it may fail.
868                q/x "failure"/,
869                q/x \$x/,
870                'q',
871            ],
872            prog => '../lib/perl5db/t/with-subroutine',
873        }
874    );
875
876    $wrapper->contents_like(
877        # qr/^0\s+HASH\([^\)]+\)\n\s+500 => 600\n/,
878        qr/^0\s+SCALAR\([^\)]+\)\n\s+-> 'hello world'\n/ms,
879        "x after AutoTrace=1 command is working."
880    );
881}
882
883# Tests for "T" (stack trace).
884{
885    my $prog_fn = '../lib/perl5db/t/rt-104168';
886    my $wrapper = DebugWrap->new(
887        {
888            prog => $prog_fn,
889            cmds =>
890            [
891                'c baz',
892                'T',
893                'q',
894            ],
895        }
896    );
897    my $re_text = join('',
898        map {
899        sprintf(
900            "%s = %s\\(\\) called from file " .
901            "'" . quotemeta($prog_fn) . "' line %s\\n",
902            (map { quotemeta($_) } @$_)
903            )
904        }
905        (
906            ['.', 'main::baz', 14,],
907            ['.', 'main::bar', 9,],
908            ['.', 'main::foo', 6],
909        )
910    );
911    $wrapper->contents_like(
912        # qr/^0\s+HASH\([^\)]+\)\n\s+500 => 600\n/,
913        qr/^$re_text/ms,
914        "T command test."
915    );
916}
917
918# Test for s.
919{
920    my $wrapper = DebugWrap->new(
921        {
922            cmds =>
923            [
924                'b 9',
925                'c',
926                's',
927                q/print "X={$x};dummy={$dummy}\n";/,
928                'q',
929            ],
930            prog => '../lib/perl5db/t/disable-breakpoints-1'
931        }
932    );
933
934    $wrapper->output_like(qr/
935        X=\{SecondVal\};dummy=\{1\}
936        /msx,
937        'test for s - single step',
938    );
939}
940
941{
942    my $wrapper = DebugWrap->new(
943        {
944            cmds =>
945            [
946                'n',
947                'n',
948                'b . $exp > 200',
949                'c',
950                q/print "Exp={$exp}\n";/,
951                'q',
952            ],
953            prog => '../lib/perl5db/t/break-on-dot'
954        }
955    );
956
957    $wrapper->output_like(qr/
958        Exp=\{256\}
959        /msx,
960        "'b .' is working correctly.");
961}
962
963{
964    my $prog_fn = '../lib/perl5db/t/rt-104168';
965    my $wrapper = DebugWrap->new(
966        {
967            cmds =>
968            [
969                's',
970                'q',
971            ],
972            prog => $prog_fn,
973        }
974    );
975
976    $wrapper->contents_like(
977        qr/
978        ^main::foo\([^\)\n]*\brt-104168:9\):[\ \t]*\n
979        ^9:\s*bar\(\);
980        /msx,
981        'Test for the s command.',
982    );
983}
984
985{
986    my $wrapper = DebugWrap->new(
987        {
988            cmds =>
989            [
990                's uncalled_subroutine()',
991                'c',
992                'q',
993            ],
994
995            prog => '../lib/perl5db/t/uncalled-subroutine'}
996    );
997
998    $wrapper->output_like(
999        qr/<1,2,3,4,5>\n/,
1000        'uncalled_subroutine was called after s EXPR()',
1001        );
1002}
1003
1004{
1005    my $wrapper = DebugWrap->new(
1006        {
1007            cmds =>
1008            [
1009                'n uncalled_subroutine()',
1010                'c',
1011                'q',
1012            ],
1013            prog => '../lib/perl5db/t/uncalled-subroutine',
1014        }
1015    );
1016
1017    $wrapper->output_like(
1018        qr/<1,2,3,4,5>\n/,
1019        'uncalled_subroutine was called after n EXPR()',
1020        );
1021}
1022
1023{
1024    my $wrapper = DebugWrap->new(
1025        {
1026            cmds =>
1027            [
1028                'b fact',
1029                'c',
1030                'c',
1031                'c',
1032                'n',
1033                'print "<$n>"',
1034                'q',
1035            ],
1036            prog => '../lib/perl5db/t/fact',
1037        }
1038    );
1039
1040    $wrapper->output_like(
1041        qr/<3>/,
1042        'b subroutine works fine',
1043    );
1044}
1045
1046# Test for 'M' (module list).
1047{
1048    my $wrapper = DebugWrap->new(
1049        {
1050            cmds =>
1051            [
1052                'M',
1053                'q',
1054            ],
1055            prog => '../lib/perl5db/t/load-modules'
1056        }
1057    );
1058
1059    $wrapper->contents_like(
1060        qr[Scalar/Util\.pm],
1061        'M (module list) works fine',
1062    );
1063}
1064
1065{
1066    my $wrapper = DebugWrap->new(
1067        {
1068            cmds =>
1069            [
1070                'b 14',
1071                'c',
1072                '$flag = 1;',
1073                'r',
1074                'print "Var=$var\n";',
1075                'q',
1076            ],
1077            prog => '../lib/perl5db/t/test-r-statement',
1078        }
1079    );
1080
1081    $wrapper->output_like(
1082        qr/
1083            ^Foo$
1084                .*?
1085            ^Bar$
1086                .*?
1087            ^Var=Test$
1088        /msx,
1089        'r statement is working properly.',
1090    );
1091}
1092
1093{
1094    my $wrapper = DebugWrap->new(
1095        {
1096            cmds =>
1097            [
1098                'l',
1099                'q',
1100            ],
1101            prog => '../lib/perl5db/t/test-l-statement-1',
1102        }
1103    );
1104
1105    $wrapper->contents_like(
1106        qr/
1107            ^1==>\s+\$x\ =\ 1;\n
1108            2:\s+print\ "1\\n";\n
1109            3\s*\n
1110            4:\s+\$x\ =\ 2;\n
1111            5:\s+print\ "2\\n";\n
1112        /msx,
1113        'l statement is working properly (test No. 1).',
1114    );
1115}
1116
1117{
1118    my $wrapper = DebugWrap->new(
1119        {
1120            cmds =>
1121            [
1122                'l',
1123                q/# After l 1/,
1124                'l',
1125                q/# After l 2/,
1126                '-',
1127                q/# After -/,
1128                'q',
1129            ],
1130            prog => '../lib/perl5db/t/test-l-statement-1',
1131        }
1132    );
1133
1134    my $first_l_out = qr/
1135        1==>\s+\$x\ =\ 1;\n
1136        2:\s+print\ "1\\n";\n
1137        3\s*\n
1138        4:\s+\$x\ =\ 2;\n
1139        5:\s+print\ "2\\n";\n
1140        6\s*\n
1141        7:\s+\$x\ =\ 3;\n
1142        8:\s+print\ "3\\n";\n
1143        9\s*\n
1144        10:\s+\$x\ =\ 4;\n
1145    /msx;
1146
1147    my $second_l_out = qr/
1148        11:\s+print\ "4\\n";\n
1149        12\s*\n
1150        13:\s+\$x\ =\ 5;\n
1151        14:\s+print\ "5\\n";\n
1152        15\s*\n
1153        16:\s+\$x\ =\ 6;\n
1154        17:\s+print\ "6\\n";\n
1155        18\s*\n
1156        19:\s+\$x\ =\ 7;\n
1157        20:\s+print\ "7\\n";\n
1158    /msx;
1159    $wrapper->contents_like(
1160        qr/
1161            ^$first_l_out
1162            [^\n]*?DB<\d+>\ \#\ After\ l\ 1\n
1163            [\ \t]*\n
1164            [^\n]*?DB<\d+>\ l\s*\n
1165            $second_l_out
1166            [^\n]*?DB<\d+>\ \#\ After\ l\ 2\n
1167            [\ \t]*\n
1168            [^\n]*?DB<\d+>\ -\s*\n
1169            $first_l_out
1170            [^\n]*?DB<\d+>\ \#\ After\ -\n
1171        /msx,
1172        'l followed by l and then followed by -',
1173    );
1174}
1175
1176{
1177    my $wrapper = DebugWrap->new(
1178        {
1179            cmds =>
1180            [
1181                'l fact',
1182                'q',
1183            ],
1184            prog => '../lib/perl5db/t/test-l-statement-2',
1185        }
1186    );
1187
1188    my $first_l_out = qr/
1189        6\s+sub\ fact\ \{\n
1190        7:\s+my\ \$n\ =\ shift;\n
1191        8:\s+if\ \(\$n\ >\ 1\)\ \{\n
1192        9:\s+return\ \$n\ \*\ fact\(\$n\ -\ 1\);
1193    /msx;
1194
1195    $wrapper->contents_like(
1196        qr/
1197            DB<1>\s+l\ fact\n
1198            $first_l_out
1199        /msx,
1200        'l subroutine_name',
1201    );
1202}
1203
1204{
1205    my $wrapper = DebugWrap->new(
1206        {
1207            cmds =>
1208            [
1209                'b fact',
1210                'c',
1211                # Repeat several times to avoid @typeahead problems.
1212                '.',
1213                '.',
1214                '.',
1215                '.',
1216                'q',
1217            ],
1218            prog => '../lib/perl5db/t/test-l-statement-2',
1219        }
1220    );
1221
1222    my $line_out = qr /
1223        ^main::fact\([^\n]*?:7\):\n
1224        ^7:\s+my\ \$n\ =\ shift;\n
1225    /msx;
1226
1227    $wrapper->contents_like(
1228        qr/
1229            $line_out
1230            $line_out
1231        /msx,
1232        'Test the "." command',
1233    );
1234}
1235
1236# Testing that the f command works.
1237{
1238    my $wrapper = DebugWrap->new(
1239        {
1240            cmds =>
1241            [
1242                'f ../lib/perl5db/t/MyModule.pm',
1243                'b 12',
1244                'c',
1245                q/do { use IO::Handle; STDOUT->autoflush(1); print "Var=$var\n"; }/,
1246                'c',
1247                'q',
1248            ],
1249            include_t => 1,
1250            prog => '../lib/perl5db/t/filename-line-breakpoint'
1251        }
1252    );
1253
1254    $wrapper->output_like(qr/
1255        ^Var=Bar$
1256            .*
1257        ^In\ MyModule\.$
1258            .*
1259        ^In\ Main\ File\.$
1260            .*
1261        /msx,
1262        "f command is working.",
1263    );
1264}
1265
1266# We broke the /pattern/ command because apparently the CORE::eval-s inside
1267# lib/perl5db.pl cannot handle lexical variable properly. So we now fix this
1268# bug.
1269#
1270# TODO :
1271#
1272# 1. Go over the rest of the "eval"s in lib/perl5db.t and see if they cause
1273# problems.
1274{
1275    my $wrapper = DebugWrap->new(
1276        {
1277            cmds =>
1278            [
1279                '/for/',
1280                'q',
1281            ],
1282            prog => '../lib/perl5db/t/eval-line-bug',
1283        }
1284    );
1285
1286    $wrapper->contents_like(
1287        qr/12: \s* for\ my\ \$q\ \(1\ \.\.\ 10\)\ \{/msx,
1288        "/pat/ command is working and found a match.",
1289    );
1290}
1291
1292{
1293    my $wrapper = DebugWrap->new(
1294        {
1295            cmds =>
1296            [
1297                'b 22',
1298                'c',
1299                '?for?',
1300                'q',
1301            ],
1302            prog => '../lib/perl5db/t/eval-line-bug',
1303        }
1304    );
1305
1306    $wrapper->contents_like(
1307        qr/12: \s* for\ my\ \$q\ \(1\ \.\.\ 10\)\ \{/msx,
1308        "?pat? command is working and found a match.",
1309    );
1310}
1311
1312# Test the L command.
1313{
1314    my $wrapper = DebugWrap->new(
1315        {
1316            cmds =>
1317            [
1318                'b 6',
1319                'b 13 ($q == 5)',
1320                'L',
1321                'q',
1322            ],
1323            prog => '../lib/perl5db/t/eval-line-bug',
1324        }
1325    );
1326
1327    $wrapper->contents_like(
1328        qr#
1329        ^\S*?eval-line-bug:\n
1330        \s*6:\s*my\ \$i\ =\ 5;\n
1331        \s*break\ if\ \(1\)\n
1332        \s*13:\s*\$i\ \+=\ \$q;\n
1333        \s*break\ if\ \(\(\$q\ ==\ 5\)\)\n
1334        #msx,
1335        "L command is listing breakpoints",
1336    );
1337}
1338
1339# Test the L command for watch expressions.
1340{
1341    my $wrapper = DebugWrap->new(
1342        {
1343            cmds =>
1344            [
1345                'w (5+6)',
1346                'L',
1347                'q',
1348            ],
1349            prog => '../lib/perl5db/t/eval-line-bug',
1350        }
1351    );
1352
1353    $wrapper->contents_like(
1354        qr#
1355        ^Watch-expressions:\n
1356        \s*\(5\+6\)\n
1357        #msx,
1358        "L command is listing watch expressions",
1359    );
1360}
1361
1362{
1363    my $wrapper = DebugWrap->new(
1364        {
1365            cmds =>
1366            [
1367                'w (5+6)',
1368                'w (11*23)',
1369                'W (5+6)',
1370                'L',
1371                'q',
1372            ],
1373            prog => '../lib/perl5db/t/eval-line-bug',
1374        }
1375    );
1376
1377    $wrapper->contents_like(
1378        qr#
1379        ^Watch-expressions:\n
1380        \s*\(11\*23\)\n
1381        ^auto\(
1382        #msx,
1383        "L command is not listing deleted watch expressions",
1384    );
1385}
1386
1387# Test the L command.
1388{
1389    my $wrapper = DebugWrap->new(
1390        {
1391            cmds =>
1392            [
1393                'b 6',
1394                'a 13 print $i',
1395                'L',
1396                'q',
1397            ],
1398            prog => '../lib/perl5db/t/eval-line-bug',
1399        }
1400    );
1401
1402    $wrapper->contents_like(
1403        qr#
1404        ^\S*?eval-line-bug:\n
1405        \s*6:\s*my\ \$i\ =\ 5;\n
1406        \s*break\ if\ \(1\)\n
1407        \s*13:\s*\$i\ \+=\ \$q;\n
1408        \s*action:\s+print\ \$i\n
1409        #msx,
1410        "L command is listing actions and breakpoints",
1411    );
1412}
1413
1414{
1415    my $wrapper = DebugWrap->new(
1416        {
1417            cmds =>
1418            [
1419                'S',
1420                'q',
1421            ],
1422            prog =>  '../lib/perl5db/t/rt-104168',
1423        }
1424    );
1425
1426    $wrapper->contents_like(
1427        qr#
1428        ^main::bar\n
1429        main::baz\n
1430        main::foo\n
1431        #msx,
1432        "S command - 1",
1433    );
1434}
1435
1436{
1437    my $wrapper = DebugWrap->new(
1438        {
1439            cmds =>
1440            [
1441                'S ^main::ba',
1442                'q',
1443            ],
1444            prog =>  '../lib/perl5db/t/rt-104168',
1445        }
1446    );
1447
1448    $wrapper->contents_like(
1449        qr#
1450        ^main::bar\n
1451        main::baz\n
1452        auto\(
1453        #msx,
1454        "S command with regex",
1455    );
1456}
1457
1458{
1459    my $wrapper = DebugWrap->new(
1460        {
1461            cmds =>
1462            [
1463                'S !^main::ba',
1464                'q',
1465            ],
1466            prog =>  '../lib/perl5db/t/rt-104168',
1467        }
1468    );
1469
1470    $wrapper->contents_unlike(
1471        qr#
1472        ^main::ba
1473        #msx,
1474        "S command with negative regex",
1475    );
1476
1477    $wrapper->contents_like(
1478        qr#
1479        ^main::foo\n
1480        #msx,
1481        "S command with negative regex - what it still matches",
1482    );
1483}
1484
1485# Test the 'a' command.
1486{
1487    my $wrapper = DebugWrap->new(
1488        {
1489            cmds =>
1490            [
1491                'a 13 print "\nVar<Q>=$q\n"',
1492                'c',
1493                'q',
1494            ],
1495            prog => '../lib/perl5db/t/eval-line-bug',
1496        }
1497    );
1498
1499    $wrapper->output_like(qr#
1500        \nVar<Q>=1\n
1501        \nVar<Q>=2\n
1502        \nVar<Q>=3\n
1503        #msx,
1504        "a command is working",
1505    );
1506}
1507
1508# Test the 'a' command with no line number.
1509{
1510    my $wrapper = DebugWrap->new(
1511        {
1512            cmds =>
1513            [
1514                'n',
1515                q/a print "Hello " . (3 * 4) . "\n";/,
1516                'c',
1517                'q',
1518            ],
1519            prog => '../lib/perl5db/t/test-a-statement-1',
1520        }
1521    );
1522
1523    $wrapper->output_like(qr#
1524        (?:^Hello\ 12\n.*?){4}
1525        #msx,
1526        "a command with no line number is working",
1527    );
1528}
1529
1530# Test the 'A' command
1531{
1532    my $wrapper = DebugWrap->new(
1533        {
1534            cmds =>
1535            [
1536                'a 13 print "\nVar<Q>=$q\n"',
1537                'A 13',
1538                'c',
1539                'q',
1540            ],
1541            prog => '../lib/perl5db/t/eval-line-bug',
1542        }
1543    );
1544
1545    $wrapper->output_like(
1546        qr#\A\z#msx, # The empty string.
1547        "A command (for removing actions) is working",
1548    );
1549}
1550
1551# Test the 'A *' command
1552{
1553    my $wrapper = DebugWrap->new(
1554        {
1555            cmds =>
1556            [
1557                'a 6 print "\nFail!\n"',
1558                'a 13 print "\nVar<Q>=$q\n"',
1559                'A *',
1560                'c',
1561                'q',
1562            ],
1563            prog => '../lib/perl5db/t/eval-line-bug',
1564        }
1565    );
1566
1567    $wrapper->output_like(
1568        qr#\A\z#msx, # The empty string.
1569        "'A *' command (for removing all actions) is working",
1570    );
1571}
1572
1573{
1574    my $wrapper = DebugWrap->new(
1575        {
1576            cmds =>
1577            [
1578                'n',
1579                'w $foo',
1580                'c',
1581                'print "\nIDX=<$idx>\n"',
1582                'q',
1583            ],
1584            prog => '../lib/perl5db/t/test-w-statement-1',
1585        }
1586    );
1587
1588
1589    $wrapper->contents_like(qr#
1590        \$foo\ changed:\n
1591        \s+old\ value:\s+'1'\n
1592        \s+new\ value:\s+'2'\n
1593        #msx,
1594        'w command - watchpoint changed',
1595    );
1596    $wrapper->output_like(qr#
1597        \nIDX=<20>\n
1598        #msx,
1599        "w command - correct output from IDX",
1600    );
1601}
1602
1603{
1604    my $wrapper = DebugWrap->new(
1605        {
1606            cmds =>
1607            [
1608                'n',
1609                'w $foo',
1610                'W $foo',
1611                'c',
1612                'print "\nIDX=<$idx>\n"',
1613                'q',
1614            ],
1615            prog => '../lib/perl5db/t/test-w-statement-1',
1616        }
1617    );
1618
1619    $wrapper->contents_unlike(qr#
1620        \$foo\ changed:
1621        #msx,
1622        'W command - watchpoint was deleted',
1623    );
1624
1625    $wrapper->output_like(qr#
1626        \nIDX=<>\n
1627        #msx,
1628        "W command - stopped at end.",
1629    );
1630}
1631
1632# Test the W * command.
1633{
1634    my $wrapper = DebugWrap->new(
1635        {
1636            cmds =>
1637            [
1638                'n',
1639                'w $foo',
1640                'w ($foo*$foo)',
1641                'W *',
1642                'c',
1643                'print "\nIDX=<$idx>\n"',
1644                'q',
1645            ],
1646            prog => '../lib/perl5db/t/test-w-statement-1',
1647        }
1648    );
1649
1650    $wrapper->contents_unlike(qr#
1651        \$foo\ changed:
1652        #msx,
1653        '"W *" command - watchpoint was deleted',
1654    );
1655
1656    $wrapper->output_like(qr#
1657        \nIDX=<>\n
1658        #msx,
1659        '"W *" command - stopped at end.',
1660    );
1661}
1662
1663# Test the 'o' command (without further arguments).
1664{
1665    my $wrapper = DebugWrap->new(
1666        {
1667            cmds =>
1668            [
1669                'o',
1670                'q',
1671            ],
1672            prog => '../lib/perl5db/t/test-w-statement-1',
1673        }
1674    );
1675
1676    $wrapper->contents_like(qr#
1677        ^\s*warnLevel\ =\ '1'\n
1678        #msx,
1679        q#"o" command (without arguments) displays warnLevel#,
1680    );
1681
1682    $wrapper->contents_like(qr#
1683        ^\s*signalLevel\ =\ '1'\n
1684        #msx,
1685        q#"o" command (without arguments) displays signalLevel#,
1686    );
1687
1688    $wrapper->contents_like(qr#
1689        ^\s*dieLevel\ =\ '1'\n
1690        #msx,
1691        q#"o" command (without arguments) displays dieLevel#,
1692    );
1693
1694    $wrapper->contents_like(qr#
1695        ^\s*hashDepth\ =\ 'N/A'\n
1696        #msx,
1697        q#"o" command (without arguments) displays hashDepth#,
1698    );
1699}
1700
1701# Test the 'o' query command.
1702{
1703    my $wrapper = DebugWrap->new(
1704        {
1705            cmds =>
1706            [
1707                'o hashDepth? signalLevel?',
1708                'q',
1709            ],
1710            prog => '../lib/perl5db/t/test-w-statement-1',
1711        }
1712    );
1713
1714    $wrapper->contents_unlike(qr#warnLevel#,
1715        q#"o" query command does not display warnLevel#,
1716    );
1717
1718    $wrapper->contents_like(qr#
1719        ^\s*signalLevel\ =\ '1'\n
1720        #msx,
1721        q#"o" query command displays signalLevel#,
1722    );
1723
1724    $wrapper->contents_unlike(qr#dieLevel#,
1725        q#"o" query command does not display dieLevel#,
1726    );
1727
1728    $wrapper->contents_like(qr#
1729        ^\s*hashDepth\ =\ 'N/A'\n
1730        #msx,
1731        q#"o" query command displays hashDepth#,
1732    );
1733}
1734
1735# Test the 'o' set command.
1736{
1737    my $wrapper = DebugWrap->new(
1738        {
1739            cmds =>
1740            [
1741                'o signalLevel=0',
1742                'o',
1743                'q',
1744            ],
1745            prog => '../lib/perl5db/t/test-w-statement-1',
1746        }
1747    );
1748
1749    $wrapper->contents_like(qr/
1750        ^\s*(signalLevel\ =\ '0'\n)
1751        .*?
1752        ^\s*\1
1753        /msx,
1754        q#o set command works#,
1755    );
1756
1757    $wrapper->contents_like(qr#
1758        ^\s*hashDepth\ =\ 'N/A'\n
1759        #msx,
1760        q#o set command - hashDepth#,
1761    );
1762}
1763
1764# Test the '<' and "< ?" commands.
1765{
1766    my $wrapper = DebugWrap->new(
1767        {
1768            cmds =>
1769            [
1770                q/< print "\nX=<$x>\n"/,
1771                q/b 7/,
1772                q/< ?/,
1773                'c',
1774                'q',
1775            ],
1776            prog => '../lib/perl5db/t/disable-breakpoints-1',
1777        }
1778    );
1779
1780    $wrapper->contents_like(qr/
1781        ^pre-perl\ commands:\n
1782        \s*<\ --\ print\ "\\nX=<\$x>\\n"\n
1783        /msx,
1784        q#Test < and < ? commands - contents.#,
1785    );
1786
1787    $wrapper->output_like(qr#
1788        ^X=<FirstVal>\n
1789        #msx,
1790        q#Test < and < ? commands - output.#,
1791    );
1792}
1793
1794# Test the '< *' command.
1795{
1796    my $wrapper = DebugWrap->new(
1797        {
1798            cmds =>
1799            [
1800                q/< print "\nX=<$x>\n"/,
1801                q/b 7/,
1802                q/< */,
1803                'c',
1804                'q',
1805            ],
1806            prog => '../lib/perl5db/t/disable-breakpoints-1',
1807        }
1808    );
1809
1810    $wrapper->output_unlike(qr/FirstVal/,
1811        q#Test the '< *' command.#,
1812    );
1813}
1814
1815# Test the '>' and "> ?" commands.
1816{
1817    my $wrapper = DebugWrap->new(
1818        {
1819            cmds =>
1820            [
1821                q/$::foo = 500;/,
1822                q/> print "\nFOO=<$::foo>\n"/,
1823                q/b 7/,
1824                q/> ?/,
1825                'c',
1826                'q',
1827            ],
1828            prog => '../lib/perl5db/t/disable-breakpoints-1',
1829        }
1830    );
1831
1832    $wrapper->contents_like(qr/
1833        ^post-perl\ commands:\n
1834        \s*>\ --\ print\ "\\nFOO=<\$::foo>\\n"\n
1835        /msx,
1836        q#Test > and > ? commands - contents.#,
1837    );
1838
1839    $wrapper->output_like(qr#
1840        ^FOO=<500>\n
1841        #msx,
1842        q#Test > and > ? commands - output.#,
1843    );
1844}
1845
1846# Test the '> *' command.
1847{
1848    my $wrapper = DebugWrap->new(
1849        {
1850            cmds =>
1851            [
1852                q/> print "\nFOO=<$::foo>\n"/,
1853                q/b 7/,
1854                q/> */,
1855                'c',
1856                'q',
1857            ],
1858            prog => '../lib/perl5db/t/disable-breakpoints-1',
1859        }
1860    );
1861
1862    $wrapper->output_unlike(qr/FOO=/,
1863        q#Test the '> *' command.#,
1864    );
1865}
1866
1867# Test the < and > commands together
1868{
1869    my $wrapper = DebugWrap->new(
1870        {
1871            cmds =>
1872            [
1873                q/$::lorem = 0;/,
1874                q/< $::lorem += 10;/,
1875                q/> print "\nLOREM=<$::lorem>\n"/,
1876                q/b 7/,
1877                q/b 5/,
1878                'c',
1879                'c',
1880                'q',
1881            ],
1882            prog => '../lib/perl5db/t/disable-breakpoints-1',
1883        }
1884    );
1885
1886    $wrapper->output_like(qr#
1887        ^LOREM=<10>\n
1888        #msx,
1889        q#Test < and > commands. #,
1890    );
1891}
1892
1893# Test the { ? and { [command] commands.
1894{
1895    my $wrapper = DebugWrap->new(
1896        {
1897            cmds =>
1898            [
1899                '{ ?',
1900                '{ l',
1901                '{ ?',
1902                q/b 5/,
1903                q/c/,
1904                q/q/,
1905            ],
1906            prog => '../lib/perl5db/t/disable-breakpoints-1',
1907        }
1908    );
1909
1910    $wrapper->contents_like(qr#
1911        ^No\ pre-debugger\ actions\.\n
1912        .*?
1913        ^pre-debugger\ commands:\n
1914        \s+\{\ --\ l\n
1915        .*?
1916        ^5==>b\s+\$x\ =\ "FirstVal";\n
1917        6\s*\n
1918        7:\s+\$dummy\+\+;\n
1919        8\s*\n
1920        9:\s+\$x\ =\ "SecondVal";\n
1921
1922        #msx,
1923        'Test the pre-prompt debugger commands',
1924    );
1925}
1926
1927# Test the { * command.
1928{
1929    my $wrapper = DebugWrap->new(
1930        {
1931            cmds =>
1932            [
1933                '{ q',
1934                '{ *',
1935                q/b 5/,
1936                q/c/,
1937                q/print (("One" x 5), "\n");/,
1938                q/q/,
1939            ],
1940            prog => '../lib/perl5db/t/disable-breakpoints-1',
1941        }
1942    );
1943
1944    $wrapper->contents_like(qr#
1945        ^All\ \{\ actions\ cleared\.\n
1946        #msx,
1947        'Test the { * command',
1948    );
1949
1950    $wrapper->output_like(qr/OneOneOneOneOne/,
1951        '{ * test - output is OK.',
1952    );
1953}
1954
1955# Test the ! command.
1956{
1957    my $wrapper = DebugWrap->new(
1958        {
1959            cmds =>
1960            [
1961                'l 3-5',
1962                '!',
1963                'q',
1964            ],
1965            prog => '../lib/perl5db/t/disable-breakpoints-1',
1966        }
1967    );
1968
1969    $wrapper->contents_like(qr#
1970        (^3:\s+my\ \$dummy\ =\ 0;\n
1971        4\s*\n
1972        5:\s+\$x\ =\ "FirstVal";)\n
1973        .*?
1974        ^l\ 3-5\n
1975        \1
1976        #msx,
1977        'Test the ! command (along with l 3-5)',
1978    );
1979}
1980
1981# Test the ! -number command.
1982{
1983    my $wrapper = DebugWrap->new(
1984        {
1985            cmds =>
1986            [
1987                'l 3-5',
1988                'l 2',
1989                '! -1',
1990                'q',
1991            ],
1992            prog => '../lib/perl5db/t/disable-breakpoints-1',
1993        }
1994    );
1995
1996    $wrapper->contents_like(qr#
1997        (^3:\s+my\ \$dummy\ =\ 0;\n
1998        4\s*\n
1999        5:\s+\$x\ =\ "FirstVal";)\n
2000        .*?
2001        ^2==\>\s+my\ \$x\ =\ "One";\n
2002        .*?
2003        ^l\ 3-5\n
2004        \1
2005        #msx,
2006        'Test the ! -n command (along with l)',
2007    );
2008}
2009
2010# Test the 'source' command.
2011{
2012    my $wrapper = DebugWrap->new(
2013        {
2014            cmds =>
2015            [
2016                'source ../lib/perl5db/t/source-cmd-test.perldb',
2017                # If we have a 'q' here, then the typeahead will override the
2018                # input, and so it won't be reached - solution:
2019                # put a q inside the .perldb commands.
2020                # ( This may be a bug or a misfeature. )
2021            ],
2022            prog => '../lib/perl5db/t/disable-breakpoints-1',
2023        }
2024    );
2025
2026    $wrapper->contents_like(qr#
2027        ^3:\s+my\ \$dummy\ =\ 0;\n
2028        4\s*\n
2029        5:\s+\$x\ =\ "FirstVal";\n
2030        6\s*\n
2031        7:\s+\$dummy\+\+;\n
2032        8\s*\n
2033        9:\s+\$x\ =\ "SecondVal";\n
2034        10\s*\n
2035        #msx,
2036        'Test the source command (along with l)',
2037    );
2038}
2039
2040# Test the 'source' command being traversed from withing typeahead.
2041{
2042    my $wrapper = DebugWrap->new(
2043        {
2044            cmds =>
2045            [
2046                'source ../lib/perl5db/t/source-cmd-test-no-q.perldb',
2047                'q',
2048            ],
2049            prog => '../lib/perl5db/t/disable-breakpoints-1',
2050        }
2051    );
2052
2053    $wrapper->contents_like(qr#
2054        ^3:\s+my\ \$dummy\ =\ 0;\n
2055        4\s*\n
2056        5:\s+\$x\ =\ "FirstVal";\n
2057        6\s*\n
2058        7:\s+\$dummy\+\+;\n
2059        8\s*\n
2060        9:\s+\$x\ =\ "SecondVal";\n
2061        10\s*\n
2062        #msx,
2063        'Test the source command inside a typeahead',
2064    );
2065}
2066
2067# Test the 'H -number' command.
2068{
2069    my $wrapper = DebugWrap->new(
2070        {
2071            cmds =>
2072            [
2073                'l 1-10',
2074                'l 5-10',
2075                'x "Hello World"',
2076                'l 1-5',
2077                'b 3',
2078                'x (20+4)',
2079                'H -7',
2080                'q',
2081            ],
2082            prog => '../lib/perl5db/t/disable-breakpoints-1',
2083        }
2084    );
2085
2086    $wrapper->contents_like(qr#
2087        ^\d+:\s+H\ -7\n
2088        \d+:\s+x\ \(20\+4\)\n
2089        \d+:\s+b\ 3\n
2090        \d+:\s+l\ 1-5\n
2091        \d+:\s+x\ "Hello\ World"\n
2092        \d+:\s+l\ 5-10\n
2093        \d+:\s+l\ 1-10\n
2094        #msx,
2095        'Test the H -num command',
2096    );
2097}
2098
2099# Add a test for H (without arguments)
2100{
2101    my $wrapper = DebugWrap->new(
2102        {
2103            cmds =>
2104            [
2105                'l 1-10',
2106                'l 5-10',
2107                'x "Hello World"',
2108                'l 1-5',
2109                'b 3',
2110                'x (20+4)',
2111                'H',
2112                'q',
2113            ],
2114            prog => '../lib/perl5db/t/disable-breakpoints-1',
2115        }
2116    );
2117
2118    $wrapper->contents_like(qr#
2119        ^\d+:\s+x\ \(20\+4\)\n
2120        \d+:\s+b\ 3\n
2121        \d+:\s+l\ 1-5\n
2122        \d+:\s+x\ "Hello\ World"\n
2123        \d+:\s+l\ 5-10\n
2124        \d+:\s+l\ 1-10\n
2125        #msx,
2126        'Test the H command (without a number.)',
2127    );
2128}
2129
2130{
2131    my $wrapper = DebugWrap->new(
2132        {
2133            cmds =>
2134            [
2135                '= quit q',
2136                '= foobar l',
2137                'foobar',
2138                'quit',
2139            ],
2140            prog => '../lib/perl5db/t/test-l-statement-1',
2141        }
2142    );
2143
2144    $wrapper->contents_like(
2145        qr/
2146            ^1==>\s+\$x\ =\ 1;\n
2147            2:\s+print\ "1\\n";\n
2148            3\s*\n
2149            4:\s+\$x\ =\ 2;\n
2150            5:\s+print\ "2\\n";\n
2151        /msx,
2152        'Test the = (command alias) command.',
2153    );
2154}
2155
2156# Test the m statement.
2157{
2158    my $wrapper = DebugWrap->new(
2159        {
2160            cmds =>
2161            [
2162                'm main',
2163                'q',
2164            ],
2165            prog => '../lib/perl5db/t/disable-breakpoints-1',
2166        }
2167    );
2168
2169    $wrapper->contents_like(qr#
2170        ^via\ UNIVERSAL:\ DOES$
2171        #msx,
2172        "Test m for main - 1",
2173    );
2174
2175    $wrapper->contents_like(qr#
2176        ^via\ UNIVERSAL:\ can$
2177        #msx,
2178        "Test m for main - 2",
2179    );
2180}
2181
2182# Test the m statement.
2183{
2184    my $wrapper = DebugWrap->new(
2185        {
2186            cmds =>
2187            [
2188                'b 41',
2189                'c',
2190                'm $obj',
2191                'q',
2192            ],
2193            prog => '../lib/perl5db/t/test-m-statement-1',
2194        }
2195    );
2196
2197    $wrapper->contents_like(qr#^greet$#ms,
2198        "Test m for obj - 1",
2199    );
2200
2201    $wrapper->contents_like(qr#^via UNIVERSAL: can$#ms,
2202        "Test m for obj - 1",
2203    );
2204}
2205
2206# Test the M command.
2207{
2208    my $wrapper = DebugWrap->new(
2209        {
2210            cmds =>
2211            [
2212                'M',
2213                'q',
2214            ],
2215            prog => '../lib/perl5db/t/test-m-statement-1',
2216        }
2217    );
2218
2219    $wrapper->contents_like(qr#
2220        ^'strict\.pm'\ =>\ '\d+\.\d+\ from
2221        #msx,
2222        "Test M",
2223    );
2224
2225}
2226
2227# Test the recallCommand option.
2228{
2229    my $wrapper = DebugWrap->new(
2230        {
2231            cmds =>
2232            [
2233                'o recallCommand=%',
2234                'l 3-5',
2235                'l 2',
2236                '% -1',
2237                'q',
2238            ],
2239            prog => '../lib/perl5db/t/disable-breakpoints-1',
2240        }
2241    );
2242
2243    $wrapper->contents_like(qr#
2244        (^3:\s+my\ \$dummy\ =\ 0;\n
2245        4\s*\n
2246        5:\s+\$x\ =\ "FirstVal";)\n
2247        .*?
2248        ^2==\>\s+my\ \$x\ =\ "One";\n
2249        .*?
2250        ^l\ 3-5\n
2251        \1
2252        #msx,
2253        'Test the o recallCommand option',
2254    );
2255}
2256
2257# Test the dieLevel option
2258{
2259    my $wrapper = DebugWrap->new(
2260        {
2261            cmds =>
2262            [
2263                q/o dieLevel='1'/,
2264                q/c/,
2265                'q',
2266            ],
2267            prog => '../lib/perl5db/t/test-dieLevel-option-1',
2268        }
2269    );
2270
2271    $wrapper->output_like(qr#
2272        ^This\ program\ dies\.\ at\ \S+\ line\ 18\.\n
2273        .*?
2274        ^\s+main::baz\(\)\ called\ at\ \S+\ line\ 13\n
2275        \s+main::bar\(\)\ called\ at\ \S+\ line\ 7\n
2276        \s+main::foo\(\)\ called\ at\ \S+\ line\ 21\n
2277        #msx,
2278        'Test the o dieLevel option',
2279    );
2280}
2281
2282# Test the warnLevel option
2283{
2284    my $wrapper = DebugWrap->new(
2285        {
2286            cmds =>
2287            [
2288                q/o warnLevel='1'/,
2289                q/c/,
2290                'q',
2291            ],
2292            prog => '../lib/perl5db/t/test-warnLevel-option-1',
2293        }
2294    );
2295
2296    $wrapper->contents_like(qr#
2297        ^This\ is\ not\ a\ warning\.\ at\ \S+\ line\ 18\.\n
2298        .*?
2299        ^\s+main::baz\(\)\ called\ at\ \S+\ line\ 13\n
2300        \s+main::bar\(\)\ called\ at\ \S+\ line\ 25\n
2301        \s+main::myfunc\(\)\ called\ at\ \S+\ line\ 28\n
2302        #msx,
2303        'Test the o warnLevel option',
2304    );
2305}
2306
2307# Test the t command
2308{
2309    my $wrapper = DebugWrap->new(
2310        {
2311            cmds =>
2312            [
2313                't',
2314                'c',
2315                'q',
2316            ],
2317            prog => '../lib/perl5db/t/disable-breakpoints-1',
2318        }
2319    );
2320
2321    $wrapper->contents_like(qr/
2322        ^main::\([^:]+:15\):\n
2323        15:\s+\$dummy\+\+;\n
2324        main::\([^:]+:17\):\n
2325        17:\s+\$x\ =\ "FourthVal";\n
2326        /msx,
2327        'Test the t command (without a number.)',
2328    );
2329}
2330
2331# Test the o AutoTrace command
2332{
2333    my $wrapper = DebugWrap->new(
2334        {
2335            cmds =>
2336            [
2337                'o AutoTrace',
2338                'c',
2339                'q',
2340            ],
2341            prog => '../lib/perl5db/t/disable-breakpoints-1',
2342        }
2343    );
2344
2345    $wrapper->contents_like(qr/
2346        ^main::\([^:]+:15\):\n
2347        15:\s+\$dummy\+\+;\n
2348        main::\([^:]+:17\):\n
2349        17:\s+\$x\ =\ "FourthVal";\n
2350        /msx,
2351        'Test the o AutoTrace command',
2352    );
2353}
2354
2355# Test the t command with function calls
2356{
2357    my $wrapper = DebugWrap->new(
2358        {
2359            cmds =>
2360            [
2361                't',
2362                'b 18',
2363                'c',
2364                'x ["foo"]',
2365                'x ["bar"]',
2366                'q',
2367            ],
2368            prog => '../lib/perl5db/t/test-warnLevel-option-1',
2369        }
2370    );
2371
2372    $wrapper->contents_like(qr/
2373        ^main::\([^:]+:28\):\n
2374        28:\s+myfunc\(\);\n
2375        main::myfunc\([^:]+:25\):\n
2376        25:\s+bar\(\);\n
2377        /msx,
2378        'Test the t command with function calls.',
2379    );
2380}
2381
2382# Test the o AutoTrace command with function calls
2383{
2384    my $wrapper = DebugWrap->new(
2385        {
2386            cmds =>
2387            [
2388                'o AutoTrace',
2389                'b 18',
2390                'c',
2391                'x ["foo"]',
2392                'x ["bar"]',
2393                'q',
2394            ],
2395            prog => '../lib/perl5db/t/test-warnLevel-option-1',
2396        }
2397    );
2398
2399    $wrapper->contents_like(qr/
2400        ^main::\([^:]+:28\):\n
2401        28:\s+myfunc\(\);\n
2402        main::myfunc\([^:]+:25\):\n
2403        25:\s+bar\(\);\n
2404        /msx,
2405        'Test the t command with function calls.',
2406    );
2407}
2408
2409# Test the final message.
2410{
2411    my $wrapper = DebugWrap->new(
2412        {
2413            cmds =>
2414            [
2415                'c',
2416                'q',
2417            ],
2418            prog => '../lib/perl5db/t/test-warnLevel-option-1',
2419        }
2420    );
2421
2422    $wrapper->contents_like(qr/
2423        ^Debugged\ program\ terminated\.
2424        /msx,
2425        'Test the final "Debugged program terminated" message.',
2426    );
2427}
2428
2429# Test the o inhibit_exit=0 command
2430{
2431    my $wrapper = DebugWrap->new(
2432        {
2433            cmds =>
2434            [
2435                'o inhibit_exit=0',
2436                'n',
2437                'n',
2438                'n',
2439                'n',
2440                'q',
2441            ],
2442            prog => '../lib/perl5db/t/test-warnLevel-option-1',
2443        }
2444    );
2445
2446    $wrapper->contents_unlike(qr/
2447        ^Debugged\ program\ terminated\.
2448        /msx,
2449        'Test the o inhibit_exit=0 command.',
2450    );
2451}
2452
2453# Test the o PrintRet=1 option
2454{
2455    my $wrapper = DebugWrap->new(
2456        {
2457            cmds =>
2458            [
2459                'o PrintRet=1',
2460                'b 29',
2461                'c',
2462                q/$x = 's';/,
2463                'b 10',
2464                'c',
2465                'r',
2466                'q',
2467            ],
2468            prog => '../lib/perl5db/t/test-PrintRet-option-1',
2469        }
2470    );
2471
2472    $wrapper->contents_like(
2473        qr/scalar context return from main::return_scalar: 20024/,
2474        "Test o PrintRet=1",
2475    );
2476}
2477
2478# Test the o PrintRet=0 option
2479{
2480    my $wrapper = DebugWrap->new(
2481        {
2482            cmds =>
2483            [
2484                'o PrintRet=0',
2485                'b 29',
2486                'c',
2487                q/$x = 's';/,
2488                'b 10',
2489                'c',
2490                'r',
2491                'q',
2492            ],
2493            prog => '../lib/perl5db/t/test-PrintRet-option-1',
2494        }
2495    );
2496
2497    $wrapper->contents_unlike(
2498        qr/scalar context/,
2499        "Test o PrintRet=0",
2500    );
2501}
2502
2503# Test the o PrintRet=1 option in list context
2504{
2505    my $wrapper = DebugWrap->new(
2506        {
2507            cmds =>
2508            [
2509                'o PrintRet=1',
2510                'b 29',
2511                'c',
2512                q/$x = 'l';/,
2513                'b 17',
2514                'c',
2515                'r',
2516                'q',
2517            ],
2518            prog => '../lib/perl5db/t/test-PrintRet-option-1',
2519        }
2520    );
2521
2522    $wrapper->contents_like(
2523        qr/list context return from main::return_list:\n0\s*'Foo'\n1\s*'Bar'\n2\s*'Baz'\n/,
2524        "Test o PrintRet=1 in list context",
2525    );
2526}
2527
2528# Test the o PrintRet=0 option in list context
2529{
2530    my $wrapper = DebugWrap->new(
2531        {
2532            cmds =>
2533            [
2534                'o PrintRet=0',
2535                'b 29',
2536                'c',
2537                q/$x = 'l';/,
2538                'b 17',
2539                'c',
2540                'r',
2541                'q',
2542            ],
2543            prog => '../lib/perl5db/t/test-PrintRet-option-1',
2544        }
2545    );
2546
2547    $wrapper->contents_unlike(
2548        qr/list context/,
2549        "Test o PrintRet=0 in list context",
2550    );
2551}
2552
2553# Test the o PrintRet=1 option in void context
2554{
2555    my $wrapper = DebugWrap->new(
2556        {
2557            cmds =>
2558            [
2559                'o PrintRet=1',
2560                'b 29',
2561                'c',
2562                q/$x = 'v';/,
2563                'b 24',
2564                'c',
2565                'r',
2566                'q',
2567            ],
2568            prog => '../lib/perl5db/t/test-PrintRet-option-1',
2569        }
2570    );
2571
2572    $wrapper->contents_like(
2573        qr/void context return from main::return_void/,
2574        "Test o PrintRet=1 in void context",
2575    );
2576}
2577
2578# Test the o PrintRet=1 option in void context
2579{
2580    my $wrapper = DebugWrap->new(
2581        {
2582            cmds =>
2583            [
2584                'o PrintRet=0',
2585                'b 29',
2586                'c',
2587                q/$x = 'v';/,
2588                'b 24',
2589                'c',
2590                'r',
2591                'q',
2592            ],
2593            prog => '../lib/perl5db/t/test-PrintRet-option-1',
2594        }
2595    );
2596
2597    $wrapper->contents_unlike(
2598        qr/void context/,
2599        "Test o PrintRet=0 in void context",
2600    );
2601}
2602
2603# Test the o frame option.
2604{
2605    my $wrapper = DebugWrap->new(
2606        {
2607            cmds =>
2608            [
2609                # This is to avoid getting the "Debugger program terminated"
2610                # junk that interferes with the normal output.
2611                'o inhibit_exit=0',
2612                'b 10',
2613                'c',
2614                'o frame=255',
2615                'c',
2616                'q',
2617            ],
2618            prog => '../lib/perl5db/t/test-frame-option-1',
2619        }
2620    );
2621
2622    $wrapper->contents_like(
2623        qr/
2624            in\s*\.=main::my_other_func\(3,\ 1200\)\ from.*?
2625            out\s*\.=main::my_other_func\(3,\ 1200\)\ from
2626        /msx,
2627        "Test o PrintRet=0 in void context",
2628    );
2629}
2630
2631{ # test t expr
2632    my $wrapper = DebugWrap->new(
2633        {
2634            cmds =>
2635            [
2636                # This is to avoid getting the "Debugger program terminated"
2637                # junk that interferes with the normal output.
2638                'o inhibit_exit=0',
2639                't fact(3)',
2640                'q',
2641            ],
2642            prog => '../lib/perl5db/t/fact',
2643        }
2644    );
2645
2646    $wrapper->contents_like(
2647        qr/
2648	    (?:^main::fact.*return\ \$n\ \*\ fact\(\$n\ -\ 1\);.*)
2649        /msx,
2650        "Test t expr",
2651    );
2652}
2653
2654# Test the w for lexical variables expression.
2655{
2656    my $wrapper = DebugWrap->new(
2657        {
2658            cmds =>
2659            [
2660                # This is to avoid getting the "Debugger program terminated"
2661                # junk that interferes with the normal output.
2662                'w $exp',
2663                'n',
2664                'n',
2665                'n',
2666                'n',
2667                'q',
2668            ],
2669            prog => '../lib/perl5db/t/break-on-dot',
2670        }
2671    );
2672
2673    $wrapper->contents_like(
2674        qr/
2675\s+old\ value:\s+'1'\n
2676\s+new\ value:\s+'2'\n
2677        /msx,
2678        "Test w for lexical values.",
2679    );
2680}
2681
2682# Test the perldoc command
2683# We don't actually run the program, but we need to provide one to the wrapper.
2684SKIP:
2685{
2686    $^O eq "linux"
2687        or skip "man errors aren't especially portable", 1;
2688    -x '/usr/bin/man'
2689        or skip "man command seems to be missing", 1;
2690    local $ENV{LANG} = "C";
2691    local $ENV{LC_MESSAGES} = "C";
2692    local $ENV{LC_ALL} = "C";
2693    my $wrapper = DebugWrap->new(
2694        {
2695            cmds =>
2696            [
2697                'perldoc perlrules',
2698                'q',
2699            ],
2700            prog => '../lib/perl5db/t/fact',
2701        }
2702    );
2703
2704    $wrapper->output_like(
2705        qr/No manual entry for perlrules/,
2706        'perldoc command works fine',
2707    );
2708}
2709
2710END {
2711    1 while unlink ($rc_filename, $out_fn);
2712}
2713