xref: /openbsd-src/gnu/usr.bin/perl/t/comp/retainedlines.t (revision f2a19305cfc49ea4d1a5feb55cd6c283c6f1e031)
143003dfeSmillert#!./perl -w
243003dfeSmillert
343003dfeSmillert# Check that lines from eval are correctly retained by the debugger
443003dfeSmillert
5b39c5158Smillert# Uncomment this for testing, but don't leave it in for "production", as
6b39c5158Smillert# we've not yet verified that use works.
7b39c5158Smillert# use strict;
8b39c5158Smillert
9*f2a19305Safresh1print "1..109\n";
10b39c5158Smillertmy $test = 0;
11b39c5158Smillert
12b39c5158Smillertsub failed {
13b39c5158Smillert    my ($got, $expected, $name) = @_;
14b39c5158Smillert
15b39c5158Smillert    print "not ok $test - $name\n";
16b39c5158Smillert    my @caller = caller(1);
17b39c5158Smillert    print "# Failed test at $caller[1] line $caller[2]\n";
18b39c5158Smillert    if (defined $got) {
19b39c5158Smillert	print "# Got '$got'\n";
20b39c5158Smillert    } else {
21b39c5158Smillert	print "# Got undef\n";
22b39c5158Smillert    }
23b39c5158Smillert    print "# Expected $expected\n";
24b39c5158Smillert    return;
2543003dfeSmillert}
2643003dfeSmillert
27898184e3Ssthensub is($$$) {
28b39c5158Smillert    my ($got, $expect, $name) = @_;
29b39c5158Smillert    $test = $test + 1;
30b39c5158Smillert    if (defined $expect) {
31b39c5158Smillert	if (defined $got && $got eq $expect) {
32b39c5158Smillert	    print "ok $test - $name\n";
33b39c5158Smillert	    return 1;
34b39c5158Smillert	}
35b39c5158Smillert	failed($got, "'$expect'", $name);
36b39c5158Smillert    } else {
37b39c5158Smillert	if (!defined $got) {
38b39c5158Smillert	    print "ok $test - $name\n";
39b39c5158Smillert	    return 1;
40b39c5158Smillert	}
41b39c5158Smillert	failed($got, 'undef', $name);
42b39c5158Smillert    }
43b39c5158Smillert}
4443003dfeSmillert
4543003dfeSmillert$^P = 0xA;
4643003dfeSmillert
4743003dfeSmillertmy @before = grep { /eval/ } keys %::;
4843003dfeSmillert
49b39c5158Smillertis ((scalar @before), 0, "No evals");
5043003dfeSmillert
5143003dfeSmillertmy %seen;
5243003dfeSmillert
5343003dfeSmillertsub check_retained_lines {
5443003dfeSmillert    my ($prog, $name) = @_;
5543003dfeSmillert    # Is there a more efficient way to write this?
5643003dfeSmillert    my @expect_lines = (undef, map ({"$_\n"} split "\n", $prog), "\n", ';');
5743003dfeSmillert
58*f2a19305Safresh1    # sort in decreasing number so that $keys[0] is the from the most
59*f2a19305Safresh1    # recent eval. In theory we should only have one, but if something
60*f2a19305Safresh1    # breaks we might have more than one, and keys will return them in a
61*f2a19305Safresh1    # random order, so if we dont do this then failing tests will have
62*f2a19305Safresh1    # inconsistent results from run to run.
63*f2a19305Safresh1    my @keys = map { $_->[0] }
64*f2a19305Safresh1               sort { $b->[1] <=> $a->[1] }
65*f2a19305Safresh1               map { (!$seen{$_} and /eval (\d+)/) ? [ $_, $1 ] : ()  }
66*f2a19305Safresh1               keys %::;
6743003dfeSmillert
68b39c5158Smillert    is ((scalar @keys), 1, "1 new eval");
6943003dfeSmillert
7043003dfeSmillert    my @got_lines = @{$::{$keys[0]}};
7143003dfeSmillert
72b39c5158Smillert    is ((scalar @got_lines),
73b39c5158Smillert	(scalar @expect_lines), "Right number of lines for $name");
7443003dfeSmillert
7543003dfeSmillert    for (0..$#expect_lines) {
7643003dfeSmillert	is ($got_lines[$_], $expect_lines[$_], "Line $_ is correct");
7743003dfeSmillert    }
78*f2a19305Safresh1    # if we are "leaking" evals we only want to fail the current test,
79*f2a19305Safresh1    # so we need to mark them all seen (older code only marked $keys[0]
80*f2a19305Safresh1    # seen and this caused tests to fail that actually worked properly.)
81*f2a19305Safresh1    $seen{$_}++ for @keys;
8243003dfeSmillert}
8343003dfeSmillert
8443003dfeSmillertmy $name = 'foo';
8543003dfeSmillert
8643003dfeSmillertfor my $sep (' ', "\0") {
8743003dfeSmillert
8843003dfeSmillert    my $prog = "sub $name {
8943003dfeSmillert    'Perl${sep}Rules'
9043003dfeSmillert};
9143003dfeSmillert1;
9243003dfeSmillert";
9343003dfeSmillert
9443003dfeSmillert    eval $prog or die;
9543003dfeSmillert    check_retained_lines($prog, ord $sep);
9643003dfeSmillert    $name++;
9743003dfeSmillert}
9843003dfeSmillert
9943003dfeSmillert{
10043003dfeSmillert  # This contains a syntax error
10143003dfeSmillert  my $prog = "sub $name {
10243003dfeSmillert    'This is $name'
10343003dfeSmillert  }
104*f2a19305Safresh1# 10 errors to triger a croak during compilation.
105*f2a19305Safresh11 +; 1 +; 1 +; 1 +; 1 +;
106*f2a19305Safresh11 +; 1 +; 1 +; 1 +; 1 +;
107*f2a19305Safresh11 +; # and one more for good measure.
10843003dfeSmillert";
10943003dfeSmillert
11043003dfeSmillert  eval $prog and die;
11143003dfeSmillert
11243003dfeSmillert  is (eval "$name()", "This is $name", "Subroutine was compiled, despite error")
113b39c5158Smillert    or print STDERR "# $@\n";
11443003dfeSmillert
115b39c5158Smillert  check_retained_lines($prog,
116b39c5158Smillert		       'eval that defines subroutine but has syntax error');
11743003dfeSmillert  $name++;
11843003dfeSmillert}
11943003dfeSmillert
12043003dfeSmillertforeach my $flags (0x0, 0x800, 0x1000, 0x1800) {
12143003dfeSmillert    local $^P = $^P | $flags;
12243003dfeSmillert    # This is easier if we accept that the guts eval will add a trailing \n
12343003dfeSmillert    # for us
12443003dfeSmillert    my $prog = "1 + 1 + 1\n";
125*f2a19305Safresh1    my $fail = "1 +;\n" x 11; # we need 10 errors to trigger a croak during
126*f2a19305Safresh1                              # compile, we add an extra one just for good
127*f2a19305Safresh1                              # measure.
12843003dfeSmillert
12943003dfeSmillert    is (eval $prog, 3, 'String eval works');
13043003dfeSmillert    if ($flags & 0x800) {
13143003dfeSmillert	check_retained_lines($prog, sprintf "%#X", $^P);
13243003dfeSmillert    } else {
13343003dfeSmillert	my @after = grep { /eval/ } keys %::;
13443003dfeSmillert
135b39c5158Smillert	is (scalar @after, 0 + keys %seen,
13643003dfeSmillert	    "evals that don't define subroutines are correctly cleaned up");
13743003dfeSmillert    }
13843003dfeSmillert
13943003dfeSmillert    is (eval $fail, undef, 'Failed string eval fails');
14043003dfeSmillert
14143003dfeSmillert    if ($flags & 0x1000) {
14243003dfeSmillert	check_retained_lines($fail, sprintf "%#X", $^P);
14343003dfeSmillert    } else {
14443003dfeSmillert	my @after = grep { /eval/ } keys %::;
14543003dfeSmillert
146b39c5158Smillert	is (scalar @after, 0 + keys %seen,
14743003dfeSmillert	    "evals that fail are correctly cleaned up");
14843003dfeSmillert    }
14943003dfeSmillert}
150898184e3Ssthen
151898184e3Ssthen# BEGIN blocks that die
152898184e3Ssthenfor (0xA, 0) {
153898184e3Ssthen  local $^P = $_;
154898184e3Ssthen
155898184e3Ssthen  eval (my $prog = "BEGIN{die}\n");
156898184e3Ssthen
157898184e3Ssthen  if ($_) {
158898184e3Ssthen    check_retained_lines($prog, 'eval that defines BEGIN that dies');
159898184e3Ssthen  }
160898184e3Ssthen  else {
161898184e3Ssthen    my @after = grep { /eval/ } keys %::;
162898184e3Ssthen
163898184e3Ssthen    is (scalar @after, 0 + keys %seen,
164898184e3Ssthen       "evals with BEGIN{die} are correctly cleaned up");
165898184e3Ssthen  }
166898184e3Ssthen}
167898184e3Ssthen
168*f2a19305Safresh1for (0xA, 0) {
169*f2a19305Safresh1  local $^P = $_;
170*f2a19305Safresh1
171*f2a19305Safresh1  eval (my $prog = "UNITCHECK{die}\n");
172*f2a19305Safresh1  is (!!$@, 1, "Is \$@ true?");
173*f2a19305Safresh1  is ($@=~/UNITCHECK failed--call queue aborted/, 1,
174*f2a19305Safresh1      "Error is expected value?");
175*f2a19305Safresh1
176*f2a19305Safresh1  if ($_) {
177*f2a19305Safresh1    check_retained_lines($prog, 'eval that defines UNITCHECK that dies');
178*f2a19305Safresh1  }
179*f2a19305Safresh1  else {
180*f2a19305Safresh1    my @after = grep { /eval/ } keys %::;
181*f2a19305Safresh1
182*f2a19305Safresh1    is (scalar @after, 0 + keys %seen,
183*f2a19305Safresh1       "evals with UNITCHECK{die} are correctly cleaned up");
184*f2a19305Safresh1  }
185*f2a19305Safresh1}
186*f2a19305Safresh1
187*f2a19305Safresh1
188898184e3Ssthen# [perl #79442] A #line "foo" directive in a string eval was not updating
189898184e3Ssthen# *{"_<foo"} in threaded perls, and was not putting the right lines into
190898184e3Ssthen# the right elements of @{"_<foo"} in non-threaded perls.
191898184e3Ssthen{
192898184e3Ssthen  local $^P = 0x400|0x100|0x10;
193898184e3Ssthen  eval qq{#line 42 "hash-line-eval"\n labadalabada()\n};
194898184e3Ssthen  is $::{"_<hash-line-eval"}[42], " labadalabada()\n",
195898184e3Ssthen   '#line 42 "foo" in a string eval updates @{"_<foo"}';
196898184e3Ssthen  eval qq{#line 42 "figgle"\n#line 85 "doggo"\n labadalabada()\n};
197898184e3Ssthen  is $::{"_<doggo"}[85], " labadalabada()\n",
198898184e3Ssthen   'subsequent #line 42 "foo" in a string eval updates @{"_<foo"}';
199898184e3Ssthen}
2006fb12b70Safresh1
2016fb12b70Safresh1# Modifying ${"_<foo"} should not stop lines from being retained.
2026fb12b70Safresh1{
2036fb12b70Safresh1  local $^P = 0x400|0x100|0x10;
2046fb12b70Safresh1  eval <<'end';
2056fb12b70Safresh1#line 42 "copfilesv-modification"
2066fb12b70Safresh1    BEGIN{ ${"_<copfilesv-modification"} = \1 }
2076fb12b70Safresh1#line 52 "copfilesv-modified"
2086fb12b70Safresh1    abcdefg();
2096fb12b70Safresh1end
2106fb12b70Safresh1  is $::{"_<copfilesv-modified"}[52], "    abcdefg();\n",
2116fb12b70Safresh1   '#line 42 "foo" in a str eval is not confused by ${"_<foo"} changing';
2126fb12b70Safresh1}
213