This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Do not use bareword TERM or KILL in kill() call in test watchdog process
[perl5.git] / t / test.pl
index cdd72ea..7063506 100644 (file)
--- a/t/test.pl
+++ b/t/test.pl
@@ -1,17 +1,18 @@
 #
-# t/test.pl - most of Test::More functionality without the fuss, plus
-# has mappings native_to_latin1 and latin1_to_native so that fewer tests
-# on non ASCII-ish platforms need to be skipped
+# t/test.pl - most of Test::More functionality without the fuss
 
 
 # NOTE:
 #
-# Increment ($x++) has a certain amount of cleverness for things like
+# It's best to not features found only in more modern Perls here, as some cpan
+# distributions copy this file and operate on older Perls.  Similarly keep
+# things simple as this may be run under fairly broken circumstances.  For
+# example, increment ($x++) has a certain amount of cleverness for things like
 #
 #   $x = 'zz';
 #   $x++; # $x eq 'aaa';
 #
-# stands more chance of breaking than just a simple
+# This stands more chance of breaking than just a simple
 #
 #   $x = $x + 1
 #
@@ -53,6 +54,7 @@ sub plan {
        }
     } else {
        my %plan = @_;
+       $plan{skip_all} and skip_all($plan{skip_all});
        $n = $plan{tests};
     }
     _print "1..$n\n" unless $noplan;
@@ -104,6 +106,12 @@ sub is_miniperl {
     return !defined &DynaLoader::boot_DynaLoader;
 }
 
