$| = 1;
chdir 't' if -d 't';
@INC = '../lib';
+ require './test.pl';
+ plan (tests => 171);
+}
+
+# Test that defined() returns true for magic variables created on the fly,
+# even before they have been created.
+# This must come first, even before turning on warnings or setting up
+# $SIG{__WARN__}, to avoid invalidating the tests. warnings.pm currently
+# does not mention any special variables, but that could easily change.
+BEGIN {
+ # not available in miniperl
+ my %non_mini = map { $_ => 1 } qw(+ - [);
+ for (qw(
+ SIG ^OPEN ^TAINT ^UNICODE ^UTF8LOCALE ^WARNING_BITS 1 2 3 4 5 6 7 8
+ 9 42 & ` ' : ? ! _ - [ ^ ~ = % . ( ) < > \ / $ | + ; ] ^A ^C ^D
+ ^E ^F ^H ^I ^L ^N ^O ^P ^S ^T ^V ^W ^UTF8CACHE ::12345 main::98732
+ )) {
+ my $v = $_;
+ # avoid using any global vars here:
+ if ($v =~ s/^\^(?=.)//) {
+ for(substr $v, 0, 1) {
+ $_ = chr ord() - 64;
+ }
+ }
+ SKIP:
+ {
+ skip_if_miniperl("the module for *$_ may not be available in "
+ . "miniperl", 1) if $non_mini{$_};
+ ok defined *$v, "*$_ appears to be defined at the outset";
+ }
+ }
+}
+
+# This must be in a separate BEGIN block, as the mere mention of ${^TAINT}
+# will invalidate the test for it.
+BEGIN {
$ENV{PATH} = '/bin' if ${^TAINT};
$SIG{__WARN__} = sub { die "Dying on warning: ", @_ };
- require './test.pl';
}
use warnings;
use Config;
-plan (tests => 80);
$Is_MSWin32 = $^O eq 'MSWin32';
$Is_NetWare = $^O eq 'NetWare';
$Is_os2 = $^O eq 'os2';
$Is_Cygwin = $^O eq 'cygwin';
$Is_MPE = $^O eq 'mpeix';
-$Is_miniperl = $ENV{PERL_CORE_MINITEST};
$Is_BeOS = $^O eq 'beos';
$PERL = $ENV{PERL}
$Is_MSWin32 ? '.\perl' :
'./perl');
+sub env_is {
+ my ($key, $val, $desc) = @_;
+ if ($Is_MSWin32) {
+ # cmd.exe will echo 'variable=value' but 4nt will echo just the value
+ # -- Nikola Knezevic
+ like `set $key`, qr/^(?:\Q$key\E=)?\Q$val\E$/, $desc;
+ } elsif ($Is_VMS) {
+ is `write sys\$output f\$trnlnm("\Q$key\E")`, "$val\n", $desc;
+ } else {
+ is `echo \$\Q$key\E`, "$val\n", $desc;
+ }
+}
+
END {
# On VMS, environment variable changes are peristent after perl exits
- delete $ENV{'FOO'} if $Is_VMS;
+ if ($Is_VMS) {
+ delete $ENV{'FOO'};
+ delete $ENV{'__NoNeSuCh'};
+ }
}
eval '$ENV{"FOO"} = "hi there";'; # check that ENV is inited inside eval
elsif ($Is_VMS) { is `write sys\$output f\$trnlnm("FOO")`, "hi there\n"; }
else { is `echo \$FOO`, "hi there\n"; }
-unlink 'ajslkdfpqjsjfk';
+unlink_all 'ajslkdfpqjsjfk';
$! = 0;
open(FOO,'ajslkdfpqjsjfk');
isnt($!, 0);
# We use a pipe rather than system() because the VMS command buffer
# would overflow with a command that long.
+ # For easy interpolation of test numbers:
+ $next_test = curr_test() - 1;
+ sub TIEARRAY {bless[]}
+ sub FETCH { $next_test + pop }
+ tie my @tn, __PACKAGE__;
+
open( CMDPIPE, "| $PERL");
- print CMDPIPE <<'END';
+ print CMDPIPE "\$t1 = $tn[1]; \$t2 = $tn[2];\n", <<'END';
$| = 1; # command buffering
- $SIG{"INT"} = "ok3"; kill "INT",$$; sleep 1;
- $SIG{"INT"} = "IGNORE"; kill "INT",$$; sleep 1; print "ok 4\n";
- $SIG{"INT"} = "DEFAULT"; kill "INT",$$; sleep 1; print "not ok 4\n";
+ $SIG{"INT"} = "ok1"; kill "INT",$$; sleep 1;
+ $SIG{"INT"} = "IGNORE"; kill "INT",$$; sleep 1; print "ok $t2\n";
+ $SIG{"INT"} = "DEFAULT"; kill "INT",$$; sleep 1; print" not ok $t2\n";
- sub ok3 {
+ sub ok1 {
if (($x = pop(@_)) eq "INT") {
- print "ok 3\n";
+ print "ok $t1\n";
}
else {
- print "not ok 3 ($x @_)\n";
+ print "not ok $t1 ($x @_)\n";
}
}
close CMDPIPE;
open( CMDPIPE, "| $PERL");
- print CMDPIPE <<'END';
+ print CMDPIPE "\$t3 = $tn[3];\n", <<'END';
{ package X;
sub DESTROY {
return sub { $x };
}
$| = 1; # command buffering
- $SIG{"INT"} = "ok5";
+ $SIG{"INT"} = "ok3";
{
local $SIG{"INT"}=x();
print ""; # Needed to expose failure in 5.8.0 (why?)
sleep 1;
delete $SIG{"INT"};
kill "INT",$$; sleep 1;
- sub ok5 {
- print "ok 5\n";
+ sub ok3 {
+ print "ok $t3\n";
}
END
close CMDPIPE;
$? >>= 8 if $^O eq 'VMS'; # POSIX status hiding in 2nd byte
my $todo = ($^O eq 'os2' ? ' # TODO: EMX v0.9d_fix4 bug: wrong nibble? ' : '');
- print $? & 0xFF ? "ok 6$todo\n" : "not ok 6$todo\n";
+ print $? & 0xFF ? "ok $tn[4]$todo\n" : "not ok $tn[4]$todo\n";
open(CMDPIPE, "| $PERL");
print CMDPIPE <<'END';
END
close CMDPIPE;
$? >>= 8 if $^O eq 'VMS';
- print $? ? "not ok 7\n" : "ok 7\n";
+ print $? ? "not ok $tn[5]\n" : "ok $tn[5]\n";
curr_test(curr_test() + 5);
}
is $', 'baz';
is $+, 'a';
+# [perl #24237]
+for (qw < ` & ' >) {
+ fresh_perl_is
+ qq < \@$_; q "fff" =~ /(?!^)./; print "[\$$_]\\n" >,
+ "[f]\n", {},
+ "referencing \@$_ before \$$_ etc. still saws off ampersands";
+}
+
# $"
@a = qw(foo bar baz);
is "@a", "foo bar baz";
is $@, "foo\n";
cmp_ok($$, '>', 0);
-eval { $$++ };
-like ($@, qr/^Modification of a read-only value attempted/);
+my $pid = $$;
+eval { $$ = 42 };
+is $$, 42, '$$ can be modified';
+SKIP: {
+ skip "no fork", 1 unless $Config{d_fork};
+ (my $kidpid = open my $fh, "-|") // skip "cannot fork: $!", 1;
+ if($kidpid) { # parent
+ my $kiddollars = <$fh>;
+ close $fh or die "cannot close pipe from kid proc: $!";
+ is $kiddollars, $kidpid, '$$ is reset on fork';
+ }
+ else { # child
+ print $$;
+ $::NO_ENDING = 1; # silence "Looks like you only ran..."
+ exit;
+ }
+}
+$$ = $pid; # Tests below use $$
# $^X and $0
{
+ my $is_abs = $Config{d_procselfexe} || $Config{usekernprocpathname}
+ || $Config{usensgetexecutablepath};
if ($^O eq 'qnx') {
chomp($wd = `/usr/bin/fullpath -t`);
}
- elsif($Is_Cygwin || $Config{'d_procselfexe'}) {
+ elsif($Is_Cygwin || $is_abs) {
# Cygwin turns the symlink into the real file
chomp($wd = `pwd`);
$wd =~ s#/t$##;
else {
$wd = '.';
}
- my $perl = $Is_VMS ? $^X : "$wd/perl";
+ my $perl = $Is_VMS || $is_abs ? $^X : "$wd/perl";
my $headmaybe = '';
my $middlemaybe = '';
my $tailmaybe = '';
$s1 = "\$^X is $perl, \$0 is $script\n";
ok open(SCRIPT, ">$script") or diag "Can't write to $script: $!";
ok print(SCRIPT $headmaybe . <<EOB . $middlemaybe . <<'EOF' . $tailmaybe) or diag $!;
-#!$wd/perl
+#!$perl
EOB
print "\$^X is $^X, \$0 is $0\n";
EOF
$_ = $Is_VMS ? `$perl $script` : `$script`;
s/\.exe//i if $Is_Dos or $Is_Cygwin or $Is_os2;
s{./$script}{$script} if $Is_BeOS; # revert BeOS execvp() side-effect
- s{\bminiperl\b}{perl}; # so that test doesn't fail with miniperl
s{is perl}{is $perl}; # for systems where $^X is only a basename
s{\\}{/}g;
if ($Is_MSWin32 || $Is_os2) {
is $_, $s1;
}
ok unlink($script) or diag $!;
+ # CHECK
+ # Could this be replaced with:
+ # unlink_all($script);
}
# $], $^O, $^T
}
$^O = $orig_osname;
-SKIP: {
- skip("%ENV manipulations fail or aren't safe on $^O", 4)
- if $Is_VMS || $Is_Dos;
+{
+ #RT #72422
+ foreach my $p (0, 1) {
+ fresh_perl_is(<<"EOP", '2 4 8', undef, "test \$^P = $p");
+\$DB::single = 2;
+\$DB::trace = 4;
+\$DB::signal = 8;
+\$^P = $p;
+print "\$DB::single \$DB::trace \$DB::signal";
+EOP
+ }
+}
- SKIP: {
- skip("clearing \%ENV is not safe when running under valgrind")
- if $ENV{PERL_VALGRIND};
+# Check that assigning to $0 on Linux sets the process name with both
+# argv[0] assignment and by calling prctl()
+{
+ SKIP: {
+ skip "We don't have prctl() here", 2 unless $Config{d_prctl_set_name};
+
+ # We don't really need these tests. prctl() is tested in the
+ # Kernel, but test it anyway for our sanity. If something doesn't
+ # work (like if the system doesn't have a ps(1) for whatever
+ # reason) just bail out gracefully.
+ my $maybe_ps = sub {
+ my ($cmd) = @_;
+ local ($?, $!);
+
+ no warnings;
+ my $res = `$cmd`;
+ skip "Couldn't shell out to '$cmd', returned code $?", 2 if $?;
+ return $res;
+ };
- $PATH = $ENV{PATH};
- $PDL = $ENV{PERL_DESTRUCT_LEVEL} || 0;
- $ENV{foo} = "bar";
- %ENV = ();
- $ENV{PATH} = $PATH;
- $ENV{PERL_DESTRUCT_LEVEL} = $PDL || 0;
- if ($Is_MSWin32) {
- is `set foo 2>NUL`, "";
- } else {
- is `echo \$foo`, "\n";
- }
- }
+ my $name = "Good Morning, Dave";
+ $0 = $name;
- $ENV{__NoNeSuCh} = "foo";
- $0 = "bar";
-# cmd.exe will echo 'variable=value' but 4nt will echo just the value
-# -- Nikola Knezevic
- if ($Is_MSWin32) {
- like `set __NoNeSuCh`, qr/^(?:__NoNeSuCh=)?foo$/;
- } else {
- is `echo \$__NoNeSuCh`, "foo\n";
- }
- SKIP: {
- skip("\$0 check only on Linux and FreeBSD", 2)
- unless $^O =~ /^(linux|freebsd)$/
- && open CMDLINE, "/proc/$$/cmdline";
+ chomp(my $argv0 = $maybe_ps->("ps h $$"));
+ chomp(my $prctl = $maybe_ps->("ps hc $$"));
- chomp(my $line = scalar <CMDLINE>);
- my $me = (split /\0/, $line)[0];
- is $me, $0, 'altering $0 is effective (testing with /proc/)';
- close CMDLINE;
- # perlbug #22811
- my $mydollarzero = sub {
- my($arg) = shift;
- $0 = $arg if defined $arg;
- # In FreeBSD the ps -o command= will cause
- # an empty header line, grab only the last line.
- my $ps = (`ps -o command= -p $$`)[-1];
- return if $?;
- chomp $ps;
- printf "# 0[%s]ps[%s]\n", $0, $ps;
- $ps;
- };
- my $ps = $mydollarzero->("x");
- ok(!$ps # we allow that something goes wrong with the ps command
- # In Linux 2.4 we would get an exact match ($ps eq 'x') but
- # in Linux 2.2 there seems to be something funny going on:
- # it seems as if the original length of the argv[] would
- # be stored in the proc struct and then used by ps(1),
- # no matter what characters we use to pad the argv[].
- # (And if we use \0:s, they are shown as spaces.) Sigh.
- || $ps =~ /^x\s*$/
- # FreeBSD cannot get rid of both the leading "perl :"
- # and the trailing " (perl)": some FreeBSD versions
- # can get rid of the first one.
- || ($^O eq 'freebsd' && $ps =~ m/^(?:perl: )?x(?: \(perl\))?$/),
- 'altering $0 is effective (testing with `ps`)');
- }
+ like($argv0, $name, "Set process name through argv[0] ($argv0)");
+ like($prctl, substr($name, 0, 15), "Set process name through prctl() ($prctl)");
+ }
}
{
ok($ok, $warn);
}
-# test case-insignificance of %ENV (these tests must be enabled only
-# when perl is compiled with -DENV_IS_CASELESS)
-SKIP: {
- skip('no caseless %ENV support', 4) unless $Is_MSWin32 || $Is_NetWare;
-
- %ENV = ();
- $ENV{'Foo'} = 'bar';
- $ENV{'fOo'} = 'baz';
- is scalar(keys(%ENV)), 1;
- ok exists $ENV{'FOo'};
- is delete $ENV{'foO'}, 'baz';
- is scalar(keys(%ENV)), 0;
-}
-
SKIP: {
- skip ("miniperl can't rely on loading %Errno", 2) if $Is_miniperl;
+ skip_if_miniperl("miniperl can't rely on loading %Errno", 2);
no warnings 'void';
# Make sure Errno hasn't been prematurely autoloaded
}
SKIP: {
- skip ("miniperl can't rely on loading %Errno") if $Is_miniperl;
+ skip_if_miniperl("miniperl can't rely on loading %Errno", 2);
# Make sure that Errno loading doesn't clobber $!
undef %Errno::;
open(FOO, "nonesuch"); # Generate ENOENT
my %errs = %{"!"}; # Cause Errno.pm to be loaded at run-time
ok ${"!"}{ENOENT};
+
+ # Make sure defined(*{"!"}) before %! does not stop %! from working
+ is
+ runperl(
+ prog => 'BEGIN { defined *{q-!-} } print qq-ok\n- if tied %!',
+ ),
+ "ok\n",
+ 'defined *{"!"} does not stop %! from working';
+}
+
+# Check that we don't auto-load packages
+SKIP: {
+ skip "staticly linked; may be preloaded", 4 unless $Config{usedl};
+ foreach (['powie::!', 'Errno'],
+ ['powie::+', 'Tie::Hash::NamedCapture']) {
+ my ($symbol, $package) = @$_;
+ foreach my $scalar_first ('', '$$symbol;') {
+ my $desc = qq{Referencing %{"$symbol"}};
+ $desc .= qq{ after mentioning \${"$symbol"}} if $scalar_first;
+ $desc .= " doesn't load $package";
+
+ fresh_perl_is(<<"EOP", 0, {}, $desc);
+use strict qw(vars subs);
+my \$symbol = '$symbol';
+$scalar_first;
+1 if %{\$symbol};
+print scalar %${package}::;
+EOP
+ }
+ }
}
is $^S, 0;
ok $ok;
}
-# Test for bug [perl #27839]
-{
- my $x;
- sub f {
- "abc" =~ /(.)./;
- $x = "@+";
- return @+;
- };
- my @y = f();
- is $x, "@y", "return a magic array ($x) vs (@y)";
-}
-
# Test for bug [perl #36434]
# Can not do this test on VMS, EPOC, and SYMBIAN according to comments
# in mg.c/Perl_magic_clear_all_env()
is int $!, 9999, q{[perl #72850] Core dump in bleadperl from perl -e '$! = 9999; $a = $!;'};
}
+
+# %+ %-
+SKIP: {
+ skip_if_miniperl("No XS in miniperl", 2);
+ # Make sure defined(*{"+"}) before %+ does not stop %+ from working
+ is
+ runperl(
+ prog => 'BEGIN { defined *{q-+-} } print qq-ok\n- if tied %+',
+ ),
+ "ok\n",
+ 'defined *{"+"} does not stop %+ from working';
+ is
+ runperl(
+ prog => 'BEGIN { defined *{q=-=} } print qq-ok\n- if tied %-',
+ ),
+ "ok\n",
+ 'defined *{"-"} does not stop %- from working';
+}
+
+SKIP: {
+ skip_if_miniperl("No XS in miniperl", 3);
+
+ for ( [qw( %- Tie::Hash::NamedCapture )], [qw( $[ arybase )],
+ [qw( %! Errno )] ) {
+ my ($var, $mod) = @$_;
+ my $modfile = $mod =~ s|::|/|gr . ".pm";
+ fresh_perl_is
+ qq 'sub UNIVERSAL::AUTOLOAD{}
+ $mod\::foo() if 0;
+ $var;
+ print "ok\\n" if \$INC{"$modfile"}',
+ "ok\n",
+ { switches => [ '-X' ] },
+ "$var still loads $mod when stash and UNIVERSAL::AUTOLOAD exist";
+ }
+}
+
+# ^^^^^^^^^ New tests go here ^^^^^^^^^
+
+SKIP: {
+ skip("%ENV manipulations fail or aren't safe on $^O", 19)
+ if $Is_Dos;
+
+ SKIP: {
+ skip("clearing \%ENV is not safe when running under valgrind or on VMS")
+ if $ENV{PERL_VALGRIND} || $Is_VMS;
+
+ $PATH = $ENV{PATH};
+ $PDL = $ENV{PERL_DESTRUCT_LEVEL} || 0;
+ $ENV{foo} = "bar";
+ %ENV = ();
+ $ENV{PATH} = $PATH;
+ $ENV{PERL_DESTRUCT_LEVEL} = $PDL || 0;
+ if ($Is_MSWin32) {
+ is `set foo 2>NUL`, "";
+ } else {
+ is `echo \$foo`, "\n";
+ }
+ }
+
+ $ENV{__NoNeSuCh} = 'foo';
+ $0 = 'bar';
+ env_is(__NoNeSuCh => 'foo', 'setting $0 does not break %ENV');
+
+ # stringify a glob
+ $ENV{foo} = *TODO;
+ env_is(foo => '*main::TODO', 'ENV store of stringified glob');
+
+ # stringify a ref
+ my $ref = [];
+ $ENV{foo} = $ref;
+ env_is(foo => "$ref", 'ENV store of stringified ref');
+
+ # downgrade utf8 when possible
+ $bytes = "eh zero \x{A0}";
+ utf8::upgrade($chars = $bytes);
+ $forced = $ENV{foo} = $chars;
+ ok(!utf8::is_utf8($forced) && $forced eq $bytes, 'ENV store downgrades utf8 in SV');
+ env_is(foo => $bytes, 'ENV store downgrades utf8 in setenv');
+
+ # warn when downgrading utf8 is not possible
+ $chars = "X-Day \x{1998}";
+ utf8::encode($bytes = $chars);
+ {
+ my $warned = 0;
+ local $SIG{__WARN__} = sub { ++$warned if $_[0] =~ /^Wide character in setenv/; print "# @_" };
+ $forced = $ENV{foo} = $chars;
+ ok($warned == 1, 'ENV store warns about wide characters');
+ }
+ ok(!utf8::is_utf8($forced) && $forced eq $bytes, 'ENV store encodes high utf8 in SV');
+ env_is(foo => $bytes, 'ENV store encodes high utf8 in SV');
+
+ # test local $ENV{foo} on existing foo
+ {
+ local $ENV{__NoNeSuCh};
+ { local $TODO = 'exists on %ENV should reflect real env';
+ ok(!exists $ENV{__NoNeSuCh}, 'not exists $ENV{existing} during local $ENV{existing}'); }
+ env_is(__NoNeLoCaL => '');
+ }
+ ok(exists $ENV{__NoNeSuCh}, 'exists $ENV{existing} after local $ENV{existing}');
+ env_is(__NoNeSuCh => 'foo');
+
+ # test local $ENV{foo} on new foo
+ {
+ local $ENV{__NoNeLoCaL} = 'foo';
+ ok(exists $ENV{__NoNeLoCaL}, 'exists $ENV{new} during local $ENV{new}');
+ env_is(__NoNeLoCaL => 'foo');
+ }
+ ok(!exists $ENV{__NoNeLoCaL}, 'not exists $ENV{new} after local $ENV{new}');
+ env_is(__NoNeLoCaL => '');
+
+ SKIP: {
+ skip("\$0 check only on Linux and FreeBSD", 2)
+ unless $^O =~ /^(linux|freebsd)$/
+ && open CMDLINE, "/proc/$$/cmdline";
+
+ chomp(my $line = scalar <CMDLINE>);
+ my $me = (split /\0/, $line)[0];
+ is $me, $0, 'altering $0 is effective (testing with /proc/)';
+ close CMDLINE;
+ # perlbug #22811
+ my $mydollarzero = sub {
+ my($arg) = shift;
+ $0 = $arg if defined $arg;
+ # In FreeBSD the ps -o command= will cause
+ # an empty header line, grab only the last line.
+ my $ps = (`ps -o command= -p $$`)[-1];
+ return if $?;
+ chomp $ps;
+ printf "# 0[%s]ps[%s]\n", $0, $ps;
+ $ps;
+ };
+ my $ps = $mydollarzero->("x");
+ ok(!$ps # we allow that something goes wrong with the ps command
+ # In Linux 2.4 we would get an exact match ($ps eq 'x') but
+ # in Linux 2.2 there seems to be something funny going on:
+ # it seems as if the original length of the argv[] would
+ # be stored in the proc struct and then used by ps(1),
+ # no matter what characters we use to pad the argv[].
+ # (And if we use \0:s, they are shown as spaces.) Sigh.
+ || $ps =~ /^x\s*$/
+ # FreeBSD cannot get rid of both the leading "perl :"
+ # and the trailing " (perl)": some FreeBSD versions
+ # can get rid of the first one.
+ || ($^O eq 'freebsd' && $ps =~ m/^(?:perl: )?x(?: \(perl\))?$/),
+ 'altering $0 is effective (testing with `ps`)');
+ }
+}
+
+# test case-insignificance of %ENV (these tests must be enabled only
+# when perl is compiled with -DENV_IS_CASELESS)
+SKIP: {
+ skip('no caseless %ENV support', 4) unless $Is_MSWin32 || $Is_NetWare;
+
+ %ENV = ();
+ $ENV{'Foo'} = 'bar';
+ $ENV{'fOo'} = 'baz';
+ is scalar(keys(%ENV)), 1;
+ ok exists $ENV{'FOo'};
+ is delete $ENV{'foO'}, 'baz';
+ is scalar(keys(%ENV)), 0;
+}
+
+__END__
+
+# Put new tests before the various ENV tests, as they blow %ENV away.