Fix test for overload in given() with smart match after last change
[p5sagit/p5-mst-13.2.git] / t / op / eval.t
index 6487b9e..23725d5 100755 (executable)
@@ -1,6 +1,12 @@
 #!./perl
 
-print "1..77\n";
+BEGIN {
+    chdir 't' if -d 't';
+    @INC = '../lib';
+    require './test.pl';
+}
+
+print "1..98\n";
 
 eval 'print "ok 1\n";';
 
@@ -33,11 +39,12 @@ $fact = 'local($foo)=$foo; $foo <= 1 ? 1 : $foo-- * (eval $fact);';
 $ans = eval $fact;
 if ($ans == 120) {print "ok 9\n";} else {print "not ok 9 $ans\n";}
 
-open(try,'>Op.eval');
-print try 'print "ok 10\n"; unlink "Op.eval";',"\n";
+my $tempfile = tempfile();
+open(try,'>',$tempfile);
+print try 'print "ok 10\n";',"\n";
 close try;
 
-do './Op.eval'; print $@;
+do "./$tempfile"; print $@;
 
 # Test the singlequoted eval optimizer
 
@@ -340,6 +347,202 @@ eval q{
 };
 fred5();
 { my $yyy = 88; my $zzz = 99; fred5(); }
-eval q{ my $yyy = 888; my $zzz = 999; fred5(); }
+eval q{ my $yyy = 888; my $zzz = 999; fred5(); };
+
+# [perl #9728] used to dump core
+{
+   $eval = eval 'sub { eval "sub { %S }" }';
+   $eval->({});
+   print "ok $test\n";
+   $test++;
+}
+
+# evals that appear in the DB package should see the lexical scope of the
+# thing outside DB that called them (usually the debugged code), rather
+# than the usual surrounding scope
+
+$test=79;
+our $x = 1;
+{
+    my $x=2;
+    sub db1    { $x; eval '$x' }
+    sub DB::db2        { $x; eval '$x' }
+    package DB;
+    sub db3    { eval '$x' }
+    sub DB::db4        { eval '$x' }
+    sub db5    { my $x=4; eval '$x' }
+    package main;
+    sub db6    { my $x=4; eval '$x' }
+}
+{
+    my $x = 3;
+    print db1()     == 2 ? 'ok' : 'not ok', " $test\n"; $test++;
+    print DB::db2() == 2 ? 'ok' : 'not ok', " $test\n"; $test++;
+    print DB::db3() == 3 ? 'ok' : 'not ok', " $test\n"; $test++;
+    print DB::db4() == 3 ? 'ok' : 'not ok', " $test\n"; $test++;
+    print DB::db5() == 3 ? 'ok' : 'not ok', " $test\n"; $test++;
+    print db6()     == 4 ? 'ok' : 'not ok', " $test\n"; $test++;
+}
+require './test.pl';
+$NO_ENDING = 1;
+# [perl #19022] used to end up with shared hash warnings
+# The program should generate no output, so anything we see is on stderr
+my $got = runperl (prog => '$h{a}=1; foreach my $k (keys %h) {eval qq{\$k}}',
+                  stderr => 1);
+
+if ($got eq '') {
+  print "ok $test\n";
+} else {
+  print "not ok $test\n";
+  _diag ("# Got '$got'\n");
+}
+$test++;
+
+# And a buggy way of fixing #19022 made this fail - $k became undef after the
+# eval for a build with copy on write
+{
+  my %h;
+  $h{a}=1;
+  foreach my $k (keys %h) {
+    if (defined $k and $k eq 'a') {
+      print "ok $test\n";
+    } else {
+      print "not $test # got ", _q ($k), "\n";
+    }
+    $test++;
+
+    eval "\$k";
+
+    if (defined $k and $k eq 'a') {
+      print "ok $test\n";
+    } else {
+      print "not $test # got ", _q ($k), "\n";
+    }
+    $test++;
+  }
+}
+
+sub Foo {} print Foo(eval {});
+print "ok ",$test++," - #20798 (used to dump core)\n";
+
+# check for context in string eval
+{
+  my(@r,$r,$c);
+  sub context { defined(wantarray) ? (wantarray ? ($c='A') : ($c='S')) : ($c='V') }
+
+  my $code = q{ context() };
+  @r = qw( a b );
+  $r = 'ab';
+  @r = eval $code;
+  print "@r$c" eq 'AA' ? "ok " : "# '@r$c' ne 'AA'\nnot ok ", $test++, "\n";
+  $r = eval $code;
+  print "$r$c" eq 'SS' ? "ok " : "# '$r$c' ne 'SS'\nnot ok ", $test++, "\n";
+  eval $code;
+  print   $c   eq 'V'  ? "ok " : "# '$c' ne 'V'\nnot ok ", $test++, "\n";
+}
+
+# [perl #34682] escaping an eval with last could coredump or dup output
+
+$got = runperl (
+    prog => 
+    'sub A::TIEARRAY { L: { eval { last L } } } tie @a, A; warn qq(ok\n)',
+stderr => 1);
+
+print "not " unless $got eq "ok\n";
+print "ok $test - eval and last\n"; $test++;
+
+# eval undef should be the same as eval "" barring any warnings
+
+{
+    local $@ = "foo";
+    eval undef;
+    print "not " unless $@ eq "";
+    print "ok $test # eval undef \n"; $test++;
+}
+
+{
+    no warnings;
+    eval "/ /a;";
+    print "not " unless $@ =~ /^syntax error/;
+    print "ok $test # eval syntax error, no warnings \n"; $test++;
+}
 
 
+# a syntax error in an eval called magically 9eg vie tie or overload)
+# resulted in an assertion failure in S_docatch, since doeval had already
+# poppedthe EVAL context due to the failure, but S_docatch expected the
+# context to still be there.
+
+{
+    my $ok  = 0;
+    package Eval1;
+    sub STORE { eval '('; $ok = 1 }
+    sub TIESCALAR { bless [] }
+
+    my $x;
+    tie $x, bless [];
+    $x = 1;
+    print "not " unless $ok;
+    print "ok $test # eval docatch \n"; $test++;
+}
+
+
+# [perl #51370] eval { die "\x{a10d}" } followed by eval { 1 } did not reset
+# length $@ 
+$@ = "";
+eval { die "\x{a10d}"; };
+$_ = length $@;
+eval { 1 };
+
+print "not " if ($@ ne "");
+print "ok $test # length of \$@ after eval\n"; $test++;
+
+print "not " if (length $@ != 0);
+print "ok $test # length of \$@ after eval\n"; $test++;
+
+# Check if eval { 1 }; compeltly resets $@
+if (eval "use Devel::Peek; 1;") {
+  $tempfile = tempfile();
+  $outfile = tempfile();
+  open PROG, ">", $tempfile or die "Can't create test file";
+  my $prog = <<'END_EVAL_TEST';
+    use Devel::Peek;
+    $! = 0;
+    $@ = $!;
+    my $ok = 0;
+    open(SAVERR, ">&STDERR") or die "Can't dup STDERR: $!";
+    if (open(OUT, '>', '@@@@')) {
+      open(STDERR, ">&OUT") or die "Can't dup OUT: $!";
+      Dump($@);
+      print STDERR "******\n";
+      eval { die "\x{a10d}"; };
+      $_ = length $@;
+      eval { 1 };
+      Dump($@);
+      open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!";
+      close(OUT);
+      if (open(IN, '<', '@@@@')) {
+        local $/;
+        my $in = <IN>;
+        my ($first, $second) = split (/\*\*\*\*\*\*\n/, $in, 2);
+        $first =~ s/,pNOK//;
+        $ok = 1 if ($first eq $second);
+      }
+    }
+
+    print $ok;
+END_EVAL_TEST
+    $prog =~ s/\@\@\@\@/$outfile/g;
+    print PROG $prog;
+   close PROG;
+
+   my $ok = runperl(progfile => $tempfile);
+   print "not " unless $ok;
+   print "ok $test # eval { 1 } completly resets \$@\n";
+
+   $test++;
+}
+else {
+  print "ok $test # skipped - eval { 1 } completly resets \$@";
+}
+