+sub set_up_inc {
+    # Don’t clobber @INC under miniperl
+    @INC = () unless is_miniperl;
+    unshift @INC, @_;
+}
+
 sub _comment {
     return map { /^#/ ? "$_\n" : "# $_\n" }
            map { split /\n/ } @_;
@@ -157,6 +165,13 @@ sub skip_all_without_config {
     }
 }
 
+sub skip_all_without_unicode_tables { # (but only under miniperl)
+    if (is_miniperl()) {
+        skip_all_if_miniperl("Unicode tables not built yet")
+            unless eval 'require "unicore/Heavy.pl"';
+    }
+}
+
 sub find_git_or_skip {
     my ($source_dir, $reason);
     if (-d '.git') {
@@ -176,6 +191,13 @@ sub find_git_or_skip {
            }
            $source_dir = $where;
        }
+    } elsif (exists $ENV{GIT_DIR}) {
+       my $commit = '8d063cd8450e59ea1c611a2f4f5a21059a2804f1';
+       my $out = `git rev-parse --verify --quiet '$commit^{commit}'`;
+       chomp $out;
+       if($out eq $commit) {
+           $source_dir = '.'
+       }
     }
     if ($source_dir) {
        my $version_string = `git --version`;
@@ -274,20 +296,26 @@ sub display {
     foreach my $x (@_) {
         if (defined $x and not ref $x) {
             my $y = '';
-            foreach my $c (unpack("U*", $x)) {
+            foreach my $c (unpack("W*", $x)) {
                 if ($c > 255) {
                     $y = $y . sprintf "\\x{%x}", $c;
                 } elsif ($backslash_escape{$c}) {
                     $y = $y . $backslash_escape{$c};
                 } else {
                     my $z = chr $c; # Maybe we can get away with a literal...
-                    if ($z =~ /[[:^print:]]/) {
 
-                        # Use octal for characters traditionally expressed as
-                        # such: the low controls, which on EBCDIC aren't
-                        # necessarily the same ones as on ASCII platforms, but
-                        # are small ordinals, nonetheless
-                        if ($c <= 037) {
+                    if ($z !~ /[^[:^print:][:^ascii:]]/) {
+                        # The pattern above is equivalent (by de Morgan's
+                        # laws) to:
+                        #     $z !~ /(?[ [:print:] & [:ascii:] ])/
+                        # or, $z is not an ascii printable character
+
+                        # Use octal for characters with small ordinals that
+                        # are traditionally expressed as octal: the controls
+                        # below space, which on EBCDIC are almost all the
+                        # controls, but on ASCII don't include DEL nor the C1
+                        # controls.
+                        if ($c < ord " ") {
                             $z = sprintf "\\%03o", $c;
                         } else {
                             $z = sprintf "\\x{%x}", $c;
@@ -413,6 +441,14 @@ sub unlike ($$@) { like_yn (1,@_) }; # 1 for un-
 
 sub like_yn ($$$@) {
     my ($flip, undef, $expected, $name, @mess) = @_;
+
+    # We just accept like(..., qr/.../), not like(..., '...'), and
+    # definitely not like(..., '/.../') like
+    # Test::Builder::maybe_regex() does.
+    unless (re::is_regexp($expected)) {
+       die "PANIC: The value '$expected' isn't a regexp. The like() function needs a qr// pattern, not a string";
+    }
+
     my $pass;
     $pass = $_[1] =~ /$expected/ if !$flip;
     $pass = $_[1] !~ /$expected/ if $flip;
@@ -448,7 +484,21 @@ sub next_test {
 # be compatible with Test::More::skip().
 sub skip {
     my $why = shift;
-    my $n    = @_ ? shift : 1;
+    my $n   = @_ ? shift : 1;
+    my $bad_swap;
+    my $both_zero;
+    {
+      local $^W = 0;
+      $bad_swap = $why > 0 && $n == 0;
+      $both_zero = $why == 0 && $n == 0;
+    }
+    if ($bad_swap || $both_zero || @_) {
+      my $arg = "'$why', '$n'";
+      if (@_) {
+        $arg .= join(", ", '', map { qq['$_'] } @_);
+      }
+      die qq[$0: expected skip(why, count), got skip($arg)\n];
+    }
     for (1..$n) {
         _print "ok $test # skip $why\n";
         $test = $test + 1;
@@ -462,10 +512,11 @@ sub skip_if_miniperl {
 }
 
 sub skip_without_dynamic_extension {
-    my ($extension) = @_;
-    skip("no dynamic loading on miniperl, no $extension") if is_miniperl();
-    return if &_have_dynamic_extension;
-    skip("$extension was not built");
+    my $extension = shift;
+    skip("no dynamic loading on miniperl, no extension $extension", @_)
+       if is_miniperl();
+    return if &_have_dynamic_extension($extension);
+    skip("extension $extension was not built", @_);
 }
 
 sub todo_skip {
@@ -548,7 +599,7 @@ USE_OK
     }
 }
 
-# runperl - Runs a separate perl interpreter.
+# runperl - Runs a separate perl interpreter and returns its output.
 # Arguments :
 #   switches => [ command-line switches ]
 #   nolib    => 1 # don't use -I../lib (included by default)
@@ -557,7 +608,8 @@ USE_OK
 #   progs    => [ multi-liner (avoid quotes) ]
 #   progfile => perl script
 #   stdin    => string to feed the stdin (or undef to redirect from /dev/null)
-#   stderr   => redirect stderr to stdout
+#   stderr   => If 'devnull' suppresses stderr, if other TRUE value redirect
+#               stderr to stdout
 #   args     => [ command-line arguments to the perl program ]
 #   verbose  => print the command line
 
@@ -600,7 +652,7 @@ sub _create_runperl { # Create the string to qx in runperl().
     if (defined $args{prog}) {
        die "test.pl:runperl(): both 'prog' and 'progs' cannot be used " . _where()
            if defined $args{progs};
-        $args{progs} = [$args{prog}]
+        $args{progs} = [split /\n/, $args{prog}, -1]
     }
     if (defined $args{progs}) {
        die "test.pl:runperl(): 'progs' must be an ARRAYREF " . _where()
@@ -673,7 +725,12 @@ sub _create_runperl { # Create the string to qx in runperl().
     if (defined $args{args}) {
        $runperl = _quote_args($runperl, $args{args});
     }
-    $runperl = $runperl . ' 2>&1' if $args{stderr};
+    if (exists $args{stderr} && $args{stderr} eq 'devnull') {
+        $runperl = $runperl . ($is_mswin ? ' 2>nul' : ' 2>/dev/null');
+    }
+    elsif ($args{stderr}) {
+        $runperl = $runperl . ' 2>&1';
+    }
     if ($args{verbose}) {
        my $runperldisplay = $runperl;
        $runperldisplay =~ s/\n/\n\#/g;
@@ -682,6 +739,7 @@ sub _create_runperl { # Create the string to qx in runperl().
     return $runperl;
 }
 
+# sub run_perl {} is alias to below
 sub runperl {
     die "test.pl:runperl() does not take a hashref"
        if ref $_[0] and ref $_[0] eq 'HASH';
@@ -726,7 +784,7 @@ sub runperl {
     } else {
        $result = `$runperl`;
     }
-    $result =~ s/\n\n/\n/ if $is_vms; # XXX pipes sometimes double these
+    $result =~ s/\n\n/\n/g if $is_vms; # XXX pipes sometimes double these
     return $result;
 }
 
@@ -862,6 +920,28 @@ sub tempfile {
     die "Can't find temporary file name starting \"tmp$$\"";
 }
 
+# register_tempfile - Adds a list of files to be removed at the end of the current test file
+# Arguments :
+#   a list of files to be removed later
+
+# returns a count of how many file names were actually added
+
+# Reuses %tmpfiles so that tempfile() will also skip any files added here
+# even if the file doesn't exist yet.
+
+sub register_tempfile {
+    my $count = 0;
+    for( @_ ){
+       if( $tmpfiles{$_} ){
+           _print_stderr "# Temporary file '$_' already added\n";
+       }else{
+           $tmpfiles{$_} = 1;
+           $count = $count + 1;
+       }
+    }
+    return $count;
+}
+
 # This is the temporary file for _fresh_perl
 my $tmpfile = tempfile();
 
@@ -961,7 +1041,8 @@ sub fresh_perl_like {
 
 # Many tests use the same format in __DATA__ or external files to specify a
 # sequence of (fresh) tests to run, extra files they may temporarily need, and
-# what the expected output is. So have excatly one copy of the code to run that
+# what the expected output is.  Putting it here allows common code to serve
+# these multiple tests.
 #
 # Each program is source code to run followed by an "EXPECT" line, followed
 # by the expected output.
@@ -1370,7 +1451,7 @@ sub class_ok {
     # Written so as to count as one test
     local $Level = $Level + 1;
     if( ref $class ) {
-        ok( 0, "$class is a refrence, not a class name" );
+        ok( 0, "$class is a reference, not a class name" );
     }
     else {
         isa_ok($class, $isa, $class_name);
@@ -1510,7 +1591,7 @@ sub watchdog ($;$)
                 my $sig = $is_vms ? 'TERM' : 'KILL';
                 my $cmd = _create_runperl( prog =>  "sleep($timeout);" .
                                                     "warn qq/# $timeout_msg" . '\n/;' .
-                                                    "kill($sig, $pid_to_kill);");
+                                                    "kill(q/$sig/, $pid_to_kill);");
                 $watchdog = system(1, $cmd);
             };
             if ($@ || ($watchdog <= 0)) {
@@ -1522,8 +1603,14 @@ sub watchdog ($;$)
 
             # Add END block to parent to terminate and
             #   clean up watchdog process
-            eval "END { local \$! = 0; local \$? = 0;
-                        wait() if kill('KILL', $watchdog); };";
+            # Win32 watchdog is launched by cmd.exe shell, so use process group
+            # kill, otherwise the watchdog is never killed and harness waits
+            # every time for the timeout, #121395
+            eval( $is_mswin ?
+            "END { local \$! = 0; local \$? = 0;
+                        wait() if kill('-KILL', $watchdog); };"
+            : "END { local \$! = 0; local \$? = 0;
+                        wait() if kill('KILL', $watchdog); };");
             return;
         }
 
@@ -1610,57 +1697,4 @@ WATCHDOG_VIA_ALARM:
     }
 }
 
-# The following 2 functions allow tests to work on both EBCDIC and
-# ASCII-ish platforms.  They convert string scalars between the native
-# character set and the set of 256 characters which is usually called
-# Latin1.
-
-sub native_to_latin1($) {
-    my $string = shift;
-
-    return $string if ord('^') == 94;   # ASCII, Latin1
-    my $output = "";
-    for my $i (0 .. length($string) - 1) {
-        $output .= chr(ord_native_to_latin1(ord(substr($string, $i, 1))));
-    }
-    # Preserve utf8ness of input onto the output, even if it didn't need to be
-    # utf8
-    utf8::upgrade($output) if utf8::is_utf8($string);
-
-    return $output;
-}
-
-sub latin1_to_native($) {
-    my $string = shift;
-
-    return $string if ord('^') == 94;   # ASCII, Latin1
-    my $output = "";
-    for my $i (0 .. length($string) - 1) {
-        $output .= chr(ord_latin1_to_native(ord(substr($string, $i, 1))));
-    }
-    # Preserve utf8ness of input onto the output, even if it didn't need to be
-    # utf8
-    utf8::upgrade($output) if utf8::is_utf8($string);
-
-    return $output;
-}
-
-sub ord_latin1_to_native {
-    # given an input code point, return the platform's native
-    # equivalent value.  Anything above latin1 is itself.
-
-    my $ord = shift;
-    return $ord if ord('^') == 94;   # ASCII, Latin1
-    return utf8::unicode_to_native($ord);
-}
-
-sub ord_native_to_latin1 {
-    # given an input platform code point, return the latin1 equivalent value.
-    # Anything above latin1 is itself.
-
-    my $ord = shift;
-    return $ord if ord('^') == 94;   # ASCII, Latin1
-    return utf8::native_to_unicode($ord);
-}
-
 1;