summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
authorNick Ing-Simmons <nik@tiuk.ti.com>1999-09-10 20:44:22 +0000
committerNick Ing-Simmons <nik@tiuk.ti.com>1999-09-10 20:44:22 +0000
commit53e9df65959190f4cd34a02fe359bc5e6d2553f6 (patch)
tree0808e1620b6ecdcd9f64c6db1b8f70966efe542e /t
parenta0ed51b321531af4b47cce24205ab9656f043f0f (diff)
parent8a7fc0dc3015c8254ce4e866be71508e3379d45d (diff)
downloadperl-53e9df65959190f4cd34a02fe359bc5e6d2553f6.tar.gz
Get resolve -at mainline
p4raw-id: //depot/utfperl@4126
Diffstat (limited to 't')
-rwxr-xr-xt/TEST21
-rwxr-xr-xt/UTEST3
-rwxr-xr-xt/base/lex.t95
-rwxr-xr-xt/base/rs.t7
-rwxr-xr-xt/base/term.t12
-rwxr-xr-xt/cmd/for.t14
-rwxr-xr-xt/cmd/subval.t9
-rwxr-xr-xt/cmd/while.t21
-rwxr-xr-xt/comp/bproto.t41
-rwxr-xr-xt/comp/colon.t2
-rwxr-xr-xt/comp/cpp.t4
-rwxr-xr-xt/comp/package.t22
-rwxr-xr-xt/comp/proto.t61
-rwxr-xr-xt/comp/require.t30
-rwxr-xr-xt/comp/use.t2
-rw-r--r--t/harness66
-rwxr-xr-xt/io/argv.t21
-rwxr-xr-xt/io/dup.t16
-rwxr-xr-xt/io/fs.t90
-rwxr-xr-xt/io/open.t111
-rwxr-xr-xt/io/openpid.t85
-rwxr-xr-xt/io/pipe.t114
-rwxr-xr-xt/io/tell.t46
-rwxr-xr-xt/lib/abbrev.t2
-rwxr-xr-xt/lib/anydbm.t32
-rw-r--r--t/lib/attrs.t125
-rwxr-xr-xt/lib/autoloader.t25
-rwxr-xr-xt/lib/basename.t2
-rwxr-xr-xt/lib/bigfloat.t408
-rwxr-xr-xt/lib/bigfloatpm.t459
-rwxr-xr-xt/lib/bigint.t2
-rwxr-xr-xt/lib/bigintpm.t116
-rwxr-xr-xt/lib/cgi-form.t10
-rwxr-xr-xt/lib/cgi-function.t2
-rwxr-xr-xt/lib/cgi-html.t37
-rwxr-xr-xt/lib/cgi-request.t19
-rw-r--r--t/lib/charnames.t53
-rwxr-xr-xt/lib/checktree.t2
-rwxr-xr-xt/lib/complex.t20
-rwxr-xr-xt/lib/db-btree.t616
-rwxr-xr-xt/lib/db-hash.t277
-rwxr-xr-xt/lib/db-recno.t418
-rwxr-xr-xt/lib/dirhand.t2
-rwxr-xr-xt/lib/dosglob.t2
-rwxr-xr-xt/lib/dprof.t80
-rw-r--r--t/lib/dprof/V.pm59
-rw-r--r--t/lib/dprof/test1_t18
-rw-r--r--t/lib/dprof/test1_v24
-rw-r--r--t/lib/dprof/test2_t21
-rw-r--r--t/lib/dprof/test2_v36
-rw-r--r--t/lib/dprof/test3_t19
-rw-r--r--t/lib/dprof/test3_v29
-rw-r--r--t/lib/dprof/test4_t24
-rw-r--r--t/lib/dprof/test4_v36
-rw-r--r--t/lib/dprof/test5_t25
-rw-r--r--t/lib/dprof/test5_v15
-rw-r--r--t/lib/dprof/test6_t29
-rw-r--r--t/lib/dprof/test6_v16
-rwxr-xr-xt/lib/dumper-ovl.t2
-rwxr-xr-xt/lib/dumper.t178
-rwxr-xr-xt/lib/english.t2
-rwxr-xr-xt/lib/env.t2
-rwxr-xr-xt/lib/errno.t2
-rwxr-xr-xt/lib/fatal.t28
-rwxr-xr-xt/lib/fields.t18
-rwxr-xr-xt/lib/filecache.t2
-rwxr-xr-xt/lib/filecopy.t2
-rwxr-xr-xt/lib/filefind.t2
-rwxr-xr-xt/lib/filefunc.t17
-rwxr-xr-xt/lib/filehand.t7
-rwxr-xr-xt/lib/filepath.t2
-rwxr-xr-xt/lib/filespec.t2
-rwxr-xr-xt/lib/findbin.t2
-rwxr-xr-xt/lib/gdbm.t192
-rwxr-xr-xt/lib/getopt.t2
-rwxr-xr-xt/lib/gol-basic.t24
-rwxr-xr-xt/lib/gol-compat.t25
-rwxr-xr-xt/lib/gol-linkage.t37
-rw-r--r--t/lib/h2ph.pht4
-rwxr-xr-xt/lib/h2ph.t3
-rwxr-xr-xt/lib/hostname.t2
-rwxr-xr-xt/lib/io_const.t33
-rwxr-xr-xt/lib/io_dir.t66
-rwxr-xr-xt/lib/io_dup.t2
-rwxr-xr-xt/lib/io_linenum.t80
-rw-r--r--t/lib/io_multihomed.t124
-rwxr-xr-xt/lib/io_pipe.t23
-rwxr-xr-xt/lib/io_poll.t72
-rwxr-xr-xt/lib/io_sel.t2
-rwxr-xr-xt/lib/io_sock.t127
-rwxr-xr-xt/lib/io_taint.t2
-rwxr-xr-xt/lib/io_tell.t2
-rwxr-xr-xt/lib/io_udp.t74
-rw-r--r--t/lib/io_unix.t89
-rwxr-xr-xt/lib/io_xs.t2
-rwxr-xr-xt/lib/ipc_sysv.t147
-rwxr-xr-xt/lib/ndbm.t192
-rwxr-xr-xt/lib/odbm.t205
-rwxr-xr-xt/lib/opcode.t2
-rwxr-xr-xt/lib/open2.t2
-rwxr-xr-xt/lib/open3.t18
-rwxr-xr-xt/lib/ops.t2
-rwxr-xr-xt/lib/parsewords.t9
-rwxr-xr-xt/lib/ph.t4
-rwxr-xr-xt/lib/posix.t5
-rwxr-xr-xt/lib/safe1.t2
-rwxr-xr-xt/lib/safe2.t15
-rwxr-xr-xt/lib/sdbm.t204
-rwxr-xr-xt/lib/searchdict.t40
-rwxr-xr-xt/lib/selectsaver.t2
-rwxr-xr-xt/lib/socket.t2
-rwxr-xr-xt/lib/soundex.t2
-rwxr-xr-xt/lib/symbol.t2
-rw-r--r--t/lib/syslfs.t171
-rwxr-xr-xt/lib/textfill.t98
-rwxr-xr-xt/lib/texttabs.t2
-rwxr-xr-xt/lib/textwrap.t139
-rwxr-xr-xt/lib/thread.t22
-rwxr-xr-xt/lib/tie-push.t4
-rwxr-xr-xt/lib/tie-stdarray.t4
-rwxr-xr-xt/lib/tie-stdhandle.t49
-rwxr-xr-xt/lib/tie-stdpush.t4
-rwxr-xr-xt/lib/timelocal.t2
-rwxr-xr-xt/lib/trig.t2
-rw-r--r--t/op/64bit.t182
-rwxr-xr-xt/op/arith.t6
-rwxr-xr-xt/op/array.t7
-rwxr-xr-xt/op/assignwarn.t2
-rw-r--r--t/op/attrs.t176
-rwxr-xr-xt/op/auto.t6
-rwxr-xr-xt/op/avhv.t2
-rwxr-xr-xt/op/bop.t23
-rwxr-xr-xt/op/chars.t74
-rwxr-xr-xt/op/chop.t10
-rwxr-xr-xt/op/closure.t2
-rwxr-xr-xt/op/defins.t3
-rwxr-xr-xt/op/die.t2
-rwxr-xr-xt/op/die_exit.t15
-rwxr-xr-xt/op/each.t20
-rwxr-xr-xt/op/eval.t103
-rwxr-xr-xt/op/exec.t26
-rwxr-xr-xt/op/fh.t26
-rwxr-xr-xt/op/filetest.t71
-rwxr-xr-xt/op/fork.t4
-rwxr-xr-xt/op/goto.t44
-rwxr-xr-xt/op/goto_xs.t2
-rwxr-xr-xt/op/grent.t139
-rwxr-xr-xt/op/grep.t31
-rwxr-xr-xt/op/groups.t106
-rwxr-xr-xt/op/gv.t39
-rwxr-xr-xt/op/hashwarn.t2
-rwxr-xr-xt/op/join.t16
-rwxr-xr-xt/op/lex_assign.t305
-rw-r--r--t/op/lfs.t177
-rwxr-xr-xt/op/list.t12
-rwxr-xr-xt/op/local.t43
-rwxr-xr-xt/op/lop.t44
-rwxr-xr-xt/op/magic.t31
-rwxr-xr-xt/op/method.t43
-rwxr-xr-xt/op/misc.t108
-rwxr-xr-xt/op/mkdir.t12
-rwxr-xr-xt/op/nothread.t4
-rwxr-xr-xt/op/numconvert.t185
-rwxr-xr-xt/op/oct.t63
-rwxr-xr-xt/op/ord.t10
-rwxr-xr-xt/op/pack.t221
-rwxr-xr-xt/op/pat.t290
-rwxr-xr-xt/op/pwent.t137
-rwxr-xr-xt/op/quotemeta.t32
-rwxr-xr-xt/op/rand.t19
-rwxr-xr-xt/op/range.t20
-rw-r--r--t/op/re_tests278
-rwxr-xr-xt/op/readdir.t6
-rwxr-xr-xt/op/ref.t22
-rwxr-xr-xt/op/regexp.t24
-rwxr-xr-xt/op/repeat.t58
-rwxr-xr-xt/op/runlevel.t24
-rwxr-xr-xt/op/sort.t119
-rwxr-xr-xt/op/sprintf.t4
-rwxr-xr-xt/op/stat.t102
-rwxr-xr-xt/op/subst.t86
-rwxr-xr-xt/op/subst_amp.t104
-rwxr-xr-xt/op/subst_wamp.t11
-rwxr-xr-xt/op/sysio.t40
-rwxr-xr-xt/op/taint.t28
-rwxr-xr-xt/op/tie.t59
-rwxr-xr-xt/op/tiearray.t2
-rwxr-xr-xt/op/tiehandle.t20
-rwxr-xr-xt/op/time.t8
-rwxr-xr-xt/op/tr.t39
-rwxr-xr-xt/op/undef.t29
-rwxr-xr-xt/op/universal.t14
-rwxr-xr-xt/op/write.t25
-rwxr-xr-xt/pod/emptycmd.t21
-rw-r--r--t/pod/emptycmd.xr2
-rwxr-xr-xt/pod/for.t59
-rw-r--r--t/pod/for.xr19
-rwxr-xr-xt/pod/headings.t140
-rw-r--r--t/pod/headings.xr29
-rwxr-xr-xt/pod/include.t36
-rw-r--r--t/pod/include.xr23
-rwxr-xr-xt/pod/included.t35
-rw-r--r--t/pod/included.xr3
-rwxr-xr-xt/pod/lref.t66
-rw-r--r--t/pod/lref.xr40
-rwxr-xr-xt/pod/nested_items.t64
-rw-r--r--t/pod/nested_items.xr19
-rwxr-xr-xt/pod/nested_seqs.t23
-rw-r--r--t/pod/nested_seqs.xr3
-rwxr-xr-xt/pod/oneline_cmds.t46
-rw-r--r--t/pod/oneline_cmds.xr29
-rwxr-xr-xt/pod/poderrs.t39
-rw-r--r--t/pod/poderrs.xr11
-rwxr-xr-xt/pod/special_seqs.t32
-rw-r--r--t/pod/special_seqs.xr15
-rw-r--r--t/pod/testcmp.pl90
-rw-r--r--t/pod/testp2pt.pl178
-rw-r--r--t/pod/testpchk.pl129
-rwxr-xr-xt/pragma/constant.t22
-rwxr-xr-xt/pragma/locale.t649
-rw-r--r--t/pragma/locale/latin110
-rw-r--r--t/pragma/locale/utf810
-rwxr-xr-xt/pragma/overload.t487
-rw-r--r--t/pragma/strict-subs22
-rwxr-xr-xt/pragma/strict.t4
-rwxr-xr-xt/pragma/sub_lval.t429
-rwxr-xr-xt/pragma/subs.t7
-rwxr-xr-xt/pragma/utf8.t82
-rw-r--r--t/pragma/warn/1global (renamed from t/pragma/warn-1global)50
-rw-r--r--t/pragma/warn/2use308
-rw-r--r--t/pragma/warn/3both197
-rw-r--r--t/pragma/warn/4lint112
-rw-r--r--t/pragma/warn/5nolint96
-rw-r--r--t/pragma/warn/6default53
-rw-r--r--t/pragma/warn/7fatal242
-rw-r--r--t/pragma/warn/8signal18
-rw-r--r--t/pragma/warn/av9
-rw-r--r--t/pragma/warn/doio191
-rw-r--r--t/pragma/warn/doop25
-rw-r--r--t/pragma/warn/gv54
-rw-r--r--t/pragma/warn/hv8
-rw-r--r--t/pragma/warn/malloc9
-rw-r--r--t/pragma/warn/mg44
-rw-r--r--t/pragma/warn/op810
-rw-r--r--t/pragma/warn/perl57
-rw-r--r--t/pragma/warn/perlio10
-rw-r--r--t/pragma/warn/perly31
-rw-r--r--t/pragma/warn/pp125
-rw-r--r--t/pragma/warn/pp_ctl217
-rw-r--r--t/pragma/warn/pp_hot192
-rw-r--r--t/pragma/warn/pp_sys259
-rw-r--r--t/pragma/warn/regcomp75
-rw-r--r--t/pragma/warn/regexec119
-rw-r--r--t/pragma/warn/run8
-rw-r--r--t/pragma/warn/sv282
-rw-r--r--t/pragma/warn/taint49
-rw-r--r--t/pragma/warn/toke611
-rw-r--r--t/pragma/warn/universal16
-rw-r--r--t/pragma/warn/utf856
-rw-r--r--t/pragma/warn/util108
-rw-r--r--[-rwxr-xr-x]t/pragma/warnings.t (renamed from t/pragma/warning.t)39
261 files changed, 16972 insertions, 938 deletions
diff --git a/t/TEST b/t/TEST
index c1d1905731..1f9190db05 100755
--- a/t/TEST
+++ b/t/TEST
@@ -1,6 +1,6 @@
#!./perl
-# Last change: Fri Jan 10 09:57:03 WET 1997
+# Last change: Fri May 28 03:16:57 BST 1999
# This is written in a peculiar style, since we're trying to avoid
# most of the constructs we'll be testing for.
@@ -43,11 +43,22 @@ TESTING COMPILER
--------------------------------------------------------------------------------
EOT
+ $ENV{PERLCC_TIMEOUT} = 120
+ if ($type eq 'compile' && !$ENV{PERLCC_TIMEOUT});
+
$bad = 0;
$good = 0;
$total = @tests;
$files = 0;
$totmax = 0;
+ $maxlen = 0;
+ foreach (@tests) {
+ $len = length;
+ $maxlen = $len if $len > $maxlen;
+ }
+ # +3 : we want three dots between the test name and the "ok"
+ # -2 : the .t suffix
+ $dotdotdot = $maxlen + 3 - 2;
while ($test = shift @tests) {
if ( $infinite{$test} && $type eq 'compile' ) {
@@ -59,7 +70,7 @@ EOT
}
$te = $test;
chop($te);
- print "$te" . '.' x (18 - length($te));
+ print "$te" . '.' x ($dotdotdot - length($te));
open(SCRIPT,"<$test") or die "Can't run $test.\n";
$_ = <SCRIPT>;
@@ -142,12 +153,12 @@ EOT
}
}
else {
- $pct = sprintf("%.2f", $good / $total * 100);
+ $pct = sprintf("%.2f", ($files - $bad) / $files * 100);
if ($bad == 1) {
- warn "Failed 1 test script out of $total, $pct% okay.\n";
+ warn "Failed 1 test script out of $files, $pct% okay.\n";
}
else {
- warn "Failed $bad test scripts out of $total, $pct% okay.\n";
+ warn "Failed $bad test scripts out of $files, $pct% okay.\n";
}
warn <<'SHRDLU';
### Since not all tests were successful, you may want to run some
diff --git a/t/UTEST b/t/UTEST
index 4fc160d3e5..b5f285bd59 100755
--- a/t/UTEST
+++ b/t/UTEST
@@ -55,6 +55,9 @@ TESTING COMPILER
--------------------------------------------------------------------------------
EOT
+ $ENV{PERLCC_TIMEOUT} = 120
+ if ($type eq 'compile' && !$ENV{PERLCC_TIMEOUT});
+
$bad = 0;
$good = 0;
$total = @tests;
diff --git a/t/base/lex.t b/t/base/lex.t
index 045cb22eb0..d90d404cac 100755
--- a/t/base/lex.t
+++ b/t/base/lex.t
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: lex.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:04 $
-
-print "1..30\n";
+print "1..46\n";
$x = 'x';
@@ -117,3 +115,94 @@ $foo =~ s/^not /substr(<<EOF, 0, 0)/e;
Ignored
EOF
print $foo;
+
+# Tests for new extended control-character variables
+# MJD 19990227
+
+{ my $CX = "\cX";
+ my $CXY ="\cXY";
+ $ {$CX} = 17;
+ $ {$CXY} = 23;
+ if ($ {^XY} != 23) { print "not " }
+ print "ok 31\n";
+
+# Does the syntax where we use the literal control character still work?
+ if (eval "\$ {\cX}" != 17 or $@) { print "not " }
+ print "ok 32\n";
+
+ eval "\$\cN = 24"; # Literal control character
+ if ($@ or ${"\cN"} != 24) { print "not " }
+ print "ok 33\n";
+ if ($^N != 24) { print "not " } # Control character escape sequence
+ print "ok 34\n";
+
+# Does the old UNBRACED syntax still do what it used to?
+ if ("$^XY" ne "17Y") { print "not " }
+ print "ok 35\n";
+
+ sub XX () { 6 }
+ $ {"\cN\cXX"} = 119;
+ $^N = 5; # This should be an unused ^Var.
+ $N = 5;
+ # The second caret here should be interpreted as an xor
+ if (($^N^XX) != 3) { print "not " }
+ print "ok 36\n";
+# if (($N ^ XX()) != 3) { print "not " }
+# print "ok 32\n";
+
+ # These next two tests are trying to make sure that
+ # $^FOO is always global; it doesn't make sense to `my' it.
+ #
+
+ eval 'my $^X;';
+ print "not " unless index ($@, 'Can\'t use global $^X in "my"') > -1;
+ print "ok 37\n";
+# print "($@)\n" if $@;
+
+ eval 'my $ {^XYZ};';
+ print "not " unless index ($@, 'Can\'t use global $^XYZ in "my"') > -1;
+ print "ok 38\n";
+# print "($@)\n" if $@;
+
+# Now let's make sure that caret variables are all forced into the main package.
+ package Someother;
+ $^N = 'Someother';
+ $ {^Nostril} = 'Someother 2';
+ $ {^M} = 'Someother 3';
+ package main;
+ print "not " unless $^N eq 'Someother';
+ print "ok 39\n";
+ print "not " unless $ {^Nostril} eq 'Someother 2';
+ print "ok 40\n";
+ print "not " unless $ {^M} eq 'Someother 3';
+ print "ok 41\n";
+
+
+}
+
+# see if eval '', s///e, and heredocs mix
+
+sub T {
+ my ($where, $num) = @_;
+ my ($p,$f,$l) = caller;
+ print "# $p:$f:$l vs /$where/\nnot " unless "$p:$f:$l" =~ /$where/;
+ print "ok $num\n";
+}
+
+my $test = 42;
+
+{
+# line 42 "plink"
+ local $_ = "not ok ";
+ eval q{
+ s/^not /<<EOT/e and T '^main:\(eval \d+\):2$', $test++;
+# fuggedaboudit
+EOT
+ print $_, $test++, "\n";
+ T('^main:\(eval \d+\):6$', $test++);
+# line 1 "plunk"
+ T('^main:plunk:1$', $test++);
+ };
+ print "# $@\nnot ok $test\n" if $@;
+ T '^main:plink:53$', $test++;
+}
diff --git a/t/base/rs.t b/t/base/rs.t
index 5428603304..021d699e2e 100755
--- a/t/base/rs.t
+++ b/t/base/rs.t
@@ -24,7 +24,7 @@ $bar = <TESTFILE>;
if ($bar eq "12\n") {print "ok 2\n";} else {print "not ok 2\n";}
# Try a non line terminator
-$/ = "3";
+$/ = 3;
$bar = <TESTFILE>;
if ($bar eq "123") {print "ok 3\n";} else {print "not ok 3\n";}
@@ -85,6 +85,7 @@ $bar = <TESTFILE>;
if ($bar eq "78") {print "ok 10\n";} else {print "not ok 10\n";}
# Get rid of the temp file
+close TESTFILE;
unlink "./foo";
# Now for the tricky bit--full record reading
@@ -120,8 +121,8 @@ if ($^O eq 'VMS') {
$bar = <TESTFILE>;
if ($bar eq "z\n") {print "ok 14\n";} else {print "not ok 14\n";}
- unlink "./foo.bar";
- unlink "./foo.com";
+ close TESTFILE;
+ 1 while unlink qw(foo.bar foo.com foo.fdl);
} else {
# Nobody else does this at the moment (well, maybe OS/390, but they can
# put their own tests in) so we just punt
diff --git a/t/base/term.t b/t/base/term.t
index 782ad397d3..638069482f 100755
--- a/t/base/term.t
+++ b/t/base/term.t
@@ -2,12 +2,22 @@
# $RCSfile: term.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:07 $
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+use Config;
+
print "1..7\n";
# check "" interpretation
$x = "\n";
-if ($x eq chr(10)) {print "ok 1\n";} else {print "not ok 1\n";}
+# 10 is ASCII/Iso Latin, 21 is EBCDIC.
+if ($x eq chr(10) ||
+ ($Config{ebcdic} eq 'define' && $x eq chr(21))) {print "ok 1\n";}
+else {print "not ok 1\n";}
# check `` processing
diff --git a/t/cmd/for.t b/t/cmd/for.t
index e45f05040b..d70af579fc 100755
--- a/t/cmd/for.t
+++ b/t/cmd/for.t
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: for.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:09 $
-
-print "1..7\n";
+print "1..10\n";
for ($i = 0; $i <= 10; $i++) {
$x[$i] = $i;
@@ -47,3 +45,13 @@ if ($foo eq '3210abcde') {print "ok 5\n";} else {print "not ok 5 $foo\n";}
foreach $foo (("ok 6\n","ok 7\n")) {
print $foo;
}
+
+sub foo {
+ for $i (1..5) {
+ return $i if $_[0] == $i;
+ }
+}
+
+print foo(1) == 1 ? "ok" : "not ok", " 8\n";
+print foo(2) == 2 ? "ok" : "not ok", " 9\n";
+print foo(5) == 5 ? "ok" : "not ok", " 10\n";
diff --git a/t/cmd/subval.t b/t/cmd/subval.t
index 3c1ffb89ea..3c60690ebf 100755
--- a/t/cmd/subval.t
+++ b/t/cmd/subval.t
@@ -33,7 +33,7 @@ sub foo6 {
'true2' unless $_[0];
}
-print "1..34\n";
+print "1..36\n";
if (&foo1(0) eq '0') {print "ok 1\n";} else {print "not ok 1 $foo\n";}
if (&foo1(1) eq 'true2') {print "ok 2\n";} else {print "not ok 2\n";}
@@ -177,3 +177,10 @@ sub iseof {
eof UNIQ ? print "not ok $main'i\n" : print "ok $main'i\n";
}
}
+
+sub autov { $_[0] = 23 };
+
+my $href = {};
+print keys %$href ? 'not ' : '', "ok 35\n";
+autov($href->{b});
+print join(':', %$href) eq 'b:23' ? '' : 'not ', "ok 36\n";
diff --git a/t/cmd/while.t b/t/cmd/while.t
index c6e464d444..392c13779f 100755
--- a/t/cmd/while.t
+++ b/t/cmd/while.t
@@ -2,7 +2,7 @@
# $RCSfile: while.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:15 $
-print "1..10\n";
+print "1..15\n";
open (tmp,'>Cmd_while.tmp') || die "Can't create Cmd_while.tmp.";
print tmp "tvi925\n";
@@ -109,3 +109,22 @@ $i = 9;
$i++;
}
print "ok $i\n";
+
+# Check curpm is reset when jumping out of a scope
+'abc' =~ /b/;
+WHILE:
+while (1) {
+ $i++;
+ print "#$`,$&,$',\nnot " unless $` . $& . $' eq "abc";
+ print "ok $i\n";
+ { # Localize changes to $` and friends
+ 'end' =~ /end/;
+ redo WHILE if $i == 11;
+ next WHILE if $i == 12;
+ # 13 do a normal loop
+ last WHILE if $i == 14;
+ }
+}
+$i++;
+print "not " unless $` . $& . $' eq "abc";
+print "ok $i\n";
diff --git a/t/comp/bproto.t b/t/comp/bproto.t
new file mode 100755
index 0000000000..699ea57a36
--- /dev/null
+++ b/t/comp/bproto.t
@@ -0,0 +1,41 @@
+#!./perl
+#
+# check if builtins behave as prototyped
+#
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+print "1..7\n";
+
+my $i = 1;
+
+sub foo {}
+my $bar = "bar";
+
+sub test_too_many {
+ eval $_[0];
+ print "not " unless $@ =~ /^Too many arguments/;
+ printf "ok %d\n",$i++;
+}
+
+sub test_no_error {
+ eval $_[0];
+ print "not " if $@;
+ printf "ok %d\n",$i++;
+}
+
+test_too_many($_) for split /\n/,
+q[ defined(&foo, $bar);
+ undef(&foo, $bar);
+ uc($bar,$bar);
+];
+
+test_no_error($_) for split /\n/,
+q[ scalar(&foo,$bar);
+ defined &foo, &foo, &foo;
+ undef &foo, $bar;
+ uc $bar,$bar;
+];
diff --git a/t/comp/colon.t b/t/comp/colon.t
index d2c64fe4c5..dee5330ff2 100755
--- a/t/comp/colon.t
+++ b/t/comp/colon.t
@@ -9,7 +9,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use strict;
diff --git a/t/comp/cpp.t b/t/comp/cpp.t
index 86e7359524..bbff38c553 100755
--- a/t/comp/cpp.t
+++ b/t/comp/cpp.t
@@ -4,14 +4,14 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Config;
if ( $^O eq 'MSWin32' or
($Config{'cppstdin'} =~ /\bcppstdin\b/) and
( ! -x $Config{'binexp'} . "/cppstdin") ) {
- print "1..0\n";
+ print "1..0 # Skip: \$Config{cppstdin} unavailable\n";
exit; # Cannot test till after install, alas.
}
diff --git a/t/comp/package.t b/t/comp/package.t
index cef02c5cb4..4982256db7 100755
--- a/t/comp/package.t
+++ b/t/comp/package.t
@@ -1,6 +1,6 @@
#!./perl
-print "1..7\n";
+print "1..8\n";
$blurfl = 123;
$foo = 3;
@@ -23,7 +23,11 @@ $main = join(':', sort(keys %main::));
$xyz = join(':', sort(keys %xyz::));
$ABC = join(':', sort(keys %ABC::));
-print $xyz eq 'ABC:bar:main:xyz' ? "ok 1\n" : "not ok 1 '$xyz'\n";
+if ('a' lt 'A') {
+ print $xyz eq 'bar:main:xyz:ABC' ? "ok 1\n" : "not ok 1 '$xyz'\n";
+} else {
+ print $xyz eq 'ABC:bar:main:xyz' ? "ok 1\n" : "not ok 1 '$xyz'\n";
+}
print $ABC eq 'blurfl:dyick' ? "ok 2\n" : "not ok 2 '$ABC'\n";
print $main'blurfl == 123 ? "ok 3\n" : "not ok 3\n";
@@ -33,3 +37,17 @@ print $blurfl == 5 ? "ok 4\n" : "not ok 4\n";
eval 'print $blurfl == 5 ? "ok 5\n" : "not ok 5\n";';
eval 'package main; print $blurfl == 123 ? "ok 6\n" : "not ok 6\n";';
print $blurfl == 5 ? "ok 7\n" : "not ok 7\n";
+
+package main;
+
+sub c { caller(0) }
+
+sub foo {
+ my $s = shift;
+ if ($s) {
+ package PQR;
+ main::c();
+ }
+}
+
+print((foo(1))[0] eq 'PQR' ? "ok 8\n" : "not ok 8\n");
diff --git a/t/comp/proto.t b/t/comp/proto.t
index 6a59107ce7..6381facbea 100755
--- a/t/comp/proto.t
+++ b/t/comp/proto.t
@@ -11,12 +11,12 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use strict;
-print "1..82\n";
+print "1..107\n";
my $i = 1;
@@ -384,11 +384,11 @@ print "ok ", $i++, "\n";
print "not " if defined prototype('CORE::system');
print "ok ", $i++, "\n";
-print "# CORE::open => ($p)\nnot " if ($p = prototype('CORE::open')) ne '*;$';
+print "# CORE::open => ($p)\nnot " if ($p = prototype('CORE::open')) ne '*;$;$';
print "ok ", $i++, "\n";
print "# CORE:Foo => ($p), \$@ => `$@'\nnot "
- if defined ($p = eval { prototype('CORE::Foo') or 1 }) or $@ !~ /^Cannot find an opnumber/;
+ if defined ($p = eval { prototype('CORE::Foo') or 1 }) or $@ !~ /^Can't find an opnumber/;
print "ok ", $i++, "\n";
# correctly note too-short parameter lists that don't end with '$',
@@ -413,3 +413,56 @@ sub X::foo4 ($);
*X::foo4 = sub ($) {'ok'};
print "not " unless X->foo4 eq 'ok';
print "ok ", $i++, "\n";
+
+# test if the (*) prototype allows barewords, constants, scalar expressions,
+# globs and globrefs (just as CORE::open() does), all under stricture
+sub star (*&) { &{$_[1]} }
+sub star2 (**&) { &{$_[2]} }
+sub BAR { "quux" }
+sub Bar::BAZ { "quuz" }
+my $star = 'FOO';
+star FOO, sub { print "ok $i\n" if $_[0] eq 'FOO' }; $i++;
+star(FOO, sub { print "ok $i\n" if $_[0] eq 'FOO' }); $i++;
+star "FOO", sub { print "ok $i\n" if $_[0] eq 'FOO' }; $i++;
+star("FOO", sub { print "ok $i\n" if $_[0] eq 'FOO' }); $i++;
+star $star, sub { print "ok $i\n" if $_[0] eq 'FOO' }; $i++;
+star($star, sub { print "ok $i\n" if $_[0] eq 'FOO' }); $i++;
+star *FOO, sub { print "ok $i\n" if $_[0] eq \*FOO }; $i++;
+star(*FOO, sub { print "ok $i\n" if $_[0] eq \*FOO }); $i++;
+star \*FOO, sub { print "ok $i\n" if $_[0] eq \*FOO }; $i++;
+star(\*FOO, sub { print "ok $i\n" if $_[0] eq \*FOO }); $i++;
+star2 FOO, BAR, sub { print "ok $i\n"
+ if $_[0] eq 'FOO' and $_[1] eq 'BAR' }; $i++;
+star2(Bar::BAZ, FOO, sub { print "ok $i\n"
+ if $_[0] eq 'Bar::BAZ' and $_[1] eq 'FOO' }); $i++;
+star2 BAR(), FOO, sub { print "ok $i\n"
+ if $_[0] eq 'quux' and $_[1] eq 'FOO' }; $i++;
+star2(FOO, BAR(), sub { print "ok $i\n"
+ if $_[0] eq 'FOO' and $_[1] eq 'quux' }); $i++;
+star2 "FOO", "BAR", sub { print "ok $i\n"
+ if $_[0] eq 'FOO' and $_[1] eq 'BAR' }; $i++;
+star2("FOO", "BAR", sub { print "ok $i\n"
+ if $_[0] eq 'FOO' and $_[1] eq 'BAR' }); $i++;
+star2 $star, $star, sub { print "ok $i\n"
+ if $_[0] eq 'FOO' and $_[1] eq 'FOO' }; $i++;
+star2($star, $star, sub { print "ok $i\n"
+ if $_[0] eq 'FOO' and $_[1] eq 'FOO' }); $i++;
+star2 *FOO, *BAR, sub { print "ok $i\n"
+ if $_[0] eq \*FOO and $_[1] eq \*BAR }; $i++;
+star2(*FOO, *BAR, sub { print "ok $i\n"
+ if $_[0] eq \*FOO and $_[1] eq \*BAR }); $i++;
+star2 \*FOO, \*BAR, sub { no strict 'refs'; print "ok $i\n"
+ if $_[0] eq \*{'FOO'} and $_[1] eq \*{'BAR'} }; $i++;
+star2(\*FOO, \*BAR, sub { no strict 'refs'; print "ok $i\n"
+ if $_[0] eq \*{'FOO'} and $_[1] eq \*{'BAR'} }); $i++;
+
+# test scalarref prototype
+sub sreftest (\$$) {
+ print "ok $_[1]\n" if ref $_[0];
+}
+{
+ no strict 'vars';
+ sreftest my $sref, $i++;
+ sreftest($helem{$i}, $i++);
+ sreftest $aelem[0], $i++;
+}
diff --git a/t/comp/require.t b/t/comp/require.t
index bae0712dfa..581dcba75c 100755
--- a/t/comp/require.t
+++ b/t/comp/require.t
@@ -2,22 +2,32 @@
BEGIN {
chdir 't' if -d 't';
- @INC = ('.');
+ unshift @INC, ('.', '../lib');
}
# don't make this lexical
$i = 1;
-print "1..3\n";
+print "1..4\n";
sub do_require {
%INC = ();
- open(REQ,">bleah.pm") or die "Can't write 'bleah.pm': $!";
- print REQ @_;
- close REQ;
+ write_file('bleah.pm',@_);
eval { require "bleah.pm" };
my @a; # magic guard for scope violations (must be first lexical in file)
}
+sub write_file {
+ my $f = shift;
+ open(REQ,">$f") or die "Can't write '$f': $!";
+ print REQ @_;
+ close REQ;
+}
+
+# interaction with pod (see the eof)
+write_file('bleah.pm', "print 'ok $i\n'; 1;\n");
+require "bleah.pm";
+$i++;
+
# run-time failure in require
do_require "0;\n";
print "# $@\nnot " unless $@ =~ /did not return a true/;
@@ -25,7 +35,9 @@ print "ok ",$i++,"\n";
# compile-time failure in require
do_require "1)\n";
-print "# $@\nnot " unless $@ =~ /syntax error/;
+# bison says 'parse error' instead of 'syntax error',
+# various yaccs may or may not capitalize 'syntax'.
+print "# $@\nnot " unless $@ =~ /(syntax|parse) error/mi;
print "ok ",$i++,"\n";
# successful require
@@ -33,4 +45,8 @@ do_require "1";
print "# $@\nnot " if $@;
print "ok ",$i++,"\n";
-unlink 'bleah.pm';
+END { 1 while unlink 'bleah.pm'; }
+
+# ***interaction with pod (don't put any thing after here)***
+
+=pod
diff --git a/t/comp/use.t b/t/comp/use.t
index a6ce2a4d56..1099547393 100755
--- a/t/comp/use.t
+++ b/t/comp/use.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..14\n";
diff --git a/t/harness b/t/harness
index f6d94de90f..e1a4dd7861 100644
--- a/t/harness
+++ b/t/harness
@@ -5,29 +5,77 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
- $ENV{PERL5LIB} = '../lib'; # so children will see it too
+ unshift @INC, '../lib';
+ $ENV{PERL5LIB} = '../lib'; # so children will see it too
}
use lib '../lib';
use Test::Harness;
-$Test::Harness::switches = ""; # Too much noise otherwise
+$Test::Harness::switches = ""; # Too much noise otherwise
$Test::Harness::verbose = shift if @ARGV && $ARGV[0] eq '-v';
+#fudge DATA for now.
+%datahandle = qw(
+ lib/bigint.t 1
+ lib/bigintpm.t 1
+ lib/bigfloat.t 1
+ lib/bigfloatpm.t 1
+ op/gv.t 1
+ lib/complex.t 1
+ lib/ph.t 1
+ lib/soundex.t 1
+ op/misc.t 1
+ op/runlevel.t 1
+ op/tie.t 1
+ op/lex_assign.t 1
+ pragma/subs.t 1
+ );
+
+foreach (keys %datahandle) {
+ unlink "$_.t";
+}
+
@tests = @ARGV;
@tests = <base/*.t comp/*.t cmd/*.t io/*.t op/*.t pragma/*.t lib/*.t> unless @tests;
Test::Harness::runtests @tests;
+exit(0) unless -e "../testcompile";
-%infinite = ('comp/require.t', 1, 'op/bop.t', 1, 'lib/hostname.t', 1 );
+%infinite = qw (
+ op/bop.t 1
+ lib/hostname.t 1
+ op/lex_assign.t 1
+ lib/ph.t 1
+ );
+
+my $dhwrapper = <<'EOT';
+open DATA,"<".__FILE__;
+until (($_=<DATA>) =~ /^__END__/) {};
+EOT
@tests = grep (!$infinite{$_}, @tests);
+@tests = map {
+ my $new = $_;
+ if ($datahandle{$_} && !( -f "$new.t") ) {
+ $new .= '.t';
+ local(*F, *T);
+ open(F,"<$_") or die "Can't open $_: $!";
+ open(T,">$new") or die "Can't open $new: $!";
+ print T $dhwrapper, <F>;
+ close F;
+ close T;
+ }
+ $new;
+ } @tests;
+
+print "The tests ", join(' ', keys(%infinite)),
+ " generate infinite loops! Skipping!\n";
-if (-e "../testcompile")
-{
- print "The tests ", join(' ', keys(%infinite)),
- " generate infinite loops! Skipping!\n";
+$ENV{'HARNESS_COMPILE_TEST'} = 1;
+$ENV{'PERLCC_TIMEOUT'} = 120 unless $ENV{'PERLCC_TIMEOUT'};
- $ENV{'COMPILE_TEST'} = 1; Test::Harness::runtests @tests;
+Test::Harness::runtests @tests;
+foreach (keys %datahandle) {
+ unlink "$_.t";
}
diff --git a/t/io/argv.t b/t/io/argv.t
index d99865e142..c6565dc9c7 100755
--- a/t/io/argv.t
+++ b/t/io/argv.t
@@ -1,10 +1,8 @@
#!./perl
-# $RCSfile: argv.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:25 $
+print "1..6\n";
-print "1..5\n";
-
-open(try, '>Io.argv.tmp') || (die "Can't open temp file.");
+open(try, '>Io.argv.tmp') || (die "Can't open temp file: $!");
print try "a line\n";
close try;
@@ -45,4 +43,17 @@ if ($y eq "1a line\n2a line\n3a line\n")
else
{print "not ok 5\n";}
-unlink 'Io.argv.tmp';
+open(try, '>Io.argv.tmp') or die "Can't open temp file: $!";
+close try;
+@ARGV = 'Io.argv.tmp';
+$^I = '.bak';
+$/ = undef;
+while (<>) {
+ s/^/ok 6\n/;
+ print;
+}
+open(try, '<Io.argv.tmp') or die "Can't open temp file: $!";
+print while <try>;
+close try;
+
+END { unlink 'Io.argv.tmp', 'Io.argv.tmp.bak' }
diff --git a/t/io/dup.t b/t/io/dup.t
index f312671e56..9ad823fff7 100755
--- a/t/io/dup.t
+++ b/t/io/dup.t
@@ -2,7 +2,7 @@
# $RCSfile: dup.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:27 $
-print "1..6\n";
+print "1..7\n";
print "ok 1\n";
@@ -37,3 +37,17 @@ else { system 'cat Io.dup' }
unlink 'Io.dup';
print STDOUT "ok 6\n";
+
+# 7 # 19990811 mjd@plover.com
+my ($out1, $out2) = ("Line 1\n", "Line 2\n");
+open(W, "> Io.dup") || die "Can't open stdout";
+print W $out1, $out2;
+close W;
+open(R1, "< Io.dup") || die "Can't read temp file";
+$in1 = <R1>;
+open(R2, "<&R1") || die "Can't dup";
+$in2 = <R2>;
+print "not " unless $in1 eq $out1 && $in2 eq $out2;
+print "ok 7\n";
+
+unlink("Io.dup");
diff --git a/t/io/fs.t b/t/io/fs.t
index eae0158103..087021bb73 100755
--- a/t/io/fs.t
+++ b/t/io/fs.t
@@ -4,63 +4,83 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Config;
-$Is_Dos=$^O eq 'dos';
+$Is_Dosish = ($^O eq 'MSWin32' or $^O eq 'dos' or
+ $^O eq 'os2' or $^O eq 'mint');
-# avoid win32 (for now)
-do { print "1..0\n"; exit(0); } if $^O eq 'MSWin32';
-
-print "1..26\n";
+print "1..28\n";
$wd = (($^O eq 'MSWin32') ? `cd` : `pwd`);
chop($wd);
-if ($^O eq 'MSWin32') { `del tmp`; `mkdir tmp`; }
+if ($^O eq 'MSWin32') { `del tmp 2>nul`; `mkdir tmp`; }
else { `rm -f tmp 2>/dev/null; mkdir tmp 2>/dev/null`; }
chdir './tmp';
`/bin/rm -rf a b c x` if -x '/bin/rm';
umask(022);
-if ((umask(0)&0777) == 022) {print "ok 1\n";} else {print "not ok 1\n";}
+if ($^O eq 'MSWin32') { print "ok 1 # skipped: bogus umask()\n"; }
+elsif ((umask(0)&0777) == 022) {print "ok 1\n";} else {print "not ok 1\n";}
open(fh,'>x') || die "Can't create x";
close(fh);
open(fh,'>a') || die "Can't create a";
close(fh);
-if (eval {link('a','b')} || $Is_Dos) {print "ok 2\n";} else {print "not ok 2\n";}
+if ($Is_Dosish) {print "ok 2 # skipped: no link\n";}
+elsif (eval {link('a','b')}) {print "ok 2\n";}
+else {print "not ok 2\n";}
-if (eval {link('b','c')} || $Is_Dos) {print "ok 3\n";} else {print "not ok 3\n";}
+if ($Is_Dosish) {print "ok 3 # skipped: no link\n";}
+elsif (eval {link('b','c')}) {print "ok 3\n";}
+else {print "not ok 3\n";}
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks) = stat('c');
-if ($Config{dont_use_nlink} || $nlink == 3 || $Is_Dos)
- {print "ok 4\n";} else {print "not ok 4\n";}
+if ($Config{dont_use_nlink} || $Is_Dosish)
+ {print "ok 4 # skipped: no link\n";}
+elsif ($nlink == 3)
+ {print "ok 4\n";}
+else {print "not ok 4\n";}
-if (($mode & 0777) == 0666 || $^O eq 'amigaos' || $Is_Dos)
- {print "ok 5\n";} else {print "not ok 5\n";}
+if ($^O eq 'amigaos' || $Is_Dosish)
+ {print "ok 5 # skipped: no link\n";}
+elsif (($mode & 0777) == 0666)
+ {print "ok 5\n";}
+else {print "not ok 5\n";}
if ((chmod 0777,'a') == 1) {print "ok 6\n";} else {print "not ok 6\n";}
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks) = stat('c');
-if (($mode & 0777) == 0777 || $Is_Dos) {print "ok 7\n";} else {print "not ok 7\n";}
+if ($Is_Dosish) {print "ok 7 # skipped: no link\n";}
+elsif (($mode & 0777) == 0777) {print "ok 7\n";}
+else {print "not ok 7\n";}
-if ((chmod 0700,'c','x') == 2 || $Is_Dos) {print "ok 8\n";} else {print "not ok 8\n";}
+if ($Is_Dosish) {print "ok 8 # skipped: no link\n";}
+elsif ((chmod 0700,'c','x') == 2) {print "ok 8\n";}
+else {print "not ok 8\n";}
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks) = stat('c');
-if (($mode & 0777) == 0700 || $Is_Dos) {print "ok 9\n";} else {print "not ok 9\n";}
+if ($Is_Dosish) {print "ok 9 # skipped: no link\n";}
+elsif (($mode & 0777) == 0700) {print "ok 9\n";}
+else {print "not ok 9\n";}
+
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks) = stat('x');
-if (($mode & 0777) == 0700 || $Is_Dos) {print "ok 10\n";} else {print "not ok 10\n";}
+if ($Is_Dosish) {print "ok 10 # skipped: no link\n";}
+elsif (($mode & 0777) == 0700) {print "ok 10\n";}
+else {print "not ok 10\n";}
-if ((unlink 'b','x') == 2 || $Is_Dos) {print "ok 11\n";} else {print "not ok 11\n";}
+if ($Is_Dosish) {print "ok 11 # skipped: no link\n"; unlink 'b','x'; }
+elsif ((unlink 'b','x') == 2) {print "ok 11\n";}
+else {print "not ok 11\n";}
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks) = stat('b');
if ($ino == 0) {print "ok 12\n";} else {print "not ok 12\n";}
@@ -72,13 +92,16 @@ if (rename('a','b')) {print "ok 14\n";} else {print "not ok 14\n";}
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks) = stat('a');
if ($ino == 0) {print "ok 15\n";} else {print "not ok 15\n";}
-$foo = (utime 500000000,500000001,'b');
+$delta = $Is_Dosish ? 2 : 1; # Granularity of time on the filesystem
+$foo = (utime 500000000,500000000 + $delta,'b');
if ($foo == 1) {print "ok 16\n";} else {print "not ok 16 $foo\n";}
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks) = stat('b');
-if ($ino) {print "ok 17\n";} else {print "not ok 17\n";}
-if (($atime == 500000000 && $mtime == 500000001)
- || $wd =~ m#/afs/# || $^O eq 'amigaos' || $Is_Dos)
+if ($^O eq 'MSWin32') { print "ok 17 # skipped: bogus (stat)[1]\n"; }
+elsif ($ino) {print "ok 17\n";} else {print "not ok 17\n";}
+if ($wd =~ m#/afs/# || $^O eq 'amigaos' || $^O eq 'dos' || $^O eq 'MSWin32')
+ {print "ok 18 # skipped: granularity of the filetime\n";}
+elsif ($atime == 500000000 && $mtime == 500000000 + $delta)
{print "ok 18\n";}
else
{print "not ok 18 $atime $mtime\n";}
@@ -90,7 +113,6 @@ if ($ino == 0) {print "ok 20\n";} else {print "not ok 20\n";}
unlink 'c';
chdir $wd || die "Can't cd back to $wd";
-rmdir 'tmp';
unlink 'c';
if ($^O ne 'MSWin32' and `ls -l perl 2>/dev/null` =~ /^l.*->/) {
@@ -120,17 +142,27 @@ else {
if (-z "Iofs.tmp") {print "ok 24\n"} else {print "not ok 24\n"}
open(FH, ">Iofs.tmp") or die "Can't create Iofs.tmp";
{ select FH; $| = 1; select STDOUT }
- print FH "helloworld\n";
- truncate FH, 5;
- if ($Is_Dos) {
+ {
+ use strict;
+ print FH "helloworld\n";
+ truncate FH, 5;
+ }
+ if ($^O eq 'dos') {
close (FH); open (FH, ">>Iofs.tmp") or die "Can't reopen Iofs.tmp";
}
if (-s "Iofs.tmp" == 5) {print "ok 25\n"} else {print "not ok 25\n"}
truncate FH, 0;
- if ($Is_Dos) {
+ if ($^O eq 'dos') {
close (FH); open (FH, ">>Iofs.tmp") or die "Can't reopen Iofs.tmp";
}
if (-z "Iofs.tmp") {print "ok 26\n"} else {print "not ok 26\n"}
close FH;
}
-unlink "Iofs.tmp";
+
+# check if rename() works on directories
+rename 'tmp', 'tmp1' or print "not ";
+print "ok 27\n";
+-d 'tmp1' or print "not ";
+print "ok 28\n";
+
+END { rmdir 'tmp1'; unlink "Iofs.tmp"; }
diff --git a/t/io/open.t b/t/io/open.t
new file mode 100755
index 0000000000..12d32f474c
--- /dev/null
+++ b/t/io/open.t
@@ -0,0 +1,111 @@
+#!./perl
+
+# $RCSfile$
+$| = 1;
+$^W = 1;
+
+print "1..32\n";
+
+# my $file tests
+
+{
+unlink("afile") if -f "afile";
+print "$!\nnot " unless open(my $f,"+>afile");
+print "ok 1\n";
+binmode $f;
+print "not " unless -f "afile";
+print "ok 2\n";
+print "not " unless print $f "SomeData\n";
+print "ok 3\n";
+print "not " unless tell($f) == 9;
+print "ok 4\n";
+print "not " unless seek($f,0,0);
+print "ok 5\n";
+$b = <$f>;
+print "not " unless $b eq "SomeData\n";
+print "ok 6\n";
+print "not " unless -f $f;
+print "ok 7\n";
+eval { die "Message" };
+# warn $@;
+print "not " unless $@ =~ /<\$f> line 1/;
+print "ok 8\n";
+print "not " unless close($f);
+print "ok 9\n";
+unlink("afile");
+}
+{
+print "# \$!='$!'\nnot " unless open(my $f,'>', 'afile');
+print "ok 10\n";
+print $f "a row\n";
+print "not " unless close($f);
+print "ok 11\n";
+print "not " unless -s 'afile' < 10;
+print "ok 12\n";
+}
+{
+print "# \$!='$!'\nnot " unless open(my $f,'>>', 'afile');
+print "ok 13\n";
+print $f "a row\n";
+print "not " unless close($f);
+print "ok 14\n";
+print "not " unless -s 'afile' > 10;
+print "ok 15\n";
+}
+{
+print "# \$!='$!'\nnot " unless open(my $f, '<', 'afile');
+print "ok 16\n";
+@rows = <$f>;
+print "not " unless @rows == 2;
+print "ok 17\n";
+print "not " unless close($f);
+print "ok 18\n";
+}
+{
+print "not " unless -s 'afile' < 20;
+print "ok 19\n";
+print "# \$!='$!'\nnot " unless open(my $f, '+<', 'afile');
+print "ok 20\n";
+@rows = <$f>;
+print "not " unless @rows == 2;
+print "ok 21\n";
+seek $f, 0, 1;
+print $f "yet another row\n";
+print "not " unless close($f);
+print "ok 22\n";
+print "not " unless -s 'afile' > 20;
+print "ok 23\n";
+
+unlink("afile");
+}
+{
+print "# \$!='$!'\nnot " unless open(my $f, '-|', <<'EOC');
+./perl -e "print qq(a row\n); print qq(another row\n)"
+EOC
+print "ok 24\n";
+@rows = <$f>;
+print "not " unless @rows == 2;
+print "ok 25\n";
+print "not " unless close($f);
+print "ok 26\n";
+}
+{
+print "# \$!='$!'\nnot " unless open(my $f, '|-', <<'EOC');
+./perl -pe "s/^not //"
+EOC
+print "ok 27\n";
+@rows = <$f>;
+print $f "not ok 28\n";
+print $f "not ok 29\n";
+print "#\nnot " unless close($f);
+sleep 1;
+print "ok 30\n";
+}
+
+eval <<'EOE' and print "not ";
+open my $f, '<&', 'afile';
+1;
+EOE
+print "ok 31\n";
+$@ =~ /Unknown open\(\) mode \'<&\'/ or print "not ";
+print "ok 32\n";
diff --git a/t/io/openpid.t b/t/io/openpid.t
new file mode 100755
index 0000000000..0e8b934e51
--- /dev/null
+++ b/t/io/openpid.t
@@ -0,0 +1,85 @@
+#!./perl
+
+#####################################################################
+#
+# Test for process id return value from open
+# Ronald Schmidt (The Software Path) RonaldWS@software-path.com
+#
+#####################################################################
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+ if ($^O eq 'dos') {
+ print "1..0 # Skip: no multitasking\n";
+ exit 0;
+ }
+}
+
+
+use FileHandle;
+use Config;
+autoflush STDOUT 1;
+$SIG{PIPE} = 'IGNORE';
+
+print "1..10\n";
+
+$perl = "$^X -I../lib";
+
+#
+# commands run 4 perl programs. Two of these programs write a
+# short message to STDOUT and exit. Two of these programs
+# read from STDIN. One reader never exits and must be killed.
+# the other reader reads one line, waits a few seconds and then
+# exits to test the waitpid function.
+#
+$cmd1 = qq/$perl -e "use FileHandle; autoflush STDOUT 1; / .
+ qq/print qq[first process\\n]; sleep 30;"/;
+$cmd2 = qq/$perl -e "use FileHandle; autoflush STDOUT 1; / .
+ qq/print qq[second process\\n]; sleep 30;"/;
+$cmd3 = qq/$perl -e "print <>;"/; # hangs waiting for end of STDIN
+$cmd4 = qq/$perl -e "print scalar <>;"/;
+
+#warn "#$cmd1\n#$cmd2\n#$cmd3\n#$cmd4\n";
+
+# start the processes
+$pid1 = open(FH1, "$cmd1 |") or print "not ";
+print "ok 1\n";
+$pid2 = open(FH2, "$cmd2 |") or print "not ";
+print "ok 2\n";
+$pid3 = open(FH3, "| $cmd3") or print "not ";
+print "ok 3\n";
+$pid4 = open(FH4, "| $cmd4") or print "not ";
+print "ok 4\n";
+
+print "# pids were $pid1, $pid2, $pid3, $pid4\n";
+
+my $killsig = 'HUP';
+$killsig = 1 unless $Config{sig_name} =~ /\bHUP\b/;
+
+# get message from first process and kill it
+chomp($from_pid1 = scalar(<FH1>));
+print "# child1 returned [$from_pid1]\nnot "
+ unless $from_pid1 eq 'first process';
+print "ok 5\n";
+$kill_cnt = kill $killsig, $pid1;
+print "not " unless $kill_cnt == 1;
+print "ok 6\n";
+
+# get message from second process and kill second process and reader process
+chomp($from_pid2 = scalar(<FH2>));
+print "# child2 returned [$from_pid2]\nnot "
+ unless $from_pid2 eq 'second process';
+print "ok 7\n";
+$kill_cnt = kill $killsig, $pid2, $pid3;
+print "not " unless $kill_cnt == 2;
+print "ok 8\n";
+
+# send one expected line of text to child process and then wait for it
+autoflush FH4 1;
+print FH4 "ok 9\n";
+print "# waiting for process $pid4 to exit\n";
+$reap_pid = waitpid $pid4, 0;
+print "# reaped pid $reap_pid != $pid4\nnot "
+ unless $reap_pid == $pid4;
+print "ok 10\n";
diff --git a/t/io/pipe.t b/t/io/pipe.t
index ba7a9b093b..826cf7434a 100755
--- a/t/io/pipe.t
+++ b/t/io/pipe.t
@@ -1,57 +1,65 @@
#!./perl
-# $RCSfile: pipe.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:31 $
-
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
unless ($Config{'d_fork'}) {
- print "1..0\n";
+ print "1..0 # Skip: no fork\n";
exit 0;
}
}
$| = 1;
-print "1..12\n";
+print "1..15\n";
+# External program 'tr' assumed.
open(PIPE, "|-") || (exec 'tr', 'YX', 'ko');
print PIPE "Xk 1\n";
print PIPE "oY 2\n";
close PIPE;
-if (open(PIPE, "-|")) {
- while(<PIPE>) {
- s/^not //;
- print;
+if ($^O eq 'vmesa') {
+ # Doesn't work, yet.
+ for (3..6) {
+ print "ok $_ # skipped\n";
+ }
+} else {
+ if (open(PIPE, "-|")) {
+ while(<PIPE>) {
+ s/^not //;
+ print;
+ }
+ close PIPE; # avoid zombies which disrupt test 12
+ }
+ else {
+ # External program 'echo' assumed.
+ print STDOUT "not ok 3\n";
+ exec 'echo', 'not ok 4';
}
- close PIPE; # avoid zombies which disrupt test 12
-}
-else {
- print STDOUT "not ok 3\n";
- exec 'echo', 'not ok 4';
-}
-pipe(READER,WRITER) || die "Can't open pipe";
+ pipe(READER,WRITER) || die "Can't open pipe";
-if ($pid = fork) {
- close WRITER;
- while(<READER>) {
- s/^not //;
- y/A-Z/a-z/;
- print;
+ if ($pid = fork) {
+ close WRITER;
+ while(<READER>) {
+ s/^not //;
+ y/A-Z/a-z/;
+ print;
+ }
+ close READER; # avoid zombies which disrupt test 12
+ }
+ else {
+ die "Couldn't fork" unless defined $pid;
+ close READER;
+ print WRITER "not ok 5\n";
+ open(STDOUT,">&WRITER") || die "Can't dup WRITER to STDOUT";
+ close WRITER;
+ # External program 'echo' assumed.
+ exec 'echo', 'not ok 6';
}
- close READER; # avoid zombies which disrupt test 12
-}
-else {
- die "Couldn't fork" unless defined $pid;
- close READER;
- print WRITER "not ok 5\n";
- open(STDOUT,">&WRITER") || die "Can't dup WRITER to STDOUT";
- close WRITER;
- exec 'echo', 'not ok 6';
}
-
+wait; # Collect from $pid
pipe(READER,WRITER) || die "Can't open pipe";
close READER;
@@ -72,19 +80,20 @@ print "ok 8\n";
# STDOUT. Someone should modify tests #9 to #12 to work with VMS.
if ($^O eq 'VMS') {
- print "ok 9\n";
- print "ok 10\n";
- print "ok 11\n";
- print "ok 12\n";
+ print "ok 9 # skipped\n";
+ print "ok 10 # skipped\n";
+ print "ok 11 # skipped\n";
+ print "ok 12 # skipped\n";
exit;
}
-if ($Config{d_sfio} || $^O eq machten || $^O eq beos) {
+if ($Config{d_sfio} || $^O eq 'machten' || $^O eq 'beos' || $^O eq 'posix-bc') {
# Sfio doesn't report failure when closing a broken pipe
# that has pending output. Go figure. MachTen doesn't either,
# but won't write to broken pipes, so nothing's pending at close.
# BeOS will not write to broken pipes, either.
- print "ok 9\n";
+ # Nor does POSIX-BC.
+ print "ok 9 # skipped\n";
}
else {
local $SIG{PIPE} = 'IGNORE';
@@ -99,6 +108,14 @@ else {
}
}
+if ($^O eq 'vmesa') {
+ # These don't work, yet.
+ print "ok 10 # skipped\n";
+ print "ok 11 # skipped\n";
+ print "ok 12 # skipped\n";
+ exit;
+}
+
# check that errno gets forced to 0 if the piped program exited non-zero
open NIL, '|exit 23;' or die "fork failed: $!";
$! = 1;
@@ -116,7 +133,6 @@ else {
}
# check that status for the correct process is collected
-wait; # Collect from $pid
my $zombie = fork or exit 37;
my $pipe = open *FH, "sleep 2;exit 13|" or die "Open: $!\n";
$SIG{ALRM} = sub { return };
@@ -133,3 +149,23 @@ if ($? == 37*256 && $wait == $zombie && ! $!) {
} else {
print "not ok 12\n# pid=$wait first=$pid pipe=$pipe zombie=$zombie me=$$ \$?=$? \$!=", $!+0, ":$!\n";
}
+
+# Test new semantics for missing command in piped open
+# 19990114 M-J. Dominus mjd@plover.com
+{ local *P;
+ print (((open P, "| " ) ? "not " : ""), "ok 13\n");
+ print (((open P, " |" ) ? "not " : ""), "ok 14\n");
+}
+
+# check that status is unaffected by implicit close
+{
+ local(*NIL);
+ open NIL, '|exit 23;' or die "fork failed: $!";
+ $? = 42;
+ # NIL implicitly closed here
+}
+if ($? != 42) {
+ print "# status $?, expected 42\nnot ";
+}
+print "ok 15\n";
+$? = 0;
diff --git a/t/io/tell.t b/t/io/tell.t
index 83904e88bb..31287e1d19 100755
--- a/t/io/tell.t
+++ b/t/io/tell.t
@@ -1,13 +1,16 @@
#!./perl
-# $RCSfile: tell.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:33 $
+# $RCSfile: tell.t,v $$Revision$$Date$
-print "1..13\n";
+print "1..21\n";
$TST = 'tst';
+$Is_Dosish = ($^O eq 'MSWin32' or $^O eq 'dos' or
+ $^O eq 'os2' or $^O eq 'mint');
+
open($TST, '../Configure') || (die "Can't open ../Configure");
-binmode $TST if $^O eq 'MSWin32';
+binmode $TST if $Is_Dosish;
if (eof(tst)) { print "not ok 1\n"; } else { print "ok 1\n"; }
$firstline = <$TST>;
@@ -42,3 +45,40 @@ if (seek(tst,0,2)) { print "ok 11\n"; } else { print "not ok 11\n"; }
if ($lastpos == tell) { print "ok 12\n"; } else { print "not ok 12\n"; }
unless (eof) { print "not ok 13\n"; } else { print "ok 13\n"; }
+
+if ($. == 0) { print "not ok 14\n"; } else { print "ok 14\n"; }
+
+$curline = $.;
+open(other, '../Configure') || (die "Can't open ../Configure");
+binmode other if $^O eq 'MSWin32';
+
+{
+ local($.);
+
+ if ($. == 0) { print "not ok 15\n"; } else { print "ok 15\n"; }
+
+ tell other;
+ if ($. == 0) { print "ok 16\n"; } else { print "not ok 16\n"; }
+
+ $. = 5;
+ scalar <other>;
+ if ($. == 6) { print "ok 17\n"; } else { print "not ok 17\n"; }
+}
+
+if ($. == $curline) { print "ok 18\n"; } else { print "not ok 18\n"; }
+
+{
+ local($.);
+
+ scalar <other>;
+ if ($. == 7) { print "ok 19\n"; } else { print "not ok 19\n"; }
+}
+
+if ($. == $curline) { print "ok 20\n"; } else { print "not ok 20\n"; }
+
+{
+ local($.);
+
+ tell other;
+ if ($. == 7) { print "ok 21\n"; } else { print "not ok 21\n"; }
+}
diff --git a/t/lib/abbrev.t b/t/lib/abbrev.t
index fb5a9841eb..05e5c70cac 100755
--- a/t/lib/abbrev.t
+++ b/t/lib/abbrev.t
@@ -4,7 +4,7 @@ print "1..7\n";
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Text::Abbrev;
diff --git a/t/lib/anydbm.t b/t/lib/anydbm.t
index 0391b7b490..9efe5e9f3e 100755
--- a/t/lib/anydbm.t
+++ b/t/lib/anydbm.t
@@ -4,7 +4,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
require AnyDBM_File;
#If Fcntl is not available, try 0x202 or 0x102 for O_RDWR|O_CREAT
@@ -12,6 +12,9 @@ use Fcntl;
print "1..12\n";
+$Is_Dosish = ($^O eq 'amigaos' || $^O eq 'MSWin32' or $^O eq 'dos' or
+ $^O eq 'os2' or $^O eq 'mint');
+
unlink <Op_dbmx*>;
umask(0);
@@ -22,7 +25,7 @@ $Dfile = "Op_dbmx.pag";
if (! -e $Dfile) {
($Dfile) = <Op_dbmx*>;
}
-if ($^O eq 'amigaos' || $^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'dos') {
+if ($Is_Dosish) {
print "ok 2 # Skipped: different file permission semantics\n";
}
else {
@@ -115,7 +118,30 @@ print ($size > 0 ? "ok 9\n" : "not ok 9\n");
print join(':',200..400) eq join(':',@foo) ? "ok 10\n" : "not ok 10\n";
print ($h{'foo'} eq '' ? "ok 11\n" : "not ok 11\n");
-print ($h{''} eq 'bar' ? "ok 12\n" : "not ok 12\n");
+if ($h{''} eq 'bar') {
+ print "ok 12\n" ;
+}
+else {
+ print "not ok 12\n" ;
+ if ($AnyDBM_File::ISA[0] eq 'DB_File' && $DB_File::db_ver >= 2.004010) {
+ ($major, $minor, $patch) = ($DB_File::db_ver =~ /^(\d+)\.(\d\d\d)(\d\d\d)/) ;
+ $major =~ s/^0+// ;
+ $minor =~ s/^0+// ;
+ $patch =~ s/^0+// ;
+ $compact = "$major.$minor.$patch" ;
+
+ print STDERR <<EOM ;
+#
+# anydbm.t test 12 will fail when AnyDBM_File uses the combination of
+# DB_File and Berkeley DB 2.4.10 (or greater).
+# You are using DB_File $DB_File::VERSION and Berkeley DB $compact
+#
+# Berkeley DB 2 from version 2.4.10 onwards does not allow null keys.
+# This feature will be reenabled in a future version of Berkeley DB.
+#
+EOM
+ }
+}
untie %h;
if ($^O eq 'VMS') {
diff --git a/t/lib/attrs.t b/t/lib/attrs.t
new file mode 100644
index 0000000000..d8afbf635a
--- /dev/null
+++ b/t/lib/attrs.t
@@ -0,0 +1,125 @@
+#!./perl
+
+# Regression tests for attrs.pm and the C<sub x : attrs> syntax.
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+ eval 'require attrs; 1' or do {
+ print "1..0\n";
+ exit 0;
+ }
+}
+
+sub NTESTS () ;
+
+my $test, $ntests;
+BEGIN {$ntests=0}
+$test=0;
+my $failed = 0;
+
+print "1..".NTESTS."\n";
+
+eval 'sub t1 ($) { use attrs "locked"; $_[0]++ }';
+(print "not "), $failed=1 if $@;
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+eval 'sub t2 { use attrs "locked"; $_[0]++ }';
+(print "not "), $failed=1 if $@;
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+eval 'sub t3 ($) : locked ;';
+(print "not "), $failed=1 if $@;
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+eval 'sub t4 : locked ;';
+(print "not "), $failed=1 if $@;
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+my $anon1;
+eval '$anon1 = sub ($) { use attrs qw(locked method); $_[0]++ }';
+(print "not "), $failed=1 if $@;
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+my $anon2;
+eval '$anon2 = sub { use attrs qw(locked method); $_[0]++ }';
+(print "not "), $failed=1 if $@;
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+my $anon3;
+eval '$anon3 = sub { use attrs "method"; $_[0]->[1] }';
+(print "not "), $failed=1 if $@;
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+my @attrs = attrs::get($anon3 ? $anon3 : \&ns);
+(print "not "), $failed=1 unless "@attrs" eq "method";
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+@attrs = sort +attrs::get($anon2 ? $anon2 : \&ns);
+(print "not "), $failed=1 unless "@attrs" eq "locked method";
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+@attrs = sort +attrs::get($anon1 ? $anon1 : \&ns);
+(print "not "), $failed=1 unless "@attrs" eq "locked method";
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+eval 'sub e1 ($) : plugh ;';
+unless ($@ && $@ =~ m/^Invalid CODE attribute: ["']?plugh["']? at/) {
+ my $x = $@;
+ $x =~ s/\n.*\z//s;
+ print "# $x\n";
+ print "not ";
+ $failed = 1;
+}
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+eval 'sub e2 ($) : plugh(0,0) xyzzy ;';
+unless ($@ && $@ =~ m/^Invalid CODE attributes: ["']?plugh\(0,0\)["']? /) {
+ my $x = $@;
+ $x =~ s/\n.*\z//s;
+ print "# $x\n";
+ print "not ";
+ $failed = 1;
+}
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+eval 'sub e3 ($) : plugh(0,0 xyzzy ;';
+unless ($@ && $@ =~ m/Unterminated attribute parameter in attribute list at/) {
+ my $x = $@;
+ $x =~ s/\n.*\z//s;
+ print "# $x\n";
+ print "not ";
+ $failed = 1;
+}
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+eval 'sub e4 ($) : plugh + xyzzy ;';
+unless ($@ && $@ =~ m/Invalid separator character '[+]' in attribute list at/) {
+ my $x = $@;
+ $x =~ s/\n.*\z//s;
+ print "# $x\n";
+ print "not ";
+ $failed = 1;
+}
+print "ok ",++$test,"\n";
+BEGIN {++$ntests}
+
+
+# Other tests should be added above this line
+
+sub NTESTS () { $ntests }
+
+exit $failed;
diff --git a/t/lib/autoloader.t b/t/lib/autoloader.t
index b1622a8ae2..3bf690bbdd 100755
--- a/t/lib/autoloader.t
+++ b/t/lib/autoloader.t
@@ -3,10 +3,10 @@
BEGIN {
chdir 't' if -d 't';
$dir = "auto-$$";
- @INC = ("./$dir", "../lib");
+ unshift @INC, ("./$dir", "../lib");
}
-print "1..9\n";
+print "1..11\n";
# First we must set up some autoloader files
mkdir $dir, 0755 or die "Can't mkdir $dir: $!";
@@ -88,12 +88,33 @@ print "ok 8\n";
print "not " unless $foo->bazmarkhianish($1) eq 'foo';
print "ok 9\n";
+# test recursive autoloads
+open(F, ">$dir/auto/Foo/a.al") or die;
+print F <<'EOT';
+package Foo;
+BEGIN { b() }
+sub a { print "ok 11\n"; }
+1;
+EOT
+close(F);
+
+open(F, ">$dir/auto/Foo/b.al") or die;
+print F <<'EOT';
+package Foo;
+sub b { print "ok 10\n"; }
+1;
+EOT
+close(F);
+Foo::a();
+
# cleanup
END {
return unless $dir && -d $dir;
unlink "$dir/auto/Foo/foo.al";
unlink "$dir/auto/Foo/bar.al";
unlink "$dir/auto/Foo/bazmarkhian.al";
+unlink "$dir/auto/Foo/a.al";
+unlink "$dir/auto/Foo/b.al";
rmdir "$dir/auto/Foo";
rmdir "$dir/auto";
rmdir "$dir";
diff --git a/t/lib/basename.t b/t/lib/basename.t
index a02aa32cb7..478e26a8a5 100755
--- a/t/lib/basename.t
+++ b/t/lib/basename.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use File::Basename qw(fileparse basename dirname);
diff --git a/t/lib/bigfloat.t b/t/lib/bigfloat.t
new file mode 100755
index 0000000000..8e0a0ef724
--- /dev/null
+++ b/t/lib/bigfloat.t
@@ -0,0 +1,408 @@
+#!./perl
+
+BEGIN { @INC = '../lib' }
+require "bigfloat.pl";
+
+$test = 0;
+$| = 1;
+print "1..355\n";
+while (<DATA>) {
+ chop;
+ if (/^&/) {
+ $f = $_;
+ } elsif (/^\$.*/) {
+ eval "$_;";
+ } else {
+ ++$test;
+ @args = split(/:/,$_,99);
+ $ans = pop(@args);
+ $try = "$f('" . join("','", @args) . "');";
+ if (($ans1 = eval($try)) eq $ans) {
+ print "ok $test\n";
+ } else {
+ print "not ok $test\n";
+ print "# '$try' expected: '$ans' got: '$ans1'\n";
+ }
+ }
+}
+__END__
+&fnorm
+abc:NaN
+ 1 a:NaN
+1bcd2:NaN
+11111b:NaN
++1z:NaN
+-1z:NaN
+0:+0E+0
++0:+0E+0
++00:+0E+0
++0 0 0:+0E+0
+000000 0000000 00000:+0E+0
+-0:+0E+0
+-0000:+0E+0
++1:+1E+0
++01:+1E+0
++001:+1E+0
++00000100000:+1E+5
+123456789:+123456789E+0
+-1:-1E+0
+-01:-1E+0
+-001:-1E+0
+-123456789:-123456789E+0
+-00000100000:-1E+5
+123.456a:NaN
+123.456:+123456E-3
+0.01:+1E-2
+.002:+2E-3
+-0.0003:-3E-4
+-.0000000004:-4E-10
+123456E2:+123456E+2
+123456E-2:+123456E-2
+-123456E2:-123456E+2
+-123456E-2:-123456E-2
+1e1:+1E+1
+2e-11:+2E-11
+-3e111:-3E+111
+-4e-1111:-4E-1111
+&fneg
+abd:NaN
++0:+0E+0
++1:-1E+0
+-1:+1E+0
++123456789:-123456789E+0
+-123456789:+123456789E+0
++123.456789:-123456789E-6
+-123456.789:+123456789E-3
+&fabs
+abc:NaN
++0:+0E+0
++1:+1E+0
+-1:+1E+0
++123456789:+123456789E+0
+-123456789:+123456789E+0
++123.456789:+123456789E-6
+-123456.789:+123456789E-3
+&fround
+$bigfloat::rnd_mode = 'trunc'
++10123456789:5:+10123E+6
+-10123456789:5:-10123E+6
++10123456789:9:+101234567E+2
+-10123456789:9:-101234567E+2
++101234500:6:+101234E+3
+-101234500:6:-101234E+3
+$bigfloat::rnd_mode = 'zero'
++20123456789:5:+20123E+6
+-20123456789:5:-20123E+6
++20123456789:9:+201234568E+2
+-20123456789:9:-201234568E+2
++201234500:6:+201234E+3
+-201234500:6:-201234E+3
+$bigfloat::rnd_mode = '+inf'
++30123456789:5:+30123E+6
+-30123456789:5:-30123E+6
++30123456789:9:+301234568E+2
+-30123456789:9:-301234568E+2
++301234500:6:+301235E+3
+-301234500:6:-301234E+3
+$bigfloat::rnd_mode = '-inf'
++40123456789:5:+40123E+6
+-40123456789:5:-40123E+6
++40123456789:9:+401234568E+2
+-40123456789:9:-401234568E+2
++401234500:6:+401234E+3
+-401234500:6:-401235E+3
+$bigfloat::rnd_mode = 'odd'
++50123456789:5:+50123E+6
+-50123456789:5:-50123E+6
++50123456789:9:+501234568E+2
+-50123456789:9:-501234568E+2
++501234500:6:+501235E+3
+-501234500:6:-501235E+3
+$bigfloat::rnd_mode = 'even'
++60123456789:5:+60123E+6
+-60123456789:5:-60123E+6
++60123456789:9:+601234568E+2
+-60123456789:9:-601234568E+2
++601234500:6:+601234E+3
+-601234500:6:-601234E+3
+&ffround
+$bigfloat::rnd_mode = 'trunc'
++1.23:-1:+12E-1
+-1.23:-1:-12E-1
++1.27:-1:+12E-1
+-1.27:-1:-12E-1
++1.25:-1:+12E-1
+-1.25:-1:-12E-1
++1.35:-1:+13E-1
+-1.35:-1:-13E-1
+-0.006:-1:+0E+0
+-0.006:-2:+0E+0
+$bigfloat::rnd_mode = 'zero'
++2.23:-1:+22E-1
+-2.23:-1:-22E-1
++2.27:-1:+23E-1
+-2.27:-1:-23E-1
++2.25:-1:+22E-1
+-2.25:-1:-22E-1
++2.35:-1:+23E-1
+-2.35:-1:-23E-1
+-0.0065:-1:+0E+0
+-0.0065:-2:-1E-2
+-0.0065:-3:-6E-3
+-0.0065:-4:-65E-4
+-0.0065:-5:-65E-4
+$bigfloat::rnd_mode = '+inf'
++3.23:-1:+32E-1
+-3.23:-1:-32E-1
++3.27:-1:+33E-1
+-3.27:-1:-33E-1
++3.25:-1:+33E-1
+-3.25:-1:-32E-1
++3.35:-1:+34E-1
+-3.35:-1:-33E-1
+-0.0065:-1:+0E+0
+-0.0065:-2:-1E-2
+-0.0065:-3:-6E-3
+-0.0065:-4:-65E-4
+-0.0065:-5:-65E-4
+$bigfloat::rnd_mode = '-inf'
++4.23:-1:+42E-1
+-4.23:-1:-42E-1
++4.27:-1:+43E-1
+-4.27:-1:-43E-1
++4.25:-1:+42E-1
+-4.25:-1:-43E-1
++4.35:-1:+43E-1
+-4.35:-1:-44E-1
+-0.0065:-1:+0E+0
+-0.0065:-2:-1E-2
+-0.0065:-3:-7E-3
+-0.0065:-4:-65E-4
+-0.0065:-5:-65E-4
+$bigfloat::rnd_mode = 'odd'
++5.23:-1:+52E-1
+-5.23:-1:-52E-1
++5.27:-1:+53E-1
+-5.27:-1:-53E-1
++5.25:-1:+53E-1
+-5.25:-1:-53E-1
++5.35:-1:+53E-1
+-5.35:-1:-53E-1
+-0.0065:-1:+0E+0
+-0.0065:-2:-1E-2
+-0.0065:-3:-7E-3
+-0.0065:-4:-65E-4
+-0.0065:-5:-65E-4
+$bigfloat::rnd_mode = 'even'
++6.23:-1:+62E-1
+-6.23:-1:-62E-1
++6.27:-1:+63E-1
+-6.27:-1:-63E-1
++6.25:-1:+62E-1
+-6.25:-1:-62E-1
++6.35:-1:+64E-1
+-6.35:-1:-64E-1
+-0.0065:-1:+0E+0
+-0.0065:-2:-1E-2
+-0.0065:-3:-6E-3
+-0.0065:-4:-65E-4
+-0.0065:-5:-65E-4
+&fcmp
+abc:abc:
+abc:+0:
++0:abc:
++0:+0:0
+-1:+0:-1
++0:-1:1
++1:+0:1
++0:+1:-1
+-1:+1:-1
++1:-1:1
+-1:-1:0
++1:+1:0
++123:+123:0
++123:+12:1
++12:+123:-1
+-123:-123:0
+-123:-12:-1
+-12:-123:1
++123:+124:-1
++124:+123:1
+-123:-124:1
+-124:-123:-1
+&fadd
+abc:abc:NaN
+abc:+0:NaN
++0:abc:NaN
++0:+0:+0E+0
++1:+0:+1E+0
++0:+1:+1E+0
++1:+1:+2E+0
+-1:+0:-1E+0
++0:-1:-1E+0
+-1:-1:-2E+0
+-1:+1:+0E+0
++1:-1:+0E+0
++9:+1:+1E+1
++99:+1:+1E+2
++999:+1:+1E+3
++9999:+1:+1E+4
++99999:+1:+1E+5
++999999:+1:+1E+6
++9999999:+1:+1E+7
++99999999:+1:+1E+8
++999999999:+1:+1E+9
++9999999999:+1:+1E+10
++99999999999:+1:+1E+11
++10:-1:+9E+0
++100:-1:+99E+0
++1000:-1:+999E+0
++10000:-1:+9999E+0
++100000:-1:+99999E+0
++1000000:-1:+999999E+0
++10000000:-1:+9999999E+0
++100000000:-1:+99999999E+0
++1000000000:-1:+999999999E+0
++10000000000:-1:+9999999999E+0
++123456789:+987654321:+111111111E+1
+-123456789:+987654321:+864197532E+0
+-123456789:-987654321:-111111111E+1
++123456789:-987654321:-864197532E+0
+&fsub
+abc:abc:NaN
+abc:+0:NaN
++0:abc:NaN
++0:+0:+0E+0
++1:+0:+1E+0
++0:+1:-1E+0
++1:+1:+0E+0
+-1:+0:-1E+0
++0:-1:+1E+0
+-1:-1:+0E+0
+-1:+1:-2E+0
++1:-1:+2E+0
++9:+1:+8E+0
++99:+1:+98E+0
++999:+1:+998E+0
++9999:+1:+9998E+0
++99999:+1:+99998E+0
++999999:+1:+999998E+0
++9999999:+1:+9999998E+0
++99999999:+1:+99999998E+0
++999999999:+1:+999999998E+0
++9999999999:+1:+9999999998E+0
++99999999999:+1:+99999999998E+0
++10:-1:+11E+0
++100:-1:+101E+0
++1000:-1:+1001E+0
++10000:-1:+10001E+0
++100000:-1:+100001E+0
++1000000:-1:+1000001E+0
++10000000:-1:+10000001E+0
++100000000:-1:+100000001E+0
++1000000000:-1:+1000000001E+0
++10000000000:-1:+10000000001E+0
++123456789:+987654321:-864197532E+0
+-123456789:+987654321:-111111111E+1
+-123456789:-987654321:+864197532E+0
++123456789:-987654321:+111111111E+1
+&fmul
+abc:abc:NaN
+abc:+0:NaN
++0:abc:NaN
++0:+0:+0E+0
++0:+1:+0E+0
++1:+0:+0E+0
++0:-1:+0E+0
+-1:+0:+0E+0
++123456789123456789:+0:+0E+0
++0:+123456789123456789:+0E+0
+-1:-1:+1E+0
+-1:+1:-1E+0
++1:-1:-1E+0
++1:+1:+1E+0
++2:+3:+6E+0
+-2:+3:-6E+0
++2:-3:-6E+0
+-2:-3:+6E+0
++111:+111:+12321E+0
++10101:+10101:+102030201E+0
++1001001:+1001001:+1002003002001E+0
++100010001:+100010001:+10002000300020001E+0
++10000100001:+10000100001:+100002000030000200001E+0
++11111111111:+9:+99999999999E+0
++22222222222:+9:+199999999998E+0
++33333333333:+9:+299999999997E+0
++44444444444:+9:+399999999996E+0
++55555555555:+9:+499999999995E+0
++66666666666:+9:+599999999994E+0
++77777777777:+9:+699999999993E+0
++88888888888:+9:+799999999992E+0
++99999999999:+9:+899999999991E+0
+&fdiv
+abc:abc:NaN
+abc:+1:abc:NaN
++1:abc:NaN
++0:+0:NaN
++0:+1:+0E+0
++1:+0:NaN
++0:-1:+0E+0
+-1:+0:NaN
++1:+1:+1E+0
+-1:-1:+1E+0
++1:-1:-1E+0
+-1:+1:-1E+0
++1:+2:+5E-1
++2:+1:+2E+0
++10:+5:+2E+0
++100:+4:+25E+0
++1000:+8:+125E+0
++10000:+16:+625E+0
++10000:-16:-625E+0
++999999999999:+9:+111111111111E+0
++999999999999:+99:+10101010101E+0
++999999999999:+999:+1001001001E+0
++999999999999:+9999:+100010001E+0
++999999999999999:+99999:+10000100001E+0
++1000000000:+9:+1111111111111111111111111111111111111111E-31
++2000000000:+9:+2222222222222222222222222222222222222222E-31
++3000000000:+9:+3333333333333333333333333333333333333333E-31
++4000000000:+9:+4444444444444444444444444444444444444444E-31
++5000000000:+9:+5555555555555555555555555555555555555556E-31
++6000000000:+9:+6666666666666666666666666666666666666667E-31
++7000000000:+9:+7777777777777777777777777777777777777778E-31
++8000000000:+9:+8888888888888888888888888888888888888889E-31
++9000000000:+9:+1E+9
++35500000:+113:+3141592920353982300884955752212389380531E-34
++71000000:+226:+3141592920353982300884955752212389380531E-34
++106500000:+339:+3141592920353982300884955752212389380531E-34
++1000000000:+3:+3333333333333333333333333333333333333333E-31
+$bigfloat::div_scale = 20
++1000000000:+9:+11111111111111111111E-11
++2000000000:+9:+22222222222222222222E-11
++3000000000:+9:+33333333333333333333E-11
++4000000000:+9:+44444444444444444444E-11
++5000000000:+9:+55555555555555555556E-11
++6000000000:+9:+66666666666666666667E-11
++7000000000:+9:+77777777777777777778E-11
++8000000000:+9:+88888888888888888889E-11
++9000000000:+9:+1E+9
++35500000:+113:+314159292035398230088E-15
++71000000:+226:+314159292035398230088E-15
++106500000:+339:+31415929203539823009E-14
++1000000000:+3:+33333333333333333333E-11
+$bigfloat::div_scale = 40
+&fsqrt
++0:+0E+0
+-1:NaN
+-2:NaN
+-16:NaN
+-123.456:NaN
++1:+1E+0
++1.44:+12E-1
++2:+141421356237309504880168872420969807857E-38
++4:+2E+0
++16:+4E+0
++100:+1E+1
++123.456:+1111107555549866648462149404118219234119E-38
++15241.383936:+123456E-3
diff --git a/t/lib/bigfloatpm.t b/t/lib/bigfloatpm.t
new file mode 100755
index 0000000000..42cd9583d1
--- /dev/null
+++ b/t/lib/bigfloatpm.t
@@ -0,0 +1,459 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ @INC = '../lib';
+}
+
+use Math::BigFloat;
+
+$test = 0;
+$| = 1;
+print "1..358\n";
+while (<DATA>) {
+ chop;
+ if (s/^&//) {
+ $f = $_;
+ } elsif (/^\$.*/) {
+ eval "$_;";
+ } else {
+ ++$test;
+ if (m|^(.*?):(/.+)$|) {
+ $ans = $2;
+ @args = split(/:/,$1,99);
+ }
+ else {
+ @args = split(/:/,$_,99);
+ $ans = pop(@args);
+ }
+ $try = "\$x = new Math::BigFloat \"$args[0]\";";
+ if ($f eq "fnorm"){
+ $try .= "\$x+0;";
+ } elsif ($f eq "fneg") {
+ $try .= "-\$x;";
+ } elsif ($f eq "fabs") {
+ $try .= "abs \$x;";
+ } elsif ($f eq "fround") {
+ $try .= "0+\$x->fround($args[1]);";
+ } elsif ($f eq "ffround") {
+ $try .= "0+\$x->ffround($args[1]);";
+ } elsif ($f eq "fsqrt") {
+ $try .= "0+\$x->fsqrt;";
+ } else {
+ $try .= "\$y = new Math::BigFloat \"$args[1]\";";
+ if ($f eq fcmp){
+ $try .= "\$x <=> \$y;";
+ }elsif ($f eq fadd){
+ $try .= "\$x + \$y;";
+ }elsif ($f eq fsub){
+ $try .= "\$x - \$y;";
+ }elsif ($f eq fmul){
+ $try .= "\$x * \$y;";
+ }elsif ($f eq fdiv){
+ $try .= "\$x / \$y;";
+ } else { warn "Unknown op"; }
+ }
+ #print ">>>",$try,"<<<\n";
+ $ans1 = eval $try;
+ if ($ans =~ m|^/(.*)$|) {
+ my $pat = $1;
+ if ($ans1 =~ /$pat/) {
+ print "ok $test\n";
+ }
+ else {
+ print "not ok $test\n";
+ print "# '$try' expected: /$pat/ got: '$ans1'\n";
+ }
+ }
+ elsif ("$ans1" eq $ans) { #bug!
+ print "ok $test\n";
+ } else {
+ print "not ok $test\n";
+ print "# '$try' expected: '$ans' got: '$ans1'\n";
+ }
+ }
+}
+__END__
+&fnorm
+abc:NaN.
+ 1 a:NaN.
+1bcd2:NaN.
+11111b:NaN.
++1z:NaN.
+-1z:NaN.
+0:0.
++0:0.
++00:0.
++0 0 0:0.
+000000 0000000 00000:0.
+-0:0.
+-0000:0.
++1:1.
++01:1.
++001:1.
++00000100000:100000.
+123456789:123456789.
+-1:-1.
+-01:-1.
+-001:-1.
+-123456789:-123456789.
+-00000100000:-100000.
+123.456a:NaN.
+123.456:123.456
+0.01:.01
+.002:.002
+-0.0003:-.0003
+-.0000000004:-.0000000004
+123456E2:12345600.
+123456E-2:1234.56
+-123456E2:-12345600.
+-123456E-2:-1234.56
+1e1:10.
+2e-11:.00000000002
+-3e111:-3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.
+-4e-1111:-.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004
+&fneg
+abd:NaN.
++0:0.
++1:-1.
+-1:1.
++123456789:-123456789.
+-123456789:123456789.
++123.456789:-123.456789
+-123456.789:123456.789
+&fabs
+abc:NaN.
++0:0.
++1:1.
+-1:1.
++123456789:123456789.
+-123456789:123456789.
++123.456789:123.456789
+-123456.789:123456.789
+&fround
+$Math::BigFloat::rnd_mode = 'trunc'
++10123456789:5:10123000000
+-10123456789:5:-10123000000
++10123456789:9:10123456700
+-10123456789:9:-10123456700
++101234500:6:101234000
+-101234500:6:-101234000
+$Math::BigFloat::rnd_mode = 'zero'
++20123456789:5:20123000000
+-20123456789:5:-20123000000
++20123456789:9:20123456800
+-20123456789:9:-20123456800
++201234500:6:201234000
+-201234500:6:-201234000
+$Math::BigFloat::rnd_mode = '+inf'
++30123456789:5:30123000000
+-30123456789:5:-30123000000
++30123456789:9:30123456800
+-30123456789:9:-30123456800
++301234500:6:301235000
+-301234500:6:-301234000
+$Math::BigFloat::rnd_mode = '-inf'
++40123456789:5:40123000000
+-40123456789:5:-40123000000
++40123456789:9:40123456800
+-40123456789:9:-40123456800
++401234500:6:401234000
+-401234500:6:-401235000
+$Math::BigFloat::rnd_mode = 'odd'
++50123456789:5:50123000000
+-50123456789:5:-50123000000
++50123456789:9:50123456800
+-50123456789:9:-50123456800
++501234500:6:501235000
+-501234500:6:-501235000
+$Math::BigFloat::rnd_mode = 'even'
++60123456789:5:60123000000
+-60123456789:5:-60123000000
++60123456789:9:60123456800
+-60123456789:9:-60123456800
++601234500:6:601234000
+-601234500:6:-601234000
+&ffround
+$Math::BigFloat::rnd_mode = 'trunc'
++1.23:-1:1.2
+-1.23:-1:-1.2
++1.27:-1:1.2
+-1.27:-1:-1.2
++1.25:-1:1.2
+-1.25:-1:-1.2
++1.35:-1:1.3
+-1.35:-1:-1.3
+-0.006:-1:0
+-0.006:-2:0
+-0.0065:-3:/-0\.006|-6e-03
+-0.0065:-4:/-0\.0065|-6\.5e-03
+-0.0065:-5:/-0\.0065|-6\.5e-03
+$Math::BigFloat::rnd_mode = 'zero'
++2.23:-1:2.2
+-2.23:-1:-2.2
++2.27:-1:2.3
+-2.27:-1:-2.3
++2.25:-1:2.2
+-2.25:-1:-2.2
++2.35:-1:2.3
+-2.35:-1:-2.3
+-0.0065:-1:0
+-0.0065:-2:/-0\.01|-1e-02
+-0.0065:-3:/-0\.006|-6e-03
+-0.0065:-4:/-0\.0065|-6\.5e-03
+-0.0065:-5:/-0\.0065|-6\.5e-03
+$Math::BigFloat::rnd_mode = '+inf'
++3.23:-1:3.2
+-3.23:-1:-3.2
++3.27:-1:3.3
+-3.27:-1:-3.3
++3.25:-1:3.3
+-3.25:-1:-3.2
++3.35:-1:3.4
+-3.35:-1:-3.3
+-0.0065:-1:0
+-0.0065:-2:/-0\.01|-1e-02
+-0.0065:-3:/-0\.006|-6e-03
+-0.0065:-4:/-0\.0065|-6\.5e-03
+-0.0065:-5:/-0\.0065|-6\.5e-03
+$Math::BigFloat::rnd_mode = '-inf'
++4.23:-1:4.2
+-4.23:-1:-4.2
++4.27:-1:4.3
+-4.27:-1:-4.3
++4.25:-1:4.2
+-4.25:-1:-4.3
++4.35:-1:4.3
+-4.35:-1:-4.4
+-0.0065:-1:0
+-0.0065:-2:/-0\.01|-1e-02
+-0.0065:-3:/-0\.007|-7e-03
+-0.0065:-4:/-0\.0065|-6\.5e-03
+-0.0065:-5:/-0\.0065|-6\.5e-03
+$Math::BigFloat::rnd_mode = 'odd'
++5.23:-1:5.2
+-5.23:-1:-5.2
++5.27:-1:5.3
+-5.27:-1:-5.3
++5.25:-1:5.3
+-5.25:-1:-5.3
++5.35:-1:5.3
+-5.35:-1:-5.3
+-0.0065:-1:0
+-0.0065:-2:/-0\.01|-1e-02
+-0.0065:-3:/-0\.007|-7e-03
+-0.0065:-4:/-0\.0065|-6\.5e-03
+-0.0065:-5:/-0\.0065|-6\.5e-03
+$Math::BigFloat::rnd_mode = 'even'
++6.23:-1:6.2
+-6.23:-1:-6.2
++6.27:-1:6.3
+-6.27:-1:-6.3
++6.25:-1:6.2
+-6.25:-1:-6.2
++6.35:-1:6.4
+-6.35:-1:-6.4
+-0.0065:-1:0
+-0.0065:-2:/-0\.01|-1e-02
+-0.0065:-3:/-0\.006|-6e-03
+-0.0065:-4:/-0\.0065|-6\.5e-03
+-0.0065:-5:/-0\.0065|-6\.5e-03
+&fcmp
+abc:abc:
+abc:+0:
++0:abc:
++0:+0:0
+-1:+0:-1
++0:-1:1
++1:+0:1
++0:+1:-1
+-1:+1:-1
++1:-1:1
+-1:-1:0
++1:+1:0
++123:+123:0
++123:+12:1
++12:+123:-1
+-123:-123:0
+-123:-12:-1
+-12:-123:1
++123:+124:-1
++124:+123:1
+-123:-124:1
+-124:-123:-1
+&fadd
+abc:abc:NaN.
+abc:+0:NaN.
++0:abc:NaN.
++0:+0:0.
++1:+0:1.
++0:+1:1.
++1:+1:2.
+-1:+0:-1.
++0:-1:-1.
+-1:-1:-2.
+-1:+1:0.
++1:-1:0.
++9:+1:10.
++99:+1:100.
++999:+1:1000.
++9999:+1:10000.
++99999:+1:100000.
++999999:+1:1000000.
++9999999:+1:10000000.
++99999999:+1:100000000.
++999999999:+1:1000000000.
++9999999999:+1:10000000000.
++99999999999:+1:100000000000.
++10:-1:9.
++100:-1:99.
++1000:-1:999.
++10000:-1:9999.
++100000:-1:99999.
++1000000:-1:999999.
++10000000:-1:9999999.
++100000000:-1:99999999.
++1000000000:-1:999999999.
++10000000000:-1:9999999999.
++123456789:+987654321:1111111110.
+-123456789:+987654321:864197532.
+-123456789:-987654321:-1111111110.
++123456789:-987654321:-864197532.
+&fsub
+abc:abc:NaN.
+abc:+0:NaN.
++0:abc:NaN.
++0:+0:0.
++1:+0:1.
++0:+1:-1.
++1:+1:0.
+-1:+0:-1.
++0:-1:1.
+-1:-1:0.
+-1:+1:-2.
++1:-1:2.
++9:+1:8.
++99:+1:98.
++999:+1:998.
++9999:+1:9998.
++99999:+1:99998.
++999999:+1:999998.
++9999999:+1:9999998.
++99999999:+1:99999998.
++999999999:+1:999999998.
++9999999999:+1:9999999998.
++99999999999:+1:99999999998.
++10:-1:11.
++100:-1:101.
++1000:-1:1001.
++10000:-1:10001.
++100000:-1:100001.
++1000000:-1:1000001.
++10000000:-1:10000001.
++100000000:-1:100000001.
++1000000000:-1:1000000001.
++10000000000:-1:10000000001.
++123456789:+987654321:-864197532.
+-123456789:+987654321:-1111111110.
+-123456789:-987654321:864197532.
++123456789:-987654321:1111111110.
+&fmul
+abc:abc:NaN.
+abc:+0:NaN.
++0:abc:NaN.
++0:+0:0.
++0:+1:0.
++1:+0:0.
++0:-1:0.
+-1:+0:0.
++123456789123456789:+0:0.
++0:+123456789123456789:0.
+-1:-1:1.
+-1:+1:-1.
++1:-1:-1.
++1:+1:1.
++2:+3:6.
+-2:+3:-6.
++2:-3:-6.
+-2:-3:6.
++111:+111:12321.
++10101:+10101:102030201.
++1001001:+1001001:1002003002001.
++100010001:+100010001:10002000300020001.
++10000100001:+10000100001:100002000030000200001.
++11111111111:+9:99999999999.
++22222222222:+9:199999999998.
++33333333333:+9:299999999997.
++44444444444:+9:399999999996.
++55555555555:+9:499999999995.
++66666666666:+9:599999999994.
++77777777777:+9:699999999993.
++88888888888:+9:799999999992.
++99999999999:+9:899999999991.
+&fdiv
+abc:abc:NaN.
+abc:+1:abc:NaN.
++1:abc:NaN.
++0:+0:NaN.
++0:+1:0.
++1:+0:NaN.
++0:-1:0.
+-1:+0:NaN.
++1:+1:1.
+-1:-1:1.
++1:-1:-1.
+-1:+1:-1.
++1:+2:.5
++2:+1:2.
++10:+5:2.
++100:+4:25.
++1000:+8:125.
++10000:+16:625.
++10000:-16:-625.
++999999999999:+9:111111111111.
++999999999999:+99:10101010101.
++999999999999:+999:1001001001.
++999999999999:+9999:100010001.
++999999999999999:+99999:10000100001.
++1000000000:+9:111111111.1111111111111111111111111111111
++2000000000:+9:222222222.2222222222222222222222222222222
++3000000000:+9:333333333.3333333333333333333333333333333
++4000000000:+9:444444444.4444444444444444444444444444444
++5000000000:+9:555555555.5555555555555555555555555555556
++6000000000:+9:666666666.6666666666666666666666666666667
++7000000000:+9:777777777.7777777777777777777777777777778
++8000000000:+9:888888888.8888888888888888888888888888889
++9000000000:+9:1000000000.
++35500000:+113:314159.2920353982300884955752212389380531
++71000000:+226:314159.2920353982300884955752212389380531
++106500000:+339:314159.2920353982300884955752212389380531
++1000000000:+3:333333333.3333333333333333333333333333333
+$Math::BigFloat::div_scale = 20
++1000000000:+9:111111111.11111111111
++2000000000:+9:222222222.22222222222
++3000000000:+9:333333333.33333333333
++4000000000:+9:444444444.44444444444
++5000000000:+9:555555555.55555555556
++6000000000:+9:666666666.66666666667
++7000000000:+9:777777777.77777777778
++8000000000:+9:888888888.88888888889
++9000000000:+9:1000000000.
++35500000:+113:314159.292035398230088
++71000000:+226:314159.292035398230088
++106500000:+339:314159.29203539823009
++1000000000:+3:333333333.33333333333
+$Math::BigFloat::div_scale = 40
+&fsqrt
++0:0
+-1:/^(?i:0|\?|NaNQ?)$
+-2:/^(?i:0|\?|NaNQ?)$
+-16:/^(?i:0|\?|NaNQ?)$
+-123.456:/^(?i:0|\?|NaNQ?)$
++1:1.
++1.44:1.2
++2:1.41421356237309504880168872420969807857
++4:2.
++16:4.
++100:10.
++123.456:11.11107555549866648462149404118219234119
++15241.383936:123.456
diff --git a/t/lib/bigint.t b/t/lib/bigint.t
index 034c5c6457..d2d520ea3c 100755
--- a/t/lib/bigint.t
+++ b/t/lib/bigint.t
@@ -1,6 +1,6 @@
#!./perl
-BEGIN { @INC = '../lib' }
+BEGIN { unshift @INC, '../lib' }
require "bigint.pl";
$test = 0;
diff --git a/t/lib/bigintpm.t b/t/lib/bigintpm.t
index ebaecac21a..ae362e20c9 100755
--- a/t/lib/bigintpm.t
+++ b/t/lib/bigintpm.t
@@ -2,15 +2,14 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
-use Config;
use Math::BigInt;
$test = 0;
$| = 1;
-print "1..246\n";
+print "1..278\n";
while (<DATA>) {
chop;
if (s/^&//) {
@@ -28,20 +27,32 @@ while (<DATA>) {
$try .= "abs \$x;";
} else {
$try .= "\$y = new Math::BigInt \"$args[1]\";";
- if ($f eq bcmp){
+ if ($f eq "bcmp"){
$try .= "\$x <=> \$y;";
- }elsif ($f eq badd){
+ }elsif ($f eq "badd"){
$try .= "\$x + \$y;";
- }elsif ($f eq bsub){
+ }elsif ($f eq "bsub"){
$try .= "\$x - \$y;";
- }elsif ($f eq bmul){
+ }elsif ($f eq "bmul"){
$try .= "\$x * \$y;";
- }elsif ($f eq bdiv){
+ }elsif ($f eq "bdiv"){
$try .= "\$x / \$y;";
- }elsif ($f eq bmod){
+ }elsif ($f eq "bmod"){
$try .= "\$x % \$y;";
- }elsif ($f eq bgcd){
+ }elsif ($f eq "bgcd"){
$try .= "Math::BigInt::bgcd(\$x, \$y);";
+ }elsif ($f eq "blsft"){
+ $try .= "\$x << \$y;";
+ }elsif ($f eq "brsft"){
+ $try .= "\$x >> \$y;";
+ }elsif ($f eq "band"){
+ $try .= "\$x & \$y;";
+ }elsif ($f eq "bior"){
+ $try .= "\$x | \$y;";
+ }elsif ($f eq "bxor"){
+ $try .= "\$x ^ \$y;";
+ }elsif ($f eq "bnot"){
+ $try .= "~\$x;";
} else { warn "Unknown op"; }
}
#print ">>>",$try,"<<<\n";
@@ -53,7 +64,24 @@ while (<DATA>) {
print "# '$try' expected: '$ans' got: '$ans1'\n";
}
}
-}
+}
+
+{
+ use Math::BigInt ':constant';
+
+ $test++;
+ print "not "
+ unless 2**150 eq "+1427247692705959881058285969449495136382746624";
+ print "ok $test\n";
+ $test++;
+ @a = ();
+ for ($i = 1; $i < 10; $i++) {
+ push @a, $i;
+ }
+ print "not " unless "@a" eq "+1 +2 +3 +4 +5 +6 +7 +8 +9";
+ print "ok $test\n";
+}
+
__END__
&bnorm
abc:NaN
@@ -94,28 +122,29 @@ abc:NaN
+123456789:+123456789
-123456789:+123456789
&bcmp
-abc:abc:NaN
-abc:+0:NaN
-+0:abc:NaN
-+0:+0:+0
+abc:abc:
+abc:+0:
++0:abc:
++0:+0:0
-1:+0:-1
-+0:-1:+1
-+1:+0:+1
++0:-1:1
++1:+0:1
+0:+1:-1
-1:+1:-1
-+1:-1:+1
--1:-1:+0
-+1:+1:+0
-+123:+123:+0
-+123:+12:+1
++1:-1:1
+-1:-1:0
++1:+1:0
++123:+123:0
++123:+12:1
+12:+123:-1
--123:-123:+0
+-123:-123:0
-123:-12:-1
--12:-123:+1
+-12:-123:1
+123:+124:-1
-+124:+123:+1
--123:-124:+1
++124:+123:1
+-123:-124:1
-124:-123:-1
++100:+5:1
&badd
abc:abc:NaN
abc:+0:NaN
@@ -311,3 +340,38 @@ abc:+0:NaN
+3:+2:+1
+100:+625:+25
+4096:+81:+1
+&blsft
+abc:abc:NaN
++2:+2:+8
++1:+32:+4294967296
++1:+48:+281474976710656
++8:-2:NaN
+&brsft
+abc:abc:NaN
++8:+2:+2
++4294967296:+32:+1
++281474976710656:+48:+1
++2:-2:NaN
+&band
+abc:abc:NaN
++8:+2:+0
++281474976710656:+0:+0
++281474976710656:+1:+0
++281474976710656:+281474976710656:+281474976710656
+&bior
+abc:abc:NaN
++8:+2:+10
++281474976710656:+0:+281474976710656
++281474976710656:+1:+281474976710657
++281474976710656:+281474976710656:+281474976710656
+&bxor
+abc:abc:NaN
++8:+2:+10
++281474976710656:+0:+281474976710656
++281474976710656:+1:+281474976710657
++281474976710656:+281474976710656:+0
+&bnot
+abc:NaN
++0:-1
++8:-9
++281474976710656:-281474976710657
diff --git a/t/lib/cgi-form.t b/t/lib/cgi-form.t
index 86df161b02..e3cba5fc20 100755
--- a/t/lib/cgi-form.t
+++ b/t/lib/cgi-form.t
@@ -5,7 +5,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
BEGIN {$| = 1; print "1..17\n"; }
@@ -44,16 +44,16 @@ test(6,textfield(-name=>'weather') eq qq(<INPUT TYPE="text" NAME="weather" VALUE
test(7,textfield(-name=>'weather',-value=>'nice') eq qq(<INPUT TYPE="text" NAME="weather" VALUE="dull">),"textfield({-name,-value})");
test(8,textfield(-name=>'weather',-value=>'nice',-override=>1) eq qq(<INPUT TYPE="text" NAME="weather" VALUE="nice">),
"textfield({-name,-value,-override})");
-test(9,checkbox(-name=>'weather',-value=>'nice') eq qq(<INPUT TYPE="checkbox" NAME="weather" VALUE="nice">weather\n),
+test(9,checkbox(-name=>'weather',-value=>'nice') eq qq(<INPUT TYPE="checkbox" NAME="weather" VALUE="nice">weather),
"checkbox()");
test(10,checkbox(-name=>'weather',-value=>'nice',-label=>'forecast') eq
- qq(<INPUT TYPE="checkbox" NAME="weather" VALUE="nice">forecast\n),
+ qq(<INPUT TYPE="checkbox" NAME="weather" VALUE="nice">forecast),
"checkbox()");
test(11,checkbox(-name=>'weather',-value=>'nice',-label=>'forecast',-checked=>1,-override=>1) eq
- qq(<INPUT TYPE="checkbox" NAME="weather" VALUE="nice" CHECKED>forecast\n),
+ qq(<INPUT TYPE="checkbox" NAME="weather" VALUE="nice" CHECKED>forecast),
"checkbox()");
test(12,checkbox(-name=>'weather',-value=>'dull',-label=>'forecast') eq
- qq(<INPUT TYPE="checkbox" NAME="weather" VALUE="dull" CHECKED>forecast\n),
+ qq(<INPUT TYPE="checkbox" NAME="weather" VALUE="dull" CHECKED>forecast),
"checkbox()");
test(13,radio_group(-name=>'game') eq
diff --git a/t/lib/cgi-function.t b/t/lib/cgi-function.t
index ad8b968161..b4cd56811f 100755
--- a/t/lib/cgi-function.t
+++ b/t/lib/cgi-function.t
@@ -5,7 +5,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
BEGIN {$| = 1; print "1..24\n"; }
diff --git a/t/lib/cgi-html.t b/t/lib/cgi-html.t
index d7f3ffb4aa..e878b21e50 100755
--- a/t/lib/cgi-html.t
+++ b/t/lib/cgi-html.t
@@ -5,18 +5,20 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
+ require Config; import Config;
}
-BEGIN {$| = 1; print "1..17\n"; }
-BEGIN {$eol = $^O eq 'VMS' ? "\n" : "\cM\cJ";}
+BEGIN {$| = 1; print "1..20\n"; }
END {print "not ok 1\n" unless $loaded;}
-use CGI (':standard','-no_debug');
+use CGI (':standard','-no_debug','*h3','start_table');
$loaded = 1;
print "ok 1\n";
######################### End of black magic.
+my $Is_EBCDIC = $Config{'ebcdic'} eq 'define';
+
# util
sub test {
local($^W) = 0;
@@ -37,10 +39,17 @@ test(7,h1({-align=>'CENTER'},['fred','agnes']) eq
local($") = '-';
test(8,h1('fred','agnes','maura') eq '<H1>fred-agnes-maura</H1>',"open/close tag \$\" interpolation");
}
-test(9,header() eq "Content-Type: text/html${eol}${eol}","header()");
-test(10,header(-type=>'image/gif') eq "Content-Type: image/gif${eol}${eol}","header()");
-test(11,header(-type=>'image/gif',-status=>'500 Sucks') eq "Status: 500 Sucks${eol}Content-Type: image/gif${eol}${eol}","header()");
-test(12,header(-nph=>1) eq "HTTP/1.0 200 OK${eol}Content-Type: text/html${eol}${eol}","header()");
+if (!$Is_EBCDIC) {
+test(9,header() eq "Content-Type: text/html\015\012\015\012","header()");
+test(10,header(-type=>'image/gif') eq "Content-Type: image/gif\015\012\015\012","header()");
+test(11,header(-type=>'image/gif',-status=>'500 Sucks') eq "Status: 500 Sucks\015\012Content-Type: image/gif\015\012\015\012","header()");
+test(12,header(-nph=>1) eq "HTTP/1.0 200 OK\015\012Content-Type: text/html\015\012\015\012","header()");
+} else {
+test(9,header() eq "Content-Type: text/html\r\n\r\n","header()");
+test(10,header(-type=>'image/gif') eq "Content-Type: image/gif\r\n\r\n","header()");
+test(11,header(-type=>'image/gif',-status=>'500 Sucks') eq "Status: 500 Sucks\r\nContent-Type: image/gif\r\n\r\n","header()");
+test(12,header(-nph=>1) eq "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n","header()");
+}
test(13,start_html() ."\n" eq <<END,"start_html()");
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML><HEAD><TITLE>Untitled Document</TITLE>
@@ -60,6 +69,14 @@ test(15,start_html(-Title=>'The world of foo') ."\n" eq <<END,"start_html()");
END
;
test(16,($cookie=cookie(-name=>'fred',-value=>['chocolate','chip'],-path=>'/')) eq
- 'fred=chocolate&chip; path=/',"cookie()");
-test(17,header(-Cookie=>$cookie) =~ m!^Set-Cookie: fred=chocolate&chip\; path=/${eol}Date:.*${eol}Content-Type: text/html${eol}${eol}!s,
+ 'fred=chocolate&chip; domain=localhost; path=/',"cookie()");
+if (!$Is_EBCDIC) {
+test(17,header(-Cookie=>$cookie) =~ m!^Set-Cookie: fred=chocolate&chip\; domain=localhost; path=/\015\012Date:.*\015\012Content-Type: text/html\015\012\015\012!s,
"header(-cookie)");
+} else {
+test(17,header(-Cookie=>$cookie) =~ m!^Set-Cookie: fred=chocolate&chip\; domain=localhost; path=/\r\nDate:.*\r\nContent-Type: text/html\r\n\r\n!s,
+ "header(-cookie)");
+}
+test(18,start_h3 eq '<H3>');
+test(19,end_h3 eq '</H3>');
+test(20,start_table({-border=>undef}) eq '<TABLE BORDER>');
diff --git a/t/lib/cgi-request.t b/t/lib/cgi-request.t
index 8c70c40350..9e8cdc290a 100755
--- a/t/lib/cgi-request.t
+++ b/t/lib/cgi-request.t
@@ -5,7 +5,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
BEGIN {$| = 1; print "1..31\n"; }
@@ -25,15 +25,16 @@ sub test {
}
# Set up a CGI environment
-$ENV{REQUEST_METHOD}='GET';
-$ENV{QUERY_STRING} ='game=chess&game=checkers&weather=dull';
-$ENV{PATH_INFO} ='/somewhere/else';
-$ENV{PATH_TRANSLATED} ='/usr/local/somewhere/else';
-$ENV{SCRIPT_NAME} ='/cgi-bin/foo.cgi';
+$ENV{REQUEST_METHOD} = 'GET';
+$ENV{QUERY_STRING} = 'game=chess&game=checkers&weather=dull';
+$ENV{PATH_INFO} = '/somewhere/else';
+$ENV{PATH_TRANSLATED} = '/usr/local/somewhere/else';
+$ENV{SCRIPT_NAME} = '/cgi-bin/foo.cgi';
$ENV{SERVER_PROTOCOL} = 'HTTP/1.0';
-$ENV{SERVER_PORT} = 8080;
-$ENV{SERVER_NAME} = 'the.good.ship.lollypop.com';
-$ENV{HTTP_LOVE} = 'true';
+$ENV{SERVER_PORT} = 8080;
+$ENV{SERVER_NAME} = 'the.good.ship.lollypop.com';
+$ENV{REQUEST_URI} = "$ENV{SCRIPT_NAME}$ENV{PATH_INFO}?$ENV{QUERY_STRING}";
+$ENV{HTTP_LOVE} = 'true';
$q = new CGI;
test(2,$q,"CGI::new()");
diff --git a/t/lib/charnames.t b/t/lib/charnames.t
new file mode 100644
index 0000000000..8d5c8db384
--- /dev/null
+++ b/t/lib/charnames.t
@@ -0,0 +1,53 @@
+#!./perl
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib' if -d '../lib';
+ }
+}
+
+$| = 1;
+print "1..5\n";
+
+use charnames ':full';
+
+print "not " unless "Here\N{EXCLAMATION MARK}?" eq 'Here!?';
+print "ok 1\n";
+
+print "# \$res=$res \$\@='$@'\nnot "
+ if $res = eval <<'EOE'
+use charnames ":full";
+"Here: \N{CYRILLIC SMALL LETTER BE}!";
+1
+EOE
+ or $@ !~ /above 0xFF/;
+print "ok 2\n";
+# print "# \$res=$res \$\@='$@'\n";
+
+print "# \$res=$res \$\@='$@'\nnot "
+ if $res = eval <<'EOE'
+use charnames 'cyrillic';
+"Here: \N{Be}!";
+1
+EOE
+ or $@ !~ /CYRILLIC CAPITAL LETTER BE.*above 0xFF/;
+print "ok 3\n";
+
+# If octal representation of unicode char is \0xyzt, then the utf8 is \3xy\2zt
+$encoded_be = "\320\261";
+$encoded_alpha = "\316\261";
+$encoded_bet = "\327\221";
+{
+ use charnames ':full';
+ use utf8;
+
+ print "not " unless "\N{CYRILLIC SMALL LETTER BE}" eq $encoded_be;
+ print "ok 4\n";
+
+ use charnames qw(cyrillic greek :short);
+
+ print "not " unless "\N{be},\N{alpha},\N{hebrew:bet}"
+ eq "$encoded_be,$encoded_alpha,$encoded_bet";
+ print "ok 5\n";
+}
diff --git a/t/lib/checktree.t b/t/lib/checktree.t
index b5426ca261..760357529b 100755
--- a/t/lib/checktree.t
+++ b/t/lib/checktree.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..1\n";
diff --git a/t/lib/complex.t b/t/lib/complex.t
index 2bb14f0866..6fbdf8dd67 100755
--- a/t/lib/complex.t
+++ b/t/lib/complex.t
@@ -9,12 +9,12 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Math::Complex;
-$VERSION = sprintf("%s", q$Id: complex.t,v 1.8 1998/02/05 16:03:39 jhi Exp $ =~ /(\d+\.d+)/);
+my $VERSION = sprintf("%s", q$Id: complex.t,v 1.9 1998/11/01 00:00:00 dsl Exp $ =~ /(\d+\.d+)/);
my ($args, $op, $target, $test, $test_set, $try, $val, $zvalue, @set, @val);
@@ -173,20 +173,6 @@ test_loz(
'acoth(-1)',
);
-# test the 0**0
-
-sub test_ztz {
- $test++;
-
- push(@script, <<'EOT');
-eval 'cplx(0)**cplx(0)';
-print 'not ' unless ($@ =~ /zero raised to the zeroth/);
-EOT
- push(@script, qq(print "ok $test\\n";\n));
-}
-
-test_ztz;
-
# test the bad roots
sub test_broot {
@@ -387,6 +373,7 @@ __END__
(1,0):(2,3):(1,0)
(2,3):(0,0):(1,0)
(2,3):(1,0):(2,3)
+(0,0):(0,0):(1,0)
&Re
(3,4):3
@@ -876,4 +863,3 @@ __END__
( 2,-3):( 0.14694666622553, 0.23182380450040)
# eof
-
diff --git a/t/lib/db-btree.t b/t/lib/db-btree.t
index bf739c81d5..cea8163a46 100755
--- a/t/lib/db-btree.t
+++ b/t/lib/db-btree.t
@@ -1,10 +1,10 @@
#!./perl -w
BEGIN {
- @INC = '../lib' if -d '../lib' ;
+ unshift @INC, '../lib' if -d '../lib' ;
require Config; import Config;
if ($Config{'extensions'} !~ /\bDB_File\b/) {
- print "1..0\n";
+ print "1..0 # Skip: DB_File was not built\n";
exit 0;
}
}
@@ -12,7 +12,7 @@ BEGIN {
use DB_File;
use Fcntl;
-print "1..102\n";
+print "1..155\n";
sub ok
{
@@ -38,7 +38,51 @@ sub lexical
return @a - @b ;
}
-$Dfile = "dbbtree.tmp";
+{
+ package Redirect ;
+ use Symbol ;
+
+ sub new
+ {
+ my $class = shift ;
+ my $filename = shift ;
+ my $fh = gensym ;
+ open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
+ my $real_stdout = select($fh) ;
+ return bless [$fh, $real_stdout ] ;
+
+ }
+ sub DESTROY
+ {
+ my $self = shift ;
+ close $self->[0] ;
+ select($self->[1]) ;
+ }
+}
+
+sub docat
+{
+ my $file = shift;
+ #local $/ = undef unless wantarray ;
+ open(CAT,$file) || die "Cannot open $file: $!";
+ my @result = <CAT>;
+ close(CAT);
+ wantarray ? @result : join("", @result) ;
+}
+
+sub docat_del
+{
+ my $file = shift;
+ #local $/ = undef unless wantarray ;
+ open(CAT,$file) || die "Cannot open $file: $!";
+ my @result = <CAT>;
+ close(CAT);
+ unlink $file ;
+ wantarray ? @result : join("", @result) ;
+}
+
+
+my $Dfile = "dbbtree.tmp";
unlink $Dfile;
umask(0);
@@ -134,7 +178,6 @@ delete $h{'goner2'};
undef $X ;
untie(%h);
-
# tie to the same file again
ok(26, $X = tie(%h,'DB_File',$Dfile, O_RDWR, 0640, $DB_BTREE)) ;
@@ -609,4 +652,567 @@ EOM
}
+{
+ # DBM Filter tests
+ use strict ;
+ my (%h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ unlink $Dfile;
+
+ sub checkOutput
+ {
+ my($fk, $sk, $fv, $sv) = @_ ;
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ ok(103, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ # fk sk fv sv
+ ok(104, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(105, $h{"fred"} eq "joe");
+ # fk sk fv sv
+ ok(106, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(107, $db->FIRSTKEY() eq "fred") ;
+ # fk sk fv sv
+ ok(108, checkOutput( "fred", "", "", "")) ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ = lc $_ ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"Fred"} = "Joe" ;
+ # fk sk fv sv
+ ok(109, checkOutput( "", "fred", "", "Jxe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(110, $h{"Fred"} eq "[Jxe]");
+ # fk sk fv sv
+ ok(111, checkOutput( "", "fred", "[Jxe]", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(112, $db->FIRSTKEY() eq "FRED") ;
+ # fk sk fv sv
+ ok(113, checkOutput( "FRED", "", "", "")) ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(114, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(115, $h{"fred"} eq "joe");
+ ok(116, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(117, $db->FIRSTKEY() eq "fred") ;
+ ok(118, checkOutput( "fred", "", "", "")) ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(119, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(120, $h{"fred"} eq "joe");
+ ok(121, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(122, $db->FIRSTKEY() eq "fred") ;
+ ok(123, checkOutput( "", "", "", "")) ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter with a closure
+
+ use strict ;
+ my (%h, $db) ;
+
+ unlink $Dfile;
+ ok(124, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok(125, $result{"store key"} eq "store key - 1: [fred]");
+ ok(126, $result{"store value"} eq "store value - 1: [joe]");
+ ok(127, ! defined $result{"fetch key"} );
+ ok(128, ! defined $result{"fetch value"} );
+ ok(129, $_ eq "original") ;
+
+ ok(130, $db->FIRSTKEY() eq "fred") ;
+ ok(131, $result{"store key"} eq "store key - 1: [fred]");
+ ok(132, $result{"store value"} eq "store value - 1: [joe]");
+ ok(133, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(134, ! defined $result{"fetch value"} );
+ ok(135, $_ eq "original") ;
+
+ $h{"jim"} = "john" ;
+ ok(136, $result{"store key"} eq "store key - 2: [fred jim]");
+ ok(137, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(138, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(139, ! defined $result{"fetch value"} );
+ ok(140, $_ eq "original") ;
+
+ ok(141, $h{"fred"} eq "joe");
+ ok(142, $result{"store key"} eq "store key - 3: [fred jim fred]");
+ ok(143, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(144, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(145, $result{"fetch value"} eq "fetch value - 1: [joe]");
+ ok(146, $_ eq "original") ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter recursion detection
+ use strict ;
+ my (%h, $db) ;
+ unlink $Dfile;
+
+ ok(147, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+
+ $db->filter_store_key (sub { $_ = $h{$_} }) ;
+
+ eval '$h{1} = 1234' ;
+ ok(148, $@ =~ /^recursion detected in filter_store_key at/ );
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+
+{
+ # Examples from the POD
+
+
+ my $file = "xyzt" ;
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 1
+ ###
+
+ use strict ;
+ use DB_File ;
+
+ my %h ;
+
+ sub Compare
+ {
+ my ($key1, $key2) = @_ ;
+ "\L$key1" cmp "\L$key2" ;
+ }
+
+ # specify the Perl sub that will do the comparison
+ $DB_BTREE->{'compare'} = \&Compare ;
+
+ unlink "tree" ;
+ tie %h, "DB_File", "tree", O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open file 'tree': $!\n" ;
+
+ # Add a key/value pair to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+ $h{'duck'} = 'donald' ;
+
+ # Delete
+ delete $h{"duck"} ;
+
+ # Cycle through the keys printing them in order.
+ # Note it is not necessary to sort the keys as
+ # the btree will have kept them in order automatically.
+ foreach (keys %h)
+ { print "$_\n" }
+
+ untie %h ;
+
+ unlink "tree" ;
+ }
+
+ delete $DB_BTREE->{'compare'} ;
+
+ ok(149, docat_del($file) eq <<'EOM') ;
+mouse
+Smith
+Wall
+EOM
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 2
+ ###
+
+ use strict ;
+ use DB_File ;
+
+ use vars qw($filename %h ) ;
+
+ $filename = "tree" ;
+ unlink $filename ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ # Add some key/value pairs to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+
+ # iterate through the associative array
+ # and print each key/value pair.
+ foreach (keys %h)
+ { print "$_ -> $h{$_}\n" }
+
+ untie %h ;
+
+ unlink $filename ;
+ }
+
+ ok(150, docat_del($file) eq ($DB_File::db_version == 1 ? <<'EOM' : <<'EOM') ) ;
+Smith -> John
+Wall -> Brick
+Wall -> Brick
+Wall -> Brick
+mouse -> mickey
+EOM
+Smith -> John
+Wall -> Larry
+Wall -> Larry
+Wall -> Larry
+mouse -> mickey
+EOM
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 3
+ ###
+
+ use strict ;
+ use DB_File ;
+
+ use vars qw($filename $x %h $status $key $value) ;
+
+ $filename = "tree" ;
+ unlink $filename ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ # Add some key/value pairs to the file
+ $h{'Wall'} = 'Larry' ;
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key
+ $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
+ $h{'Smith'} = 'John' ;
+ $h{'mouse'} = 'mickey' ;
+
+ # iterate through the btree using seq
+ # and print each key/value pair.
+ $key = $value = 0 ;
+ for ($status = $x->seq($key, $value, R_FIRST) ;
+ $status == 0 ;
+ $status = $x->seq($key, $value, R_NEXT) )
+ { print "$key -> $value\n" }
+
+
+ undef $x ;
+ untie %h ;
+ }
+
+ ok(151, docat_del($file) eq ($DB_File::db_version == 1 ? <<'EOM' : <<'EOM') ) ;
+Smith -> John
+Wall -> Brick
+Wall -> Brick
+Wall -> Larry
+mouse -> mickey
+EOM
+Smith -> John
+Wall -> Larry
+Wall -> Brick
+Wall -> Brick
+mouse -> mickey
+EOM
+
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 4
+ ###
+
+ use strict ;
+ use DB_File ;
+
+ use vars qw($filename $x %h ) ;
+
+ $filename = "tree" ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ my $cnt = $x->get_dup("Wall") ;
+ print "Wall occurred $cnt times\n" ;
+
+ my %hash = $x->get_dup("Wall", 1) ;
+ print "Larry is there\n" if $hash{'Larry'} ;
+ print "There are $hash{'Brick'} Brick Walls\n" ;
+
+ my @list = sort $x->get_dup("Wall") ;
+ print "Wall => [@list]\n" ;
+
+ @list = $x->get_dup("Smith") ;
+ print "Smith => [@list]\n" ;
+
+ @list = $x->get_dup("Dog") ;
+ print "Dog => [@list]\n" ;
+
+ undef $x ;
+ untie %h ;
+ }
+
+ ok(152, docat_del($file) eq <<'EOM') ;
+Wall occurred 3 times
+Larry is there
+There are 2 Brick Walls
+Wall => [Brick Brick Larry]
+Smith => [John]
+Dog => []
+EOM
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 5
+ ###
+
+ use strict ;
+ use DB_File ;
+
+ use vars qw($filename $x %h $found) ;
+
+ my $filename = "tree" ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
+ print "Larry Wall is $found there\n" ;
+
+ $found = ( $x->find_dup("Wall", "Harry") == 0 ? "" : "not") ;
+ print "Harry Wall is $found there\n" ;
+
+ undef $x ;
+ untie %h ;
+ }
+
+ ok(153, docat_del($file) eq <<'EOM') ;
+Larry Wall is there
+Harry Wall is not there
+EOM
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 6
+ ###
+
+ use strict ;
+ use DB_File ;
+
+ use vars qw($filename $x %h $found) ;
+
+ my $filename = "tree" ;
+
+ # Enable duplicate records
+ $DB_BTREE->{'flags'} = R_DUP ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ $x->del_dup("Wall", "Larry") ;
+
+ $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
+ print "Larry Wall is $found there\n" ;
+
+ undef $x ;
+ untie %h ;
+
+ unlink $filename ;
+ }
+
+ ok(154, docat_del($file) eq <<'EOM') ;
+Larry Wall is not there
+EOM
+
+ {
+ my $redirect = new Redirect $file ;
+
+ # BTREE example 7
+ ###
+
+ use strict ;
+ use DB_File ;
+ use Fcntl ;
+
+ use vars qw($filename $x %h $st $key $value) ;
+
+ sub match
+ {
+ my $key = shift ;
+ my $value = 0;
+ my $orig_key = $key ;
+ $x->seq($key, $value, R_CURSOR) ;
+ print "$orig_key\t-> $key\t-> $value\n" ;
+ }
+
+ $filename = "tree" ;
+ unlink $filename ;
+
+ $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
+ or die "Cannot open $filename: $!\n";
+
+ # Add some key/value pairs to the file
+ $h{'mouse'} = 'mickey' ;
+ $h{'Wall'} = 'Larry' ;
+ $h{'Walls'} = 'Brick' ;
+ $h{'Smith'} = 'John' ;
+
+
+ $key = $value = 0 ;
+ print "IN ORDER\n" ;
+ for ($st = $x->seq($key, $value, R_FIRST) ;
+ $st == 0 ;
+ $st = $x->seq($key, $value, R_NEXT) )
+
+ { print "$key -> $value\n" }
+
+ print "\nPARTIAL MATCH\n" ;
+
+ match "Wa" ;
+ match "A" ;
+ match "a" ;
+
+ undef $x ;
+ untie %h ;
+
+ unlink $filename ;
+
+ }
+
+ ok(155, docat_del($file) eq <<'EOM') ;
+IN ORDER
+Smith -> John
+Wall -> Larry
+Walls -> Brick
+mouse -> mickey
+
+PARTIAL MATCH
+Wa -> Wall -> Larry
+A -> Smith -> John
+a -> mouse -> mickey
+EOM
+
+}
+
+#{
+# # R_SETCURSOR
+# use strict ;
+# my (%h, $db) ;
+# unlink $Dfile;
+#
+# ok(156, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) );
+#
+# $h{abc} = 33 ;
+# my $k = "newest" ;
+# my $v = 44 ;
+# my $status = $db->put($k, $v, R_SETCURSOR) ;
+# print "status = [$status]\n" ;
+# ok(157, $status == 0) ;
+# $status = $db->del($k, R_CURSOR) ;
+# print "status = [$status]\n" ;
+# ok(158, $status == 0) ;
+# $k = "newest" ;
+# ok(159, $db->get($k, $v, R_CURSOR)) ;
+#
+# ok(160, keys %h == 1) ;
+#
+# undef $db ;
+# untie %h;
+# unlink $Dfile;
+#}
+
exit ;
diff --git a/t/lib/db-hash.t b/t/lib/db-hash.t
index e748472263..c52d8ae9dd 100755
--- a/t/lib/db-hash.t
+++ b/t/lib/db-hash.t
@@ -1,10 +1,10 @@
#!./perl -w
BEGIN {
- @INC = '../lib' if -d '../lib' ;
+ unshift @INC, '../lib' if -d '../lib' ;
require Config; import Config;
if ($Config{'extensions'} !~ /\bDB_File\b/) {
- print "1..0\n";
+ print "1..0 # Skip: DB_File was not built\n";
exit 0;
}
}
@@ -12,7 +12,7 @@ BEGIN {
use DB_File;
use Fcntl;
-print "1..62\n";
+print "1..109\n";
sub ok
{
@@ -23,7 +23,40 @@ sub ok
print "ok $no\n" ;
}
-$Dfile = "dbhash.tmp";
+{
+ package Redirect ;
+ use Symbol ;
+
+ sub new
+ {
+ my $class = shift ;
+ my $filename = shift ;
+ my $fh = gensym ;
+ open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
+ my $real_stdout = select($fh) ;
+ return bless [$fh, $real_stdout ] ;
+
+ }
+ sub DESTROY
+ {
+ my $self = shift ;
+ close $self->[0] ;
+ select($self->[1]) ;
+ }
+}
+
+sub docat_del
+{
+ my $file = shift;
+ local $/ = undef;
+ open(CAT,$file) || die "Cannot open $file: $!";
+ my $result = <CAT>;
+ close(CAT);
+ unlink $file ;
+ return $result;
+}
+
+my $Dfile = "dbhash.tmp";
unlink $Dfile;
umask(0);
@@ -164,6 +197,8 @@ ok(25, $#keys == 31) ;
$h{'foo'} = '';
ok(26, $h{'foo'} eq '' );
+# Berkeley DB 2 from version 2.4.10 onwards does not allow null keys.
+# This feature will be reenabled in a future version of Berkeley DB.
#$h{''} = 'bar';
#ok(27, $h{''} eq 'bar' );
ok(27,1) ;
@@ -413,4 +448,238 @@ EOM
unlink "SubDB.pm", "dbhash.tmp" ;
}
+
+{
+ # DBM Filter tests
+ use strict ;
+ my (%h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ unlink $Dfile;
+
+ sub checkOutput
+ {
+ my($fk, $sk, $fv, $sv) = @_ ;
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ ok(63, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ # fk sk fv sv
+ ok(64, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(65, $h{"fred"} eq "joe");
+ # fk sk fv sv
+ ok(66, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(67, $db->FIRSTKEY() eq "fred") ;
+ # fk sk fv sv
+ ok(68, checkOutput( "fred", "", "", "")) ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ = lc $_ ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"Fred"} = "Joe" ;
+ # fk sk fv sv
+ ok(69, checkOutput( "", "fred", "", "Jxe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(70, $h{"Fred"} eq "[Jxe]");
+ # fk sk fv sv
+ ok(71, checkOutput( "", "fred", "[Jxe]", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(72, $db->FIRSTKEY() eq "FRED") ;
+ # fk sk fv sv
+ ok(73, checkOutput( "FRED", "", "", "")) ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(74, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(75, $h{"fred"} eq "joe");
+ ok(76, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(77, $db->FIRSTKEY() eq "fred") ;
+ ok(78, checkOutput( "fred", "", "", "")) ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(79, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(80, $h{"fred"} eq "joe");
+ ok(81, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(82, $db->FIRSTKEY() eq "fred") ;
+ ok(83, checkOutput( "", "", "", "")) ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter with a closure
+
+ use strict ;
+ my (%h, $db) ;
+
+ unlink $Dfile;
+ ok(84, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok(85, $result{"store key"} eq "store key - 1: [fred]");
+ ok(86, $result{"store value"} eq "store value - 1: [joe]");
+ ok(87, ! defined $result{"fetch key"} );
+ ok(88, ! defined $result{"fetch value"} );
+ ok(89, $_ eq "original") ;
+
+ ok(90, $db->FIRSTKEY() eq "fred") ;
+ ok(91, $result{"store key"} eq "store key - 1: [fred]");
+ ok(92, $result{"store value"} eq "store value - 1: [joe]");
+ ok(93, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(94, ! defined $result{"fetch value"} );
+ ok(95, $_ eq "original") ;
+
+ $h{"jim"} = "john" ;
+ ok(96, $result{"store key"} eq "store key - 2: [fred jim]");
+ ok(97, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(98, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(99, ! defined $result{"fetch value"} );
+ ok(100, $_ eq "original") ;
+
+ ok(101, $h{"fred"} eq "joe");
+ ok(102, $result{"store key"} eq "store key - 3: [fred jim fred]");
+ ok(103, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(104, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(105, $result{"fetch value"} eq "fetch value - 1: [joe]");
+ ok(106, $_ eq "original") ;
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter recursion detection
+ use strict ;
+ my (%h, $db) ;
+ unlink $Dfile;
+
+ ok(107, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+ $db->filter_store_key (sub { $_ = $h{$_} }) ;
+
+ eval '$h{1} = 1234' ;
+ ok(108, $@ =~ /^recursion detected in filter_store_key at/ );
+
+ undef $db ;
+ untie %h;
+ unlink $Dfile;
+}
+
+
+{
+ # Examples from the POD
+
+ my $file = "xyzt" ;
+ {
+ my $redirect = new Redirect $file ;
+
+ use strict ;
+ use DB_File ;
+ use vars qw( %h $k $v ) ;
+
+ unlink "fruit" ;
+ tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0640, $DB_HASH
+ or die "Cannot open file 'fruit': $!\n";
+
+ # Add a few key/value pairs to the file
+ $h{"apple"} = "red" ;
+ $h{"orange"} = "orange" ;
+ $h{"banana"} = "yellow" ;
+ $h{"tomato"} = "red" ;
+
+ # Check for existence of a key
+ print "Banana Exists\n\n" if $h{"banana"} ;
+
+ # Delete a key/value pair.
+ delete $h{"apple"} ;
+
+ # print the contents of the file
+ while (($k, $v) = each %h)
+ { print "$k -> $v\n" }
+
+ untie %h ;
+
+ unlink "fruit" ;
+ }
+
+ ok(109, docat_del($file) eq <<'EOM') ;
+Banana Exists
+
+orange -> orange
+tomato -> red
+banana -> yellow
+EOM
+
+}
+
exit ;
diff --git a/t/lib/db-recno.t b/t/lib/db-recno.t
index c89c3cafde..276f38bc3a 100755
--- a/t/lib/db-recno.t
+++ b/t/lib/db-recno.t
@@ -1,10 +1,10 @@
#!./perl -w
BEGIN {
- @INC = '../lib' if -d '../lib' ;
+ unshift @INC, '../lib' if -d '../lib' ;
require Config; import Config;
if ($Config{'extensions'} !~ /\bDB_File\b/) {
- print "1..0\n";
+ print "1..0 # Skip: DB_File was not built\n";
exit 0;
}
}
@@ -38,23 +38,68 @@ sub ok
return $result ;
}
+{
+ package Redirect ;
+ use Symbol ;
+
+ sub new
+ {
+ my $class = shift ;
+ my $filename = shift ;
+ my $fh = gensym ;
+ open ($fh, ">$filename") || die "Cannot open $filename: $!" ;
+ my $real_stdout = select($fh) ;
+ return bless [$fh, $real_stdout ] ;
+
+ }
+ sub DESTROY
+ {
+ my $self = shift ;
+ close $self->[0] ;
+ select($self->[1]) ;
+ }
+}
+
+sub docat
+{
+ my $file = shift;
+ local $/ = undef;
+ open(CAT,$file) || die "Cannot open $file:$!";
+ my $result = <CAT>;
+ close(CAT);
+ return $result;
+}
+
+sub docat_del
+{
+ my $file = shift;
+ local $/ = undef;
+ open(CAT,$file) || die "Cannot open $file: $!";
+ my $result = <CAT>;
+ close(CAT);
+ unlink $file ;
+ return $result;
+}
+
sub bad_one
{
print STDERR <<EOM unless $bad_ones++ ;
#
-# Some older versions of Berkeley DB will fail tests 51, 53 and 55.
+# Some older versions of Berkeley DB version 1 will fail tests 51,
+# 53 and 55.
#
# You can safely ignore the errors if you're never going to use the
# broken functionality (recno databases with a modified bval).
# Otherwise you'll have to upgrade your DB library.
#
-# If you want to upgrade Berkeley DB, the most recent version is 1.85.
-# Check out http://www.bostic.com/db for more details.
+# If you want to use Berkeley DB version 1, then 1.85 and 1.86 are the
+# last versions that were released. Berkeley DB version 2 is continually
+# being updated -- Check out http://www.sleepycat.com/ for more details.
#
EOM
}
-print "1..78\n";
+print "1..126\n";
my $Dfile = "recno.tmp";
unlink $Dfile ;
@@ -207,16 +252,6 @@ untie(@h);
unlink $Dfile;
-sub docat
-{
- my $file = shift;
- local $/ = undef;
- open(CAT,$file) || die "Cannot open $file:$!";
- my $result = <CAT>;
- close(CAT);
- return $result;
-}
-
{
# Check bval defaults to \n
@@ -450,4 +485,355 @@ EOM
}
+{
+ # DBM Filter tests
+ use strict ;
+ my (@h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ unlink $Dfile;
+
+ sub checkOutput
+ {
+ my($fk, $sk, $fv, $sv) = @_ ;
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ ok(79, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h[0] = "joe" ;
+ # fk sk fv sv
+ ok(80, checkOutput( "", 0, "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(81, $h[0] eq "joe");
+ # fk sk fv sv
+ ok(82, checkOutput( "", 0, "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(83, $db->FIRSTKEY() == 0) ;
+ # fk sk fv sv
+ ok(84, checkOutput( 0, "", "", "")) ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { ++ $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ *= 2 ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h[1] = "Joe" ;
+ # fk sk fv sv
+ ok(85, checkOutput( "", 2, "", "Jxe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(86, $h[1] eq "[Jxe]");
+ # fk sk fv sv
+ ok(87, checkOutput( "", 2, "[Jxe]", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(88, $db->FIRSTKEY() == 1) ;
+ # fk sk fv sv
+ ok(89, checkOutput( 1, "", "", "")) ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h[0] = "joe" ;
+ ok(90, checkOutput( "", 0, "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(91, $h[0] eq "joe");
+ ok(92, checkOutput( "", 0, "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(93, $db->FIRSTKEY() == 0) ;
+ ok(94, checkOutput( 0, "", "", "")) ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h[0] = "joe" ;
+ ok(95, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(96, $h[0] eq "joe");
+ ok(97, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(98, $db->FIRSTKEY() == 0) ;
+ ok(99, checkOutput( "", "", "", "")) ;
+
+ undef $db ;
+ untie @h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter with a closure
+
+ use strict ;
+ my (@h, $db) ;
+
+ unlink $Dfile;
+ ok(100, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h[0] = "joe" ;
+ ok(101, $result{"store key"} eq "store key - 1: [0]");
+ ok(102, $result{"store value"} eq "store value - 1: [joe]");
+ ok(103, ! defined $result{"fetch key"} );
+ ok(104, ! defined $result{"fetch value"} );
+ ok(105, $_ eq "original") ;
+
+ ok(106, $db->FIRSTKEY() == 0 ) ;
+ ok(107, $result{"store key"} eq "store key - 1: [0]");
+ ok(108, $result{"store value"} eq "store value - 1: [joe]");
+ ok(109, $result{"fetch key"} eq "fetch key - 1: [0]");
+ ok(110, ! defined $result{"fetch value"} );
+ ok(111, $_ eq "original") ;
+
+ $h[7] = "john" ;
+ ok(112, $result{"store key"} eq "store key - 2: [0 7]");
+ ok(113, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(114, $result{"fetch key"} eq "fetch key - 1: [0]");
+ ok(115, ! defined $result{"fetch value"} );
+ ok(116, $_ eq "original") ;
+
+ ok(117, $h[0] eq "joe");
+ ok(118, $result{"store key"} eq "store key - 3: [0 7 0]");
+ ok(119, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(120, $result{"fetch key"} eq "fetch key - 1: [0]");
+ ok(121, $result{"fetch value"} eq "fetch value - 1: [joe]");
+ ok(122, $_ eq "original") ;
+
+ undef $db ;
+ untie @h;
+ unlink $Dfile;
+}
+
+{
+ # DBM Filter recursion detection
+ use strict ;
+ my (@h, $db) ;
+ unlink $Dfile;
+
+ ok(123, $db = tie(@h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) );
+
+ $db->filter_store_key (sub { $_ = $h[0] }) ;
+
+ eval '$h[1] = 1234' ;
+ ok(124, $@ =~ /^recursion detected in filter_store_key at/ );
+
+ undef $db ;
+ untie @h;
+ unlink $Dfile;
+}
+
+
+{
+ # Examples from the POD
+
+ my $file = "xyzt" ;
+ {
+ my $redirect = new Redirect $file ;
+
+ use strict ;
+ use DB_File ;
+
+ my $filename = "text" ;
+ unlink $filename ;
+
+ my @h ;
+ my $x = tie @h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_RECNO
+ or die "Cannot open file 'text': $!\n" ;
+
+ # Add a few key/value pairs to the file
+ $h[0] = "orange" ;
+ $h[1] = "blue" ;
+ $h[2] = "yellow" ;
+
+ $FA ? push @h, "green", "black"
+ : $x->push("green", "black") ;
+
+ my $elements = $FA ? scalar @h : $x->length ;
+ print "The array contains $elements entries\n" ;
+
+ my $last = $FA ? pop @h : $x->pop ;
+ print "popped $last\n" ;
+
+ $FA ? unshift @h, "white"
+ : $x->unshift("white") ;
+ my $first = $FA ? shift @h : $x->shift ;
+ print "shifted $first\n" ;
+
+ # Check for existence of a key
+ print "Element 1 Exists with value $h[1]\n" if $h[1] ;
+
+ # use a negative index
+ print "The last element is $h[-1]\n" ;
+ print "The 2nd last element is $h[-2]\n" ;
+
+ undef $x ;
+ untie @h ;
+
+ unlink $filename ;
+ }
+
+ ok(125, docat_del($file) eq <<'EOM') ;
+The array contains 5 entries
+popped black
+shifted white
+Element 1 Exists with value blue
+The last element is green
+The 2nd last element is yellow
+EOM
+
+ my $save_output = "xyzt" ;
+ {
+ my $redirect = new Redirect $save_output ;
+
+ use strict ;
+ use vars qw(@h $H $file $i) ;
+ use DB_File ;
+ use Fcntl ;
+
+ $file = "text" ;
+
+ unlink $file ;
+
+ $H = tie @h, "DB_File", $file, O_RDWR|O_CREAT, 0640, $DB_RECNO
+ or die "Cannot open file $file: $!\n" ;
+
+ # first create a text file to play with
+ $h[0] = "zero" ;
+ $h[1] = "one" ;
+ $h[2] = "two" ;
+ $h[3] = "three" ;
+ $h[4] = "four" ;
+
+
+ # Print the records in order.
+ #
+ # The length method is needed here because evaluating a tied
+ # array in a scalar context does not return the number of
+ # elements in the array.
+
+ print "\nORIGINAL\n" ;
+ foreach $i (0 .. $H->length - 1) {
+ print "$i: $h[$i]\n" ;
+ }
+
+ # use the push & pop methods
+ $a = $H->pop ;
+ $H->push("last") ;
+ print "\nThe last record was [$a]\n" ;
+
+ # and the shift & unshift methods
+ $a = $H->shift ;
+ $H->unshift("first") ;
+ print "The first record was [$a]\n" ;
+
+ # Use the API to add a new record after record 2.
+ $i = 2 ;
+ $H->put($i, "Newbie", R_IAFTER) ;
+
+ # and a new record before record 1.
+ $i = 1 ;
+ $H->put($i, "New One", R_IBEFORE) ;
+
+ # delete record 3
+ $H->del(3) ;
+
+ # now print the records in reverse order
+ print "\nREVERSE\n" ;
+ for ($i = $H->length - 1 ; $i >= 0 ; -- $i)
+ { print "$i: $h[$i]\n" }
+
+ # same again, but use the API functions instead
+ print "\nREVERSE again\n" ;
+ my ($s, $k, $v) = (0, 0, 0) ;
+ for ($s = $H->seq($k, $v, R_LAST) ;
+ $s == 0 ;
+ $s = $H->seq($k, $v, R_PREV))
+ { print "$k: $v\n" }
+
+ undef $H ;
+ untie @h ;
+
+ unlink $file ;
+ }
+
+ ok(126, docat_del($save_output) eq <<'EOM') ;
+
+ORIGINAL
+0: zero
+1: one
+2: two
+3: three
+4: four
+
+The last record was [four]
+The first record was [zero]
+
+REVERSE
+5: last
+4: three
+3: Newbie
+2: one
+1: New One
+0: first
+
+REVERSE again
+5: last
+4: three
+3: Newbie
+2: one
+1: New One
+0: first
+EOM
+
+}
+
exit ;
diff --git a/t/lib/dirhand.t b/t/lib/dirhand.t
index aa7be356df..a8683c7fb8 100755
--- a/t/lib/dirhand.t
+++ b/t/lib/dirhand.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if (not $Config{'d_readdir'}) {
print "1..0\n";
diff --git a/t/lib/dosglob.t b/t/lib/dosglob.t
index 577d4eac22..ea537bf6d1 100755
--- a/t/lib/dosglob.t
+++ b/t/lib/dosglob.t
@@ -6,7 +6,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..10\n";
diff --git a/t/lib/dprof.t b/t/lib/dprof.t
new file mode 100755
index 0000000000..4d6f7823c3
--- /dev/null
+++ b/t/lib/dprof.t
@@ -0,0 +1,80 @@
+#!perl
+
+BEGIN {
+ chdir( 't' ) if -d 't';
+ unshift @INC, '../lib';
+}
+
+END {
+ unlink 'tmon.out', 'err';
+}
+
+use Benchmark qw( timediff timestr );
+use Getopt::Std 'getopts';
+use Config '%Config';
+getopts('vI:p:');
+
+# -v Verbose
+# -I Add to @INC
+# -p Name of perl binary
+
+@tests = @ARGV ? @ARGV : sort <lib/dprof/*_t lib/dprof/*_v>; # glob-sort, for OS/2
+
+$path_sep = $Config{path_sep} || ':';
+$perl5lib = $opt_I || join( $path_sep, @INC );
+$perl = $opt_p || $^X;
+
+if( $opt_v ){
+ print "tests: @tests\n";
+ print "perl: $perl\n";
+ print "perl5lib: $perl5lib\n";
+}
+if( $perl =~ m|^\./| ){
+ # turn ./perl into ../perl, because of chdir(t) above.
+ $perl = ".$perl";
+}
+if( ! -f $perl ){ die "Where's Perl?" }
+
+sub profile {
+ my $test = shift;
+ my @results;
+ local $ENV{PERL5LIB} = $perl5lib;
+ my $opt_d = '-d:DProf';
+
+ my $t_start = new Benchmark;
+ open( R, "$perl $opt_d $test |" ) || warn "$0: Can't run. $!\n";
+ @results = <R>;
+ close R;
+ my $t_total = timediff( new Benchmark, $t_start );
+
+ if( $opt_v ){
+ print "\n";
+ print @results
+ }
+
+ print timestr( $t_total, 'nop' ), "\n";
+}
+
+
+sub verify {
+ my $test = shift;
+
+ system $perl, '-I../lib', '-I./lib/dprof', $test,
+ $opt_v?'-v':'', '-p', $perl;
+}
+
+
+$| = 1;
+print "1..18\n";
+while( @tests ){
+ $test = shift @tests;
+ if( $test =~ /_t$/i ){
+ print "# $test" . '.' x (20 - length $test);
+ profile $test;
+ }
+ else{
+ verify $test;
+ }
+}
+
+unlink("tmon.out");
diff --git a/t/lib/dprof/V.pm b/t/lib/dprof/V.pm
new file mode 100644
index 0000000000..7e34da5d47
--- /dev/null
+++ b/t/lib/dprof/V.pm
@@ -0,0 +1,59 @@
+package V;
+
+use Getopt::Std 'getopts';
+getopts('vp:d:');
+
+require Exporter;
+@ISA = 'Exporter';
+
+@EXPORT = qw( dprofpp $opt_v $results $expected report @results );
+@EXPORT_OK = qw( notok ok $num );
+
+$num = 0;
+$results = $expected = '';
+$perl = $opt_p || $^X;
+$dpp = $opt_d || '../utils/dprofpp';
+
+print "\nperl: $perl\n" if $opt_v;
+if( ! -f $perl ){ die "Where's Perl?" }
+if( ! -f $dpp ){ die "Where's dprofpp?" }
+
+sub dprofpp {
+ my $switches = shift;
+
+ open( D, "$perl -I../lib $dpp $switches 2> err |" ) || warn "$0: Can't run. $!\n";
+ @results = <D>;
+ close D;
+
+ open( D, "<err" ) || warn "$0: Can't open: $!\n";
+ @err = <D>;
+ close D;
+ push( @results, @err ) if @err;
+
+ $results = qq{@results};
+ # ignore Loader (Dyna/Auto etc), leave newline
+ $results =~ s/^\w+Loader::import//;
+ $results =~ s/\n /\n/gm;
+ $results;
+}
+
+sub report {
+ $num = shift;
+ my $sub = shift;
+ my $x;
+
+ $x = &$sub;
+ $x ? &ok : &notok;
+}
+
+sub ok {
+ print "ok $num\n";
+}
+
+sub notok {
+ print "not ok $num\n";
+ print "\nResult\n{$results}\n";
+ print "Expected\n{$expected}\n";
+}
+
+1;
diff --git a/t/lib/dprof/test1_t b/t/lib/dprof/test1_t
new file mode 100644
index 0000000000..d504cd5536
--- /dev/null
+++ b/t/lib/dprof/test1_t
@@ -0,0 +1,18 @@
+sub foo {
+ print "in sub foo\n";
+ bar();
+}
+
+sub bar {
+ print "in sub bar\n";
+}
+
+sub baz {
+ print "in sub baz\n";
+ bar();
+ foo();
+}
+
+bar();
+baz();
+foo();
diff --git a/t/lib/dprof/test1_v b/t/lib/dprof/test1_v
new file mode 100644
index 0000000000..542a503414
--- /dev/null
+++ b/t/lib/dprof/test1_v
@@ -0,0 +1,24 @@
+# perl
+
+use V;
+
+dprofpp( '-T' );
+$expected =
+qq{main::bar
+main::baz
+ main::bar
+ main::foo
+ main::bar
+main::foo
+ main::bar
+};
+report 1, sub { $expected eq $results };
+
+dprofpp('-TF');
+report 2, sub { $expected eq $results };
+
+dprofpp( '-t' );
+report 3, sub { $expected eq $results };
+
+dprofpp('-tF');
+report 4, sub { $expected eq $results };
diff --git a/t/lib/dprof/test2_t b/t/lib/dprof/test2_t
new file mode 100644
index 0000000000..edc46c527e
--- /dev/null
+++ b/t/lib/dprof/test2_t
@@ -0,0 +1,21 @@
+sub foo {
+ print "in sub foo\n";
+ bar();
+}
+
+sub bar {
+ print "in sub bar\n";
+}
+
+sub baz {
+ print "in sub baz\n";
+ bar();
+ bar();
+ bar();
+ foo();
+}
+
+bar();
+bar();
+baz();
+foo();
diff --git a/t/lib/dprof/test2_v b/t/lib/dprof/test2_v
new file mode 100644
index 0000000000..8b775b3131
--- /dev/null
+++ b/t/lib/dprof/test2_v
@@ -0,0 +1,36 @@
+# perl
+
+use V;
+
+dprofpp( '-T' );
+$expected =
+qq{main::bar
+main::bar
+main::baz
+ main::bar
+ main::bar
+ main::bar
+ main::foo
+ main::bar
+main::foo
+ main::bar
+};
+report 5, sub { $expected eq $results };
+
+dprofpp('-TF');
+report 6, sub { $expected eq $results };
+
+dprofpp( '-t' );
+$expected =
+qq{main::bar (2x)
+main::baz
+ main::bar (3x)
+ main::foo
+ main::bar
+main::foo
+ main::bar
+};
+report 7, sub { $expected eq $results };
+
+dprofpp('-tF');
+report 8, sub { $expected eq $results };
diff --git a/t/lib/dprof/test3_t b/t/lib/dprof/test3_t
new file mode 100644
index 0000000000..a5327f4d7a
--- /dev/null
+++ b/t/lib/dprof/test3_t
@@ -0,0 +1,19 @@
+sub foo {
+ print "in sub foo\n";
+ exit(0);
+ bar();
+}
+
+sub bar {
+ print "in sub bar\n";
+}
+
+sub baz {
+ print "in sub baz\n";
+ bar();
+ foo();
+}
+
+bar();
+baz();
+foo();
diff --git a/t/lib/dprof/test3_v b/t/lib/dprof/test3_v
new file mode 100644
index 0000000000..df7543e2b8
--- /dev/null
+++ b/t/lib/dprof/test3_v
@@ -0,0 +1,29 @@
+# perl
+
+use V;
+
+dprofpp( '-T' );
+$e1 = $expected =
+qq{main::bar
+main::baz
+ main::bar
+ main::foo
+};
+report 9, sub { $expected eq $results };
+
+dprofpp('-TF');
+$e2 = $expected =
+qq{main::bar
+main::baz
+ main::bar
+ main::foo
+};
+report 10, sub { $expected eq $results };
+
+dprofpp( '-t' );
+$expected = $e1;
+report 11, sub { 1 };
+
+dprofpp('-tF');
+$expected = $e2;
+report 12, sub { $expected eq $results };
diff --git a/t/lib/dprof/test4_t b/t/lib/dprof/test4_t
new file mode 100644
index 0000000000..729968270a
--- /dev/null
+++ b/t/lib/dprof/test4_t
@@ -0,0 +1,24 @@
+sub foo {
+ print "in sub foo\n";
+ bar();
+}
+
+sub bar {
+ print "in sub bar\n";
+}
+
+sub baz {
+ print "in sub baz\n";
+ bar();
+ bar();
+ bar();
+ foo();
+}
+
+bar();
+
+eval { fork };
+
+bar();
+baz();
+foo();
diff --git a/t/lib/dprof/test4_v b/t/lib/dprof/test4_v
new file mode 100644
index 0000000000..d9677ff785
--- /dev/null
+++ b/t/lib/dprof/test4_v
@@ -0,0 +1,36 @@
+# perl
+
+use V;
+
+dprofpp( '-T' );
+$expected =
+qq{main::bar
+main::bar
+main::baz
+ main::bar
+ main::bar
+ main::bar
+ main::foo
+ main::bar
+main::foo
+ main::bar
+};
+report 13, sub { $expected eq $results };
+
+dprofpp('-TF');
+report 14, sub { $expected eq $results };
+
+dprofpp( '-t' );
+$expected =
+qq{main::bar (2x)
+main::baz
+ main::bar (3x)
+ main::foo
+ main::bar
+main::foo
+ main::bar
+};
+report 15, sub { $expected eq $results };
+
+dprofpp('-tF');
+report 16, sub { $expected eq $results };
diff --git a/t/lib/dprof/test5_t b/t/lib/dprof/test5_t
new file mode 100644
index 0000000000..0b1113757f
--- /dev/null
+++ b/t/lib/dprof/test5_t
@@ -0,0 +1,25 @@
+# Test that dprof doesn't break
+# &bar; used as &bar(@_);
+
+sub foo1 {
+ print "in foo1(@_)\n";
+ bar(@_);
+}
+sub foo2 {
+ print "in foo2(@_)\n";
+ &bar;
+}
+sub bar {
+ print "in bar(@_)\n";
+ if( @_ > 0 ){
+ &yeppers;
+ }
+}
+sub yeppers {
+ print "rest easy\n";
+}
+
+
+&foo1( A );
+&foo2( B );
+
diff --git a/t/lib/dprof/test5_v b/t/lib/dprof/test5_v
new file mode 100644
index 0000000000..9e9298c689
--- /dev/null
+++ b/t/lib/dprof/test5_v
@@ -0,0 +1,15 @@
+# perl
+
+use V;
+
+dprofpp( '-T' );
+$expected =
+qq{main::foo1
+ main::bar
+ main::yeppers
+main::foo2
+ main::bar
+ main::yeppers
+};
+report 17, sub { $expected eq $results };
+
diff --git a/t/lib/dprof/test6_t b/t/lib/dprof/test6_t
new file mode 100644
index 0000000000..7b8bf4a722
--- /dev/null
+++ b/t/lib/dprof/test6_t
@@ -0,0 +1,29 @@
+sub foo {
+ my $x;
+ my $y;
+ print "in sub foo\n";
+ for( $x = 1; $x < 100; ++$x ){
+ bar();
+ for( $y = 1; $y < 100; ++$y ){
+ }
+ }
+}
+
+sub bar {
+ my $x;
+ print "in sub bar\n";
+ for( $x = 1; $x < 100; ++$x ){
+ }
+ die "bar exiting";
+}
+
+sub baz {
+ print "in sub baz\n";
+ eval { bar(); };
+ eval { foo(); };
+}
+
+eval { bar(); };
+baz();
+eval { foo(); };
+
diff --git a/t/lib/dprof/test6_v b/t/lib/dprof/test6_v
new file mode 100644
index 0000000000..2f651ea794
--- /dev/null
+++ b/t/lib/dprof/test6_v
@@ -0,0 +1,16 @@
+# perl
+
+use V;
+
+dprofpp( '-T' );
+$expected =
+qq{main::bar
+main::baz
+ main::bar
+ main::foo
+ main::bar
+main::foo
+ main::bar
+};
+report 18, sub { $expected eq $results };
+
diff --git a/t/lib/dumper-ovl.t b/t/lib/dumper-ovl.t
index db4a5d9e75..8c095e59be 100755
--- a/t/lib/dumper-ovl.t
+++ b/t/lib/dumper-ovl.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
use Data::Dumper;
diff --git a/t/lib/dumper.t b/t/lib/dumper.t
index 70f8abeb9e..9130d1c690 100755
--- a/t/lib/dumper.t
+++ b/t/lib/dumper.t
@@ -5,7 +5,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
use Data::Dumper;
@@ -20,6 +20,8 @@ sub TEST {
my $string = shift;
my $t = eval $string;
++$TNUM;
+ $t =~ s/([A-Z]+)\(0x[0-9a-f]+\)/$1(0xdeadbeef)/g
+ if ($WANT =~ /deadbeef/);
print( ($t eq $WANT and not $@) ? "ok $TNUM\n"
: "not ok $TNUM\n--Expected--\n$WANT\n--Got--\n$@$t\n");
@@ -29,17 +31,19 @@ sub TEST {
$t = eval $string;
++$TNUM;
+ $t =~ s/([A-Z]+)\(0x[0-9a-f]+\)/$1(0xdeadbeef)/g
+ if ($WANT =~ /deadbeef/);
print( ($t eq $WANT and not $@) ? "ok $TNUM\n"
: "not ok $TNUM\n--Expected--\n$WANT\n--Got--\n$@$t\n");
}
if (defined &Data::Dumper::Dumpxs) {
print "### XS extension loaded, will run XS tests\n";
- $TMAX = 138; $XS = 1;
+ $TMAX = 174; $XS = 1;
}
else {
print "### XS extensions not loaded, will NOT run XS tests\n";
- $TMAX = 69; $XS = 0;
+ $TMAX = 87; $XS = 0;
}
print "1..$TMAX\n";
@@ -236,11 +240,11 @@ EOT
##
$WANT = <<'EOT';
#$VAR1 = {
-# "abc\000\efg" => "mno\000"
+# "abc\0'\efg" => "mno\0"
#};
EOT
-$foo = { "abc\000\efg" => "mno\000" };
+$foo = { "abc\000\'\efg" => "mno\000" };
{
local $Data::Dumper::Useqq = 1;
TEST q(Dumper($foo));
@@ -248,7 +252,7 @@ $foo = { "abc\000\efg" => "mno\000" };
$WANT = <<"EOT";
#\$VAR1 = {
-# 'abc\000\efg' => 'mno\000'
+# 'abc\0\\'\efg' => 'mno\0'
#};
EOT
@@ -450,8 +454,8 @@ EOT
# Second => \'Wags'
#);
#@dogs = (
-# $kennels{First},
-# $kennels{Second},
+# ${$kennels{First}},
+# ${$kennels{Second}},
# \%kennels
#);
#%mutts = %kennels;
@@ -489,8 +493,8 @@ EOT
# Second => \'Wags'
#);
#@dogs = (
-# $kennels{First},
-# $kennels{Second},
+# ${$kennels{First}},
+# ${$kennels{Second}},
# \%kennels
#);
#%mutts = %kennels;
@@ -566,8 +570,8 @@ EOT
{
-sub a { print "foo\n" }
-$c = [ \&a ];
+sub z { print "foo\n" }
+$c = [ \&z ];
############# 121
##
@@ -578,8 +582,8 @@ $c = [ \&a ];
#];
EOT
-TEST q(Data::Dumper->new([\&a,$c],['a','c'])->Seen({'b' => \&a})->Dump;);
-TEST q(Data::Dumper->new([\&a,$c],['a','c'])->Seen({'b' => \&a})->Dumpxs;)
+TEST q(Data::Dumper->new([\&z,$c],['a','c'])->Seen({'b' => \&z})->Dump;);
+TEST q(Data::Dumper->new([\&z,$c],['a','c'])->Seen({'b' => \&z})->Dumpxs;)
if $XS;
############# 127
@@ -591,8 +595,8 @@ TEST q(Data::Dumper->new([\&a,$c],['a','c'])->Seen({'b' => \&a})->Dumpxs;)
#];
EOT
-TEST q(Data::Dumper->new([\&a,$c],['a','c'])->Seen({'*b' => \&a})->Dump;);
-TEST q(Data::Dumper->new([\&a,$c],['a','c'])->Seen({'*b' => \&a})->Dumpxs;)
+TEST q(Data::Dumper->new([\&z,$c],['a','c'])->Seen({'*b' => \&z})->Dump;);
+TEST q(Data::Dumper->new([\&z,$c],['a','c'])->Seen({'*b' => \&z})->Dumpxs;)
if $XS;
############# 133
@@ -604,8 +608,146 @@ TEST q(Data::Dumper->new([\&a,$c],['a','c'])->Seen({'*b' => \&a})->Dumpxs;)
#);
EOT
-TEST q(Data::Dumper->new([\&a,$c],['*a','*c'])->Seen({'*b' => \&a})->Dump;);
-TEST q(Data::Dumper->new([\&a,$c],['*a','*c'])->Seen({'*b' => \&a})->Dumpxs;)
+TEST q(Data::Dumper->new([\&z,$c],['*a','*c'])->Seen({'*b' => \&z})->Dump;);
+TEST q(Data::Dumper->new([\&z,$c],['*a','*c'])->Seen({'*b' => \&z})->Dumpxs;)
if $XS;
}
+
+{
+ $a = [];
+ $a->[1] = \$a->[0];
+
+############# 139
+##
+ $WANT = <<'EOT';
+#@a = (
+# undef,
+# ''
+#);
+#$a[1] = \$a[0];
+EOT
+
+TEST q(Data::Dumper->new([$a],['*a'])->Purity(1)->Dump;);
+TEST q(Data::Dumper->new([$a],['*a'])->Purity(1)->Dumpxs;)
+ if $XS;
+}
+
+{
+ $a = \\\\\'foo';
+ $b = $$$a;
+
+############# 145
+##
+ $WANT = <<'EOT';
+#$a = \\\\\'foo';
+#$b = ${${$a}};
+EOT
+
+TEST q(Data::Dumper->new([$a,$b],['a','b'])->Purity(1)->Dump;);
+TEST q(Data::Dumper->new([$a,$b],['a','b'])->Purity(1)->Dumpxs;)
+ if $XS;
+}
+
+{
+ $a = [{ a => \$b }, { b => undef }];
+ $b = [{ c => \$b }, { d => \$a }];
+
+############# 151
+##
+ $WANT = <<'EOT';
+#$a = [
+# {
+# a => \[
+# {
+# c => ''
+# },
+# {
+# d => \[]
+# }
+# ]
+# },
+# {
+# b => undef
+# }
+#];
+#${$a->[0]{a}}->[0]->{c} = $a->[0]{a};
+#${${$a->[0]{a}}->[1]->{d}} = $a;
+#$b = ${$a->[0]{a}};
+EOT
+
+TEST q(Data::Dumper->new([$a,$b],['a','b'])->Purity(1)->Dump;);
+TEST q(Data::Dumper->new([$a,$b],['a','b'])->Purity(1)->Dumpxs;)
+ if $XS;
+}
+
+{
+ $a = [[[[\\\\\'foo']]]];
+ $b = $a->[0][0];
+ $c = $${$b->[0][0]};
+
+############# 157
+##
+ $WANT = <<'EOT';
+#$a = [
+# [
+# [
+# [
+# \\\\\'foo'
+# ]
+# ]
+# ]
+#];
+#$b = $a->[0][0];
+#$c = ${${$a->[0][0][0][0]}};
+EOT
+
+TEST q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Purity(1)->Dump;);
+TEST q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Purity(1)->Dumpxs;)
+ if $XS;
+}
+
+{
+ $f = "pearl";
+ $e = [ $f ];
+ $d = { 'e' => $e };
+ $c = [ $d ];
+ $b = { 'c' => $c };
+ $a = { 'b' => $b };
+
+############# 163
+##
+ $WANT = <<'EOT';
+#$a = {
+# b => {
+# c => [
+# {
+# e => 'ARRAY(0xdeadbeef)'
+# }
+# ]
+# }
+#};
+#$b = $a->{b};
+#$c = $a->{b}{c};
+EOT
+
+TEST q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Maxdepth(4)->Dump;);
+TEST q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Maxdepth(4)->Dumpxs;)
+ if $XS;
+
+############# 169
+##
+ $WANT = <<'EOT';
+#$a = {
+# b => 'HASH(0xdeadbeef)'
+#};
+#$b = $a->{b};
+#$c = [
+# 'HASH(0xdeadbeef)'
+#];
+EOT
+
+TEST q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Maxdepth(1)->Dump;);
+TEST q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Maxdepth(1)->Dumpxs;)
+ if $XS;
+}
diff --git a/t/lib/english.t b/t/lib/english.t
index 9691229be0..2ee613352b 100755
--- a/t/lib/english.t
+++ b/t/lib/english.t
@@ -2,7 +2,7 @@
print "1..16\n";
-BEGIN { @INC = '../lib' }
+BEGIN { unshift @INC, '../lib' }
use English;
use Config;
my $threads = $Config{'usethreads'} || 0;
diff --git a/t/lib/env.t b/t/lib/env.t
index 5a8220778a..93d24066e6 100755
--- a/t/lib/env.t
+++ b/t/lib/env.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
BEGIN {
diff --git a/t/lib/errno.t b/t/lib/errno.t
index 361723f1b2..6320f6b236 100755
--- a/t/lib/errno.t
+++ b/t/lib/errno.t
@@ -3,7 +3,7 @@
BEGIN {
unless(grep /blib/, @INC) {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
}
diff --git a/t/lib/fatal.t b/t/lib/fatal.t
new file mode 100755
index 0000000000..019265899a
--- /dev/null
+++ b/t/lib/fatal.t
@@ -0,0 +1,28 @@
+#!./perl -w
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+ print "1..13\n";
+}
+
+use strict;
+use Fatal qw(open close);
+
+my $i = 1;
+eval { open FOO, '<lkjqweriuapofukndajsdlfjnvcvn' };
+print "not " unless $@ =~ /^Can't open/;
+print "ok $i\n"; ++$i;
+
+my $foo = 'FOO';
+for ('$foo', "'$foo'", "*$foo", "\\*$foo") {
+ eval qq{ open $_, '<$0' };
+ print "not " if $@;
+ print "ok $i\n"; ++$i;
+
+ print "not " if $@ or scalar(<$foo>) !~ m|^#!./perl|;
+ print "ok $i\n"; ++$i;
+ eval qq{ close FOO };
+ print "not " if $@;
+ print "ok $i\n"; ++$i;
+}
diff --git a/t/lib/fields.t b/t/lib/fields.t
index 139e469b5a..6f3ea5bb48 100755
--- a/t/lib/fields.t
+++ b/t/lib/fields.t
@@ -4,7 +4,7 @@ my $w;
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
$SIG{__WARN__} = sub {
if ($_[0] =~ /^Hides field 'b1' in base class/) {
$w++;
@@ -82,7 +82,7 @@ my %expect = (
'Foo::Bar::Baz' => 'b1:1,b2:2,b3:3,foo:4,bar:5,baz:6',
);
-print "1..", int(keys %expect)+3, "\n";
+print "1..", int(keys %expect)+5, "\n";
my $testno = 0;
while (my($class, $exp) = each %expect) {
no strict 'refs';
@@ -110,3 +110,17 @@ print "not " unless $@ && $@ =~ /^No such field "notthere"/;
print "ok ", ++$testno, "\n";
#fields::_dump();
+
+# check if
+{
+ package Foo;
+ use fields qw(foo bar);
+ sub new { bless [], $_[0]; }
+
+ package main;
+ my Foo $a = Foo->new();
+ $a->{foo} = ['a', 'ok ' . ++$testno, 'c'];
+ $a->{bar} = { A => 'ok ' . ++$testno };
+ print $a->{foo}[1], "\n";
+ print $a->{bar}->{A}, "\n";
+}
diff --git a/t/lib/filecache.t b/t/lib/filecache.t
index a97fdd532c..019f3742c5 100755
--- a/t/lib/filecache.t
+++ b/t/lib/filecache.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..1\n";
diff --git a/t/lib/filecopy.t b/t/lib/filecopy.t
index 329931f4b4..e461595d9b 100755
--- a/t/lib/filecopy.t
+++ b/t/lib/filecopy.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..11\n";
diff --git a/t/lib/filefind.t b/t/lib/filefind.t
index cd2e9771c7..5d1492f040 100755
--- a/t/lib/filefind.t
+++ b/t/lib/filefind.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..2\n";
diff --git a/t/lib/filefunc.t b/t/lib/filefunc.t
new file mode 100755
index 0000000000..46a1e35774
--- /dev/null
+++ b/t/lib/filefunc.t
@@ -0,0 +1,17 @@
+#!./perl
+
+BEGIN {
+ $^O = '';
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+print "1..1\n";
+
+use File::Spec::Functions;
+
+if (catfile('a','b','c') eq 'a/b/c') {
+ print "ok 1\n";
+} else {
+ print "not ok 1\n";
+}
diff --git a/t/lib/filehand.t b/t/lib/filehand.t
index 08cae71872..22cff0ecb0 100755
--- a/t/lib/filehand.t
+++ b/t/lib/filehand.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if ($Config{'extensions'} !~ /\bIO\b/ && $^O ne 'VMS') {
print "1..0\n";
@@ -31,7 +31,7 @@ $buffer = <$fh>;
print $buffer eq "#!./perl\n" ? "ok 3\n" : "not ok 3\n";
-ungetc $fh 65;
+ungetc $fh ord 'A';
CORE::read($fh, $buf,1);
print $buf eq 'A' ? "ok 4\n" : "not ok 4\n";
@@ -72,7 +72,8 @@ if ($^O eq 'dos')
($rd,$wr) = FileHandle::pipe;
-if ($^O eq 'VMS' || $^O eq 'os2' || $^O eq 'amigaos' || $^O eq 'MSWin32') {
+if ($^O eq 'VMS' || $^O eq 'os2' || $^O eq 'amigaos' || $^O eq 'MSWin32' ||
+ $Config{d_fork} ne 'define') {
$wr->autoflush;
$wr->printf("ok %d\n",11);
print $rd->getline;
diff --git a/t/lib/filepath.t b/t/lib/filepath.t
index c3bf4a4479..40e6e213c1 100755
--- a/t/lib/filepath.t
+++ b/t/lib/filepath.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use File::Path;
diff --git a/t/lib/filespec.t b/t/lib/filespec.t
index ca22d3e12b..3aeed17958 100755
--- a/t/lib/filespec.t
+++ b/t/lib/filespec.t
@@ -3,7 +3,7 @@
BEGIN {
$^O = '';
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..4\n";
diff --git a/t/lib/findbin.t b/t/lib/findbin.t
index 3e742f9a4f..f0939e94a9 100755
--- a/t/lib/findbin.t
+++ b/t/lib/findbin.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..1\n";
diff --git a/t/lib/gdbm.t b/t/lib/gdbm.t
index 2395611d1e..dc4e96e4d8 100755
--- a/t/lib/gdbm.t
+++ b/t/lib/gdbm.t
@@ -3,17 +3,17 @@
# $RCSfile: dbm.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:43 $
BEGIN {
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if ($Config{'extensions'} !~ /\bGDBM_File\b/) {
- print "1..0\n";
+ print "1..0 # Skip: GDBM_File was not built\n";
exit 0;
}
}
use GDBM_File;
-print "1..20\n";
+print "1..66\n";
unlink <Op.dbmx*>;
@@ -206,3 +206,189 @@ EOM
unlink "SubDB.pm", <dbhash.tmp*> ;
}
+
+{
+ # DBM Filter tests
+ use strict ;
+ my (%h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+
+ sub checkOutput
+ {
+ my($fk, $sk, $fv, $sv) = @_ ;
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ unlink <Op.dbmx*>;
+ ok(21, $db = tie(%h, 'GDBM_File','Op.dbmx', &GDBM_WRCREAT, 0640)) ;
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ # fk sk fv sv
+ ok(22, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(23, $h{"fred"} eq "joe");
+ # fk sk fv sv
+ ok(24, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(25, $db->FIRSTKEY() eq "fred") ;
+ # fk sk fv sv
+ ok(26, checkOutput( "fred", "", "", "")) ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ = lc $_ ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"Fred"} = "Joe" ;
+ # fk sk fv sv
+ ok(27, checkOutput( "", "fred", "", "Jxe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(28, $h{"Fred"} eq "[Jxe]");
+ # fk sk fv sv
+ ok(29, checkOutput( "", "fred", "[Jxe]", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(30, $db->FIRSTKEY() eq "FRED") ;
+ # fk sk fv sv
+ ok(31, checkOutput( "FRED", "", "", "")) ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(32, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(33, $h{"fred"} eq "joe");
+ ok(34, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(35, $db->FIRSTKEY() eq "fred") ;
+ ok(36, checkOutput( "fred", "", "", "")) ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(37, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(38, $h{"fred"} eq "joe");
+ ok(39, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(40, $db->FIRSTKEY() eq "fred") ;
+ ok(41, checkOutput( "", "", "", "")) ;
+
+ undef $db ;
+ untie %h;
+ unlink <Op.dbmx*>;
+}
+
+{
+ # DBM Filter with a closure
+
+ use strict ;
+ my (%h, $db) ;
+
+ unlink <Op.dbmx*>;
+ ok(42, $db = tie(%h, 'GDBM_File','Op.dbmx', &GDBM_WRCREAT, 0640)) ;
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok(43, $result{"store key"} eq "store key - 1: [fred]");
+ ok(44, $result{"store value"} eq "store value - 1: [joe]");
+ ok(45, !defined $result{"fetch key"} );
+ ok(46, !defined $result{"fetch value"} );
+ ok(47, $_ eq "original") ;
+
+ ok(48, $db->FIRSTKEY() eq "fred") ;
+ ok(49, $result{"store key"} eq "store key - 1: [fred]");
+ ok(50, $result{"store value"} eq "store value - 1: [joe]");
+ ok(51, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(52, ! defined $result{"fetch value"} );
+ ok(53, $_ eq "original") ;
+
+ $h{"jim"} = "john" ;
+ ok(54, $result{"store key"} eq "store key - 2: [fred jim]");
+ ok(55, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(56, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(57, $result{"fetch value"} eq "");
+ ok(58, $_ eq "original") ;
+
+ ok(59, $h{"fred"} eq "joe");
+ ok(60, $result{"store key"} eq "store key - 3: [fred jim fred]");
+ ok(61, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(62, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(63, $result{"fetch value"} eq "fetch value - 1: [joe]");
+ ok(64, $_ eq "original") ;
+
+ undef $db ;
+ untie %h;
+ unlink <Op.dbmx*>;
+}
+
+{
+ # DBM Filter recursion detection
+ use strict ;
+ my (%h, $db) ;
+ unlink <Op.dbmx*>;
+
+ ok(65, $db = tie(%h, 'GDBM_File','Op.dbmx', &GDBM_WRCREAT, 0640)) ;
+
+ $db->filter_store_key (sub { $_ = $h{$_} }) ;
+
+ eval '$h{1} = 1234' ;
+ ok(66, $@ =~ /^recursion detected in filter_store_key at/ );
+
+ undef $db ;
+ untie %h;
+ unlink <Op.dbmx*>;
+}
diff --git a/t/lib/getopt.t b/t/lib/getopt.t
index fb70f10aae..035462722b 100755
--- a/t/lib/getopt.t
+++ b/t/lib/getopt.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..11\n";
diff --git a/t/lib/gol-basic.t b/t/lib/gol-basic.t
new file mode 100755
index 0000000000..4b25322336
--- /dev/null
+++ b/t/lib/gol-basic.t
@@ -0,0 +1,24 @@
+#!./perl -w
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+use Getopt::Long 2.17;
+
+print "1..9\n";
+
+@ARGV = qw(-Foo -baR --foo bar);
+Getopt::Long::Configure ("no_ignore_case");
+undef $opt_baR;
+undef $opt_bar;
+print "ok 1\n" if GetOptions ("foo", "Foo=s");
+print ((defined $opt_foo) ? "" : "not ", "ok 2\n");
+print (($opt_foo == 1) ? "" : "not ", "ok 3\n");
+print ((defined $opt_Foo) ? "" : "not ", "ok 4\n");
+print (($opt_Foo eq "-baR") ? "" : "not ", "ok 5\n");
+print ((@ARGV == 1) ? "" : "not ", "ok 6\n");
+print (($ARGV[0] eq "bar") ? "" : "not ", "ok 7\n");
+print (!(defined $opt_baR) ? "" : "not ", "ok 8\n");
+print (!(defined $opt_bar) ? "" : "not ", "ok 9\n");
diff --git a/t/lib/gol-compat.t b/t/lib/gol-compat.t
new file mode 100755
index 0000000000..a4f807c7dd
--- /dev/null
+++ b/t/lib/gol-compat.t
@@ -0,0 +1,25 @@
+#!./perl -w
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+require "newgetopt.pl";
+
+print "1..9\n";
+
+@ARGV = qw(-Foo -baR --foo bar);
+$newgetopt::ignorecase = 0;
+$newgetopt::ignorecase = 0;
+undef $opt_baR;
+undef $opt_bar;
+print "ok 1\n" if NGetOpt ("foo", "Foo=s");
+print ((defined $opt_foo) ? "" : "not ", "ok 2\n");
+print (($opt_foo == 1) ? "" : "not ", "ok 3\n");
+print ((defined $opt_Foo) ? "" : "not ", "ok 4\n");
+print (($opt_Foo eq "-baR") ? "" : "not ", "ok 5\n");
+print ((@ARGV == 1) ? "" : "not ", "ok 6\n");
+print (($ARGV[0] eq "bar") ? "" : "not ", "ok 7\n");
+print (!(defined $opt_baR) ? "" : "not ", "ok 8\n");
+print (!(defined $opt_bar) ? "" : "not ", "ok 9\n");
diff --git a/t/lib/gol-linkage.t b/t/lib/gol-linkage.t
new file mode 100755
index 0000000000..a1b2c05be3
--- /dev/null
+++ b/t/lib/gol-linkage.t
@@ -0,0 +1,37 @@
+#!./perl -w
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+use Getopt::Long;
+
+print "1..18\n";
+
+@ARGV = qw(-Foo -baR --foo bar);
+Getopt::Long::Configure ("no_ignore_case");
+%lnk = ();
+print "ok 1\n" if GetOptions (\%lnk, "foo", "Foo=s");
+print ((defined $lnk{foo}) ? "" : "not ", "ok 2\n");
+print (($lnk{foo} == 1) ? "" : "not ", "ok 3\n");
+print ((defined $lnk{Foo}) ? "" : "not ", "ok 4\n");
+print (($lnk{Foo} eq "-baR") ? "" : "not ", "ok 5\n");
+print ((@ARGV == 1) ? "" : "not ", "ok 6\n");
+print (($ARGV[0] eq "bar") ? "" : "not ", "ok 7\n");
+print (!(exists $lnk{baR}) ? "" : "not ", "ok 8\n");
+
+@ARGV = qw(-Foo -baR --foo bar);
+Getopt::Long::Configure ("default","no_ignore_case");
+%lnk = ();
+my $foo;
+print "ok 9\n" if GetOptions (\%lnk, "foo" => \$foo, "Foo=s");
+print ((defined $foo) ? "" : "not ", "ok 10\n");
+print (($foo == 1) ? "" : "not ", "ok 11\n");
+print ((defined $lnk{Foo}) ? "" : "not ", "ok 12\n");
+print (($lnk{Foo} eq "-baR") ? "" : "not ", "ok 13\n");
+print ((@ARGV == 1) ? "" : "not ", "ok 14\n");
+print (($ARGV[0] eq "bar") ? "" : "not ", "ok 15\n");
+print (!(exists $lnk{foo}) ? "" : "not ", "ok 16\n");
+print (!(exists $lnk{baR}) ? "" : "not ", "ok 17\n");
+print (!(exists $lnk{bar}) ? "" : "not ", "ok 18\n");
diff --git a/t/lib/h2ph.pht b/t/lib/h2ph.pht
index 80867a6113..e5b293243e 100644
--- a/t/lib/h2ph.pht
+++ b/t/lib/h2ph.pht
@@ -1,3 +1,5 @@
+require '_h2ph_pre.ph';
+
unless(defined(&SQUARE)) {
sub SQUARE {
local($x) = @_;
@@ -27,7 +29,7 @@ unless(defined(&_H2PH_H_)) {
if(!(defined (defined(&__SOMETHING_MORE_IMPORTANT) ? &__SOMETHING_MORE_IMPORTANT : 0))) {
}
elsif(!(defined (defined(&__SOMETHING_REALLY_REALLY_IMPORTANT) ? &__SOMETHING_REALLY_REALLY_IMPORTANT : 0))) {
- die("Nup, can't go on ");
+ die("Nup\,\ can\'t\ go\ on\ ");
} else {
eval 'sub EVERYTHING_IS_OK () {1;}' unless defined(&EVERYTHING_IS_OK);
}
diff --git a/t/lib/h2ph.t b/t/lib/h2ph.t
index 1fa7f63536..acb150dfcd 100755
--- a/t/lib/h2ph.t
+++ b/t/lib/h2ph.t
@@ -5,7 +5,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..2\n";
@@ -31,4 +31,5 @@ unless(-e '../utils/h2ph') {
# cleanup - should this be in an END block?
unlink("lib/h2ph.ph");
+ unlink("_h2ph_pre.ph");
}
diff --git a/t/lib/hostname.t b/t/lib/hostname.t
index e4ac36521c..30dcf0f0b7 100755
--- a/t/lib/hostname.t
+++ b/t/lib/hostname.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Sys::Hostname;
diff --git a/t/lib/io_const.t b/t/lib/io_const.t
new file mode 100755
index 0000000000..48cb6b5dc8
--- /dev/null
+++ b/t/lib/io_const.t
@@ -0,0 +1,33 @@
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib' if -d '../lib';
+ }
+}
+
+use Config;
+
+BEGIN {
+ if(-d "lib" && -f "TEST") {
+ if ($Config{'extensions'} !~ /\bIO\b/ && $^O ne 'VMS') {
+ print "1..0\n";
+ exit 0;
+ }
+ }
+}
+
+use IO::Handle;
+
+print "1..6\n";
+my $i = 1;
+foreach (qw(SEEK_SET SEEK_CUR SEEK_END _IOFBF _IOLBF _IONBF)) {
+ my $d1 = defined(&{"IO::Handle::" . $_}) ? 1 : 0;
+ my $v1 = $d1 ? &{"IO::Handle::" . $_}() : undef;
+ my $v2 = IO::Handle::constant($_);
+ my $d2 = defined($v2);
+
+ print "not "
+ if($d1 != $d2 || ($d1 && ($v1 != $v2)));
+ print "ok ",$i++,"\n";
+}
diff --git a/t/lib/io_dir.t b/t/lib/io_dir.t
new file mode 100755
index 0000000000..11ec8bcbf9
--- /dev/null
+++ b/t/lib/io_dir.t
@@ -0,0 +1,66 @@
+#!./perl
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib' if -d '../lib';
+ }
+ require Config; import Config;
+ if ($] < 5.00326 || not $Config{'d_readdir'}) {
+ print "1..0\n";
+ exit 0;
+ }
+}
+
+select(STDERR); $| = 1;
+select(STDOUT); $| = 1;
+
+use IO::Dir qw(DIR_UNLINK);
+
+print "1..10\n";
+
+$dot = new IO::Dir ".";
+print defined($dot) ? "ok" : "not ok", " 1\n";
+
+@a = sort <*>;
+do { $first = $dot->read } while defined($first) && $first =~ /^\./;
+print +(grep { $_ eq $first } @a) ? "ok" : "not ok", " 2\n";
+
+@b = sort($first, (grep {/^[^.]/} $dot->read));
+print +(join("\0", @a) eq join("\0", @b)) ? "ok" : "not ok", " 3\n";
+
+$dot->rewind;
+@c = sort grep {/^[^.]/} $dot->read;
+print +(join("\0", @b) eq join("\0", @c)) ? "ok" : "not ok", " 4\n";
+
+$dot->close;
+$dot->rewind;
+print defined($dot->read) ? "not ok" : "ok", " 5\n";
+
+open(FH,'>X') || die "Can't create x";
+print FH "X";
+close(FH);
+
+tie %dir, IO::Dir, ".";
+my @files = keys %dir;
+
+# I hope we do not have an empty dir :-)
+print @files ? "ok" : "not ok", " 6\n";
+
+my $stat = $dir{'X'};
+print defined($stat) && UNIVERSAL::isa($stat,'File::stat') && $stat->size == 1
+ ? "ok" : "not ok", " 7\n";
+
+delete $dir{'X'};
+
+print -f 'X' ? "ok" : "not ok", " 8\n";
+
+tie %dirx, IO::Dir, ".", DIR_UNLINK;
+
+my $statx = $dirx{'X'};
+print defined($statx) && UNIVERSAL::isa($statx,'File::stat') && $statx->size == 1
+ ? "ok" : "not ok", " 9\n";
+
+delete $dirx{'X'};
+
+print -f 'X' ? "not ok" : "ok", " 10\n";
diff --git a/t/lib/io_dup.t b/t/lib/io_dup.t
index 6b0caf14fa..c895fb4c25 100755
--- a/t/lib/io_dup.t
+++ b/t/lib/io_dup.t
@@ -3,7 +3,7 @@
BEGIN {
unless(grep /blib/, @INC) {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
}
diff --git a/t/lib/io_linenum.t b/t/lib/io_linenum.t
new file mode 100755
index 0000000000..3503215201
--- /dev/null
+++ b/t/lib/io_linenum.t
@@ -0,0 +1,80 @@
+#!./perl
+
+# test added 29th April 1999 by Paul Johnson (pjcj@transeda.com)
+# updated 28th May 1999 by Paul Johnson
+
+my $File;
+
+BEGIN
+{
+ $File = __FILE__;
+ if (-d 't')
+ {
+ chdir 't';
+ $File =~ s/^t\W+//; # Remove first directory
+ }
+ unshift @INC, '../lib' if -d '../lib';
+ require strict; import strict;
+}
+
+use Test;
+
+BEGIN { plan tests => 12 }
+
+use IO::File;
+
+sub lineno
+{
+ my ($f) = @_;
+ my $l;
+ $l .= "$. ";
+ $l .= $f->input_line_number;
+ $l .= " $."; # check $. before and after input_line_number
+ $l;
+}
+
+my $t;
+
+open (F, $File) or die $!;
+my $io = IO::File->new($File) or die $!;
+
+<F> for (1 .. 10);
+ok(lineno($io), "10 0 10");
+
+$io->getline for (1 .. 5);
+ok(lineno($io), "5 5 5");
+
+<F>;
+ok(lineno($io), "11 5 11");
+
+$io->getline;
+ok(lineno($io), "6 6 6");
+
+$t = tell F; # tell F; provokes a warning
+ok(lineno($io), "11 6 11");
+
+<F>;
+ok(lineno($io), "12 6 12");
+
+select F;
+ok(lineno($io), "12 6 12");
+
+<F> for (1 .. 10);
+ok(lineno($io), "22 6 22");
+
+$io->getline for (1 .. 5);
+ok(lineno($io), "11 11 11");
+
+$t = tell F;
+# We used to have problems here before local $. worked.
+# input_line_number() used to use select and tell. When we did the
+# same, that mechanism broke. It should work now.
+ok(lineno($io), "22 11 22");
+
+{
+ local $.;
+ $io->getline for (1 .. 5);
+ ok(lineno($io), "16 16 16");
+}
+
+ok(lineno($io), "22 16 22");
diff --git a/t/lib/io_multihomed.t b/t/lib/io_multihomed.t
new file mode 100644
index 0000000000..7337a5f8d6
--- /dev/null
+++ b/t/lib/io_multihomed.t
@@ -0,0 +1,124 @@
+#!./perl
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib' if -d '../lib';
+ }
+}
+
+use Config;
+
+BEGIN {
+ if(-d "lib" && -f "TEST") {
+ my $reason;
+ if (! $Config{'d_fork'}) {
+ $reason = 'no fork';
+ }
+ elsif ($Config{'extensions'} !~ /\bSocket\b/) {
+ $reason = 'Socket extension unavailable';
+ }
+ elsif ($Config{'extensions'} !~ /\bIO\b/) {
+ $reason = 'IO extension unavailable';
+ }
+ if ($reason) {
+ print "1..0 # Skip: $reason\n";
+ exit 0;
+ }
+ }
+}
+
+$| = 1;
+
+print "1..8\n";
+
+
+package Multi;
+require IO::Socket::INET;
+@ISA=qw(IO::Socket::INET);
+
+use Socket qw(inet_aton inet_ntoa unpack_sockaddr_in);
+
+sub _get_addr
+{
+ my($sock,$addr_str, $multi) = @_;
+ #print "_get_addr($sock, $addr_str, $multi)\n";
+
+ print "not " unless $multi;
+ print "ok 2\n";
+
+ (
+ # private IP-addresses which I hope does not work anywhere :-)
+ inet_aton("10.250.230.10"),
+ inet_aton("10.250.230.12"),
+ inet_aton("127.0.0.1") # loopback
+ )
+}
+
+sub connect
+{
+ my $self = shift;
+ if (@_ == 1) {
+ my($port, $addr) = unpack_sockaddr_in($_[0]);
+ $addr = inet_ntoa($addr);
+ #print "connect($self, $port, $addr)\n";
+ if($addr eq "10.250.230.10") {
+ print "ok 3\n";
+ return 0;
+ }
+ if($addr eq "10.250.230.12") {
+ print "ok 4\n";
+ return 0;
+ }
+ }
+ $self->SUPER::connect(@_);
+}
+
+
+
+package main;
+
+use IO::Socket;
+
+$listen = IO::Socket::INET->new(Listen => 2,
+ Proto => 'tcp',
+ Timeout => 5,
+ ) or die "$!";
+
+print "ok 1\n";
+
+$port = $listen->sockport;
+
+if($pid = fork()) {
+
+ $sock = $listen->accept() or die "$!";
+ print "ok 5\n";
+
+ print $sock->getline();
+ print $sock "ok 7\n";
+
+ waitpid($pid,0);
+
+ $sock->close;
+
+ print "ok 8\n";
+
+} elsif(defined $pid) {
+
+ $sock = Multi->new(PeerPort => $port,
+ Proto => 'tcp',
+ PeerAddr => 'localhost',
+ MultiHomed => 1,
+ Timeout => 1,
+ ) or die "$!";
+
+ print $sock "ok 6\n";
+ sleep(1); # race condition
+ print $sock->getline();
+
+ $sock->close;
+
+ exit;
+} else {
+ die;
+}
diff --git a/t/lib/io_pipe.t b/t/lib/io_pipe.t
index e1c48b6a7e..bcb89a0daf 100755
--- a/t/lib/io_pipe.t
+++ b/t/lib/io_pipe.t
@@ -3,7 +3,7 @@
BEGIN {
unless(grep /blib/, @INC) {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
}
@@ -11,10 +11,16 @@ use Config;
BEGIN {
if(-d "lib" && -f "TEST") {
- if (! $Config{'d_fork'} ||
- ($Config{'extensions'} !~ /\bIO\b/ && $^O ne 'VMS'))
- {
- print "1..0\n";
+ my $reason;
+ if (! $Config{'d_fork'}) {
+ $reason = 'no fork';
+ }
+ elsif ($Config{'extensions'} !~ /\bIO\b/) {
+ $reason = 'IO extension unavailable';
+ }
+ undef $reason if $^O eq 'VMS';
+ if ($reason) {
+ print "1..0 # Skip: $reason\n";
exit 0;
}
}
@@ -41,6 +47,13 @@ print $pipe "not ok 3\n" ;
$pipe->close or print "# \$!=$!\nnot ";
print "ok 4\n";
+# Check if can fork with dynamic extensions (bug in CRT):
+if ($^O eq 'os2' and
+ system "$^X -I../lib -MOpcode -e 'defined fork or die' > /dev/null 2>&1") {
+ print "ok $_ # skipped: broken fork\n" for 5..10;
+ exit 0;
+}
+
$pipe = new IO::Pipe;
$pid = fork();
diff --git a/t/lib/io_poll.t b/t/lib/io_poll.t
new file mode 100755
index 0000000000..c179ce96fb
--- /dev/null
+++ b/t/lib/io_poll.t
@@ -0,0 +1,72 @@
+#!./perl
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib' if -d '../lib';
+ }
+}
+
+select(STDERR); $| = 1;
+select(STDOUT); $| = 1;
+
+print "1..8\n";
+
+use IO::Handle;
+use IO::Poll qw(/POLL/);
+
+my $poll = new IO::Poll;
+
+my $stdout = \*STDOUT;
+my $dupout = IO::Handle->new_from_fd(fileno($stdout),"w");
+
+$poll->mask($stdout => POLLOUT);
+
+print "not "
+ unless $poll->mask($stdout) == POLLOUT;
+print "ok 1\n";
+
+$poll->mask($dupout => POLLPRI);
+
+print "not "
+ unless $poll->mask($dupout) == POLLPRI;
+print "ok 2\n";
+
+$poll->poll(0.1);
+
+if ($^O eq 'MSWin32') {
+print "ok 3 # skipped, doesn't work on non-socket fds\n";
+print "ok 4 # skipped, doesn't work on non-socket fds\n";
+}
+else {
+print "not "
+ unless $poll->events($stdout) == POLLOUT;
+print "ok 3\n";
+
+print "not "
+ if $poll->events($dupout);
+print "ok 4\n";
+}
+
+my @h = $poll->handles;
+print "not "
+ unless @h == 2;
+print "ok 5\n";
+
+$poll->remove($stdout);
+
+@h = $poll->handles;
+
+print "not "
+ unless @h == 1;
+print "ok 6\n";
+
+print "not "
+ if $poll->mask($stdout);
+print "ok 7\n";
+
+$poll->poll(0.1);
+
+print "not "
+ if $poll->events($stdout);
+print "ok 8\n";
diff --git a/t/lib/io_sel.t b/t/lib/io_sel.t
index 3dc651bbc2..e0d7a45338 100755
--- a/t/lib/io_sel.t
+++ b/t/lib/io_sel.t
@@ -3,7 +3,7 @@
BEGIN {
unless(grep /blib/, @INC) {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
}
diff --git a/t/lib/io_sock.t b/t/lib/io_sock.t
index 9fab56b237..782f2554c8 100755
--- a/t/lib/io_sock.t
+++ b/t/lib/io_sock.t
@@ -3,7 +3,7 @@
BEGIN {
unless(grep /blib/, @INC) {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
}
@@ -11,32 +11,50 @@ use Config;
BEGIN {
if (-d "lib" && -f "TEST") {
- if (!$Config{'d_fork'} ||
- (($Config{'extensions'} !~ /\bSocket\b/ ||
- $Config{'extensions'} !~ /\bIO\b/) &&
- !(($^O eq 'VMS') && $Config{d_socket}))) {
- print "1..0\n";
+ my $reason;
+ if (! $Config{'d_fork'}) {
+ $reason = 'no fork';
+ }
+ elsif ($Config{'extensions'} !~ /\bSocket\b/) {
+ $reason = 'Socket extension unavailable';
+ }
+ elsif ($Config{'extensions'} !~ /\bIO\b/) {
+ $reason = 'IO extension unavailable';
+ }
+ undef $reason if $^O eq 'VMS' and $Config{d_socket};
+ if ($reason) {
+ print "1..0 # Skip: $reason\n";
exit 0;
}
}
}
$| = 1;
-print "1..5\n";
+print "1..14\n";
use IO::Socket;
$listen = IO::Socket::INET->new(Listen => 2,
Proto => 'tcp',
+ # some systems seem to need as much as 10,
+ # so be generous with the timeout
+ Timeout => 15,
) or die "$!";
print "ok 1\n";
+# Check if can fork with dynamic extensions (bug in CRT):
+if ($^O eq 'os2' and
+ system "$^X -I../lib -MOpcode -e 'defined fork or die' > /dev/null 2>&1") {
+ print "ok $_ # skipped: broken fork\n" for 2..5;
+ exit 0;
+}
+
$port = $listen->sockport;
if($pid = fork()) {
- $sock = $listen->accept();
+ $sock = $listen->accept() or die "accept failed: $!";
print "ok 2\n";
$sock->autoflush(1);
@@ -62,7 +80,7 @@ if($pid = fork()) {
Proto => 'tcp',
PeerAddr => 'localhost'
)
- or die "$! (maybe your system does not have the 'localhost' address defined)";
+ or die "$! (maybe your system does not have the 'localhost' address defined)";
$sock->autoflush(1);
@@ -77,8 +95,99 @@ if($pid = fork()) {
die;
}
+# Test various other ways to create INET sockets that should
+# also work.
+$listen = IO::Socket::INET->new(Listen => '', Timeout => 15) or die "$!";
+$port = $listen->sockport;
+
+if($pid = fork()) {
+ SERVER_LOOP:
+ while (1) {
+ last SERVER_LOOP unless $sock = $listen->accept;
+ while (<$sock>) {
+ last SERVER_LOOP if /^quit/;
+ last if /^done/;
+ print;
+ }
+ $sock = undef;
+ }
+ $listen->close;
+} elsif (defined $pid) {
+ # child, try various ways to connect
+ $sock = IO::Socket::INET->new("localhost:$port");
+ if ($sock) {
+ print "not " unless $sock->connected;
+ print "ok 6\n";
+ $sock->print("ok 7\n");
+ sleep(1);
+ print "ok 8\n";
+ $sock->print("ok 9\n");
+ $sock->print("done\n");
+ $sock->close;
+ }
+ else {
+ print "# $@\n";
+ print "not ok 6\n";
+ print "not ok 7\n";
+ print "not ok 8\n";
+ print "not ok 9\n";
+ }
+ # some machines seem to suffer from a race condition here
+ sleep(2);
+ $sock = IO::Socket::INET->new("127.0.0.1:$port");
+ if ($sock) {
+ $sock->print("ok 10\n");
+ $sock->print("done\n");
+ $sock->close;
+ }
+ else {
+ print "# $@\n";
+ print "not ok 10\n";
+ }
+ # some machines seem to suffer from a race condition here
+# sleep(1);
+
+ $sock = IO::Socket->new(Domain => AF_INET,
+ PeerAddr => "localhost:$port");
+ if ($sock) {
+ $sock->print("ok 11\n");
+ $sock->print("quit\n");
+ }
+ $sock = undef;
+ sleep(1);
+ exit;
+} else {
+ die;
+}
+
+# Then test UDP sockets
+$server = IO::Socket->new(Domain => AF_INET,
+ Proto => 'udp',
+ LocalAddr => 'localhost');
+$port = $server->sockport;
+
+if ($pid = fork()) {
+ my $buf;
+ $server->recv($buf, 100);
+ print $buf;
+} elsif (defined($pid)) {
+ #child
+ $sock = IO::Socket::INET->new(Proto => 'udp',
+ PeerAddr => "localhost:$port");
+ $sock->send("ok 12\n");
+ sleep(1);
+ $sock->send("ok 12\n"); # send another one to be sure
+ exit;
+} else {
+ die;
+}
+print "not " unless $server->blocking;
+print "ok 13\n";
+$server->blocking(0);
+print "not " if $server->blocking;
+print "ok 14\n";
diff --git a/t/lib/io_taint.t b/t/lib/io_taint.t
index 0ef2cfd63f..deaa6c7f61 100755
--- a/t/lib/io_taint.t
+++ b/t/lib/io_taint.t
@@ -3,7 +3,7 @@
BEGIN {
unless(grep /blib/, @INC) {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
}
diff --git a/t/lib/io_tell.t b/t/lib/io_tell.t
index 2009d610db..8d75242251 100755
--- a/t/lib/io_tell.t
+++ b/t/lib/io_tell.t
@@ -3,7 +3,7 @@
BEGIN {
unless(grep /blib/, @INC) {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
$tell_file = "TEST";
}
else {
diff --git a/t/lib/io_udp.t b/t/lib/io_udp.t
index 014e12dc58..3d5145ec5e 100755
--- a/t/lib/io_udp.t
+++ b/t/lib/io_udp.t
@@ -3,7 +3,7 @@
BEGIN {
unless(grep /blib/, @INC) {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
}
@@ -11,18 +11,48 @@ use Config;
BEGIN {
if(-d "lib" && -f "TEST") {
- if ( ($Config{'extensions'} !~ /\bSocket\b/ ||
- $Config{'extensions'} !~ /\bIO\b/ ||
- $^O eq 'os2') &&
- !(($^O eq 'VMS') && $Config{d_socket})) {
- print "1..0\n";
+ my $reason;
+
+ if ($Config{'extensions'} !~ /\bSocket\b/) {
+ $reason = 'Socket was not built';
+ }
+ elsif ($Config{'extensions'} !~ /\bIO\b/) {
+ $reason = 'IO was not built';
+ }
+ elsif ($^O eq 'apollo') {
+ $reason = "unknown *FIXME*";
+ }
+ undef $reason if $^O eq 'VMS' and $Config{d_socket};
+ if ($reason) {
+ print "1..0 # Skip: $reason\n";
exit 0;
- }
+ }
+ }
+}
+
+sub compare_addr {
+ no utf8;
+ my $a = shift;
+ my $b = shift;
+ if (length($a) != length $b) {
+ my $min = (length($a) < length $b) ? length($a) : length $b;
+ if ($min and substr($a, 0, $min) eq substr($b, 0, $min)) {
+ printf "# Apparently: %d bytes junk at the end of %s\n# %s\n",
+ abs(length($a) - length ($b)),
+ $_[length($a) < length ($b) ? 1 : 0],
+ "consider decreasing bufsize of recfrom.";
+ substr($a, $min) = "";
+ substr($b, $min) = "";
+ }
+ return 0;
}
+ my @a = unpack_sockaddr_in($a);
+ my @b = unpack_sockaddr_in($b);
+ "$a[0]$a[1]" eq "$b[0]$b[1]";
}
$| = 1;
-print "1..3\n";
+print "1..7\n";
use Socket;
use IO::Socket qw(AF_INET SOCK_DGRAM INADDR_ANY);
@@ -35,14 +65,34 @@ use IO::Socket qw(AF_INET SOCK_DGRAM INADDR_ANY);
$udpa = IO::Socket::INET->new(Proto => 'udp', LocalAddr => 'localhost')
or die "$! (maybe your system does not have the 'localhost' address defined)";
+
+print "ok 1\n";
+
$udpb = IO::Socket::INET->new(Proto => 'udp', LocalAddr => 'localhost')
or die "$! (maybe your system does not have the 'localhost' address defined)";
-print "ok 1\n";
+print "ok 2\n";
-$udpa->send("ok 2\n",0,$udpb->sockname);
-$udpb->recv($buf="",5);
+$udpa->send("ok 4\n",0,$udpb->sockname);
+
+print "not "
+ unless compare_addr($udpa->peername,$udpb->sockname, 'peername', 'sockname');
+print "ok 3\n";
+
+my $where = $udpb->recv($buf="",5);
print $buf;
-$udpb->send("ok 3\n");
+
+my @xtra = ();
+
+unless(compare_addr($where,$udpa->sockname, 'recv name', 'sockname')) {
+ print "not ";
+ @xtra = (0,$udpa->sockname);
+}
+print "ok 5\n";
+
+$udpb->send("ok 6\n",@xtra);
$udpa->recv($buf="",5);
print $buf;
+
+print "not " if $udpa->connected;
+print "ok 7\n";
diff --git a/t/lib/io_unix.t b/t/lib/io_unix.t
new file mode 100644
index 0000000000..7338861fb4
--- /dev/null
+++ b/t/lib/io_unix.t
@@ -0,0 +1,89 @@
+#!./perl
+
+BEGIN {
+ unless(grep /blib/, @INC) {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib' if -d '../lib';
+ }
+}
+
+use Config;
+
+BEGIN {
+ if(-d "lib" && -f "TEST") {
+ my $reason;
+ if (! $Config{'d_fork'}) {
+ $reason = 'no fork';
+ }
+ elsif ($Config{'extensions'} !~ /\bSocket\b/) {
+ $reason = 'Socket extension unavailable';
+ }
+ elsif ($Config{'extensions'} !~ /\bIO\b/) {
+ $reason = 'IO extension unavailable';
+ }
+ elsif ($^O eq 'os2') {
+ use IO::Socket;
+
+ eval {IO::Socket::pack_sockaddr_un('/tmp/foo') || 1}
+ or $@ !~ /not implemented/ or
+ $reason = 'compiled without TCP/IP stack v4';
+ } elsif ($^O eq 'qnx') {
+ $reason = 'Not implemented';
+ }
+ undef $reason if $^O eq 'VMS' and $Config{d_socket};
+ if ($reason) {
+ print "1..0 # Skip: $reason\n";
+ exit 0;
+ }
+ }
+}
+
+$PATH = "/tmp/sock-$$";
+
+# Test if we can create the file within the tmp directory
+if (-e $PATH or not open(TEST, ">$PATH") and $^O ne 'os2') {
+ print "1..0 # Skip: cannot open '$PATH' for write\n";
+ exit 0;
+}
+close(TEST);
+unlink($PATH) or $^O eq 'os2' or die "Can't unlink $PATH: $!";
+
+# Start testing
+$| = 1;
+print "1..5\n";
+
+use IO::Socket;
+
+$listen = IO::Socket::UNIX->new(Local=>$PATH, Listen=>0) || die "$!";
+print "ok 1\n";
+
+if($pid = fork()) {
+
+ $sock = $listen->accept();
+ print "ok 2\n";
+
+ print $sock->getline();
+
+ print $sock "ok 4\n";
+
+ $sock->close;
+
+ waitpid($pid,0);
+ unlink($PATH) || $^O eq 'os2' || warn "Can't unlink $PATH: $!";
+
+ print "ok 5\n";
+
+} elsif(defined $pid) {
+
+ $sock = IO::Socket::UNIX->new(Peer => $PATH) or die "$!";
+
+ print $sock "ok 3\n";
+
+ print $sock->getline();
+
+ $sock->close;
+
+ exit;
+} else {
+ die;
+}
diff --git a/t/lib/io_xs.t b/t/lib/io_xs.t
index 1a6fd381a3..6bbba16f8c 100755
--- a/t/lib/io_xs.t
+++ b/t/lib/io_xs.t
@@ -3,7 +3,7 @@
BEGIN {
unless(grep /blib/, @INC) {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
}
diff --git a/t/lib/ipc_sysv.t b/t/lib/ipc_sysv.t
index f74c5fa060..00a157ba54 100755
--- a/t/lib/ipc_sysv.t
+++ b/t/lib/ipc_sysv.t
@@ -3,14 +3,20 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
- unless ($Config{'d_msg'} eq 'define' &&
- $Config{'d_sem'} eq 'define') {
- print "1..0\n";
- exit;
+ my $reason;
+
+ if ($Config{'d_sem'} ne 'define') {
+ $reason = '$Config{d_sem} undefined';
+ } elsif ($Config{'d_msg'} ne 'define') {
+ $reason = '$Config{d_msg} undefined';
+ }
+ if ($reason) {
+ print "1..0 # Skip: $reason\n";
+ exit 0;
}
}
@@ -18,7 +24,7 @@ BEGIN {
# Later the sem* tests will import more for themselves.
use IPC::SysV qw(IPC_PRIVATE IPC_NOWAIT IPC_STAT IPC_RMID
- S_IRWXU S_IRWXG S_IRWXO);
+ S_IRWXU S_IRWXG S_IRWXO S_IWGRP S_IROTH S_IWOTH);
use strict;
print "1..16\n";
@@ -28,11 +34,40 @@ my $sem;
$SIG{__DIE__} = 'cleanup'; # will cleanup $msg and $sem if needed
+# FreeBSD is known to throw this if there's no SysV IPC in the kernel.
+$SIG{SYS} = sub {
+ print STDERR <<EOM;
+SIGSYS caught.
+It may be that your kernel does not have SysV IPC configured.
+
+EOM
+ if ($^O eq 'freebsd') {
+ print STDERR <<EOM;
+You must have following options in your kernel:
+
+options SYSVSHM
+options SYSVSEM
+options SYSVMSG
+
+See config(8).
+EOM
+ }
+ exit(1);
+};
+
+my $perm;
+
+$perm = S_IRWXU | S_IRWXG | S_IRWXO | S_IWGRP | S_IROTH | S_IWOTH
+ if $^O eq 'vmesa';
+
+$perm = S_IRWXU | S_IRWXG | S_IRWXO unless defined $perm;
+
if ($Config{'d_msgget'} eq 'define' &&
$Config{'d_msgctl'} eq 'define' &&
$Config{'d_msgsnd'} eq 'define' &&
$Config{'d_msgrcv'} eq 'define') {
- $msg = msgget(IPC_PRIVATE, S_IRWXU | S_IRWXG | S_IRWXO);
+
+ $msg = msgget(IPC_PRIVATE, $perm);
# Very first time called after machine is booted value may be 0
die "msgget failed: $!\n" unless defined($msg) && $msg >= 0;
@@ -69,80 +104,64 @@ if ($Config{'d_msgget'} eq 'define' &&
if($Config{'d_semget'} eq 'define' &&
$Config{'d_semctl'} eq 'define') {
- use IPC::SysV qw(IPC_CREAT GETALL SETALL);
-
- $sem = semget(IPC_PRIVATE, 10, S_IRWXU | S_IRWXG | S_IRWXO | IPC_CREAT);
- # Very first time called after machine is booted value may be 0
- die "semget: $!\n" unless defined($sem) && $sem >= 0;
+ if ($Config{'d_semctl_semid_ds'} eq 'define' ||
+ $Config{'d_semctl_semun'} eq 'define') {
- print "ok 7\n";
-
- my $data;
- semctl($sem,0,IPC_STAT,$data) or print "not ";
- print "ok 8\n";
+ use IPC::SysV qw(IPC_CREAT GETALL SETALL);
- print "not " unless length($data);
- print "ok 9\n";
-
- my $template;
-
- # Find the pack/unpack template capable of handling native C shorts.
-
- if ($Config{shortsize} == 2) {
- $template = "s";
- } elsif ($Config{shortsize} == 4) {
- $template = "l";
- } elsif ($Config{shortsize} == 8) {
- # Try quad last because not supported everywhere.
- foreach my $t (qw(i q)) {
- # We could trap the unsupported quad template with eval
- # but if we get this far we should have quad support anyway.
- if (length(pack($t, 0)) == 8) {
- $template = $t;
- last;
- }
- }
- }
+ $sem = semget(IPC_PRIVATE, 10, $perm | IPC_CREAT);
+ # Very first time called after machine is booted value may be 0
+ die "semget: $!\n" unless defined($sem) && $sem >= 0;
- die "$0: cannot pack native shorts\n" unless defined $template;
+ print "ok 7\n";
- $template .= "*";
+ my $data;
+ semctl($sem,0,IPC_STAT,$data) or print "not ";
+ print "ok 8\n";
+
+ print "not " unless length($data);
+ print "ok 9\n";
- my $nsem = 10;
+ my $nsem = 10;
- semctl($sem,0,SETALL,pack($template,(0) x $nsem)) or print "not ";
- print "ok 10\n";
+ semctl($sem,0,SETALL,pack("s!*",(0) x $nsem)) or print "not ";
+ print "ok 10\n";
- $data = "";
- semctl($sem,0,GETALL,$data) or print "not ";
- print "ok 11\n";
+ $data = "";
+ semctl($sem,0,GETALL,$data) or print "not ";
+ print "ok 11\n";
- print "not " unless length($data) == length(pack($template,(0) x $nsem));
- print "ok 12\n";
+ print "not " unless length($data) == length(pack("s!*",(0) x $nsem));
+ print "ok 12\n";
- my @data = unpack($template,$data);
+ my @data = unpack("s!*",$data);
- my $adata = "0" x $nsem;
+ my $adata = "0" x $nsem;
- print "not " unless @data == $nsem and join("",@data) eq $adata;
- print "ok 13\n";
+ print "not " unless @data == $nsem and join("",@data) eq $adata;
+ print "ok 13\n";
- my $poke = 2;
+ my $poke = 2;
- $data[$poke] = 1;
- semctl($sem,0,SETALL,pack($template,@data)) or print "not ";
- print "ok 14\n";
+ $data[$poke] = 1;
+ semctl($sem,0,SETALL,pack("s!*",@data)) or print "not ";
+ print "ok 14\n";
- $data = "";
- semctl($sem,0,GETALL,$data) or print "not ";
- print "ok 15\n";
+ $data = "";
+ semctl($sem,0,GETALL,$data) or print "not ";
+ print "ok 15\n";
- @data = unpack($template,$data);
+ @data = unpack("s!*",$data);
- my $bdata = "0" x $poke . "1" . "0" x ($nsem-$poke-1);
+ my $bdata = "0" x $poke . "1" . "0" x ($nsem-$poke-1);
- print "not " unless join("",@data) eq $bdata;
- print "ok 16\n";
+ print "not " unless join("",@data) eq $bdata;
+ print "ok 16\n";
+ } else {
+ for (7..16) {
+ print "ok $_ # skipped, no semctl possible\n";
+ }
+ }
} else {
for (7..16) {
print "ok $_\n"; # fake it
diff --git a/t/lib/ndbm.t b/t/lib/ndbm.t
index a97dbd1f1e..39c3f400a0 100755
--- a/t/lib/ndbm.t
+++ b/t/lib/ndbm.t
@@ -4,10 +4,10 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if ($Config{'extensions'} !~ /\bNDBM_File\b/) {
- print "1..0\n";
+ print "1..0 # Skip: NDBM_File was not built\n";
exit 0;
}
}
@@ -16,7 +16,7 @@ require NDBM_File;
#If Fcntl is not available, try 0x202 or 0x102 for O_RDWR|O_CREAT
use Fcntl;
-print "1..18\n";
+print "1..64\n";
unlink <Op.dbmx*>;
@@ -205,3 +205,189 @@ EOM
unlink "SubDB.pm", <dbhash.tmp*> ;
}
+
+{
+ # DBM Filter tests
+ use strict ;
+ my (%h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+
+ sub checkOutput
+ {
+ my($fk, $sk, $fv, $sv) = @_ ;
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ unlink <Op.dbmx*>;
+ ok(19, $db = tie(%h, 'NDBM_File','Op.dbmx', O_RDWR|O_CREAT, 0640)) ;
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ # fk sk fv sv
+ ok(20, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(21, $h{"fred"} eq "joe");
+ # fk sk fv sv
+ ok(22, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(23, $db->FIRSTKEY() eq "fred") ;
+ # fk sk fv sv
+ ok(24, checkOutput( "fred", "", "", "")) ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ = lc $_ ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"Fred"} = "Joe" ;
+ # fk sk fv sv
+ ok(25, checkOutput( "", "fred", "", "Jxe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(26, $h{"Fred"} eq "[Jxe]");
+ # fk sk fv sv
+ ok(27, checkOutput( "", "fred", "[Jxe]", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(28, $db->FIRSTKEY() eq "FRED") ;
+ # fk sk fv sv
+ ok(29, checkOutput( "FRED", "", "", "")) ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(30, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(31, $h{"fred"} eq "joe");
+ ok(32, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(33, $db->FIRSTKEY() eq "fred") ;
+ ok(34, checkOutput( "fred", "", "", "")) ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(35, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(36, $h{"fred"} eq "joe");
+ ok(37, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(38, $db->FIRSTKEY() eq "fred") ;
+ ok(39, checkOutput( "", "", "", "")) ;
+
+ undef $db ;
+ untie %h;
+ unlink <Op.dbmx*>;
+}
+
+{
+ # DBM Filter with a closure
+
+ use strict ;
+ my (%h, $db) ;
+
+ unlink <Op.dbmx*>;
+ ok(40, $db = tie(%h, 'NDBM_File','Op.dbmx', O_RDWR|O_CREAT, 0640)) ;
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok(41, $result{"store key"} eq "store key - 1: [fred]");
+ ok(42, $result{"store value"} eq "store value - 1: [joe]");
+ ok(43, !defined $result{"fetch key"} );
+ ok(44, !defined $result{"fetch value"} );
+ ok(45, $_ eq "original") ;
+
+ ok(46, $db->FIRSTKEY() eq "fred") ;
+ ok(47, $result{"store key"} eq "store key - 1: [fred]");
+ ok(48, $result{"store value"} eq "store value - 1: [joe]");
+ ok(49, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(50, ! defined $result{"fetch value"} );
+ ok(51, $_ eq "original") ;
+
+ $h{"jim"} = "john" ;
+ ok(52, $result{"store key"} eq "store key - 2: [fred jim]");
+ ok(53, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(54, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(55, $result{"fetch value"} eq "");
+ ok(56, $_ eq "original") ;
+
+ ok(57, $h{"fred"} eq "joe");
+ ok(58, $result{"store key"} eq "store key - 3: [fred jim fred]");
+ ok(59, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(60, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(61, $result{"fetch value"} eq "fetch value - 1: [joe]");
+ ok(62, $_ eq "original") ;
+
+ undef $db ;
+ untie %h;
+ unlink <Op.dbmx*>;
+}
+
+{
+ # DBM Filter recursion detection
+ use strict ;
+ my (%h, $db) ;
+ unlink <Op.dbmx*>;
+
+ ok(63, $db = tie(%h, 'NDBM_File','Op.dbmx', O_RDWR|O_CREAT, 0640)) ;
+
+ $db->filter_store_key (sub { $_ = $h{$_} }) ;
+
+ eval '$h{1} = 1234' ;
+ ok(64, $@ =~ /^recursion detected in filter_store_key at/ );
+
+ undef $db ;
+ untie %h;
+ unlink <Op.dbmx*>;
+}
diff --git a/t/lib/odbm.t b/t/lib/odbm.t
index 8ba9bcf3a4..f8b8a110ad 100755
--- a/t/lib/odbm.t
+++ b/t/lib/odbm.t
@@ -4,10 +4,10 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if ($Config{'extensions'} !~ /\bODBM_File\b/) {
- print "1..0\n";
+ print "1..0 # Skip: ODBM_File was not built\n";
exit 0;
}
}
@@ -16,7 +16,7 @@ require ODBM_File;
#If Fcntl is not available, try 0x202 or 0x102 for O_RDWR|O_CREAT
use Fcntl;
-print "1..18\n";
+print "1..64\n";
unlink <Op.dbmx*>;
@@ -205,3 +205,202 @@ EOM
unlink "SubDB.pm", <dbhash.tmp*> ;
}
+
+{
+ # DBM Filter tests
+ use strict ;
+ my (%h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+
+ sub checkOutput
+ {
+ my($fk, $sk, $fv, $sv) = @_ ;
+ print "# ", join('|', $fetch_key, $fk, $store_key, $sk,
+ $fetch_value, $fv, $store_value, $sv, $_), "\n";
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ unlink <Op.dbmx*>;
+ ok(19, $db = tie(%h, 'ODBM_File','Op.dbmx', O_RDWR|O_CREAT, 0640)) ;
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ # fk sk fv sv
+ ok(20, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(21, $h{"fred"} eq "joe");
+ # fk sk fv sv
+ ok(22, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(23, $db->FIRSTKEY() eq "fred") ;
+ # fk sk fv sv
+ ok(24, checkOutput( "fred", "", "", "")) ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ = lc $_ ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"Fred"} = "Joe" ;
+ # fk sk fv sv
+ ok(25, checkOutput( "", "fred", "", "Jxe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(26, $h{"Fred"} eq "[Jxe]");
+ # fk sk fv sv
+ ok(27, checkOutput( "", "fred", "[Jxe]", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(28, $db->FIRSTKEY() eq "FRED") ;
+ # fk sk fv sv
+ ok(29, checkOutput( "FRED", "", "", "")) ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(30, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(31, $h{"fred"} eq "joe");
+ ok(32, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(33, $db->FIRSTKEY() eq "fred") ;
+ ok(34, checkOutput( "fred", "", "", "")) ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(35, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(36, $h{"fred"} eq "joe");
+ ok(37, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(38, $db->FIRSTKEY() eq "fred") ;
+ ok(39, checkOutput( "", "", "", "")) ;
+
+ undef $db ;
+ untie %h;
+ unlink <Op.dbmx*>;
+}
+
+{
+ # DBM Filter with a closure
+
+ use strict ;
+ my (%h, $db) ;
+
+ unlink <Op.dbmx*>;
+ ok(40, $db = tie(%h, 'ODBM_File','Op.dbmx', O_RDWR|O_CREAT, 0640)) ;
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok(41, $result{"store key"} eq "store key - 1: [fred]");
+ ok(42, $result{"store value"} eq "store value - 1: [joe]");
+ ok(43, !defined $result{"fetch key"} );
+ ok(44, !defined $result{"fetch value"} );
+ ok(45, $_ eq "original") ;
+
+ ok(46, $db->FIRSTKEY() eq "fred") ;
+ ok(47, $result{"store key"} eq "store key - 1: [fred]");
+ ok(48, $result{"store value"} eq "store value - 1: [joe]");
+ ok(49, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(50, ! defined $result{"fetch value"} );
+ ok(51, $_ eq "original") ;
+
+ $h{"jim"} = "john" ;
+ ok(52, $result{"store key"} eq "store key - 2: [fred jim]");
+ ok(53, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(54, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(55, $result{"fetch value"} eq "");
+ ok(56, $_ eq "original") ;
+
+ ok(57, $h{"fred"} eq "joe");
+ ok(58, $result{"store key"} eq "store key - 3: [fred jim fred]");
+ ok(59, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(60, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(61, $result{"fetch value"} eq "fetch value - 1: [joe]");
+ ok(62, $_ eq "original") ;
+
+ undef $db ;
+ untie %h;
+ unlink <Op.dbmx*>;
+}
+
+{
+ # DBM Filter recursion detection
+ use strict ;
+ my (%h, $db) ;
+ unlink <Op.dbmx*>;
+
+ ok(63, $db = tie(%h, 'ODBM_File','Op.dbmx', O_RDWR|O_CREAT, 0640)) ;
+
+ $db->filter_store_key (sub { $_ = $h{$_} }) ;
+
+ eval '$h{1} = 1234' ;
+ ok(64, $@ =~ /^recursion detected in filter_store_key at/ );
+
+ undef $db ;
+ untie %h;
+ unlink <Op.dbmx*>;
+}
+
+if ($^O eq 'hpux') {
+ print <<EOM;
+#
+# If you experience failures with the odbm test in HP-UX,
+# this is a well-known bug that's unfortunately very hard to fix.
+# The suggested course of action is to avoid using the ODBM_File,
+# but to use instead the NDBM_File extension.
+#
+EOM
+}
diff --git a/t/lib/opcode.t b/t/lib/opcode.t
index a785fce48b..f83a689f05 100755
--- a/t/lib/opcode.t
+++ b/t/lib/opcode.t
@@ -4,7 +4,7 @@ $|=1;
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if ($Config{'extensions'} !~ /\bOpcode\b/ && $Config{'osname'} ne 'VMS') {
print "1..0\n";
diff --git a/t/lib/open2.t b/t/lib/open2.t
index 85b807c98a..64431123e8 100755
--- a/t/lib/open2.t
+++ b/t/lib/open2.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if (!$Config{'d_fork'}
# open2/3 supported on win32 (but not Borland due to CRT bugs)
diff --git a/t/lib/open3.t b/t/lib/open3.t
index b84dac9f14..7cd0ca306c 100755
--- a/t/lib/open3.t
+++ b/t/lib/open3.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if (!$Config{'d_fork'}
# open2/3 supported on win32 (but not Borland due to CRT bugs)
@@ -49,7 +49,7 @@ my ($pid, $reaped_pid);
STDOUT->autoflush;
STDERR->autoflush;
-print "1..21\n";
+print "1..22\n";
# basic
ok 1, $pid = open3 'WRITE', 'READ', 'ERROR', $perl, '-e', cmd_line(<<'EOF');
@@ -134,3 +134,17 @@ EOF
print WRITE "ok 20\n";
print WRITE "ok 21\n";
waitpid $pid, 0;
+
+# command line in single parameter variant of open3
+# for understanding of Config{'sh'} test see exec description in camel book
+my $cmd = 'print(scalar(<STDIN>))';
+$cmd = $Config{'sh'} =~ /sh/ ? "'$cmd'" : cmd_line($cmd);
+eval{$pid = open3 'WRITE', '>&STDOUT', 'ERROR', "$perl -e " . $cmd; };
+if ($@) {
+ print "error $@\n";
+ print "not ok 22\n";
+}
+else {
+ print WRITE "ok 22\n";
+ waitpid $pid, 0;
+}
diff --git a/t/lib/ops.t b/t/lib/ops.t
index 56b1bacabb..ce8b6d0d5f 100755
--- a/t/lib/ops.t
+++ b/t/lib/ops.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if ($Config{'extensions'} !~ /\bOpcode\b/ && $Config{'osname'} ne 'VMS') {
print "1..0\n";
diff --git a/t/lib/parsewords.t b/t/lib/parsewords.t
index 90791790ab..86323b6fc6 100755
--- a/t/lib/parsewords.t
+++ b/t/lib/parsewords.t
@@ -2,12 +2,12 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Text::ParseWords;
-print "1..17\n";
+print "1..18\n";
@words = shellwords(qq(foo "bar quiz" zoo));
print "not " if $words[0] ne 'foo';
@@ -101,3 +101,8 @@ $string = 'aaaa"bbbbb" cc\ cc \\\\\"dddd\' eee\\\\\"\\\'ffff\' gg';
$result = join('|', parse_line('\s+', 0, $string));
print "not " unless $result eq 'aaaabbbbb|cc cc|\"dddd eee\\\\"\'ffff|gg';
print "ok 17\n";
+
+# test whitespace in the delimiters
+@words = quotewords(' ', 1, '4 3 2 1 0');
+print "not " unless join(";", @words) eq qq(4;3;2;1;0);
+print "ok 18\n";
diff --git a/t/lib/ph.t b/t/lib/ph.t
index d0a48f6c51..dd24c79f2d 100755
--- a/t/lib/ph.t
+++ b/t/lib/ph.t
@@ -6,11 +6,9 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
-use Config;
-
# All the constants which Socket.pm tries to make available:
my @possibly_defined = qw(
INADDR_ANY INADDR_LOOPBACK INADDR_NONE AF_802 AF_APPLETALK AF_CCITT
diff --git a/t/lib/posix.t b/t/lib/posix.t
index c071c3b067..4c6aa49a05 100755
--- a/t/lib/posix.t
+++ b/t/lib/posix.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if ($^O ne 'VMS' and $Config{'extensions'} !~ /\bPOSIX\b/) {
print "1..0\n";
@@ -96,5 +96,6 @@ print &POSIX::acos(1.0) == 0.0 ? "ok 17\n" : "not ok 17\n";
print POSIX::strftime("ok 18 # %H:%M, on %D\n", localtime());
$| = 0;
-print '@#!*$@(!@#$';
+# The following line assumes buffered output, which may be not true with EMX:
+print '@#!*$@(!@#$' unless ($^O eq 'os2' || $^O eq 'uwin' || $^O eq 'os390');
_exit(0);
diff --git a/t/lib/safe1.t b/t/lib/safe1.t
index 27993d95c9..6e12873585 100755
--- a/t/lib/safe1.t
+++ b/t/lib/safe1.t
@@ -2,7 +2,7 @@
$|=1;
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if ($Config{'extensions'} !~ /\bOpcode\b/ && $Config{'osname'} ne 'VMS') {
print "1..0\n";
diff --git a/t/lib/safe2.t b/t/lib/safe2.t
index c9e38808b3..572876c5ca 100755
--- a/t/lib/safe2.t
+++ b/t/lib/safe2.t
@@ -2,14 +2,15 @@
$|=1;
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if ($Config{'extensions'} !~ /\bOpcode\b/ && $Config{'osname'} ne 'VMS') {
print "1..0\n";
exit 0;
}
- # test 30 rather naughtily expects English error messages
- $ENV{'LC_ALL'} = 'C';
+ # test 30 rather naughtily expects English error messages
+ $ENV{'LC_ALL'} = 'C';
+ $ENV{LANGUAGE} = 'C'; # GNU locale extension
}
# Tests Todo:
@@ -122,11 +123,9 @@ print $@ =~ /foo bar/ ? "ok 29\n" : "not ok 29\n";
my $t = 30;
$cpt->rdo('/non/existant/file.name');
-print +(($! =~ /No such file/ || $! =~ /file specification syntax error/) ||
- $! =~ /A file or directory in the path name does not exist/ ||
- $! =~ /Invalid argument/ ||
- $! =~ /Device not configured/ ?
- "ok $t\n" : "not ok $t # $!\n"); $t++;
+# The regexp is getting rather baroque.
+print $! =~ /No such file|file specification syntax error|A file or directory in the path name does not exist|Invalid argument|Device not configured|file not found/i ? "ok $t\n" : "not ok $t # $!\n"; $t++;
+# test #31 is gone.
print 1 ? "ok $t\n" : "not ok $t\n#$@/$!\n"; $t++;
#my $rdo_file = "tmp_rdo.tpl";
diff --git a/t/lib/sdbm.t b/t/lib/sdbm.t
index 591fe14c60..2689d1962e 100755
--- a/t/lib/sdbm.t
+++ b/t/lib/sdbm.t
@@ -4,7 +4,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if (($Config{'extensions'} !~ /\bSDBM_File\b/) && ($^O ne 'VMS')){
print "1..0\n";
@@ -15,7 +15,7 @@ require SDBM_File;
#If Fcntl is not available, try 0x202 or 0x102 for O_RDWR|O_CREAT
use Fcntl;
-print "1..18\n";
+print "1..66\n";
unlink <Op_dbmx.*>;
@@ -122,13 +122,6 @@ print join(':',200..400) eq join(':',@foo) ? "ok 10\n" : "not ok 10\n";
print ($h{'foo'} eq '' ? "ok 11\n" : "not ok 11\n");
print ($h{''} eq 'bar' ? "ok 12\n" : "not ok 12\n");
-untie %h;
-if ($^O eq 'VMS') {
- unlink 'Op_dbmx.sdbm_dir', $Dfile;
-} else {
- unlink 'Op_dbmx.dir', $Dfile;
-}
-
sub ok
{
@@ -210,3 +203,196 @@ EOM
unlink "SubDB.pm", <dbhash_tmp.*> ;
}
+
+ok(19, !exists $h{'goner1'});
+ok(20, exists $h{'foo'});
+
+untie %h;
+unlink <Op_dbmx*>, $Dfile;
+
+{
+ # DBM Filter tests
+ use strict ;
+ my (%h, $db) ;
+ my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+
+ sub checkOutput
+ {
+ my($fk, $sk, $fv, $sv) = @_ ;
+ return
+ $fetch_key eq $fk && $store_key eq $sk &&
+ $fetch_value eq $fv && $store_value eq $sv &&
+ $_ eq 'original' ;
+ }
+
+ unlink <Op_dbmx*>;
+ ok(21, $db = tie(%h, 'SDBM_File','Op_dbmx', O_RDWR|O_CREAT, 0640)) ;
+
+ $db->filter_fetch_key (sub { $fetch_key = $_ }) ;
+ $db->filter_store_key (sub { $store_key = $_ }) ;
+ $db->filter_fetch_value (sub { $fetch_value = $_}) ;
+ $db->filter_store_value (sub { $store_value = $_ }) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ # fk sk fv sv
+ ok(22, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(23, $h{"fred"} eq "joe");
+ # fk sk fv sv
+ ok(24, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(25, $db->FIRSTKEY() eq "fred") ;
+ # fk sk fv sv
+ ok(26, checkOutput( "fred", "", "", "")) ;
+
+ # replace the filters, but remember the previous set
+ my ($old_fk) = $db->filter_fetch_key
+ (sub { $_ = uc $_ ; $fetch_key = $_ }) ;
+ my ($old_sk) = $db->filter_store_key
+ (sub { $_ = lc $_ ; $store_key = $_ }) ;
+ my ($old_fv) = $db->filter_fetch_value
+ (sub { $_ = "[$_]"; $fetch_value = $_ }) ;
+ my ($old_sv) = $db->filter_store_value
+ (sub { s/o/x/g; $store_value = $_ }) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"Fred"} = "Joe" ;
+ # fk sk fv sv
+ ok(27, checkOutput( "", "fred", "", "Jxe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(28, $h{"Fred"} eq "[Jxe]");
+ # fk sk fv sv
+ ok(29, checkOutput( "", "fred", "[Jxe]", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(30, $db->FIRSTKEY() eq "FRED") ;
+ # fk sk fv sv
+ ok(31, checkOutput( "FRED", "", "", "")) ;
+
+ # put the original filters back
+ $db->filter_fetch_key ($old_fk);
+ $db->filter_store_key ($old_sk);
+ $db->filter_fetch_value ($old_fv);
+ $db->filter_store_value ($old_sv);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(32, checkOutput( "", "fred", "", "joe")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(33, $h{"fred"} eq "joe");
+ ok(34, checkOutput( "", "fred", "joe", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(35, $db->FIRSTKEY() eq "fred") ;
+ ok(36, checkOutput( "fred", "", "", "")) ;
+
+ # delete the filters
+ $db->filter_fetch_key (undef);
+ $db->filter_store_key (undef);
+ $db->filter_fetch_value (undef);
+ $db->filter_store_value (undef);
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ $h{"fred"} = "joe" ;
+ ok(37, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(38, $h{"fred"} eq "joe");
+ ok(39, checkOutput( "", "", "", "")) ;
+
+ ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ;
+ ok(40, $db->FIRSTKEY() eq "fred") ;
+ ok(41, checkOutput( "", "", "", "")) ;
+
+ undef $db ;
+ untie %h;
+ unlink <Op_dbmx*>;
+}
+
+{
+ # DBM Filter with a closure
+
+ use strict ;
+ my (%h, $db) ;
+
+ unlink <Op_dbmx*>;
+ ok(42, $db = tie(%h, 'SDBM_File','Op_dbmx', O_RDWR|O_CREAT, 0640)) ;
+
+ my %result = () ;
+
+ sub Closure
+ {
+ my ($name) = @_ ;
+ my $count = 0 ;
+ my @kept = () ;
+
+ return sub { ++$count ;
+ push @kept, $_ ;
+ $result{$name} = "$name - $count: [@kept]" ;
+ }
+ }
+
+ $db->filter_store_key(Closure("store key")) ;
+ $db->filter_store_value(Closure("store value")) ;
+ $db->filter_fetch_key(Closure("fetch key")) ;
+ $db->filter_fetch_value(Closure("fetch value")) ;
+
+ $_ = "original" ;
+
+ $h{"fred"} = "joe" ;
+ ok(43, $result{"store key"} eq "store key - 1: [fred]");
+ ok(44, $result{"store value"} eq "store value - 1: [joe]");
+ ok(45, !defined $result{"fetch key"} );
+ ok(46, !defined $result{"fetch value"} );
+ ok(47, $_ eq "original") ;
+
+ ok(48, $db->FIRSTKEY() eq "fred") ;
+ ok(49, $result{"store key"} eq "store key - 1: [fred]");
+ ok(50, $result{"store value"} eq "store value - 1: [joe]");
+ ok(51, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(52, ! defined $result{"fetch value"} );
+ ok(53, $_ eq "original") ;
+
+ $h{"jim"} = "john" ;
+ ok(54, $result{"store key"} eq "store key - 2: [fred jim]");
+ ok(55, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(56, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(57, $result{"fetch value"} eq "");
+ ok(58, $_ eq "original") ;
+
+ ok(59, $h{"fred"} eq "joe");
+ ok(60, $result{"store key"} eq "store key - 3: [fred jim fred]");
+ ok(61, $result{"store value"} eq "store value - 2: [joe john]");
+ ok(62, $result{"fetch key"} eq "fetch key - 1: [fred]");
+ ok(63, $result{"fetch value"} eq "fetch value - 1: [joe]");
+ ok(64, $_ eq "original") ;
+
+ undef $db ;
+ untie %h;
+ unlink <Op_dbmx*>;
+}
+
+{
+ # DBM Filter recursion detection
+ use strict ;
+ my (%h, $db) ;
+ unlink <Op_dbmx*>;
+
+ ok(65, $db = tie(%h, 'SDBM_File','Op_dbmx', O_RDWR|O_CREAT, 0640)) ;
+
+ $db->filter_store_key (sub { $_ = $h{$_} }) ;
+
+ eval '$h{1} = 1234' ;
+ ok(66, $@ =~ /^recursion detected in filter_store_key at/ );
+
+ undef $db ;
+ untie %h;
+ unlink <Op_dbmx*>;
+}
+
diff --git a/t/lib/searchdict.t b/t/lib/searchdict.t
index 447c425b27..46cea394bc 100755
--- a/t/lib/searchdict.t
+++ b/t/lib/searchdict.t
@@ -2,10 +2,10 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
-print "1..3\n";
+print "1..4\n";
$DICT = <<EOT;
Aarhus
@@ -44,22 +44,44 @@ open(DICT, "+>dict-$$") or die "Can't create dict-$$: $!";
binmode DICT; # To make length expected one.
print DICT $DICT;
-my $pos = look *DICT, "abash";
+my $pos = look *DICT, "Ababa";
chomp($word = <DICT>);
-print "not " if $pos < 0 || $word ne "abash";
+print "not " if $pos < 0 || $word ne "Ababa";
print "ok 1\n";
-$pos = look *DICT, "foo";
-chomp($word = <DICT>);
+if (ord('a') > ord('A') ) { # ASCII
+
+ $pos = look *DICT, "foo";
+ chomp($word = <DICT>);
+
+ print "not " if $pos != length($DICT); # will search to end of file
+ print "ok 2\n";
-print "not " if $pos != length($DICT); # will search to end of file
-print "ok 2\n";
+ my $pos = look *DICT, "abash";
+ chomp($word = <DICT>);
+ print "not " if $pos < 0 || $word ne "abash";
+ print "ok 3\n";
+
+}
+else { # EBCDIC systems e.g. os390
+
+ $pos = look *DICT, "FOO";
+ chomp($word = <DICT>);
+
+ print "not " if $pos != length($DICT); # will search to end of file
+ print "ok 2\n";
+
+ my $pos = look *DICT, "Abba";
+ chomp($word = <DICT>);
+ print "not " if $pos < 0 || $word ne "Abba";
+ print "ok 3\n";
+}
$pos = look *DICT, "aarhus", 1, 1;
chomp($word = <DICT>);
print "not " if $pos < 0 || $word ne "Aarhus";
-print "ok 3\n";
+print "ok 4\n";
close DICT or die "cannot close";
unlink "dict-$$";
diff --git a/t/lib/selectsaver.t b/t/lib/selectsaver.t
index 3b58d709ab..677caec894 100755
--- a/t/lib/selectsaver.t
+++ b/t/lib/selectsaver.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..3\n";
diff --git a/t/lib/socket.t b/t/lib/socket.t
index 4e382958ce..8f945ac6f7 100755
--- a/t/lib/socket.t
+++ b/t/lib/socket.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
require Config; import Config;
if ($Config{'extensions'} !~ /\bSocket\b/ &&
!(($^O eq 'VMS') && $Config{d_socket})) {
diff --git a/t/lib/soundex.t b/t/lib/soundex.t
index d35f264c7a..a04cccd43c 100755
--- a/t/lib/soundex.t
+++ b/t/lib/soundex.t
@@ -18,7 +18,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Text::Soundex;
diff --git a/t/lib/symbol.t b/t/lib/symbol.t
index 03449a3ed7..14c919c0f3 100755
--- a/t/lib/symbol.t
+++ b/t/lib/symbol.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..8\n";
diff --git a/t/lib/syslfs.t b/t/lib/syslfs.t
new file mode 100644
index 0000000000..4d38a8e779
--- /dev/null
+++ b/t/lib/syslfs.t
@@ -0,0 +1,171 @@
+# NOTE: this file tests how large files (>2GB) work with raw system IO.
+# open(), tell(), seek(), print(), read() are tested in t/op/lfs.t.
+# If you modify/add tests here, remember to update also t/op/lfs.t.
+
+BEGIN {
+ # Don't bother if there are no quads.
+ eval { my $q = pack "q", 0 };
+ if ($@) {
+ print "1..0\n# no 64-bit types\n";
+ exit(0);
+ }
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+ require Config; import Config;
+ # Don't bother if there are no quad offsets.
+ if ($Config{lseeksize} < 8) {
+ print "1..0\n# no 64-bit file offsets\n";
+ exit(0);
+ }
+ require Fcntl; import Fcntl;
+}
+
+sub bye {
+ close(BIG);
+ unlink "big";
+ exit(0);
+}
+
+sub explain {
+ print <<EOM;
+#
+# If the lfs (large file support: large meaning larger than two gigabytes)
+# tests are skipped or fail, it may mean either that your process is not
+# allowed to write large files or that the file system you are running
+# the tests on doesn't support large files, or both. You may also need
+# to reconfigure your kernel. (This is all very system-dependent.)
+#
+# Perl may still be able to support large files, once you have
+# such a process and such a (file) system.
+#
+EOM
+}
+
+# Known have-nots.
+if ($^O eq 'win32' || $^O eq 'vms') {
+ print "1..0\n# no sparse files\n";
+ bye();
+}
+
+# Then try to deduce whether we have sparse files.
+
+# We'll start off by creating a one megabyte file which has
+# only three "true" bytes. If we have sparseness, we should
+# consume less blocks than one megabyte (assuming nobody has
+# one megabyte blocks...)
+
+sysopen(BIG, "big", O_WRONLY|O_CREAT|O_TRUNC) or
+ do { warn "sysopen failed: $!\n"; bye };
+sysseek(BIG, 1_000_000, SEEK_SET);
+syswrite(BIG, "big");
+close(BIG);
+
+my @s;
+
+@s = stat("big");
+
+print "# @s\n";
+
+my $BLOCKSIZE = 512; # is this really correct everywhere?
+
+unless (@s == 13 &&
+ $s[7] == 1_000_003 &&
+ defined $s[12] &&
+ $BLOCKSIZE * $s[12] < 1_000_003) {
+ print "1..0\n# no sparse files?\n";
+ bye();
+}
+
+# By now we better be sure that we do have sparse files:
+# if we are not, the following will hog 5 gigabytes of disk. Ooops.
+
+sysopen(BIG, "big", O_WRONLY|O_CREAT|O_TRUNC) or
+ do { warn "sysopen failed: $!\n"; bye };
+sysseek(BIG, 5_000_000_000, SEEK_SET);
+# The syswrite will fail if there are are filesize limitations (process or fs).
+unless(syswrite(BIG, "big") == 3) {
+ $ENV{LC_ALL} = "C";
+ if ($! =~/File too large/) {
+ print "1..0\n# writing past 2GB failed\n";
+ explain();
+ bye();
+ }
+}
+close BIG;
+
+@s = stat("big");
+
+print "# @s\n";
+
+sub fail () {
+ print "not ";
+ $fail++;
+}
+
+print "1..17\n";
+
+my $fail = 0;
+
+fail unless $s[7] == 5_000_000_003; # exercizes pp_stat
+print "ok 1\n";
+
+fail unless -s "big" == 5_000_000_003; # exercizes pp_ftsize
+print "ok 2\n";
+
+fail unless -e "big";
+print "ok 3\n";
+
+fail unless -f "big";
+print "ok 4\n";
+
+sysopen(BIG, "big", O_RDONLY) or do { warn "sysopen failed: $!\n"; bye };
+
+fail unless sysseek(BIG, 4_500_000_000, SEEK_SET) == 4_500_000_000;
+print "ok 5\n";
+
+fail unless sysseek(BIG, 0, SEEK_CUR) == 4_500_000_000;
+print "ok 6\n";
+
+fail unless sysseek(BIG, 1, SEEK_CUR) == 4_500_000_001;
+print "ok 7\n";
+
+fail unless sysseek(BIG, 0, SEEK_CUR) == 4_500_000_001;
+print "ok 8\n";
+
+fail unless sysseek(BIG, -1, SEEK_CUR) == 4_500_000_000;
+print "ok 9\n";
+
+fail unless sysseek(BIG, 0, SEEK_CUR) == 4_500_000_000;
+print "ok 10\n";
+
+fail unless sysseek(BIG, -3, SEEK_END) == 5_000_000_000;
+print "ok 11\n";
+
+fail unless sysseek(BIG, 0, SEEK_CUR) == 5_000_000_000;
+print "ok 12\n";
+
+my $big;
+
+fail unless sysread(BIG, $big, 3) == 3;
+print "ok 13\n";
+
+fail unless $big eq "big";
+print "ok 14\n";
+
+# 705_032_704 = (I32)5_000_000_000
+fail unless seek(BIG, 705_032_704, $SEEK_SET);
+print "ok 15\n";
+
+my $zero;
+
+fail unless read(BIG, $zero, 3) == 3;
+print "ok 16\n";
+
+fail unless $zero eq "\0\0\0";
+print "ok 17\n";
+
+explain if $fail;
+
+bye(); # does the necessary cleanup
+
+# eof
diff --git a/t/lib/textfill.t b/t/lib/textfill.t
new file mode 100755
index 0000000000..daeee2367c
--- /dev/null
+++ b/t/lib/textfill.t
@@ -0,0 +1,98 @@
+#!./perl -w
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+use Text::Wrap qw(&fill);
+
+@tests = (split(/\nEND\n/s, <<DONE));
+TEST1
+Cyberdog Information
+
+Cyberdog & Netscape in the news
+Important Press Release regarding Cyberdog and Netscape. Check it out!
+
+Cyberdog Plug-in Support!
+Cyberdog support for Netscape Plug-ins is now available to download! Go
+to the Cyberdog Beta Download page and download it now!
+
+Cyberdog Book
+Check out Jesse Feiler's way-cool book about Cyberdog. You can find
+details out about the book as well as ordering information at Philmont
+Software Mill site.
+
+Java!
+Looking to view Java applets in Cyberdog 1.1 Beta 3? Download and install
+the Mac OS Runtime for Java and try it out!
+
+Cyberdog 1.1 Beta 3
+We hope that Cyberdog and OpenDoc 1.1 will be available within the next
+two weeks. In the meantime, we have released another version of
+Cyberdog, Cyberdog 1.1 Beta 3. This version fixes several bugs that were
+reported to us during out public beta period. You can check out our release
+notes to see what we fixed!
+END
+ Cyberdog Information
+ Cyberdog & Netscape in the news Important Press Release regarding
+ Cyberdog and Netscape. Check it out!
+ Cyberdog Plug-in Support! Cyberdog support for Netscape Plug-ins is now
+ available to download! Go to the Cyberdog Beta Download page and download
+ it now!
+ Cyberdog Book Check out Jesse Feiler's way-cool book about Cyberdog.
+ You can find details out about the book as well as ordering information at
+ Philmont Software Mill site.
+ Java! Looking to view Java applets in Cyberdog 1.1 Beta 3? Download and
+ install the Mac OS Runtime for Java and try it out!
+ Cyberdog 1.1 Beta 3 We hope that Cyberdog and OpenDoc 1.1 will be
+ available within the next two weeks. In the meantime, we have released
+ another version of Cyberdog, Cyberdog 1.1 Beta 3. This version fixes
+ several bugs that were reported to us during out public beta period. You
+ can check out our release notes to see what we fixed!
+END
+DONE
+
+
+$| = 1;
+
+print "1..", @tests/2, "\n";
+
+use Text::Wrap;
+
+$rerun = $ENV{'PERL_DL_NONLAZY'} ? 0 : 1;
+
+$tn = 1;
+while (@tests) {
+ my $in = shift(@tests);
+ my $out = shift(@tests);
+
+ $in =~ s/^TEST(\d+)?\n//;
+
+ my $back = fill(' ', ' ', $in);
+
+ if ($back eq $out) {
+ print "ok $tn\n";
+ } elsif ($rerun) {
+ my $oi = $in;
+ open(F,">#o") and do { print F $back; close(F) };
+ open(F,">#e") and do { print F $out; close(F) };
+ foreach ($in, $back, $out) {
+ s/\t/^I\t/gs;
+ s/\n/\$\n/gs;
+ }
+ print "------------ input ------------\n";
+ print $in;
+ print "\n------------ output -----------\n";
+ print $back;
+ print "\n------------ expected ---------\n";
+ print $out;
+ print "\n-------------------------------\n";
+ $Text::Wrap::debug = 1;
+ fill(' ', ' ', $oi);
+ exit(1);
+ } else {
+ print "not ok $tn\n";
+ }
+ $tn++;
+}
diff --git a/t/lib/texttabs.t b/t/lib/texttabs.t
index ea9012c652..80395f4c02 100755
--- a/t/lib/texttabs.t
+++ b/t/lib/texttabs.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..3\n";
diff --git a/t/lib/textwrap.t b/t/lib/textwrap.t
index 9c8d1b4975..bb1d5ca4a5 100755
--- a/t/lib/textwrap.t
+++ b/t/lib/textwrap.t
@@ -1,40 +1,129 @@
-#!./perl
+#!./perl -w
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
+use Text::Wrap qw(&wrap);
-print "1..5\n";
+@tests = (split(/\nEND\n/s, <<DONE));
+TEST1
+This
+is
+a
+test
+END
+ This
+ is
+ a
+ test
+END
+TEST2
+This is a test of a very long line. It should be broken up and put onto multiple lines.
+This is a test of a very long line. It should be broken up and put onto multiple lines.
-use Text::Wrap qw(wrap $columns);
+This is a test of a very long line. It should be broken up and put onto multiple lines.
+END
+ This is a test of a very long line. It should be broken up and put onto
+ multiple lines.
+ This is a test of a very long line. It should be broken up and put onto
+ multiple lines.
+
+ This is a test of a very long line. It should be broken up and put onto
+ multiple lines.
+END
+TEST3
+This is a test of a very long line. It should be broken up and put onto multiple lines.
+END
+ This is a test of a very long line. It should be broken up and put onto
+ multiple lines.
+END
+TEST4
+This is a test of a very long line. It should be broken up and put onto multiple lines.
-$columns = 30;
+END
+ This is a test of a very long line. It should be broken up and put onto
+ multiple lines.
-$text = <<'EOT';
-Text::Wrap is a very simple paragraph formatter. It formats a
-single paragraph at a time by breaking lines at word boundries.
-Indentation is controlled for the first line ($initial_tab) and
-all subsquent lines ($subsequent_tab) independently. $Text::Wrap::columns
-should be set to the full width of your output device.
-EOT
+END
+TEST5
+This is a test of a very long line. It should be broken up and put onto multiple This is a test of a very long line. It should be broken up and put
+END
+ This is a test of a very long line. It should be broken up and put onto
+ multiple This is a test of a very long line. It should be broken up and
+ put
+END
+TEST6
+11111111 22222222 33333333 44444444 55555555 66666666 77777777 888888888 999999999 aaaaaaaaa bbbbbbbbb ccccccccc ddddddddd eeeeeeeee ffffffff gggggggg hhhhhhhh iiiiiiii jjjjjjjj kkkkkkkk llllllll mmmmmmmmm nnnnnnnnn ooooooooo ppppppppp qqqqqqqqq rrrrrrrrr sssssssss
+END
+ 11111111 22222222 33333333 44444444 55555555 66666666 77777777 888888888
+ 999999999 aaaaaaaaa bbbbbbbbb ccccccccc ddddddddd eeeeeeeee ffffffff
+ gggggggg hhhhhhhh iiiiiiii jjjjjjjj kkkkkkkk llllllll mmmmmmmmm nnnnnnnnn
+ ooooooooo ppppppppp qqqqqqqqq rrrrrrrrr sssssssss
+END
+TEST7
+c3t1d0s6 c4t1d0s6 c5t1d0s6 c6t1d0s6 c7t1d0s6 c8t1d0s6 c9t1d0s6 c10t1d0s6 c11t1d0s6 c12t1d0s6 c13t1d0s6 c14t1d0s6 c15t1d0s6 c16t1d0s6 c3t1d0s0 c4t1d0s0 c5t1d0s0 c6t1d0s0 c7t1d0s0 c8t1d0s0 c9t1d0s0 c10t1d0s0 c11t1d0s0 c12t1d0s0 c13t1d0s0 c14t1d0s0 c15t1d0s0 c16t1d0s0
+END
+ c3t1d0s6 c4t1d0s6 c5t1d0s6 c6t1d0s6 c7t1d0s6 c8t1d0s6 c9t1d0s6 c10t1d0s6
+ c11t1d0s6 c12t1d0s6 c13t1d0s6 c14t1d0s6 c15t1d0s6 c16t1d0s6 c3t1d0s0
+ c4t1d0s0 c5t1d0s0 c6t1d0s0 c7t1d0s0 c8t1d0s0 c9t1d0s0 c10t1d0s0 c11t1d0s0
+ c12t1d0s0 c13t1d0s0 c14t1d0s0 c15t1d0s0 c16t1d0s0
+END
+TEST8
+A test of a very very long word.
+a123456789b123456789c123456789d123456789e123456789f123456789g123456789g1234567
+END
+ A test of a very very long word.
+ a123456789b123456789c123456789d123456789e123456789f123456789g123456789g123
+ 4567
+END
+TEST9
+A test of a very very long word. a123456789b123456789c123456789d123456789e123456789f123456789g123456789g1234567
+END
+ A test of a very very long word.
+ a123456789b123456789c123456789d123456789e123456789f123456789g123456789g123
+ 4567
+END
+DONE
-$text =~ s/\n/ /g;
-$_ = wrap "| ", "|", $text;
-#print "$_\n";
+$| = 1;
-print "not " unless /^\| Text::Wrap is/; # start is ok
-print "ok 1\n";
+print "1..", @tests/2, "\n";
-print "not " if /^.{31,}$/m; # no line longer than 30 chars
-print "ok 2\n";
+use Text::Wrap;
-print "not " unless /^\|\w/m; # other lines start with
-print "ok 3\n";
+$rerun = $ENV{'PERL_DL_NONLAZY'} ? 0 : 1;
-print "not " unless /\bsubsquent\b/; # look for a random word
-print "ok 4\n";
+$tn = 1;
+while (@tests) {
+ my $in = shift(@tests);
+ my $out = shift(@tests);
-print "not " unless /\bdevice\./; # look for last word
-print "ok 5\n";
+ $in =~ s/^TEST(\d+)?\n//;
+
+ my $back = wrap(' ', ' ', $in);
+
+ if ($back eq $out) {
+ print "ok $tn\n";
+ } elsif ($rerun) {
+ my $oi = $in;
+ foreach ($in, $back, $out) {
+ s/\t/^I\t/gs;
+ s/\n/\$\n/gs;
+ }
+ print "------------ input ------------\n";
+ print $in;
+ print "\n------------ output -----------\n";
+ print $back;
+ print "\n------------ expected ---------\n";
+ print $out;
+ print "\n-------------------------------\n";
+ $Text::Wrap::debug = 1;
+ wrap(' ', ' ', $oi);
+ exit(1);
+ } else {
+ print "not ok $tn\n";
+ }
+ $tn++;
+}
diff --git a/t/lib/thread.t b/t/lib/thread.t
index 83407a9fab..3bca8ba726 100755
--- a/t/lib/thread.t
+++ b/t/lib/thread.t
@@ -2,10 +2,10 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
if (! $Config{'usethreads'}) {
- print "1..0\n";
+ print "1..0 # Skip: this perl is not threaded\n";
exit 0;
}
@@ -13,7 +13,7 @@ BEGIN {
$ENV{PERL_DESTRUCT_LEVEL} = 0 unless $ENV{PERL_DESTRUCT_LEVEL} > 3;
}
$| = 1;
-print "1..14\n";
+print "1..18\n";
use Thread;
print "ok 1\n";
@@ -24,7 +24,7 @@ sub content
}
# create a thread passing args and immedaietly wait for it.
-my $t = new Thread \&content,("ok 2\n","ok 3\n");
+my $t = new Thread \&content,("ok 2\n","ok 3\n", 1..1000);
print $t->join;
# check that lock works ...
@@ -71,3 +71,17 @@ sub islocked
$t = Thread->new(\&islocked, "ok 13\n", "ok 14\n");
$t->join->join;
+{
+ package Loch::Ness;
+ sub new { bless [], shift }
+ sub monster {
+ use attrs qw(locked method);
+ my($s, $m) = @_;
+ print "ok $m\n";
+ }
+ sub gollum { &monster }
+}
+Loch::Ness->monster(15);
+Loch::Ness->new->monster(16);
+Loch::Ness->gollum(17);
+Loch::Ness->new->gollum(18);
diff --git a/t/lib/tie-push.t b/t/lib/tie-push.t
index dd718deb14..23a0a9403a 100755
--- a/t/lib/tie-push.t
+++ b/t/lib/tie-push.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
{
@@ -21,4 +21,4 @@ tie @x,Basic;
tie @get,Basic;
tie @got,Basic;
tie @tests,Basic;
-require "../t/op/push.t"
+require "op/push.t"
diff --git a/t/lib/tie-stdarray.t b/t/lib/tie-stdarray.t
index 7ca4d76f11..5a678a5a1f 100755
--- a/t/lib/tie-stdarray.t
+++ b/t/lib/tie-stdarray.t
@@ -2,11 +2,11 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Tie::Array;
tie @foo,Tie::StdArray;
tie @ary,Tie::StdArray;
tie @bar,Tie::StdArray;
-require "../t/op/array.t"
+require "op/array.t"
diff --git a/t/lib/tie-stdhandle.t b/t/lib/tie-stdhandle.t
new file mode 100755
index 0000000000..cb8303d94d
--- /dev/null
+++ b/t/lib/tie-stdhandle.t
@@ -0,0 +1,49 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+use Tie::Handle;
+tie *tst,Tie::StdHandle;
+
+$f = 'tst';
+
+print "1..13\n";
+
+# my $file tests
+
+unlink("afile.new") if -f "afile";
+print "$!\nnot " unless open($f,"+>afile");
+print "ok 1\n";
+print "$!\nnot " unless binmode($f);
+print "ok 2\n";
+print "not " unless -f "afile";
+print "ok 3\n";
+print "not " unless print $f "SomeData\n";
+print "ok 4\n";
+print "not " unless tell($f) == 9;
+print "ok 5\n";
+print "not " unless printf $f "Some %d value\n",1234;
+print "ok 6\n";
+print "not " unless seek($f,0,0);
+print "ok 7\n";
+$b = <$f>;
+print "not " unless $b eq "SomeData\n";
+print "ok 8\n";
+print "not " if eof($f);
+print "ok 9\n";
+read($f,($b=''),4);
+print "'$b' not " unless $b eq 'Some';
+print "ok 10\n";
+print "not " unless getc($f) eq ' ';
+print "ok 11\n";
+$b = <$f>;
+print "not " unless eof($f);
+print "ok 12\n";
+print "not " unless close($f);
+print "ok 13\n";
+unlink("afile");
+
+
diff --git a/t/lib/tie-stdpush.t b/t/lib/tie-stdpush.t
index 34a69472f4..35ae1b89a4 100755
--- a/t/lib/tie-stdpush.t
+++ b/t/lib/tie-stdpush.t
@@ -2,9 +2,9 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Tie::Array;
tie @x,Tie::StdArray;
-require "../t/op/push.t"
+require "op/push.t"
diff --git a/t/lib/timelocal.t b/t/lib/timelocal.t
index 100e0768aa..359d71e64c 100755
--- a/t/lib/timelocal.t
+++ b/t/lib/timelocal.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Time::Local;
diff --git a/t/lib/trig.t b/t/lib/trig.t
index 3114176ab0..20669f0bd9 100755
--- a/t/lib/trig.t
+++ b/t/lib/trig.t
@@ -10,7 +10,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Math::Trig;
diff --git a/t/op/64bit.t b/t/op/64bit.t
new file mode 100644
index 0000000000..09419f8790
--- /dev/null
+++ b/t/op/64bit.t
@@ -0,0 +1,182 @@
+BEGIN {
+ eval { my $q = pack "q", 0 };
+ if ($@) {
+ print "1..0\n# no 64-bit types\n";
+ exit(0);
+ }
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+# This could use a lot of more tests.
+#
+# Nota bene: bit operations (&, |, ^, ~, <<, >>) are not 64-bit clean.
+# See the beginning of pp.c and the explanation next to IBW/UBW.
+
+# so that using > 0xfffffff constants and
+# 32+ bit vector sizes doesn't cause noise
+no warnings qw(overflow portable);
+
+print "1..34\n";
+
+my $q = 12345678901;
+my $r = 23456789012;
+my $f = 0xffffffff;
+my $x;
+my $y;
+
+$x = unpack "q", pack "q", $q;
+print "not " unless $x == $q && $x > $f;
+print "ok 1\n";
+
+
+$x = sprintf("%lld", 12345678901);
+print "not " unless $x eq $q && $x > $f;
+print "ok 2\n";
+
+
+$x = sprintf("%lld", $q);
+print "not " unless $x == $q && $x eq $q && $x > $f;
+print "ok 3\n";
+
+$x = sprintf("%Ld", $q);
+print "not " unless $x == $q && $x eq $q && $x > $f;
+print "ok 4\n";
+
+$x = sprintf("%qd", $q);
+print "not " unless $x == $q && $x eq $q && $x > $f;
+print "ok 5\n";
+
+
+$x = sprintf("%llx", $q);
+print "not " unless hex($x) == 0x2dfdc1c35 && hex($x) > $f;
+print "ok 6\n";
+
+$x = sprintf("%Lx", $q);
+print "not " unless hex($x) == 0x2dfdc1c35 && hex($x) > $f;
+print "ok 7\n";
+
+$x = sprintf("%qx", $q);
+print "not " unless hex($x) == 0x2dfdc1c35 && hex($x) > $f;
+print "ok 8\n";
+
+
+$x = sprintf("%llo", $q);
+print "not " unless oct("0$x") == 0133767016065 && oct($x) > $f;
+print "ok 9\n";
+
+$x = sprintf("%Lo", $q);
+print "not " unless oct("0$x") == 0133767016065 && oct($x) > $f;
+print "ok 10\n";
+
+$x = sprintf("%qo", $q);
+print "not " unless oct("0$x") == 0133767016065 && oct($x) > $f;
+print "ok 11\n";
+
+
+$x = sprintf("%llb", $q);
+print "not " unless oct("0b$x") == 0b1011011111110111000001110000110101 &&
+ oct("0b$x") > $f;
+print "ok 12\n";
+
+$x = sprintf("%Lb", $q);
+print "not " unless oct("0b$x") == 0b1011011111110111000001110000110101 &&
+ oct("0b$x") > $f;
+print "ok 13\n";
+
+$x = sprintf("%qb", $q);
+print "not " unless oct("0b$x") == 0b1011011111110111000001110000110101 &&
+ oct("0b$x") > $f;
+print "ok 14\n";
+
+
+$x = sprintf("%llu", $q);
+print "not " unless $x eq $q && $x > $f;
+print "ok 15\n";
+
+$x = sprintf("%Lu", $q);
+print "not " unless $x == $q && $x eq $q && $x > $f;
+print "ok 16\n";
+
+$x = sprintf("%qu", $q);
+print "not " unless $x == $q && $x eq $q && $x > $f;
+print "ok 17\n";
+
+
+$x = sprintf("%D", $q);
+print "not " unless $x == $q && $x eq $q && $x > $f;
+print "ok 18\n";
+
+$x = sprintf("%U", $q);
+print "not " unless $x == $q && $x eq $q && $x > $f;
+print "ok 19\n";
+
+$x = sprintf("%O", $q);
+print "not " unless oct($x) == $q && oct($x) > $f;
+print "ok 20\n";
+
+
+$x = $q + $r;
+print "not " unless $x == 35802467913 && $x > $f;
+print "ok 21\n";
+
+$x = $q - $r;
+print "not " unless $x == -11111110111 && -$x > $f;
+print "ok 22\n";
+
+$x = $q * 1234567;
+print "not " unless $x == 15241567763770867 && $x > $f;
+print "ok 23\n";
+
+$x /= 1234567;
+print "not " unless $x == $q && $x > $f;
+print "ok 24\n";
+
+$x = 98765432109 % 12345678901;
+print "not " unless $x == 901;
+print "ok 25\n";
+
+# The following six adapted from op/inc.
+
+$a = 9223372036854775807;
+$c = $a++;
+print "not " unless $a == 9223372036854775808;
+print "ok 26\n";
+
+$a = 9223372036854775807;
+$c = ++$a;
+print "not " unless $a == 9223372036854775808;
+print "ok 27\n";
+
+$a = 9223372036854775807;
+$c = $a + 1;
+print "not " unless $a == 9223372036854775808;
+print "ok 28\n";
+
+$a = -9223372036854775808;
+$c = $a--;
+print "not " unless $a == -9223372036854775809;
+print "ok 29\n";
+
+$a = -9223372036854775808;
+$c = --$a;
+print "not " unless $a == -9223372036854775809;
+print "ok 30\n";
+
+$a = -9223372036854775808;
+$c = $a - 1;
+print "not " unless $a == -9223372036854775809;
+print "ok 31\n";
+
+
+$x = '';
+print "not " unless (vec($x, 1, 64) = $q) == $q;
+print "ok 32\n";
+
+print "not " unless vec($x, 1, 64) == $q && vec($x, 1, 64) > $f;
+print "ok 33\n";
+
+print "not " unless vec($x, 0, 64) == 0 && vec($x, 2, 64) == 0;
+print "ok 34\n";
+
+# eof
diff --git a/t/op/arith.t b/t/op/arith.t
index 43af807b8b..f1bd827f9b 100755
--- a/t/op/arith.t
+++ b/t/op/arith.t
@@ -1,6 +1,6 @@
#!./perl
-print "1..4\n";
+print "1..8\n";
sub try ($$) {
print +($_[1] ? "ok" : "not ok"), " $_[0]\n";
@@ -10,3 +10,7 @@ try 1, 13 % 4 == 1;
try 2, -13 % 4 == 3;
try 3, 13 % -4 == -3;
try 4, -13 % -4 == -1;
+try 5, abs( 13e21 % 4e21 - 1e21) < 1e6;
+try 6, abs(-13e21 % 4e21 - 3e21) < 1e6;
+try 7, abs( 13e21 % -4e21 - -3e21) < 1e6;
+try 8, abs(-13e21 % -4e21 - -1e21) < 1e6;
diff --git a/t/op/array.t b/t/op/array.t
index 8dea44de3f..3409556396 100755
--- a/t/op/array.t
+++ b/t/op/array.t
@@ -1,6 +1,6 @@
#!./perl
-print "1..63\n";
+print "1..65\n";
#
# @foo, @bar, and @ary are also used from tie-stdarray after tie-ing them
@@ -206,3 +206,8 @@ t("@bar" eq "foo bar"); # 43
t("@bee" eq "foo bar burbl blah"); # 63
}
+# make sure reification behaves
+my $t = 63;
+sub reify { $_[1] = ++$t; print "@_\n"; }
+reify('ok');
+reify('ok');
diff --git a/t/op/assignwarn.t b/t/op/assignwarn.t
index 57e89c45e0..00f7abbf67 100755
--- a/t/op/assignwarn.t
+++ b/t/op/assignwarn.t
@@ -8,7 +8,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use strict;
diff --git a/t/op/attrs.t b/t/op/attrs.t
new file mode 100644
index 0000000000..e89c2cb816
--- /dev/null
+++ b/t/op/attrs.t
@@ -0,0 +1,176 @@
+#!./perl -w
+
+# Regression tests for attributes.pm and the C< : attrs> syntax.
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+sub NTESTS () ;
+
+my ($test, $ntests);
+BEGIN {$ntests=0}
+$test=0;
+my $failed = 0;
+
+print "1..".NTESTS."\n";
+
+$SIG{__WARN__} = sub { die @_ };
+
+sub mytest {
+ if (!$@ ne !$_[0] || $_[0] && $@ !~ $_[0]) {
+ if ($@) {
+ my $x = $@;
+ $x =~ s/\n.*\z//s;
+ print "# Got: $x\n"
+ }
+ else {
+ print "# Got unexpected success\n";
+ }
+ if ($_[0]) {
+ print "# Expected: $_[0]\n";
+ }
+ else {
+ print "# Expected success\n";
+ }
+ $failed = 1;
+ print "not ";
+ }
+ elsif (@_ == 3 && $_[1] ne $_[2]) {
+ print "# Got: $_[1]\n";
+ print "# Expected: $_[2]\n";
+ $failed = 1;
+ print "not ";
+ }
+ print "ok ",++$test,"\n";
+}
+
+eval 'sub t1 ($) : locked { $_[0]++ }';
+mytest;
+BEGIN {++$ntests}
+
+eval 'sub t2 : locked { $_[0]++ }';
+mytest;
+BEGIN {++$ntests}
+
+eval 'sub t3 ($) : locked ;';
+mytest;
+BEGIN {++$ntests}
+
+eval 'sub t4 : locked ;';
+mytest;
+BEGIN {++$ntests}
+
+my $anon1;
+eval '$anon1 = sub ($) : locked,,method { $_[0]++ }';
+mytest;
+BEGIN {++$ntests}
+
+my $anon2;
+eval '$anon2 = sub : locked , method { $_[0]++ }';
+mytest;
+BEGIN {++$ntests}
+
+my $anon3;
+eval '$anon3 = sub : method { $_[0]->[1] }';
+mytest;
+BEGIN {++$ntests}
+
+eval 'sub e1 ($) : plugh ;';
+mytest qr/^Invalid CODE attributes?: ["']?plugh["']? at/;
+BEGIN {++$ntests}
+
+eval 'sub e2 ($) : plugh(0,0) xyzzy ;';
+mytest qr/^Invalid CODE attributes: ["']?plugh\(0,0\)["']? /;
+BEGIN {++$ntests}
+
+eval 'sub e3 ($) : plugh(0,0 xyzzy ;';
+mytest qr/Unterminated attribute parameter in attribute list at/;
+BEGIN {++$ntests}
+
+eval 'sub e4 ($) : plugh + xyzzy ;';
+mytest qr/Invalid separator character '[+]' in attribute list at/;
+BEGIN {++$ntests}
+
+eval 'my main $x : = 0;';
+mytest;
+BEGIN {++$ntests}
+
+eval 'my $x : = 0;';
+mytest;
+BEGIN {++$ntests}
+
+eval 'my $x ;';
+mytest;
+BEGIN {++$ntests}
+
+eval 'my ($x) : = 0;';
+mytest;
+BEGIN {++$ntests}
+
+eval 'my ($x) ;';
+mytest;
+BEGIN {++$ntests}
+
+eval 'my ($x) : ;';
+mytest;
+BEGIN {++$ntests}
+
+eval 'my ($x,$y) : = 0;';
+mytest;
+BEGIN {++$ntests}
+
+eval 'my ($x,$y) ;';
+mytest;
+BEGIN {++$ntests}
+
+eval 'my ($x,$y) : ;';
+mytest;
+BEGIN {++$ntests}
+
+eval 'my ($x,$y) : plugh;';
+mytest qr/^Invalid SCALAR attribute: ["']?plugh["']? at/;
+BEGIN {++$ntests}
+
+sub A::MODIFY_SCALAR_ATTRIBUTES { return }
+eval 'my A $x : plugh;';
+mytest qr/^SCALAR package attribute may clash with future reserved word: ["']?plugh["']? at/;
+BEGIN {++$ntests}
+
+eval 'my A $x : plugh plover;';
+mytest qr/^SCALAR package attributes may clash with future reserved words: ["']?plugh["']? /;
+BEGIN {++$ntests}
+
+sub X::MODIFY_CODE_ATTRIBUTES { die "$_[0]" }
+sub X::foo { 1 }
+*Y::bar = \&X::foo;
+*Y::bar = \&X::foo; # second time for -w
+eval 'package Z; sub Y::bar : locked';
+mytest qr/^X at /;
+BEGIN {++$ntests}
+
+my @attrs = eval 'attributes::get \&Y::bar';
+mytest '', "@attrs", "locked";
+BEGIN {++$ntests}
+
+@attrs = eval 'attributes::get $anon1';
+mytest '', "@attrs", "locked method";
+BEGIN {++$ntests}
+
+sub Z::DESTROY { }
+sub Z::FETCH_CODE_ATTRIBUTES { return 'Z' }
+my $thunk = eval 'bless +sub : method locked { 1 }, "Z"';
+mytest '', ref($thunk), "Z";
+BEGIN {++$ntests}
+
+@attrs = eval 'attributes::get $thunk';
+mytest '', "@attrs", "locked method Z";
+BEGIN {++$ntests}
+
+
+# Other tests should be added above this line
+
+sub NTESTS () { $ntests }
+
+exit $failed;
diff --git a/t/op/auto.t b/t/op/auto.t
index 93a42f8472..2eb0097650 100755
--- a/t/op/auto.t
+++ b/t/op/auto.t
@@ -2,7 +2,7 @@
# $RCSfile: auto.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:39 $
-print "1..34\n";
+print "1..37\n";
$x = 10000;
if (0 + ++$x - 1 == 10000) { print "ok 1\n";} else {print "not ok 1\n";}
@@ -46,3 +46,7 @@ if (++($foo = '99') eq '100') {print "ok 31\n";} else {print "not ok 31\n";}
if (++($foo = 'a0') eq 'a1') {print "ok 32\n";} else {print "not ok 32\n";}
if (++($foo = 'Az') eq 'Ba') {print "ok 33\n";} else {print "not ok 33\n";}
if (++($foo = 'zz') eq 'aaa') {print "ok 34\n";} else {print "not ok 34\n";}
+if (++($foo = 'A99') eq 'B00') {print "ok 35\n";} else {print "not ok 35\n";}
+# EBCDIC guards: i and j, r and s, are not contiguous.
+if (++($foo = 'zi') eq 'zj') {print "ok 36\n";} else {print "not ok 36\n";}
+if (++($foo = 'zr') eq 'zs') {print "ok 37\n";} else {print "not ok 37\n";}
diff --git a/t/op/avhv.t b/t/op/avhv.t
index 55cc992e63..6837127d52 100755
--- a/t/op/avhv.t
+++ b/t/op/avhv.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
require Tie::Array;
diff --git a/t/op/bop.t b/t/op/bop.t
index 0c55029b93..0c5ef4874d 100755
--- a/t/op/bop.t
+++ b/t/op/bop.t
@@ -6,7 +6,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
print "1..18\n";
@@ -42,14 +42,23 @@ print ((($cusp >> 1) == ($cusp / 2) &&
do { use integer; $cusp >> 1 } == -($cusp / 2))
? "ok 12\n" : "not ok 12\n");
+$Aaz = chr(ord("A") & ord("z"));
+$Aoz = chr(ord("A") | ord("z"));
+$Axz = chr(ord("A") ^ ord("z"));
+
# short strings
-print (("AAAAA" & "zzzzz") eq '@@@@@' ? "ok 13\n" : "not ok 13\n");
-print (("AAAAA" | "zzzzz") eq '{{{{{' ? "ok 14\n" : "not ok 14\n");
-print (("AAAAA" ^ "zzzzz") eq ';;;;;' ? "ok 15\n" : "not ok 15\n");
+print (("AAAAA" & "zzzzz") eq ($Aaz x 5) ? "ok 13\n" : "not ok 13\n");
+print (("AAAAA" | "zzzzz") eq ($Aoz x 5) ? "ok 14\n" : "not ok 14\n");
+print (("AAAAA" ^ "zzzzz") eq ($Axz x 5) ? "ok 15\n" : "not ok 15\n");
# long strings
$foo = "A" x 150;
$bar = "z" x 75;
-print (($foo & $bar) eq ('@'x75 ) ? "ok 16\n" : "not ok 16\n");
-print (($foo | $bar) eq ('{'x75 . 'A'x75) ? "ok 17\n" : "not ok 17\n");
-print (($foo ^ $bar) eq (';'x75 . 'A'x75) ? "ok 18\n" : "not ok 18\n");
+$zap = "A" x 75;
+# & truncates
+print (($foo & $bar) eq ($Aaz x 75 ) ? "ok 16\n" : "not ok 16\n");
+# | does not truncate
+print (($foo | $bar) eq ($Aoz x 75 . $zap) ? "ok 17\n" : "not ok 17\n");
+# ^ does not truncate
+print (($foo ^ $bar) eq ($Axz x 75 . $zap) ? "ok 18\n" : "not ok 18\n");
+
diff --git a/t/op/chars.t b/t/op/chars.t
new file mode 100755
index 0000000000..efdea027bb
--- /dev/null
+++ b/t/op/chars.t
@@ -0,0 +1,74 @@
+#!./perl
+
+print "1..33\n";
+
+# because of ebcdic.c these should be the same on asciiish
+# and ebcdic machines.
+# Peter Prymmer <pvhp@best.com>.
+
+my $c = "\c@";
+print +((ord($c) == 0) ? "" : "not "),"ok 1\n";
+$c = "\cA";
+print +((ord($c) == 1) ? "" : "not "),"ok 2\n";
+$c = "\cB";
+print +((ord($c) == 2) ? "" : "not "),"ok 3\n";
+$c = "\cC";
+print +((ord($c) == 3) ? "" : "not "),"ok 4\n";
+$c = "\cD";
+print +((ord($c) == 4) ? "" : "not "),"ok 5\n";
+$c = "\cE";
+print +((ord($c) == 5) ? "" : "not "),"ok 6\n";
+$c = "\cF";
+print +((ord($c) == 6) ? "" : "not "),"ok 7\n";
+$c = "\cG";
+print +((ord($c) == 7) ? "" : "not "),"ok 8\n";
+$c = "\cH";
+print +((ord($c) == 8) ? "" : "not "),"ok 9\n";
+$c = "\cI";
+print +((ord($c) == 9) ? "" : "not "),"ok 10\n";
+$c = "\cJ";
+print +((ord($c) == 10) ? "" : "not "),"ok 11\n";
+$c = "\cK";
+print +((ord($c) == 11) ? "" : "not "),"ok 12\n";
+$c = "\cL";
+print +((ord($c) == 12) ? "" : "not "),"ok 13\n";
+$c = "\cM";
+print +((ord($c) == 13) ? "" : "not "),"ok 14\n";
+$c = "\cN";
+print +((ord($c) == 14) ? "" : "not "),"ok 15\n";
+$c = "\cO";
+print +((ord($c) == 15) ? "" : "not "),"ok 16\n";
+$c = "\cP";
+print +((ord($c) == 16) ? "" : "not "),"ok 17\n";
+$c = "\cQ";
+print +((ord($c) == 17) ? "" : "not "),"ok 18\n";
+$c = "\cR";
+print +((ord($c) == 18) ? "" : "not "),"ok 19\n";
+$c = "\cS";
+print +((ord($c) == 19) ? "" : "not "),"ok 20\n";
+$c = "\cT";
+print +((ord($c) == 20) ? "" : "not "),"ok 21\n";
+$c = "\cU";
+print +((ord($c) == 21) ? "" : "not "),"ok 22\n";
+$c = "\cV";
+print +((ord($c) == 22) ? "" : "not "),"ok 23\n";
+$c = "\cW";
+print +((ord($c) == 23) ? "" : "not "),"ok 24\n";
+$c = "\cX";
+print +((ord($c) == 24) ? "" : "not "),"ok 25\n";
+$c = "\cY";
+print +((ord($c) == 25) ? "" : "not "),"ok 26\n";
+$c = "\cZ";
+print +((ord($c) == 26) ? "" : "not "),"ok 27\n";
+$c = "\c[";
+print +((ord($c) == 27) ? "" : "not "),"ok 28\n";
+$c = "\c\\";
+print +((ord($c) == 28) ? "" : "not "),"ok 29\n";
+$c = "\c]";
+print +((ord($c) == 29) ? "" : "not "),"ok 30\n";
+$c = "\c^";
+print +((ord($c) == 30) ? "" : "not "),"ok 31\n";
+$c = "\c_";
+print +((ord($c) == 31) ? "" : "not "),"ok 32\n";
+$c = "\c?";
+print +((ord($c) == 127) ? "" : "not "),"ok 33\n";
diff --git a/t/op/chop.t b/t/op/chop.t
index 77263ad3ad..6723ca3f1b 100755
--- a/t/op/chop.t
+++ b/t/op/chop.t
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: chop.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:40 $
-
-print "1..28\n";
+print "1..30\n";
# optimized
@@ -85,3 +83,9 @@ $_ = "axx";
$/ = "yy";
print chomp() == 0 ? "ok 27\n" : "not ok 27\n";
print $_ eq "axx" ? "ok 28\n" : "not ok 28\n";
+
+# This case once mistakenly behaved like paragraph mode.
+$_ = "ab\n";
+$/ = \3;
+print chomp() == 0 ? "ok 29\n" : "not ok 29\n";
+print $_ eq "ab\n" ? "ok 30\n" : "not ok 30\n";
diff --git a/t/op/closure.t b/t/op/closure.t
index 95d44f51e3..2284be6df1 100755
--- a/t/op/closure.t
+++ b/t/op/closure.t
@@ -7,7 +7,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Config;
diff --git a/t/op/defins.t b/t/op/defins.t
index 0ed61ce2fb..9e714a718b 100755
--- a/t/op/defins.t
+++ b/t/op/defins.t
@@ -6,7 +6,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
$SIG{__WARN__} = sub { $warns++; warn $_[0] };
print "1..14\n";
}
@@ -61,6 +61,7 @@ while ($where{$seen} = <FILE>)
}
print "not " unless $seen;
print "ok 5\n";
+close FILE;
opendir(DIR,'.');
$seen = 0;
diff --git a/t/op/die.t b/t/op/die.t
index d473ed6b7f..cf4f8b0555 100755
--- a/t/op/die.t
+++ b/t/op/die.t
@@ -4,7 +4,7 @@ print "1..10\n";
$SIG{__DIE__} = sub { print ref($_[0]) ? ("ok ",$_[0]->[0]++,"\n") : @_ } ;
-$err = "ok 1\n";
+$err = "#[\000]\nok 1\n";
eval {
die $err;
};
diff --git a/t/op/die_exit.t b/t/op/die_exit.t
index b5760d6fa0..7808d9d7c5 100755
--- a/t/op/die_exit.t
+++ b/t/op/die_exit.t
@@ -7,7 +7,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -e '../lib';
+ unshift @INC, '../lib' if -e '../lib';
}
my $perl = -e '../perl' ? '../perl' : -e './perl' ? './perl' : 'perl';
@@ -30,6 +30,8 @@ my %tests = (
14 => [ 255, 0],
15 => [ 255, 1],
16 => [ 255, 256],
+ # see if implicit close preserves $?
+ 17 => [ 0, 512, '{ local *F; open F, q[TEST]; close F; $!=0 } die;'],
);
my $max = keys %tests;
@@ -37,14 +39,15 @@ my $max = keys %tests;
print "1..$max\n";
foreach my $test (1 .. $max) {
- my($bang, $query) = @{$tests{$test}};
+ my($bang, $query, $code) = @{$tests{$test}};
+ $code ||= 'die;';
my $exit =
($^O eq 'MSWin32'
- ? system qq($perl -e "\$! = $bang; \$? = $query; die;" 2> nul)
- : system qq($perl -e '\$! = $bang; \$? = $query; die;' 2> /dev/null));
+ ? system qq($perl -e "\$! = $bang; \$? = $query; $code" 2> nul)
+ : system qq($perl -e '\$! = $bang; \$? = $query; $code' 2> /dev/null));
- printf "# 0x%04x 0x%04x 0x%04x\nnot ", $exit, $bang, $query
- unless $exit == (($bang || ($query >> 8) || 255) << 8);
+ printf "# 0x%04x 0x%04x 0x%04x\n", $exit, $bang, $query;
+ print "not " unless $exit == (($bang || ($query >> 8) || 255) << 8);
print "ok $test\n";
}
diff --git a/t/op/each.t b/t/op/each.t
index 420fdc09c3..879c0d0fd3 100755
--- a/t/op/each.t
+++ b/t/op/each.t
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: each.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:47 $
-
-print "1..16\n";
+print "1..19\n";
$h{'abc'} = 'ABC';
$h{'def'} = 'DEF';
@@ -43,7 +41,8 @@ if ($#keys == 29 && $#values == 29) {print "ok 1\n";} else {print "not ok 1\n";}
$i = 0; # stop -w complaints
while (($key,$value) = each(%h)) {
- if ($key eq $keys[$i] && $value eq $values[$i] && $key eq lc($value)) {
+ if ($key eq $keys[$i] && $value eq $values[$i]
+ && (('a' lt 'A' && $key lt $value) || $key gt $value)) {
$key =~ y/a-z/A-Z/;
$i++ if $key eq $value;
}
@@ -119,3 +118,16 @@ while (($key, $value) = each(h)) {
}
}
if ($i == 5) { print "ok 16\n" } else { print "not ok\n" }
+
+{
+ package Obj;
+ sub DESTROY { print "ok 18\n"; }
+ {
+ my $h = { A => bless [], __PACKAGE__ };
+ while (my($k,$v) = each %$h) {
+ print "ok 17\n" if $k eq 'A' and ref($v) eq 'Obj';
+ }
+ }
+ print "ok 19\n";
+}
+
diff --git a/t/op/eval.t b/t/op/eval.t
index 9368281d5b..abcb3794b7 100755
--- a/t/op/eval.t
+++ b/t/op/eval.t
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: eval.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:48 $
-
-print "1..23\n";
+print "1..37\n";
eval 'print "ok 1\n";';
@@ -79,3 +77,102 @@ eval {
};
&$x();
}
+
+my $b = 'wrong';
+my $X = sub {
+ my $b = "right";
+ print eval('"$b"') eq $b ? "ok 24\n" : "not ok 24\n";
+};
+&$X();
+
+
+# check navigation of multiple eval boundaries to find lexicals
+
+my $x = 25;
+eval <<'EOT'; die if $@;
+ print "# $x\n"; # clone into eval's pad
+ sub do_eval1 {
+ eval $_[0]; die if $@;
+ }
+EOT
+do_eval1('print "ok $x\n"');
+$x++;
+do_eval1('eval q[print "ok $x\n"]');
+$x++;
+do_eval1('sub { eval q[print "ok $x\n"] }->()');
+$x++;
+
+# calls from within eval'' should clone outer lexicals
+
+eval <<'EOT'; die if $@;
+ sub do_eval2 {
+ eval $_[0]; die if $@;
+ }
+do_eval2('print "ok $x\n"');
+$x++;
+do_eval2('eval q[print "ok $x\n"]');
+$x++;
+do_eval2('sub { eval q[print "ok $x\n"] }->()');
+$x++;
+EOT
+
+# calls outside eval'' should NOT clone lexicals from called context
+
+$main::x = 'ok';
+eval <<'EOT'; die if $@;
+ # $x unbound here
+ sub do_eval3 {
+ eval $_[0]; die if $@;
+ }
+EOT
+do_eval3('print "$x ' . $x . '\n"');
+$x++;
+do_eval3('eval q[print "$x ' . $x . '\n"]');
+$x++;
+do_eval3('sub { eval q[print "$x ' . $x . '\n"] }->()');
+$x++;
+
+# can recursive subroutine-call inside eval'' see its own lexicals?
+sub recurse {
+ my $l = shift;
+ if ($l < $x) {
+ ++$l;
+ eval 'print "# level $l\n"; recurse($l);';
+ die if $@;
+ }
+ else {
+ print "ok $l\n";
+ }
+}
+{
+ local $SIG{__WARN__} = sub { die "not ok $x\n" if $_[0] =~ /^Deep recurs/ };
+ recurse($x-5);
+}
+$x++;
+
+# do closures created within eval bind correctly?
+eval <<'EOT';
+ sub create_closure {
+ my $self = shift;
+ return sub {
+ print $self;
+ };
+ }
+EOT
+create_closure("ok $x\n")->();
+$x++;
+
+# does lexical search terminate correctly at subroutine boundary?
+$main::r = "ok $x\n";
+sub terminal { eval 'print $r' }
+{
+ my $r = "not ok $x\n";
+ eval 'terminal($r)';
+}
+$x++;
+
+# Have we cured panic which occurred with require/eval in die handler ?
+$SIG{__DIE__} = sub { eval {1}; die shift };
+eval { die "ok ".$x++,"\n" };
+print $@;
+
diff --git a/t/op/exec.t b/t/op/exec.t
index 506fc09fbd..5d014369ba 100755
--- a/t/op/exec.t
+++ b/t/op/exec.t
@@ -1,19 +1,24 @@
#!./perl
-# $RCSfile: exec.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:49 $
-
$| = 1; # flush stdout
+$ENV{LC_ALL} = 'C'; # Forge English error messages.
+$ENV{LANGUAGE} = 'C'; # Ditto in GNU.
+
if ($^O eq 'MSWin32') {
- print "# exec is unsupported on Win32\n";
# XXX the system tests could be written to use ./perl and so work on Win32
- print "1..0\n";
+ print "1..0 # Skip: shh, win32\n";
exit(0);
}
print "1..8\n";
-print "not ok 1\n" if system "echo ok \\1"; # shell interpreted
+if ($^O ne 'os2') {
+ print "not ok 1\n" if system "echo ok \\1"; # shell interpreted
+}
+else {
+ print "ok 1 # skipped: bug/feature of pdksh\n"; # shell interpreted
+}
print "not ok 2\n" if system "echo ok 2"; # split and directly called
print "not ok 3\n" if system "echo", "ok", "3"; # directly called
@@ -23,7 +28,16 @@ if (system "true") {print "not ok 4\n";} else {print "ok 4\n";}
if ((system "/bin/sh -c 'exit 1'") != 256) { print "not "; }
print "ok 5\n";
-if ((system "lskdfj") == 255 << 8) {print "ok 6\n";} else {print "not ok 6\n";}
+$rc = system "lskdfj";
+if ($rc == 255 << 8 or $rc == -1 and
+ (
+ $! == 2 or
+ $! =~ /\bno\b.*\bfile/i or
+ $! == 13 or
+ $! =~ /permission denied/i
+ )
+ )
+ {print "ok 6\n";} else {print "not ok 6\n";}
unless (exec "lskdjfalksdjfdjfkls") {print "ok 7\n";} else {print "not ok 7\n";}
diff --git a/t/op/fh.t b/t/op/fh.t
new file mode 100755
index 0000000000..86e405a992
--- /dev/null
+++ b/t/op/fh.t
@@ -0,0 +1,26 @@
+#!./perl
+
+print "1..5\n";
+
+my $test = 0;
+
+# symbolic filehandles should only result in glob entries with FH constructors
+
+$|=1;
+my $a = "SYM000";
+print "not " if defined(fileno($a)) or defined *{$a};
+++$test; print "ok $test\n";
+
+select select $a;
+print "not " unless defined *{$a};
+++$test; print "ok $test\n";
+
+$a++;
+print "not " if close $a or defined *{$a};
+++$test; print "ok $test\n";
+
+print "not " unless open($a, ">&STDOUT") and defined *{$a};
+++$test; print $a "ok $test\n";
+
+print "not " unless close $a;
+++$test; print $a "not "; print "ok $test\n";
diff --git a/t/op/filetest.t b/t/op/filetest.t
new file mode 100755
index 0000000000..e00d5fb7b0
--- /dev/null
+++ b/t/op/filetest.t
@@ -0,0 +1,71 @@
+#!./perl
+
+# There are few filetest operators that are portable enough to test.
+# See pod/perlport.pod for details.
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib' if -d '../lib';
+}
+
+use Config;
+print "1..10\n";
+
+print "not " unless -d 'op';
+print "ok 1\n";
+
+print "not " unless -f 'TEST';
+print "ok 2\n";
+
+print "not " if -f 'op';
+print "ok 3\n";
+
+print "not " if -d 'TEST';
+print "ok 4\n";
+
+print "not " unless -r 'TEST';
+print "ok 5\n";
+
+# make sure TEST is r-x
+eval { chmod 0555, 'TEST' };
+$bad_chmod = $@;
+
+$oldeuid = $>; # root can read and write anything
+eval '$> = 1'; # so switch uid (may not be implemented)
+
+print "# oldeuid = $oldeuid, euid = $>\n";
+
+if (!$Config{d_seteuid}) {
+ print "ok 6 #skipped, no seteuid\n";
+}
+elsif ($bad_chmod) {
+ print "#[$@]\nok 6 #skipped\n";
+}
+else {
+ print "not " if -w 'TEST';
+ print "ok 6\n";
+}
+
+# Scripts are not -x everywhere so cannot test that.
+
+eval '$> = $oldeuid'; # switch uid back (may not be implemented)
+
+# this would fail for the euid 1
+# (unless we have unpacked the source code as uid 1...)
+print "not " unless -r 'op';
+print "ok 7\n";
+
+# this would fail for the euid 1
+# (unless we have unpacked the source code as uid 1...)
+if ($Config{d_seteuid}) {
+ print "not " unless -w 'op';
+ print "ok 8\n";
+} else {
+ print "ok 8 #skipped, no seteuid\n";
+}
+
+print "not " unless -x 'op'; # Hohum. Are directories -x everywhere?
+print "ok 9\n";
+
+print "not " unless "@{[grep -r, qw(foo io noo op zoo)]}" eq "io op";
+print "ok 10\n";
diff --git a/t/op/fork.t b/t/op/fork.t
index 9790ff0f8c..20c87472b2 100755
--- a/t/op/fork.t
+++ b/t/op/fork.t
@@ -4,10 +4,10 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
require Config; import Config;
unless ($Config{'d_fork'}) {
- print "1..0\n";
+ print "1..0 # Skip: no fork\n";
exit 0;
}
}
diff --git a/t/op/goto.t b/t/op/goto.t
index 1b34acda39..7a5de5fea5 100755
--- a/t/op/goto.t
+++ b/t/op/goto.t
@@ -1,10 +1,8 @@
#!./perl
-# $RCSfile: goto.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:56 $
-
# "This IS structured code. It's just randomly structured."
-print "1..9\n";
+print "1..16\n";
while ($?) {
$foo = 1;
@@ -56,7 +54,28 @@ sub bar {
exit;
FINALE:
-print "ok 9\n";
+print "ok 13\n";
+
+# does goto LABEL handle block contexts correctly?
+
+my $cond = 1;
+for (1) {
+ if ($cond == 1) {
+ $cond = 0;
+ goto OTHER;
+ }
+ elsif ($cond == 0) {
+ OTHER:
+ $cond = 2;
+ print "ok 14\n";
+ goto THIRD;
+ }
+ else {
+ THIRD:
+ print "ok 15\n";
+ }
+}
+print "ok 16\n";
exit;
bypass:
@@ -86,5 +105,22 @@ $wherever = NOWHERE;
eval { goto $wherever };
print $@ =~ /Can't find label NOWHERE/ ? "ok 8\n" : "not ok 8\n";
+# see if a modified @_ propagates
+{
+ package Foo;
+ sub DESTROY { my $s = shift; print "ok $s->[0]\n"; }
+ sub show { print "# @_\nnot ok $_[0][0]\n" if @_ != 5; }
+ sub start { push @_, 1, "foo", {}; goto &show; }
+ for (9..11) { start(bless([$_]), 'bar'); }
+}
+
+sub auto {
+ goto &loadit;
+}
+
+sub AUTOLOAD { print @_ }
+
+auto("ok 12\n");
+
$wherever = FINALE;
goto $wherever;
diff --git a/t/op/goto_xs.t b/t/op/goto_xs.t
index a35575eb26..8d9bca1cd6 100755
--- a/t/op/goto_xs.t
+++ b/t/op/goto_xs.t
@@ -10,7 +10,7 @@
# break correctly as well.
chdir 't' if -d 't';
-@INC = "../lib";
+unshift @INC, "../lib";
$ENV{PERL5LIB} = "../lib";
# turn warnings into fatal errors
diff --git a/t/op/grent.t b/t/op/grent.t
new file mode 100755
index 0000000000..761d8b9cf6
--- /dev/null
+++ b/t/op/grent.t
@@ -0,0 +1,139 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, "../lib" if -d "../lib";
+ eval {my @n = getgrgid 0};
+ if ($@ && $@ =~ /(The \w+ function is unimplemented)/) {
+ print "1..0 # Skip: $1\n";
+ exit 0;
+ }
+ eval { require Config; import Config; };
+ my $reason;
+ if ($Config{'i_grp'} ne 'define') {
+ $reason = '$Config{i_grp} not defined';
+ }
+ elsif (not -f "/etc/group" ) { # Play safe.
+ $reason = 'no /etc/group file';
+ }
+
+ if (not defined $where) { # Try NIS.
+ foreach my $ypcat (qw(/usr/bin/ypcat /bin/ypcat /etc/ypcat)) {
+ if (-x $ypcat &&
+ open(GR, "$ypcat group 2>/dev/null |") &&
+ defined(<GR>)) {
+ $where = "NIS group";
+ undef $reason;
+ last;
+ }
+ }
+ }
+
+ if (not defined $where) { # Try NetInfo.
+ foreach my $nidump (qw(/usr/bin/nidump)) {
+ if (-x $nidump &&
+ open(GR, "$nidump group . 2>/dev/null |") &&
+ defined(<GR>)) {
+ $where = "NetInfo group";
+ undef $reason;
+ last;
+ }
+ }
+ }
+
+ if (not defined $where) { # Try local.
+ my $GR = "/etc/group";
+ if (-f $GR && open(GR, $GR) && defined(<GR>)) {
+ undef $reason;
+ $where = $GR;
+ }
+ }
+ if ($reason) {
+ print "1..0 # Skip: $reason\n";
+ exit 0;
+ }
+}
+
+# By now GR filehandle should be open and full of juicy group entries.
+
+print "1..1\n";
+
+# Go through at most this many groups.
+# (note that the first entry has been read away by now)
+my $max = 25;
+
+my $n = 0;
+my $tst = 1;
+my %perfect;
+my %seen;
+
+while (<GR>) {
+ chomp;
+ my @s = split /:/;
+ my ($name_s,$passwd_s,$gid_s,$members_s) = @s;
+ if (@s) {
+ push @{ $seen{$name_s} }, $.;
+ } else {
+ warn "# Your $where line $. is empty.\n";
+ next;
+ }
+ if ($n == $max) {
+ local $/;
+ my $junk = <GR>;
+ last;
+ }
+ # In principle we could whine if @s != 4 but do we know enough
+ # of group file formats everywhere?
+ if (@s == 4) {
+ $members_s =~ s/\s*,\s*/,/g;
+ $members_s =~ s/\s+$//;
+ $members_s =~ s/^\s+//;
+ @n = getgrgid($gid_s);
+ # 'nogroup' et al.
+ next unless @n;
+ my ($name,$passwd,$gid,$members) = @n;
+ # Protect against one-to-many and many-to-one mappings.
+ if ($name_s ne $name) {
+ @n = getgrnam($name_s);
+ ($name,$passwd,$gid,$members) = @n;
+ next if $name_s ne $name;
+ }
+ # NOTE: group names *CAN* contain whitespace.
+ $members =~ s/\s+/,/g;
+ # what about different orders of members?
+ $perfect{$name_s}++
+ if $name eq $name_s and
+# Do not compare passwords: think shadow passwords.
+# Not that group passwords are used much but better not assume anything.
+ $gid eq $gid_s and
+ $members eq $members_s;
+ }
+ $n++;
+}
+
+if (keys %perfect == 0) {
+ $max++;
+ print <<EOEX;
+#
+# The failure of op/grent test is not necessarily serious.
+# It may fail due to local group administration conventions.
+# If you are for example using both NIS and local groups,
+# test failure is possible. Any distributed group scheme
+# can cause such failures.
+#
+# What the grent test is doing is that it compares the $max first
+# entries of $where
+# with the results of getgrgid() and getgrnam() call. If it finds no
+# matches at all, it suspects something is wrong.
+#
+EOEX
+ print "not ";
+ $not = 1;
+} else {
+ $not = 0;
+}
+print "ok ", $tst++;
+print "\t# (not necessarily serious: run t/op/grent.t by itself)" if $not;
+print "\n";
+
+close(GR);
diff --git a/t/op/grep.t b/t/op/grep.t
new file mode 100755
index 0000000000..45d0e25a27
--- /dev/null
+++ b/t/op/grep.t
@@ -0,0 +1,31 @@
+#!./perl
+
+#
+# grep() and map() tests
+#
+
+print "1..3\n";
+
+$test = 1;
+
+sub ok {
+ my ($got,$expect) = @_;
+ print "# expected [$expect], got [$got]\nnot " if $got ne $expect;
+ print "ok $test\n";
+}
+
+{
+ my @lol = ([qw(a b c)], [], [qw(1 2 3)]);
+ my @mapped = map {scalar @$_} @lol;
+ ok "@mapped", "3 0 3";
+ $test++;
+
+ my @grepped = grep {scalar @$_} @lol;
+ ok "@grepped", "$lol[0] $lol[2]";
+ $test++;
+
+ @grepped = grep { $_ } @mapped;
+ ok "@grepped", "3 3";
+ $test++;
+}
+
diff --git a/t/op/groups.t b/t/op/groups.t
index 47aabe3d7b..f46af93bd3 100755
--- a/t/op/groups.t
+++ b/t/op/groups.t
@@ -1,13 +1,101 @@
#!./perl
-if (! -x ($groups = '/usr/ucb/groups') &&
- ! -x ($groups = '/usr/bin/groups') &&
- ! -x ($groups = '/bin/groups')
-) {
- print "1..0\n";
+$ENV{PATH} ="/bin:/usr/bin:/usr/xpg4/bin:/usr/ucb" .
+ exists $ENV{PATH} ? ":$ENV{PATH}" : "";
+$ENV{LC_ALL} = "C"; # so that external utilities speak English
+$ENV{LANGUAGE} = 'C'; # GNU locale extension
+
+sub quit {
+ print "1..0 # Skip: no `id` or `groups`\n";
exit 0;
}
+quit() if $^O eq 'MSWin32';
+
+# We have to find a command that prints all (effective
+# and real) group names (not ids). The known commands are:
+# groups
+# id -Gn
+# id -a
+# Beware 1: some systems do just 'id -G' even when 'id -Gn' is used.
+# Beware 2: id -Gn or id -a format might be id(name) or name(id).
+# Beware 3: the groups= might be anywhere in the id output.
+# Beware 4: groups can have spaces ('id -a' being the only defense against this)
+# Beware 5: id -a might not contain the groups= part.
+#
+# That is, we might meet the following:
+#
+# foo bar zot # accept
+# foo 22 42 bar zot # accept
+# 1 22 42 2 3 # reject
+# groups=(42),foo(1),bar(2),zot me(3) # parse
+# groups=22,42,1(foo),2(bar),3(zot me) # parse
+#
+# and the groups= might be after, before, or between uid=... and gid=...
+
+GROUPS: {
+ # prefer 'id' over 'groups' (is this ever wrong anywhere?)
+ # and 'id -a' over 'id -Gn' (the former is good about spaces in group names)
+ if (($groups = `id -a 2>/dev/null`) ne '') {
+ # $groups is of the form:
+ # uid=39957(gsar) gid=22(users) groups=33536,39181,22(users),0(root),1067(dev)
+ last GROUPS if $groups =~ /groups=/;
+ }
+ if (($groups = `id -Gn 2>/dev/null`) ne '') {
+ # $groups could be of the form:
+ # users 33536 39181 root dev
+ last GROUPS if $groups !~ /^(\d|\s)+$/;
+ }
+ if (($groups = `groups 2>/dev/null`) ne '') {
+ # may not reflect all groups in some places, so do a sanity check
+ if (-d '/afs') {
+ print <<EOM;
+# These test results *may* be bogus, as you appear to have AFS,
+# and I can't find a working 'id' in your PATH (which I have set
+# to '$ENV{PATH}').
+#
+# If these tests fail, report the particular incantation you use
+# on this platform to find *all* the groups that an arbitrary
+# luser may belong to, using the 'perlbug' program.
+EOM
+ }
+ last GROUPS;
+ }
+ # Okay, not today.
+ quit();
+}
+
+unless (eval { getgrgid(0); 1 }) {
+ print "1..0 # Skip: getgrgid() not implemented\n";
+ exit 0;
+}
+
+# Remember that group names can contain whitespace, '-', et cetera.
+# That is: do not \w, do not \S.
+if ($groups =~ /groups=(.+)( [ug]id=|$)/) {
+ my $gr = $1;
+ my @g0 = split /,/, $gr;
+ my @g1;
+ # prefer names over numbers
+ for (@g0) {
+ # 42(zot me)
+ if (/^(\d+)(?:\(([^)]+)\))?$/) {
+ push @g1, ($2 || $1);
+ }
+ # zot me(42)
+ elsif (/^([^(]*)\((\d+)\)$/) {
+ push @g1, ($1 || $2);
+ }
+ else {
+ print "# ignoring group entry [$_]\n";
+ }
+ }
+ print "# groups=$gr\n";
+ print "# g0 = @g0\n";
+ print "# g1 = @g1\n";
+ $groups = "@g1";
+}
+
print "1..2\n";
$pwgid = $( + 0;
@@ -27,9 +115,13 @@ for (split(' ', $()) {
}
}
-$gr1 = join(' ', sort @gr);
+if ($^O eq "uwin") { # Or anybody else who can have spaces in group names.
+ $gr1 = join(' ', grep(!$did{$_}++, sort split(' ', join(' ', @gr))));
+} else {
+ $gr1 = join(' ', sort @gr);
+}
-$gr2 = join(' ', grep(!$basegroup{$_}++, sort split(' ',`$groups`)));
+$gr2 = join(' ', grep(!$basegroup{$_}++, sort split(' ',$groups)));
if ($gr1 eq $gr2) {
print "ok 1\n";
diff --git a/t/op/gv.t b/t/op/gv.t
index c253e4bd9d..ee7978e046 100755
--- a/t/op/gv.t
+++ b/t/op/gv.t
@@ -4,7 +4,7 @@
# various typeglob tests
#
-print "1..23\n";
+print "1..30\n";
# type coersion on assignment
$foo = 'foo';
@@ -62,7 +62,7 @@ if (defined $baa) {
# fact that %X::Y:: is stored in %X:: isn't documented.
# (I hope.)
-{ package Foo::Bar }
+{ package Foo::Bar; $test=1; }
print exists $Foo::{'Bar::'} ? "ok 12\n" : "not ok 12\n";
print $Foo::{'Bar::'} eq '*Foo::Bar::' ? "ok 13\n" : "not ok 13\n";
@@ -95,4 +95,39 @@ print *{*x{GLOB}} eq "*main::STDOUT" ? "ok 21\n" : "not ok 21\n";
print {*x{IO}} "ok 22\n";
print {*x{FILEHANDLE}} "ok 23\n";
+# test if defined() doesn't create any new symbols
+{
+ my $test = 23;
+
+ my $a = "SYM000";
+ print "not " if defined *{$a};
+ ++$test; print "ok $test\n";
+
+ print "not " if defined @{$a} or defined *{$a};
+ ++$test; print "ok $test\n";
+
+ print "not " if defined %{$a} or defined *{$a};
+ ++$test; print "ok $test\n";
+
+ print "not " if defined ${$a} or defined *{$a};
+ ++$test; print "ok $test\n";
+
+ print "not " if defined &{$a} or defined *{$a};
+ ++$test; print "ok $test\n";
+
+ *{$a} = sub { print "ok $test\n" };
+ print "not " unless defined &{$a} and defined *{$a};
+ ++$test; &{$a};
+}
+
+# does pp_readline() handle glob-ness correctly?
+
+{
+ my $g = *foo;
+ $g = <DATA>;
+ print $g;
+}
+
+__END__
+ok 30
diff --git a/t/op/hashwarn.t b/t/op/hashwarn.t
index 6343a2a8d5..634e7e1f25 100755
--- a/t/op/hashwarn.t
+++ b/t/op/hashwarn.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use strict;
diff --git a/t/op/join.t b/t/op/join.t
index eec4611e62..def5a9e9fa 100755
--- a/t/op/join.t
+++ b/t/op/join.t
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: join.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:01 $
-
-print "1..3\n";
+print "1..6\n";
@x = (1, 2, 3);
if (join(':',@x) eq '1:2:3') {print "ok 1\n";} else {print "not ok 1\n";}
@@ -10,3 +8,15 @@ if (join(':',@x) eq '1:2:3') {print "ok 1\n";} else {print "not ok 1\n";}
if (join('',1,2,3) eq '123') {print "ok 2\n";} else {print "not ok 2\n";}
if (join(':',split(/ /,"1 2 3")) eq '1:2:3') {print "ok 3\n";} else {print "not ok 3\n";}
+
+my $f = 'a';
+$f = join ',', 'b', $f, 'e';
+if ($f eq 'b,a,e') {print "ok 4\n";} else {print "# '$f'\nnot ok 4\n";}
+
+$f = 'a';
+$f = join ',', $f, 'b', 'e';
+if ($f eq 'a,b,e') {print "ok 5\n";} else {print "not ok 5\n";}
+
+$f = 'a';
+$f = join $f, 'b', 'e', 'k';
+if ($f eq 'baeak') {print "ok 6\n";} else {print "# '$f'\nnot ok 6\n";}
diff --git a/t/op/lex_assign.t b/t/op/lex_assign.t
new file mode 100755
index 0000000000..b5c471a5a0
--- /dev/null
+++ b/t/op/lex_assign.t
@@ -0,0 +1,305 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+umask 0;
+$xref = \ "";
+$runme = ($^O eq 'VMS' ? 'MCR ' : '') . $^X;
+@a = (1..5);
+%h = (1..6);
+$aref = \@a;
+$href = \%h;
+open OP, qq{$runme -le "print 'aaa Ok ok' for 1..100"|};
+$chopit = 'aaaaaa';
+@chopar = (113 .. 119);
+$posstr = '123456';
+$cstr = 'aBcD.eF';
+pos $posstr = 3;
+$nn = $n = 2;
+sub subb {"in s"}
+
+@INPUT = <DATA>;
+@simple_input = grep /^\s*\w+\s*\$\w+\s*[#\n]/, @INPUT;
+print "1..", (8 + @INPUT + @simple_input), "\n";
+$ord = 0;
+
+sub wrn {"@_"}
+
+# Check correct optimization of ucfirst etc
+$ord++;
+my $a = "AB";
+my $b = "\u\L$a";
+print "not " unless $b eq 'Ab';
+print "ok $ord\n";
+
+# Check correct destruction of objects:
+my $dc = 0;
+sub A::DESTROY {$dc += 1}
+$a=8;
+my $b;
+{ my $c = 6; $b = bless \$c, "A"}
+
+$ord++;
+print "not " unless $dc == 0;
+print "ok $ord\n";
+
+$b = $a+5;
+
+$ord++;
+print "not " unless $dc == 1;
+print "ok $ord\n";
+
+{ # Check calling STORE
+ my $sc = 0;
+ sub B::TIESCALAR {bless [11], 'B'}
+ sub B::FETCH { -(shift->[0]) }
+ sub B::STORE { $sc++; my $o = shift; $o->[0] = 17 + shift }
+
+ my $m;
+ tie $m, 'B';
+ $m = 100;
+
+ $ord++;
+ print "not " unless $sc == 1;
+ print "ok $ord\n";
+
+ my $t = 11;
+ $m = $t + 89;
+
+ $ord++;
+ print "not " unless $sc == 2;
+ print "ok $ord\n";
+
+ $ord++;
+ print "# $m\nnot " unless $m == -117;
+ print "ok $ord\n";
+
+ $m += $t;
+
+ $ord++;
+ print "not " unless $sc == 3;
+ print "ok $ord\n";
+
+ $ord++;
+ print "# $m\nnot " unless $m == 89;
+ print "ok $ord\n";
+
+}
+
+for (@INPUT) {
+ $ord++;
+ ($op, undef, $comment) = /^([^\#]+)(\#\s+(.*))?/;
+ $comment = $op unless defined $comment;
+ $op = "$op==$op" unless $op =~ /==/;
+ ($op, $expectop) = $op =~ /(.*)==(.*)/;
+
+ $skip = ($op =~ /^'\?\?\?'/ or $comment =~ /skip\(.*\Q$^O\E.*\)/i)
+ ? "skip" : "not";
+ $integer = ($comment =~ /^i_/) ? "use integer" : '' ;
+ (print "#skipping $comment:\nok $ord\n"), next if $skip eq 'skip';
+
+ eval <<EOE;
+ local \$SIG{__WARN__} = \\&wrn;
+ my \$a = 'fake';
+ $integer;
+ \$a = $op;
+ \$b = $expectop;
+ if (\$a ne \$b) {
+ print "# \$comment: got `\$a', expected `\$b'\n";
+ print "\$skip " if \$a ne \$b or \$skip eq 'skip';
+ }
+ print "ok \$ord\\n";
+EOE
+ if ($@) {
+ if ($@ =~ /is unimplemented/) {
+ print "# skipping $comment: unimplemented:\nok $ord\n";
+ } else {
+ warn $@;
+ print "not ok $ord\n";
+ }
+ }
+}
+
+for (@simple_input) {
+ $ord++;
+ ($op, undef, $comment) = /^([^\#]+)(\#\s+(.*))?/;
+ $comment = $op unless defined $comment;
+ ($operator, $variable) = /^\s*(\w+)\s*\$(\w+)/ or warn "misprocessed '$_'\n";
+ eval <<EOE;
+ local \$SIG{__WARN__} = \\&wrn;
+ my \$$variable = "Ac# Ca\\nxxx";
+ \$$variable = $operator \$$variable;
+ \$toself = \$$variable;
+ \$direct = $operator "Ac# Ca\\nxxx";
+ print "# \\\$$variable = $operator \\\$$variable\\nnot "
+ unless \$toself eq \$direct;
+ print "ok \$ord\\n";
+EOE
+ if ($@) {
+ if ($@ =~ /is unimplemented/) {
+ print "# skipping $comment: unimplemented:\nok $ord\n";
+ } elsif ($@ =~ /Can't (modify|take log of 0)/) {
+ print "# skipping $comment: syntax not good for selfassign:\nok $ord\n";
+ } else {
+ warn $@;
+ print "not ok $ord\n";
+ }
+ }
+}
+__END__
+ref $xref # ref
+ref $cstr # ref nonref
+`$runme -e "print qq[1\n]"` # backtick skip(MSWin32)
+`$undefed` # backtick undef skip(MSWin32)
+<*> # glob
+<OP> # readline
+'faked' # rcatline
+(@z = (1 .. 3)) # aassign
+chop $chopit # chop
+(chop (@x=@chopar)) # schop
+chomp $chopit # chomp
+(chop (@x=@chopar)) # schomp
+pos $posstr # pos
+pos $chopit # pos returns undef
+$nn++==2 # postinc
+$nn++==3 # i_postinc
+$nn--==4 # postdec
+$nn--==3 # i_postdec
+$n ** $n # pow
+$n * $n # multiply
+$n * $n # i_multiply
+$n / $n # divide
+$n / $n # i_divide
+$n % $n # modulo
+$n % $n # i_modulo
+$n x $n # repeat
+$n + $n # add
+$n + $n # i_add
+$n - $n # subtract
+$n - $n # i_subtract
+$n . $n # concat
+$n . $a=='2fake' # concat with self
+"3$a"=='3fake' # concat with self in stringify
+"$n" # stringify
+$n << $n # left_shift
+$n >> $n # right_shift
+$n <=> $n # ncmp
+$n <=> $n # i_ncmp
+$n cmp $n # scmp
+$n & $n # bit_and
+$n ^ $n # bit_xor
+$n | $n # bit_or
+-$n # negate
+-$n # i_negate
+~$n # complement
+atan2 $n,$n # atan2
+sin $n # sin
+cos $n # cos
+'???' # rand
+exp $n # exp
+log $n # log
+sqrt $n # sqrt
+int $n # int
+hex $n # hex
+oct $n # oct
+abs $n # abs
+length $posstr # length
+substr $posstr, 2, 2 # substr
+vec("abc",2,8) # vec
+index $posstr, 2 # index
+rindex $posstr, 2 # rindex
+sprintf "%i%i", $n, $n # sprintf
+ord $n # ord
+chr $n # chr
+crypt $n, $n # crypt
+ucfirst ($cstr . "a") # ucfirst padtmp
+ucfirst $cstr # ucfirst
+lcfirst $cstr # lcfirst
+uc $cstr # uc
+lc $cstr # lc
+quotemeta $cstr # quotemeta
+@$aref # rv2av
+@$undefed # rv2av undef
+each %h==1 # each
+values %h # values
+keys %h # keys
+%$href # rv2hv
+pack "C2", $n,$n # pack
+split /a/, "abad" # split
+join "a"; @a # join
+push @a,3==6 # push
+unshift @aaa # unshift
+reverse @a # reverse
+reverse $cstr # reverse - scal
+grep $_, 1,0,2,0,3 # grepwhile
+map "x$_", 1,0,2,0,3 # mapwhile
+subb() # entersub
+caller # caller
+warn "ignore this\n" # warn
+'faked' # die
+open BLAH, "<non-existent" # open
+fileno STDERR # fileno
+umask 0 # umask
+select STDOUT # sselect
+select "","","",0 # select
+getc OP # getc
+'???' # read
+'???' # sysread
+'???' # syswrite
+'???' # send
+'???' # recv
+'???' # tell
+'???' # fcntl
+'???' # ioctl
+'???' # flock
+'???' # accept
+'???' # shutdown
+'???' # ftsize
+'???' # ftmtime
+'???' # ftatime
+'???' # ftctime
+chdir 'non-existent' # chdir
+'???' # chown
+'???' # chroot
+unlink 'non-existent' # unlink
+chmod 'non-existent' # chmod
+utime 'non-existent' # utime
+rename 'non-existent', 'non-existent1' # rename
+link 'non-existent', 'non-existent1' # link
+'???' # symlink
+readlink 'non-existent', 'non-existent1' # readlink
+'???' # mkdir
+'???' # rmdir
+'???' # telldir
+'???' # fork
+'???' # wait
+'???' # waitpid
+system "$runme -e 0" # system skip(VMS)
+'???' # exec
+'???' # kill
+getppid # getppid
+getpgrp # getpgrp
+'???' # setpgrp
+getpriority $$, $$ # getpriority
+'???' # setpriority
+time # time
+localtime $^T # localtime
+gmtime $^T # gmtime
+sleep 1 # sleep
+'???' # alarm
+'???' # shmget
+'???' # shmctl
+'???' # shmread
+'???' # shmwrite
+'???' # msgget
+'???' # msgctl
+'???' # msgsnd
+'???' # msgrcv
+'???' # semget
+'???' # semctl
+'???' # semop
+'???' # getlogin
+'???' # syscall
diff --git a/t/op/lfs.t b/t/op/lfs.t
new file mode 100644
index 0000000000..ae6aac6079
--- /dev/null
+++ b/t/op/lfs.t
@@ -0,0 +1,177 @@
+# NOTE: this file tests how large files (>2GB) work with perlio (stdio/sfio).
+# sysopen(), sysseek(), syswrite(), sysread() are tested in t/lib/syslfs.t.
+# If you modify/add tests here, remember to update also t/lib/syslfs.t.
+
+BEGIN {
+ # Don't bother if there are no quads.
+ eval { my $q = pack "q", 0 };
+ if ($@) {
+ print "1..0\n# no 64-bit types\n";
+ exit(0);
+ }
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+ # Don't bother if there are no quad offsets.
+ require Config; import Config;
+ if ($Config{lseeksize} < 8) {
+ print "1..0\n# no 64-bit file offsets\n";
+ exit(0);
+ }
+}
+
+sub bye {
+ close(BIG);
+ unlink "big";
+ exit(0);
+}
+
+sub explain {
+ print <<EOM;
+#
+# If the lfs (large file support: large meaning larger than two gigabytes)
+# tests are skipped or fail, it may mean either that your process is not
+# allowed to write large files or that the file system you are running
+# the tests on doesn't support large files, or both. You may also need
+# to reconfigure your kernel. (This is all very system-dependent.)
+#
+# Perl may still be able to support large files, once you have
+# such a process and such a (file) system.
+#
+EOM
+}
+
+# Known have-nots.
+if ($^O eq 'win32' || $^O eq 'vms') {
+ print "1..0\n# no sparse files\n";
+ bye();
+}
+
+# Then try to deduce whether we have sparse files.
+
+# Let's not depend on Fcntl or any other extension.
+
+my ($SEEK_SET, $SEEK_CUR, $SEEK_END) = (0, 1, 2);
+
+# We'll start off by creating a one megabyte file which has
+# only three "true" bytes. If we have sparseness, we should
+# consume less blocks than one megabyte (assuming nobody has
+# one megabyte blocks...)
+
+open(BIG, ">big") or do { warn "open failed: $!\n"; bye };
+binmode BIG;
+seek(BIG, 1_000_000, $SEEK_SET);
+print BIG "big";
+close(BIG);
+
+my @s;
+
+@s = stat("big");
+
+print "# @s\n";
+
+my $BLOCKSIZE = 512; # is this really correct everywhere?
+
+unless (@s == 13 &&
+ $s[7] == 1_000_003 &&
+ defined $s[12] &&
+ $BLOCKSIZE * $s[12] < 1_000_003) {
+ print "1..0\n# no sparse files?\n";
+ bye();
+}
+
+# By now we better be sure that we do have sparse files:
+# if we are not, the following will hog 5 gigabytes of disk. Ooops.
+
+open(BIG, ">big") or do { warn "open failed: $!\n"; bye };
+binmode BIG;
+seek(BIG, 5_000_000_000, $SEEK_SET);
+# Either the print or (more likely, thanks to buffering) the close will
+# fail if there are are filesize limitations (process or fs).
+my $print = print BIG "big";
+my $close = close BIG if $print;
+unless ($print && $close) {
+ $ENV{LC_ALL} = "C";
+ if ($! =~/File too large/) {
+ print "1..0\n# writing past 2GB failed\n";
+ explain();
+ }
+ bye();
+}
+
+@s = stat("big");
+
+print "# @s\n";
+
+sub fail () {
+ print "not ";
+ $fail++;
+}
+
+print "1..17\n";
+
+my $fail = 0;
+
+fail unless $s[7] == 5_000_000_003; # exercizes pp_stat
+print "ok 1\n";
+
+fail unless -s "big" == 5_000_000_003; # exercizes pp_ftsize
+print "ok 2\n";
+
+fail unless -e "big";
+print "ok 3\n";
+
+fail unless -f "big";
+print "ok 4\n";
+
+open(BIG, "big") or do { warn "open failed: $!\n"; bye };
+binmode BIG;
+
+fail unless seek(BIG, 4_500_000_000, $SEEK_SET);
+print "ok 5\n";
+
+fail unless tell(BIG) == 4_500_000_000;
+print "ok 6\n";
+
+fail unless seek(BIG, 1, $SEEK_CUR);
+print "ok 7\n";
+
+fail unless tell(BIG) == 4_500_000_001;
+print "ok 8\n";
+
+fail unless seek(BIG, -1, $SEEK_CUR);
+print "ok 9\n";
+
+fail unless tell(BIG) == 4_500_000_000;
+print "ok 10\n";
+
+fail unless seek(BIG, -3, $SEEK_END);
+print "ok 11\n";
+
+fail unless tell(BIG) == 5_000_000_000;
+print "ok 12\n";
+
+my $big;
+
+fail unless read(BIG, $big, 3) == 3;
+print "ok 13\n";
+
+fail unless $big eq "big";
+print "ok 14\n";
+
+# 705_032_704 = (I32)5_000_000_000
+fail unless seek(BIG, 705_032_704, $SEEK_SET);
+print "ok 15\n";
+
+my $zero;
+
+fail unless read(BIG, $zero, 3) == 3;
+print "ok 16\n";
+
+fail unless $zero eq "\0\0\0";
+print "ok 17\n";
+
+explain if $fail;
+
+bye(); # does the necessary cleanup
+
+# eof
diff --git a/t/op/list.t b/t/op/list.t
index a4230b681b..4d7a2d5444 100755
--- a/t/op/list.t
+++ b/t/op/list.t
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: list.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:02 $
-
-print "1..27\n";
+print "1..28\n";
@foo = (1, 2, 3, 4);
if ($foo[0] == 1 && $foo[3] == 4) {print "ok 1\n";} else {print "not ok 1\n";}
@@ -81,3 +79,11 @@ for ($x = 0; $x < 3; $x++) {
print $a,$b,$c;
}
+# slices
+{
+ my @a = (0, undef, undef, 3);
+ my @b = @a[1,2];
+ my @c = (0, undef, undef, 3)[1, 2];
+ print "not " unless @b == @c and @c == 2;
+ print "ok 28\n";
+}
diff --git a/t/op/local.t b/t/op/local.t
index 2f674d103b..b478e01993 100755
--- a/t/op/local.t
+++ b/t/op/local.t
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: local.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:04 $
-
-print "1..58\n";
+print "1..69\n";
# XXX known to leak scalars
$ENV{PERL_DESTRUCT_LEVEL} = 0 unless $ENV{PERL_DESTRUCT_LEVEL} > 3;
@@ -198,3 +196,42 @@ print +($ENV{_X_} eq 'a') ? "" : "not ", "ok 56\n";
print +($ENV{_Y_} eq 'b') ? "" : "not ", "ok 57\n";
print +($ENV{_Z_} eq 'c') ? "" : "not ", "ok 58\n";
+# does implicit localization in foreach skip magic?
+
+$_ = "ok 59,ok 60,";
+my $iter = 0;
+while (/(o.+?),/gc) {
+ print "$1\n";
+ foreach (1..1) { $iter++ }
+ if ($iter > 2) { print "not ok 60\n"; last; }
+}
+
+{
+ package UnderScore;
+ sub TIESCALAR { bless \my $self, shift }
+ sub FETCH { die "read \$_ forbidden" }
+ sub STORE { die "write \$_ forbidden" }
+ tie $_, __PACKAGE__;
+ my $t = 61;
+ my @tests = (
+ "Nesting" => sub { print '#'; for (1..3) { print }
+ print "\n" }, 1,
+ "Reading" => sub { print }, 0,
+ "Matching" => sub { $x = /badness/ }, 0,
+ "Concat" => sub { $_ .= "a" }, 0,
+ "Chop" => sub { chop }, 0,
+ "Filetest" => sub { -x }, 0,
+ "Assignment" => sub { $_ = "Bad" }, 0,
+ # XXX whether next one should fail is debatable
+ "Local \$_" => sub { local $_ = 'ok?'; print }, 0,
+ "for local" => sub { for("#ok?\n"){ print } }, 1,
+ );
+ while ( ($name, $code, $ok) = splice(@tests, 0, 3) ) {
+ print "# Testing $name\n";
+ eval { &$code };
+ print(($ok xor $@) ? "ok $t\n" : "not ok $t\n");
+ ++$t;
+ }
+ untie $_;
+}
+
diff --git a/t/op/lop.t b/t/op/lop.t
new file mode 100755
index 0000000000..f15201ff09
--- /dev/null
+++ b/t/op/lop.t
@@ -0,0 +1,44 @@
+#!./perl
+
+#
+# test the logical operators '&&', '||', '!', 'and', 'or', 'not'
+#
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+print "1..7\n";
+
+my $test = 0;
+for my $i (undef, 0 .. 2, "", "0 but true") {
+ my $true = 1;
+ my $false = 0;
+ for my $j (undef, 0 .. 2, "", "0 but true") {
+ $true &&= !(
+ ((!$i || !$j) != !($i && $j))
+ or (!($i || $j) != (!$i && !$j))
+ or (!!($i || $j) != !(!$i && !$j))
+ or (!(!$i || !$j) != !!($i && $j))
+ );
+ $false ||= (
+ ((!$i || !$j) == !!($i && $j))
+ and (!!($i || $j) == (!$i && !$j))
+ and ((!$i || $j) == ($i && !$j))
+ and (($i || !$j) != (!$i && $j))
+ );
+ }
+ if (not $true) {
+ print "not ";
+ } elsif ($false) {
+ print "not ";
+ }
+ print "ok ", ++$test, "\n";
+}
+
+# $test == 6
+my $i = 0;
+(($i ||= 1) &&= 3) += 4;
+print "not " unless $i == 7;
+print "ok ", ++$test, "\n";
diff --git a/t/op/magic.t b/t/op/magic.t
index 61e4522913..31765e2c50 100755
--- a/t/op/magic.t
+++ b/t/op/magic.t
@@ -4,7 +4,7 @@ BEGIN {
$^W = 1;
$| = 1;
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
$SIG{__WARN__} = sub { die "Dying on warning: ", @_ };
}
@@ -22,6 +22,7 @@ sub ok {
$Is_MSWin32 = $^O eq 'MSWin32';
$Is_VMS = $^O eq 'VMS';
$Is_Dos = $^O eq 'dos';
+$Is_Cygwin = $^O =~ /cygwin/;
$PERL = ($Is_MSWin32 ? '.\perl' : './perl');
print "1..35\n";
@@ -111,6 +112,11 @@ ok 18, $$ > 0, $$;
if ($^O eq 'qnx') {
chomp($wd = `/usr/bin/fullpath -t`);
}
+ elsif($Is_Cygwin) {
+ # Cygwin turns the symlink into the real file
+ chomp($wd = `pwd`);
+ $wd =~ s#/t$##;
+ }
else {
$wd = '.';
}
@@ -120,8 +126,9 @@ ok 18, $$ > 0, $$;
$script = "$wd/show-shebang";
if ($Is_MSWin32) {
chomp($wd = `cd`);
- $perl = "$wd\\perl.exe";
- $script = "$wd\\show-shebang.bat";
+ $wd =~ s|\\|/|g;
+ $perl = "$wd/perl.exe";
+ $script = "$wd/show-shebang.bat";
$headmaybe = <<EOH ;
\@rem ='
\@echo off
@@ -135,7 +142,13 @@ __END__
:endofperl
EOT
}
- $s1 = $s2 = "\$^X is $perl, \$0 is $script\n";
+ if ($^O eq 'os390' or $^O eq 'posix-bc' or $^O eq 'vmesa') { # no shebang
+ $headmaybe = <<EOH ;
+ eval 'exec ./perl -S \$0 \${1+"\$\@"}'
+ if 0;
+EOH
+ }
+ $s1 = "\$^X is $perl, \$0 is $script\n";
ok 19, open(SCRIPT, ">$script"), $!;
ok 20, print(SCRIPT $headmaybe . <<EOB . <<'EOF' . $tailmaybe), $!;
#!$wd/perl
@@ -145,12 +158,14 @@ EOF
ok 21, close(SCRIPT), $!;
ok 22, chmod(0755, $script), $!;
$_ = `$script`;
- s/.exe//i if $Is_Dos;
+ s/\.exe//i if $Is_Dos or $Is_Cygwin;
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
- ok 23, ($Is_MSWin32 ? uc($_) eq uc($s2) : $_ eq $s2), ":$_:!=:$s2:";
+ s{\\}{/}g;
+ ok 23, ($Is_MSWin32 ? uc($_) eq uc($s1) : $_ eq $s1), ":$_:!=:$s1:";
$_ = `$perl $script`;
- s/.exe//i if $Is_Dos;
+ s/\.exe//i if $Is_Dos;
+ s{\\}{/}g;
ok 24, ($Is_MSWin32 ? uc($_) eq uc($s1) : $_ eq $s1), ":$_:!=:$s1: after `$perl $script`";
ok 25, unlink($script), $!;
}
@@ -179,7 +194,7 @@ else {
}
{
- local $SIG{'__WARN__'} = sub { print "not " };
+ local $SIG{'__WARN__'} = sub { print "# @_\nnot " };
$! = undef;
print "ok 31\n";
}
diff --git a/t/op/method.t b/t/op/method.t
index f1b1888ef6..1c6f3c5d9d 100755
--- a/t/op/method.t
+++ b/t/op/method.t
@@ -4,7 +4,7 @@
# test method calls and autoloading.
#
-print "1..26\n";
+print "1..49\n";
@A::ISA = 'B';
@B::ISA = 'C';
@@ -19,6 +19,35 @@ sub test {
print "ok ", ++$cnt, "\n"
}
+# First, some basic checks of method-calling syntax:
+$obj = bless [], "Pack";
+sub Pack::method { shift; join(",", "method", @_) }
+$mname = "method";
+
+test(Pack->method("a","b","c"), "method,a,b,c");
+test(Pack->$mname("a","b","c"), "method,a,b,c");
+test(method Pack ("a","b","c"), "method,a,b,c");
+test((method Pack "a","b","c"), "method,a,b,c");
+
+test(Pack->method(), "method");
+test(Pack->$mname(), "method");
+test(method Pack (), "method");
+test(Pack->method, "method");
+test(Pack->$mname, "method");
+test(method Pack, "method");
+
+test($obj->method("a","b","c"), "method,a,b,c");
+test($obj->$mname("a","b","c"), "method,a,b,c");
+test((method $obj ("a","b","c")), "method,a,b,c");
+test((method $obj "a","b","c"), "method,a,b,c");
+
+test($obj->method(), "method");
+test($obj->$mname(), "method");
+test((method $obj ()), "method");
+test($obj->method, "method");
+test($obj->$mname, "method");
+test(method $obj, "method");
+
test( A->d, "C::d"); # Update hash table;
*B::d = \&D::d; # Import now.
@@ -126,3 +155,15 @@ test(A->eee(), "new B: In A::eee, 4"); # Which sticks
# this test added due to bug discovery
test(defined(@{"unknown_package::ISA"}) ? "defined" : "undefined", "undefined");
+
+# test that failed subroutine calls don't affect method calls
+{
+ package A1;
+ sub foo { "foo" }
+ package A2;
+ @ISA = 'A1';
+ package main;
+ test(A2->foo(), "foo");
+ test(do { eval 'A2::foo()'; $@ ? 1 : 0}, 1);
+ test(A2->foo(), "foo");
+}
diff --git a/t/op/misc.t b/t/op/misc.t
index 449d87cea1..926c7f38d0 100755
--- a/t/op/misc.t
+++ b/t/op/misc.t
@@ -4,7 +4,7 @@
# separate executable and can't simply use eval.
chdir 't' if -d 't';
-@INC = "../lib";
+unshift @INC, "../lib";
$ENV{PERL5LIB} = "../lib";
$|=1;
@@ -25,19 +25,25 @@ for (@prgs){
$switch = $1;
}
my($prog,$expected) = split(/\nEXPECT\n/, $_);
+ open TEST, ">$tmpfile" or die "Cannot open $tmpfile: $!";
+ print TEST $prog, "\n";
+ close TEST or die "Cannot close $tmpfile: $!";
+
if ($^O eq 'MSWin32') {
- open TEST, "| .\\perl -I../lib $switch >$tmpfile 2>&1";
+ $results = `.\\perl -I../lib $switch $tmpfile 2>&1`;
}
else {
- open TEST, "| sh -c './perl $switch' >$tmpfile 2>&1";
+ $results = `./perl $switch $tmpfile 2>&1`;
}
- print TEST $prog, "\n";
- close TEST;
$status = $?;
- $results = `$CAT $tmpfile`;
$results =~ s/\n+$//;
+ $results =~ s/at\s+misctmp\d+\s+line/at - line/g;
+ $results =~ s/of\s+misctmp\d+\s+aborted/of - aborted/g;
+# bison says 'parse error' instead of 'syntax error',
+# various yaccs may or may not capitalize 'syntax'.
+ $results =~ s/^(syntax|parse) error/syntax error/mig;
$expected =~ s/\n+$//;
- if ( $results ne $expected){
+ if ( $results ne $expected ) {
print STDERR "PROG: $switch\n$prog\n";
print STDERR "EXPECTED:\n$expected\n";
print STDERR "GOT:\n$results\n";
@@ -74,7 +80,7 @@ $x=0x0eabcd; print $x->ref;
EXPECT
Can't call method "ref" without a package or object reference at - line 1.
########
-chop ($str .= <STDIN>);
+chop ($str .= <DATA>);
########
close ($banana);
########
@@ -86,7 +92,7 @@ eval {sub bar {print "In bar";}}
########
system './perl -ne "print if eof" /dev/null'
########
-chop($file = <>);
+chop($file = <DATA>);
########
package N;
sub new {my ($obj,$n)=@_; bless \$n}
@@ -343,7 +349,7 @@ Sequence (?{...}) not terminated or not {}-balanced at - line 1, within pattern
########
/(?{"{"}})/ # Check it outside of eval too
EXPECT
-Unmatched right bracket at (re_eval 1) line 1, at end of line
+Unmatched right curly bracket at (re_eval 1) line 1, at end of line
syntax error at (re_eval 1) line 1, near ""{"}"
Compilation failed in regexp at - line 1.
########
@@ -417,3 +423,85 @@ EXPECT
destroyed
destroyed
########
+BEGIN {
+ $| = 1;
+ $SIG{__WARN__} = sub {
+ eval { print $_[0] };
+ die "bar\n";
+ };
+ warn "foo\n";
+}
+EXPECT
+foo
+bar
+BEGIN failed--compilation aborted at - line 8.
+########
+package X;
+@ISA='Y';
+sub new {
+ my $class = shift;
+ my $self = { };
+ bless $self, $class;
+ my $init = shift;
+ $self->foo($init);
+ print "new", $init;
+ return $self;
+}
+sub DESTROY {
+ my $self = shift;
+ print "DESTROY", $self->foo;
+}
+package Y;
+sub attribute {
+ my $self = shift;
+ my $var = shift;
+ if (@_ == 0) {
+ return $self->{$var};
+ } elsif (@_ == 1) {
+ $self->{$var} = shift;
+ }
+}
+sub AUTOLOAD {
+ $AUTOLOAD =~ /::([^:]+)$/;
+ my $method = $1;
+ splice @_, 1, 0, $method;
+ goto &attribute;
+}
+package main;
+my $x = X->new(1);
+for (2..3) {
+ my $y = X->new($_);
+ print $y->foo;
+}
+print $x->foo;
+EXPECT
+new1new22DESTROY2new33DESTROY31DESTROY1
+########
+re();
+sub re {
+ my $re = join '', eval 'qr/(?p{ $obj->method })/';
+ $re;
+}
+EXPECT
+########
+use strict;
+my $foo = "ZZZ\n";
+END { print $foo }
+EXPECT
+ZZZ
+########
+eval '
+use strict;
+my $foo = "ZZZ\n";
+END { print $foo }
+';
+EXPECT
+ZZZ
+########
+-w
+if (@ARGV) { print "" }
+else {
+ if ($x == 0) { print "" } else { print $x }
+}
+EXPECT
+Use of uninitialized value at - line 4.
diff --git a/t/op/mkdir.t b/t/op/mkdir.t
index 5ba0a0f18d..4bd1b21c80 100755
--- a/t/op/mkdir.t
+++ b/t/op/mkdir.t
@@ -4,10 +4,18 @@
print "1..7\n";
-$^O eq 'MSWin32' ? `del /s /q blurfl 2>&1` : `rm -rf blurfl`;
+if ($^O eq 'VMS') { # May as well test the library too
+ unshift @INC, '../lib';
+ require File::Path;
+ File::Path::rmtree('blurfl');
+}
+else {
+ $^O eq 'MSWin32' ? `del /s /q blurfl 2>&1` : `rm -rf blurfl`;
+}
# tests 3 and 7 rather naughtily expect English error messages
$ENV{'LC_ALL'} = 'C';
+$ENV{LANGUAGE} = 'C'; # GNU locale extension
print (mkdir('blurfl',0777) ? "ok 1\n" : "not ok 1\n");
print (mkdir('blurfl',0777) ? "not ok 2\n" : "ok 2\n");
@@ -15,4 +23,4 @@ print ($! =~ /exist|denied/ ? "ok 3\n" : "# $!\nnot ok 3\n");
print (-d 'blurfl' ? "ok 4\n" : "not ok 4\n");
print (rmdir('blurfl') ? "ok 5\n" : "not ok 5\n");
print (rmdir('blurfl') ? "not ok 6\n" : "ok 6\n");
-print ($! =~ /such|exist/ ? "ok 7\n" : "not ok 7\n");
+print ($! =~ /such|exist|not found/i ? "ok 7\n" : "not ok 7\n");
diff --git a/t/op/nothread.t b/t/op/nothread.t
index a0d444d90b..a434956cb0 100755
--- a/t/op/nothread.t
+++ b/t/op/nothread.t
@@ -6,12 +6,12 @@
BEGIN
{
chdir 't' if -d 't';
- @INC = "../lib";
+ unshift @INC, "../lib";
require Config;
import Config;
if ($Config{'usethreads'})
{
- print "1..0\n";
+ print "1..0 # Skip: this perl is threaded\n";
exit 0;
}
}
diff --git a/t/op/numconvert.t b/t/op/numconvert.t
new file mode 100755
index 0000000000..f71fd6c141
--- /dev/null
+++ b/t/op/numconvert.t
@@ -0,0 +1,185 @@
+#!./perl
+
+#
+# test the conversion operators
+#
+# Notations:
+#
+# "N p i N vs N N": Apply op-N, then op-p, then op-i, then reporter-N
+# Compare with application of op-N, then reporter-N
+# Right below are descriptions of different ops and reporters.
+
+# We do not use these subroutines any more, sub overhead makes a "switch"
+# solution better:
+
+# obviously, 0, 1 and 2, 3 are destructive. (XXXX 64-bit? 4 destructive too)
+
+# *0 = sub {--$_[0]}; # -
+# *1 = sub {++$_[0]}; # +
+
+# # Converters
+# *2 = sub { $_[0] = $max_uv & $_[0]}; # U
+# *3 = sub { use integer; $_[0] += $zero}; # I
+# *4 = sub { $_[0] += $zero}; # N
+# *5 = sub { $_[0] = "$_[0]" }; # P
+
+# # Side effects
+# *6 = sub { $max_uv & $_[0]}; # u
+# *7 = sub { use integer; $_[0] + $zero}; # i
+# *8 = sub { $_[0] + $zero}; # n
+# *9 = sub { $_[0] . "" }; # p
+
+# # Reporters
+# sub a2 { sprintf "%u", $_[0] } # U
+# sub a3 { sprintf "%d", $_[0] } # I
+# sub a4 { sprintf "%g", $_[0] } # N
+# sub a5 { "$_[0]" } # P
+
+BEGIN {
+ chdir 't' if -d 't';
+ @INC = '../lib';
+}
+
+use strict 'vars';
+
+my $max_chain = $ENV{PERL_TEST_NUMCONVERTS} || 2;
+
+# Bulk out if unsigned type is hopelessly wrong:
+my $max_uv1 = ~0;
+my $max_uv2 = sprintf "%u", $max_uv1 ** 6; # 6 is an arbitrary number here
+my $big_iv = do {use integer; $max_uv1 * 16}; # 16 is an arbitrary number here
+
+if ($max_uv1 ne $max_uv2 or $big_iv > $max_uv1) {
+ print "1..0\n# Unsigned arithmetic is not sane\n";
+ exit 0;
+}
+
+my $st_t = 4*4; # We try 4 initializers and 4 reporters
+
+my $num = 0;
+$num += 10**$_ - 4**$_ for 1.. $max_chain;
+$num *= $st_t;
+print "1..$num\n"; # In fact 15 times more subsubtests...
+
+my $max_uv = ~0;
+my $max_iv = int($max_uv/2);
+my $zero = 0;
+
+my $l_uv = length $max_uv;
+my $l_iv = length $max_iv;
+
+# Hope: the first digits are good
+my $larger_than_uv = substr 97 x 100, 0, $l_uv;
+my $smaller_than_iv = substr 12 x 100, 0, $l_iv;
+my $yet_smaller_than_iv = substr 97 x 100, 0, ($l_iv - 1);
+
+my @list = (1, $yet_smaller_than_iv, $smaller_than_iv, $max_iv, $max_iv + 1,
+ $max_uv, $max_uv + 1);
+unshift @list, (reverse map -$_, @list), 0; # 15 elts
+@list = map "$_", @list; # Normalize
+
+# print "@list\n";
+
+
+my @opnames = split //, "-+UINPuinp";
+
+# @list = map { 2->($_), 3->($_), 4->($_), 5->($_), } @list; # Prepare input
+
+#print "@list\n";
+#print "'@ops'\n";
+
+my $test = 1;
+my $nok;
+for my $num_chain (1..$max_chain) {
+ my @ops = map [split //], grep /[4-9]/,
+ map { sprintf "%0${num_chain}d", $_ } 0 .. 10**$num_chain - 1;
+
+ #@ops = ([]) unless $num_chain;
+ #@ops = ([6, 4]);
+
+ # print "'@ops'\n";
+ for my $op (@ops) {
+ for my $first (2..5) {
+ for my $last (2..5) {
+ $nok = 0;
+ my @otherops = grep $_ <= 3, @$op;
+ my @curops = ($op,\@otherops);
+
+ for my $num (@list) {
+ my $inpt;
+ my @ans;
+
+ for my $short (0, 1) {
+ # undef $inpt; # Forget all we had - some bugs were masked
+
+ $inpt = $num; # Try to not contaminate $num...
+ $inpt = "$inpt";
+ if ($first == 2) {
+ $inpt = $max_uv & $inpt; # U 2
+ } elsif ($first == 3) {
+ use integer; $inpt += $zero; # I 3
+ } elsif ($first == 4) {
+ $inpt += $zero; # N 4
+ } else {
+ $inpt = "$inpt"; # P 5
+ }
+
+ # Saves 20% of time - not with this logic:
+ #my $tmp = $inpt;
+ #my $tmp1 = $num;
+ #next if $num_chain > 1
+ # and "$tmp" ne "$tmp1"; # Already the coercion gives problems...
+
+ for my $curop (@{$curops[$short]}) {
+ if ($curop < 5) {
+ if ($curop < 3) {
+ if ($curop == 0) {
+ --$inpt; # - 0
+ } elsif ($curop == 1) {
+ ++$inpt; # + 1
+ } else {
+ $inpt = $max_uv & $inpt; # U 2
+ }
+ } elsif ($curop == 3) {
+ use integer; $inpt += $zero;
+ } else {
+ $inpt += $zero; # N 4
+ }
+ } elsif ($curop < 8) {
+ if ($curop == 5) {
+ $inpt = "$inpt"; # P 5
+ } elsif ($curop == 6) {
+ $max_uv & $inpt; # u 6
+ } else {
+ use integer; $inpt + $zero;
+ }
+ } elsif ($curop == 8) {
+ $inpt + $zero; # n 8
+ } else {
+ $inpt . ""; # p 9
+ }
+ }
+
+ if ($last == 2) {
+ $inpt = sprintf "%u", $inpt; # U 2
+ } elsif ($last == 3) {
+ $inpt = sprintf "%d", $inpt; # I 3
+ } elsif ($last == 4) {
+ $inpt = sprintf "%g", $inpt; # N 4
+ } else {
+ $inpt = "$inpt"; # P 5
+ }
+ push @ans, $inpt;
+ }
+ $nok++,
+ print "# '$ans[0]' ne '$ans[1]',\t$num\t=> @opnames[$first,@{$curops[0]},$last] vs @opnames[$first,@{$curops[1]},$last]\n"
+ if $ans[0] ne $ans[1];
+ }
+ print "not " if $nok;
+ print "ok $test\n";
+ #print $txt if $nok;
+ $test++;
+ }
+ }
+ }
+}
diff --git a/t/op/oct.t b/t/op/oct.t
index 24b5c4309d..27ac5aa042 100755
--- a/t/op/oct.t
+++ b/t/op/oct.t
@@ -1,14 +1,53 @@
#!./perl
-# $RCSfile: oct.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:08 $
-
-print "1..8\n";
-
-print +(oct('01234') == 01234) ? "ok" : "not ok", " 1\n";
-print +(oct('0x1234') == 0x1234) ? "ok" : "not ok", " 2\n";
-print +(hex('01234') == 0x1234) ? "ok" : "not ok", " 3\n";
-print +(oct('20000000000') == 020000000000) ? "ok" : "not ok", " 4\n";
-print +(oct('x80000000') == 0x80000000) ? "ok" : "not ok", " 5\n";
-print +(hex('80000000') == 0x80000000) ? "ok" : "not ok", " 6\n";
-print +(oct('1234') == 668) ? "ok" : "not ok", " 7\n";
-print +(hex('1234') == 4660) ? "ok" : "not ok", " 8\n";
+print "1..36\n";
+
+print +(oct('0b10101') == 0b10101) ? "ok" : "not ok", " 1\n";
+print +(oct('0b10101') == 025) ? "ok" : "not ok", " 2\n";
+print +(oct('0b10101') == 21) ? "ok" : "not ok", " 3\n";
+print +(oct('0b10101') == 0x15) ? "ok" : "not ok", " 4\n";
+
+print +(oct('b10101') == 0b10101) ? "ok" : "not ok", " 5\n";
+print +(oct('b10101') == 025) ? "ok" : "not ok", " 6\n";
+print +(oct('b10101') == 21) ? "ok" : "not ok", " 7\n";
+print +(oct('b10101') == 0x15) ? "ok" : "not ok", " 8\n";
+
+print +(oct('01234') == 0b1010011100) ? "ok" : "not ok", " 9\n";
+print +(oct('01234') == 01234) ? "ok" : "not ok", " 10\n";
+print +(oct('01234') == 668) ? "ok" : "not ok", " 11\n";
+print +(oct('01234') == 0x29c) ? "ok" : "not ok", " 12\n";
+
+print +(oct('0x1234') == 0b1001000110100) ? "ok" : "not ok", " 13\n";
+print +(oct('0x1234') == 011064) ? "ok" : "not ok", " 14\n";
+print +(oct('0x1234') == 4660) ? "ok" : "not ok", " 15\n";
+print +(oct('0x1234') == 0x1234) ? "ok" : "not ok", " 16\n";
+
+print +(oct('x1234') == 0b1001000110100) ? "ok" : "not ok", " 17\n";
+print +(oct('x1234') == 011064) ? "ok" : "not ok", " 18\n";
+print +(oct('x1234') == 4660) ? "ok" : "not ok", " 19\n";
+print +(oct('x1234') == 0x1234) ? "ok" : "not ok", " 20\n";
+
+print +(hex('01234') == 0b1001000110100) ? "ok" : "not ok", " 21\n";
+print +(hex('01234') == 011064) ? "ok" : "not ok", " 22\n";
+print +(hex('01234') == 4660) ? "ok" : "not ok", " 23\n";
+print +(hex('01234') == 0x1234) ? "ok" : "not ok", " 24\n";
+
+print +(hex('0x1234') == 0b1001000110100) ? "ok" : "not ok", " 25\n";
+print +(hex('0x1234') == 011064) ? "ok" : "not ok", " 26\n";
+print +(hex('0x1234') == 4660) ? "ok" : "not ok", " 27\n";
+print +(hex('0x1234') == 0x1234) ? "ok" : "not ok", " 28\n";
+
+print +(hex('x1234') == 0b1001000110100) ? "ok" : "not ok", " 29\n";
+print +(hex('x1234') == 011064) ? "ok" : "not ok", " 30\n";
+print +(hex('x1234') == 4660) ? "ok" : "not ok", " 31\n";
+print +(hex('x1234') == 0x1234) ? "ok" : "not ok", " 32\n";
+
+print +(oct('0b11111111111111111111111111111111') == 4294967295) ?
+ "ok" : "not ok", " 33\n";
+print +(oct('037777777777') == 4294967295) ?
+ "ok" : "not ok", " 34\n";
+print +(oct('0xffffffff') == 4294967295) ?
+ "ok" : "not ok", " 35\n";
+
+print +(hex('0xffffffff') == 4294967295) ?
+ "ok" : "not ok", " 36\n";
diff --git a/t/op/ord.t b/t/op/ord.t
index 37128382d8..bc6d924554 100755
--- a/t/op/ord.t
+++ b/t/op/ord.t
@@ -1,16 +1,16 @@
#!./perl
-# $RCSfile: ord.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:09 $
-
print "1..3\n";
# compile time evaluation
-if (ord('A') == 65) {print "ok 1\n";} else {print "not ok 1\n";}
+# 65 ASCII
+# 193 EBCDIC
+if (ord('A') == 65 || ord('A') == 193) {print "ok 1\n";} else {print "not ok 1\n";}
# run time evaluation
$x = 'ABC';
-if (ord($x) == 65) {print "ok 2\n";} else {print "not ok 2\n";}
+if (ord($x) == 65 || ord($x) == 193) {print "ok 2\n";} else {print "not ok 2\n";}
-if (chr 65 == A) {print "ok 3\n";} else {print "not ok 3\n";}
+if (chr 65 == 'A' || chr 193 == 'A') {print "ok 3\n";} else {print "not ok 3\n";}
diff --git a/t/op/pack.t b/t/op/pack.t
index b8aece6b6b..082b954756 100755
--- a/t/op/pack.t
+++ b/t/op/pack.t
@@ -1,8 +1,12 @@
#!./perl
-# $RCSfile: pack.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:11 $
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib' if -d '../lib';
+ require Config; import Config;
+}
-print "1..56\n";
+print "1..148\n";
$format = "c2 x5 C C x s d i l a6";
# Need the expression in here to force ary[5] to be numeric. This avoids
@@ -30,7 +34,10 @@ print +($x = unpack("%32b69", "\001\002\004\010\020\040\100\200\017")) == 12
print +($x = unpack("%32B69", "\001\002\004\010\020\040\100\200\017")) == 9
? "ok 6\n" : "not ok 6 $x\n";
-print +($x = unpack("%32B*", "Now is the time for all good blurfl")) == 129
+my $sum = 129; # ASCII
+$sum = 103 if ($Config{ebcdic} eq 'define');
+
+print +($x = unpack("%32B*", "Now is the time for all good blurfl")) == $sum
? "ok 7\n" : "not ok 7 $x\n";
open(BIN, "./perl") || open(BIN, "./perl.exe")
@@ -154,3 +161,211 @@ foreach my $t (@templates) {
unless @t == 2 and (($t[0] == 12 and $t[1] == 34) or ($t =~ /[nv]/i));
print "ok ", $test++, "\n";
}
+
+# 57..60: uuencode/decode
+
+# Note that first uuencoding known 'text' data and then checking the
+# binary values of the uuencoded version would not be portable between
+# character sets. Uuencoding is meant for encoding binary data, not
+# text data.
+
+$in = pack 'C*', 0 .. 255;
+
+# just to be anal, we do some random tr/`/ /
+$uu = <<'EOUU';
+M` $"`P0%!@<("0H+# T.#Q`1$A,4%187&!D:&QP='A\@(2(C)"4F)R@I*BLL
+M+2XO,#$R,S0U-C<X.3H[/#T^/T!!0D-$149'2$E*2TQ-3D]045)35%565UA9
+M6EM<75Y?8&%B8V1E9F=H:6IK;&UN;W!Q<G-T=79W>'EZ>WQ]?G^`@8*#A(6&
+MAXB)BHN,C8Z/D)&2DY25EI>8F9J;G)V>GZ"AHJ.DI::GJ*FJJZRMKJ^PL;*S
+MM+6VM[BYNKN\O;Z_P,'"P\3%QL?(R<K+S,W.S]#1TM/4U=;7V-G:V]S=WM_@
+?X>+CY.7FY^CIZNOL[>[O\/'R\_3U]O?X^?K[_/W^_P `
+EOUU
+
+$_ = $uu;
+tr/ /`/;
+print "not " unless pack('u', $in) eq $_;
+print "ok ", $test++, "\n";
+
+print "not " unless unpack('u', $uu) eq $in;
+print "ok ", $test++, "\n";
+
+$in = "\x1f\x8b\x08\x08\x58\xdc\xc4\x35\x02\x03\x4a\x41\x50\x55\x00\xf3\x2a\x2d\x2e\x51\x48\xcc\xcb\x2f\xc9\x48\x2d\x52\x08\x48\x2d\xca\x51\x28\x2d\x4d\xce\x4f\x49\x2d\xe2\x02\x00\x64\x66\x60\x5c\x1a\x00\x00\x00";
+$uu = <<'EOUU';
+M'XL("%C<Q#4"`TI!4%4`\RHM+E%(S,LOR4@M4@A(+<I1*"U-SD])+>("`&1F
+&8%P:````
+EOUU
+
+print "not " unless unpack('u', $uu) eq $in;
+print "ok ", $test++, "\n";
+
+# 60 identical to 59 except that backquotes have been changed to spaces
+
+$uu = <<'EOUU';
+M'XL("%C<Q#4" TI!4%4 \RHM+E%(S,LOR4@M4@A(+<I1*"U-SD])+>(" &1F
+&8%P:
+EOUU
+
+print "not " unless unpack('u', $uu) eq $in;
+print "ok ", $test++, "\n";
+
+# 61..72: test the ascii template types (A, a, Z)
+
+print "not " unless pack('A*', "foo\0bar\0 ") eq "foo\0bar\0 ";
+print "ok ", $test++, "\n";
+
+print "not " unless pack('A11', "foo\0bar\0 ") eq "foo\0bar\0 ";
+print "ok ", $test++, "\n";
+
+print "not " unless unpack('A*', "foo\0bar \0") eq "foo\0bar";
+print "ok ", $test++, "\n";
+
+print "not " unless unpack('A8', "foo\0bar \0") eq "foo\0bar";
+print "ok ", $test++, "\n";
+
+print "not " unless pack('a*', "foo\0bar\0 ") eq "foo\0bar\0 ";
+print "ok ", $test++, "\n";
+
+print "not " unless pack('a11', "foo\0bar\0 ") eq "foo\0bar\0 \0\0";
+print "ok ", $test++, "\n";
+
+print "not " unless unpack('a*', "foo\0bar \0") eq "foo\0bar \0";
+print "ok ", $test++, "\n";
+
+print "not " unless unpack('a8', "foo\0bar \0") eq "foo\0bar ";
+print "ok ", $test++, "\n";
+
+print "not " unless pack('Z*', "foo\0bar\0 ") eq "foo\0bar\0 ";
+print "ok ", $test++, "\n";
+
+print "not " unless pack('Z11', "foo\0bar\0 ") eq "foo\0bar\0 \0\0";
+print "ok ", $test++, "\n";
+
+print "not " unless unpack('Z*', "foo\0bar \0") eq "foo";
+print "ok ", $test++, "\n";
+
+print "not " unless unpack('Z8', "foo\0bar \0") eq "foo";
+print "ok ", $test++, "\n";
+
+# 73..78: packing native shorts/ints/longs
+
+print "not " unless length(pack("s!", 0)) == $Config{shortsize};
+print "ok ", $test++, "\n";
+
+print "not " unless length(pack("i!", 0)) == $Config{intsize};
+print "ok ", $test++, "\n";
+
+print "not " unless length(pack("l!", 0)) == $Config{longsize};
+print "ok ", $test++, "\n";
+
+print "not " unless length(pack("s!", 0)) <= length(pack("i!", 0));
+print "ok ", $test++, "\n";
+
+print "not " unless length(pack("i!", 0)) <= length(pack("l!", 0));
+print "ok ", $test++, "\n";
+
+print "not " unless length(pack("i!", 0)) == length(pack("i", 0));
+print "ok ", $test++, "\n";
+
+# 79..138: pack <-> unpack bijectionism
+
+# 79.. 83 c
+foreach my $c (-128, -1, 0, 1, 127) {
+ print "not " unless unpack("c", pack("c", $c)) == $c;
+ print "ok ", $test++, "\n";
+}
+
+# 84.. 88: C
+foreach my $C (0, 1, 127, 128, 255) {
+ print "not " unless unpack("C", pack("C", $C)) == $C;
+ print "ok ", $test++, "\n";
+}
+
+# 89.. 93: s
+foreach my $s (-32768, -1, 0, 1, 32767) {
+ print "not " unless unpack("s", pack("s", $s)) == $s;
+ print "ok ", $test++, "\n";
+}
+
+# 94.. 98: S
+foreach my $S (0, 1, 32767, 32768, 65535) {
+ print "not " unless unpack("S", pack("S", $S)) == $S;
+ print "ok ", $test++, "\n";
+}
+
+# 99..103: i
+foreach my $i (-2147483648, -1, 0, 1, 2147483647) {
+ print "not " unless unpack("i", pack("i", $i)) == $i;
+ print "ok ", $test++, "\n";
+}
+
+# 104..108: I
+foreach my $I (0, 1, 2147483647, 2147483648, 4294967295) {
+ print "not " unless unpack("I", pack("I", $I)) == $I;
+ print "ok ", $test++, "\n";
+}
+
+# 109..113: l
+foreach my $l (-2147483648, -1, 0, 1, 2147483647) {
+ print "not " unless unpack("l", pack("l", $l)) == $l;
+ print "ok ", $test++, "\n";
+}
+
+# 114..118: L
+foreach my $L (0, 1, 2147483647, 2147483648, 4294967295) {
+ print "not " unless unpack("L", pack("L", $L)) == $L;
+ print "ok ", $test++, "\n";
+}
+
+# 119..123: n
+foreach my $n (0, 1, 32767, 32768, 65535) {
+ print "not " unless unpack("n", pack("n", $n)) == $n;
+ print "ok ", $test++, "\n";
+}
+
+# 124..128: v
+foreach my $v (0, 1, 32767, 32768, 65535) {
+ print "not " unless unpack("v", pack("v", $v)) == $v;
+ print "ok ", $test++, "\n";
+}
+
+# 129..133: N
+foreach my $N (0, 1, 2147483647, 2147483648, 4294967295) {
+ print "not " unless unpack("N", pack("N", $N)) == $N;
+ print "ok ", $test++, "\n";
+}
+
+# 134..138: V
+foreach my $V (0, 1, 2147483647, 2147483648, 4294967295) {
+ print "not " unless unpack("V", pack("V", $V)) == $V;
+ print "ok ", $test++, "\n";
+}
+
+# 139..142: pack nvNV byteorders
+
+print "not " unless pack("n", 0xdead) eq "\xde\xad";
+print "ok ", $test++, "\n";
+
+print "not " unless pack("v", 0xdead) eq "\xad\xde";
+print "ok ", $test++, "\n";
+
+print "not " unless pack("N", 0xdeadbeef) eq "\xde\xad\xbe\xef";
+print "ok ", $test++, "\n";
+
+print "not " unless pack("V", 0xdeadbeef) eq "\xef\xbe\xad\xde";
+print "ok ", $test++, "\n";
+
+# 143..148: #
+
+my $z;
+eval { ($x) = unpack '#a*','hello' };
+print 'not ' unless $@; print "ok $test\n"; $test++;
+eval { ($z,$x,$y) = unpack 'a3#A C#a* C#Z', "003ok \003yes\004z\000abc" };
+print $@ eq '' && $z eq 'ok' ? "ok $test\n" : "not ok $test\n"; $test++;
+print $@ eq '' && $x eq 'yes' ? "ok $test\n" : "not ok $test\n"; $test++;
+print $@ eq '' && $y eq 'z' ? "ok $test\n" : "not ok $test\n"; $test++;
+
+eval { ($x) = pack '#a*','hello' };
+print 'not ' unless $@; print "ok $test\n"; $test++;
+$z = pack 'n#a* w#A*','string','etc';
+print 'not ' unless $z eq "\000\006string\003etc"; print "ok $test\n"; $test++;
+
diff --git a/t/op/pat.t b/t/op/pat.t
index 7d4278f38a..6312c75cea 100755
--- a/t/op/pat.t
+++ b/t/op/pat.t
@@ -4,11 +4,11 @@
# the format supported by op/regexp.t. If you want to add a test
# that does fit that format, add it to op/re_tests, not here.
-print "1..141\n";
+print "1..188\n";
BEGIN {
chdir 't' if -d 't';
- @INC = "../lib" if -d "../lib";
+ unshift @INC, "../lib" if -d "../lib";
}
eval 'use Config'; # Defaults assumed if this fails
@@ -282,14 +282,7 @@ eval qq("${context}y" =~ /(?<=$context)y/);
print "not " if $@ !~ m%^\Q/(?<=\Ex+/: lookbehind longer than 255 not%;
print "ok 71\n";
-# This one will fail when POSIX character classes do get implemented
-{
- my $w;
- local $^W = 1;
- local $SIG{__WARN__} = sub{$w = shift};
- eval q('a' =~ /[[:alpha:]]/);
- print "not " if $w !~ /^\QCharacter class syntax [: :] is reserved/;
-}
+# removed test
print "ok 72\n";
# Long Monsters
@@ -363,6 +356,7 @@ sub matchit {
/xg;
}
+@ans = ();
push @ans, $res while $res = matchit;
print "# ans='@ans'\n# expect='$expect'\nnot " if "@ans" ne "1 1 1";
@@ -375,6 +369,26 @@ print "# ans='@ans'\n# expect='$expect'\nnot " if "@ans" ne $expect;
print "ok $test\n";
$test++;
+my $matched;
+$matched = qr/\((?:(?>[^()]+)|(?p{$matched}))*\)/;
+
+@ans = @ans1 = ();
+push(@ans, $res), push(@ans1, $&) while $res = m/$matched/g;
+
+print "# ans='@ans'\n# expect='$expect'\nnot " if "@ans" ne "1 1 1";
+print "ok $test\n";
+$test++;
+
+print "# ans1='@ans1'\n# expect='$expect'\nnot " if "@ans1" ne $expect;
+print "ok $test\n";
+$test++;
+
+@ans = m/$matched/g;
+
+print "# ans='@ans'\n# expect='$expect'\nnot " if "@ans" ne $expect;
+print "ok $test\n";
+$test++;
+
@ans = ('a/b' =~ m%(.*/)?(.*)%); # Stack may be bad
print "not " if "@ans" ne 'a/ b';
print "ok $test\n";
@@ -595,3 +609,259 @@ print "not " if @_;
print "ok $test\n";
$test++;
+/a(?=.$)/;
+print "not " if $#+ != 0 or $#- != 0;
+print "ok $test\n";
+$test++;
+
+print "not " if $+[0] != 2 or $-[0] != 1;
+print "ok $test\n";
+$test++;
+
+print "not "
+ if defined $+[1] or defined $-[1] or defined $+[2] or defined $-[2];
+print "ok $test\n";
+$test++;
+
+/a(a)(a)/;
+print "not " if $#+ != 2 or $#- != 2;
+print "ok $test\n";
+$test++;
+
+print "not " if $+[0] != 3 or $-[0] != 0;
+print "ok $test\n";
+$test++;
+
+print "not " if $+[1] != 2 or $-[1] != 1;
+print "ok $test\n";
+$test++;
+
+print "not " if $+[2] != 3 or $-[2] != 2;
+print "ok $test\n";
+$test++;
+
+print "not "
+ if defined $+[3] or defined $-[3] or defined $+[4] or defined $-[4];
+print "ok $test\n";
+$test++;
+
+/.(a)(b)?(a)/;
+print "not " if $#+ != 3 or $#- != 3;
+print "ok $test\n";
+$test++;
+
+print "not " if $+[0] != 3 or $-[0] != 0;
+print "ok $test\n";
+$test++;
+
+print "not " if $+[1] != 2 or $-[1] != 1;
+print "ok $test\n";
+$test++;
+
+print "not " if $+[3] != 3 or $-[3] != 2;
+print "ok $test\n";
+$test++;
+
+print "not "
+ if defined $+[2] or defined $-[2] or defined $+[4] or defined $-[4];
+print "ok $test\n";
+$test++;
+
+/.(a)/;
+print "not " if $#+ != 1 or $#- != 1;
+print "ok $test\n";
+$test++;
+
+print "not " if $+[0] != 2 or $-[0] != 0;
+print "ok $test\n";
+$test++;
+
+print "not " if $+[1] != 2 or $-[1] != 1;
+print "ok $test\n";
+$test++;
+
+print "not "
+ if defined $+[2] or defined $-[2] or defined $+[3] or defined $-[3];
+print "ok $test\n";
+$test++;
+
+/.(a)(ba*)?/;
+print "#$#-..$#+\nnot " if $#+ != 2 or $#- != 1;
+print "ok $test\n";
+$test++;
+
+$_ = 'aaa';
+pos = 1;
+@a = /\Ga/g;
+print "not " unless "@a" eq "a a";
+print "ok $test\n";
+$test++;
+
+$str = 'abcde';
+pos $str = 2;
+
+print "not " if $str =~ /^\G/;
+print "ok $test\n";
+$test++;
+
+print "not " if $str =~ /^.\G/;
+print "ok $test\n";
+$test++;
+
+print "not " unless $str =~ /^..\G/;
+print "ok $test\n";
+$test++;
+
+print "not " if $str =~ /^...\G/;
+print "ok $test\n";
+$test++;
+
+print "not " unless $str =~ /.\G./ and $& eq 'bc';
+print "ok $test\n";
+$test++;
+
+print "not " unless $str =~ /\G../ and $& eq 'cd';
+print "ok $test\n";
+$test++;
+
+undef $foo; undef $bar;
+print "#'$str','$foo','$bar'\nnot "
+ unless $str =~ /b(?{$foo = $_; $bar = pos})c/
+ and $foo eq 'abcde' and $bar eq 2;
+print "ok $test\n";
+$test++;
+
+undef $foo; undef $bar;
+pos $str = undef;
+print "#'$str','$foo','$bar'\nnot "
+ unless $str =~ /b(?{$foo = $_; $bar = pos})c/g
+ and $foo eq 'abcde' and $bar eq 2 and pos $str eq 3;
+print "ok $test\n";
+$test++;
+
+$_ = $str;
+
+undef $foo; undef $bar;
+print "#'$str','$foo','$bar'\nnot "
+ unless /b(?{$foo = $_; $bar = pos})c/
+ and $foo eq 'abcde' and $bar eq 2;
+print "ok $test\n";
+$test++;
+
+undef $foo; undef $bar;
+print "#'$str','$foo','$bar'\nnot "
+ unless /b(?{$foo = $_; $bar = pos})c/g
+ and $foo eq 'abcde' and $bar eq 2 and pos eq 3;
+print "ok $test\n";
+$test++;
+
+undef $foo; undef $bar;
+pos = undef;
+1 while /b(?{$foo = $_; $bar = pos})c/g;
+print "#'$str','$foo','$bar'\nnot "
+ unless $foo eq 'abcde' and $bar eq 2 and not defined pos;
+print "ok $test\n";
+$test++;
+
+undef $foo; undef $bar;
+$_ = 'abcde|abcde';
+print "#'$str','$foo','$bar','$_'\nnot "
+ unless s/b(?{$foo = $_; $bar = pos})c/x/g and $foo eq 'abcde|abcde'
+ and $bar eq 8 and $_ eq 'axde|axde';
+print "ok $test\n";
+$test++;
+
+@res = ();
+# List context:
+$_ = 'abcde|abcde';
+@dummy = /([ace]).(?{push @res, $1,$2})([ce])(?{push @res, $1,$2})/g;
+@res = map {defined $_ ? "'$_'" : 'undef'} @res;
+$res = "@res";
+print "#'@res' '$_'\nnot "
+ unless "@res" eq "'a' undef 'a' 'c' 'e' undef 'a' undef 'a' 'c'";
+print "ok $test\n";
+$test++;
+
+@res = ();
+@dummy = /([ace]).(?{push @res, $`,$&,$'})([ce])(?{push @res, $`,$&,$'})/g;
+@res = map {defined $_ ? "'$_'" : 'undef'} @res;
+$res = "@res";
+print "#'@res' '$_'\nnot "
+ unless "@res" eq
+ "'' 'ab' 'cde|abcde' " .
+ "'' 'abc' 'de|abcde' " .
+ "'abcd' 'e|' 'abcde' " .
+ "'abcde|' 'ab' 'cde' " .
+ "'abcde|' 'abc' 'de'" ;
+print "ok $test\n";
+$test++;
+
+#Some more \G anchor checks
+$foo='aabbccddeeffgg';
+
+pos($foo)=1;
+
+$foo=~/.\G(..)/g;
+print "not " unless($1 eq 'ab');
+print "ok $test\n";
+$test++;
+
+pos($foo) += 1;
+$foo=~/.\G(..)/g;
+print "not " unless($1 eq 'cc');
+print "ok $test\n";
+$test++;
+
+pos($foo) += 1;
+$foo=~/.\G(..)/g;
+print "not " unless($1 eq 'de');
+print "ok $test\n";
+$test++;
+
+print "not " unless $foo =~ /\Gef/g;
+print "ok $test\n";
+$test++;
+
+undef pos $foo;
+
+$foo=~/\G(..)/g;
+print "not " unless($1 eq 'aa');
+print "ok $test\n";
+$test++;
+
+$foo=~/\G(..)/g;
+print "not " unless($1 eq 'bb');
+print "ok $test\n";
+$test++;
+
+pos($foo)=5;
+$foo=~/\G(..)/g;
+print "not " unless($1 eq 'cd');
+print "ok $test\n";
+$test++;
+
+$_='123x123';
+@res = /(\d*|x)/g;
+print "not " unless('123||x|123|' eq join '|', @res);
+print "ok $test\n";
+$test++;
+
+# see if matching against temporaries (created via pp_helem()) is safe
+{ foo => "ok $test\n".$^X }->{foo} =~ /^(.*)\n/g;
+print "$1\n";
+$test++;
+
+# See if $i work inside (?{}) in the presense of saved substrings and
+# changing $_
+@a = qw(foo bar);
+@b = ();
+s/(\w)(?{push @b, $1})/,$1,/g for @a;
+
+print "# \@b='@b', expect 'f o o b a r'\nnot " unless("@b" eq "f o o b a r");
+print "ok $test\n";
+$test++;
+
+print "not " unless("@a" eq ",f,,o,,o, ,b,,a,,r,");
+print "ok $test\n";
+$test++;
+
diff --git a/t/op/pwent.t b/t/op/pwent.t
new file mode 100755
index 0000000000..ca14a99eec
--- /dev/null
+++ b/t/op/pwent.t
@@ -0,0 +1,137 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, "../lib" if -d "../lib";
+ eval {my @n = getpwuid 0};
+ if ($@ && $@ =~ /(The \w+ function is unimplemented)/) {
+ print "1..0 # Skip: $1\n";
+ exit 0;
+ }
+ eval { require Config; import Config; };
+ my $reason;
+ if ($Config{'i_pwd'} ne 'define') {
+ $reason = '$Config{i_pwd} undefined';
+ }
+ elsif (not -f "/etc/passwd" ) { # Play safe.
+ $reason = 'no /etc/passwd file';
+ }
+
+ if (not defined $where) { # Try NIS.
+ foreach my $ypcat (qw(/usr/bin/ypcat /bin/ypcat /etc/ypcat)) {
+ if (-x $ypcat &&
+ open(PW, "$ypcat passwd 2>/dev/null |") &&
+ defined(<PW>)) {
+ $where = "NIS passwd";
+ undef $reason;
+ last;
+ }
+ }
+ }
+
+ if (not defined $where) { # Try NetInfo.
+ foreach my $nidump (qw(/usr/bin/nidump)) {
+ if (-x $nidump &&
+ open(PW, "$nidump passwd . 2>/dev/null |") &&
+ defined(<PW>)) {
+ $where = "NetInfo passwd";
+ undef $reason;
+ last;
+ }
+ }
+ }
+
+ if (not defined $where) { # Try local.
+ my $PW = "/etc/passwd";
+ if (-f $PW && open(PW, $PW) && defined(<PW>)) {
+ $where = $PW;
+ undef $reason;
+ }
+ }
+
+ if ($reason) { # Give up.
+ print "1..0 # Skip: $reason\n";
+ exit 0;
+ }
+}
+
+# By now PW filehandle should be open and full of juicy password entries.
+
+print "1..1\n";
+
+# Go through at most this many users.
+# (note that the first entry has been read away by now)
+my $max = 25;
+
+my $n = 0;
+my $tst = 1;
+my %perfect;
+my %seen;
+
+while (<PW>) {
+ chomp;
+ my @s = split /:/;
+ my ($name_s, $passwd_s, $uid_s, $gid_s, $gcos_s, $home_s, $shell_s) = @s;
+ next if /^\+/; # ignore NIS includes
+ if (@s) {
+ push @{ $seen{$name_s} }, $.;
+ } else {
+ warn "# Your $where line $. is empty.\n";
+ next;
+ }
+ if ($n == $max) {
+ local $/;
+ my $junk = <PW>;
+ last;
+ }
+ # In principle we could whine if @s != 7 but do we know enough
+ # of passwd file formats everywhere?
+ if (@s == 7) {
+ @n = getpwuid($uid_s);
+ # 'nobody' et al.
+ next unless @n;
+ my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$home,$shell) = @n;
+ # Protect against one-to-many and many-to-one mappings.
+ if ($name_s ne $name) {
+ @n = getpwnam($name_s);
+ ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$home,$shell) = @n;
+ next if $name_s ne $name;
+ }
+ $perfect{$name_s}++
+ if $name eq $name_s and
+ $uid eq $uid_s and
+# Do not compare passwords: think shadow passwords.
+ $gid eq $gid_s and
+ $gcos eq $gcos_s and
+ $home eq $home_s and
+ $shell eq $shell_s;
+ }
+ $n++;
+}
+
+if (keys %perfect == 0) {
+ $max++;
+ print <<EOEX;
+#
+# The failure of op/pwent test is not necessarily serious.
+# It may fail due to local password administration conventions.
+# If you are for example using both NIS and local passwords,
+# test failure is possible. Any distributed password scheme
+# can cause such failures.
+#
+# What the pwent test is doing is that it compares the $max first
+# entries of $where
+# with the results of getpwuid() and getpwnam() call. If it finds no
+# matches at all, it suspects something is wrong.
+#
+EOEX
+ print "not ";
+ $not = 1;
+} else {
+ $not = 0;
+}
+print "ok ", $tst++;
+print "\t# (not necessarily serious: run t/op/pwent.t by itself)" if $not;
+print "\n";
+
+close(PW);
diff --git a/t/op/quotemeta.t b/t/op/quotemeta.t
index 20dd312b31..60e5b7be05 100755
--- a/t/op/quotemeta.t
+++ b/t/op/quotemeta.t
@@ -1,14 +1,32 @@
#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib' if -d '../lib';
+ require Config; import Config;
+}
+
print "1..15\n";
-$_=join "", map chr($_), 32..127;
+if ($Config{ebcdic} eq 'define') {
+ $_=join "", map chr($_), 129..233;
+
+ # 105 characters - 52 letters = 53 backslashes
+ # 105 characters + 53 backslashes = 158 characters
+ $_=quotemeta $_;
+ if ( length == 158 ){print "ok 1\n"} else {print "not ok 1\n"}
+ # 104 non-backslash characters
+ if (tr/\\//cd == 104){print "ok 2\n"} else {print "not ok 2\n"}
+} else { # some ASCII descendant, then.
+ $_=join "", map chr($_), 32..127;
-# 96 characters - 52 letters - 10 digits - 1 underscore = 33 backslashes
-# 96 characters + 33 backslashes = 129 characters
-$_=quotemeta $_;
-if ( length == 129 ){print "ok 1\n"} else {print "not ok 1\n"}
-# 95 non-backslash characters
-if (tr/\\//cd == 95){print "ok 2\n"} else {print "not ok 2\n"}
+ # 96 characters - 52 letters - 10 digits - 1 underscore = 33 backslashes
+ # 96 characters + 33 backslashes = 129 characters
+ $_=quotemeta $_;
+ if ( length == 129 ){print "ok 1\n"} else {print "not ok 1\n"}
+ # 95 non-backslash characters
+ if (tr/\\//cd == 95){print "ok 2\n"} else {print "not ok 2\n"}
+}
if (length quotemeta "" == 0){print "ok 3\n"} else {print "not ok 3\n"}
diff --git a/t/op/rand.t b/t/op/rand.t
index c779f9dad9..97019bb099 100755
--- a/t/op/rand.t
+++ b/t/op/rand.t
@@ -17,7 +17,7 @@
BEGIN {
chdir "t" if -d "t";
- @INC = "../lib" if -d "../lib";
+ unshift @INC, "../lib" if -d "../lib";
}
use strict;
@@ -52,6 +52,17 @@ sub bits ($) {
$max = $min = rand(1);
for (1..$reps) {
my $n = rand(1);
+ if ($n < 0.0 or $n >= 1.0) {
+ print <<EOM;
+# WHOA THERE! \$Config{drand01} is set to '$Config{drand01}',
+# but that apparently produces values < 0.0 or >= 1.0.
+# Make sure \$Config{drand01} is a valid expression in the
+# C-language, and produces values in the range [0.0,1.0).
+#
+# I give up.
+EOM
+ exit;
+ }
$sum += $n;
$bits += bits($n * 256); # Don't be greedy; 8 is enough
# It's too many if randbits is less than 8!
@@ -74,8 +85,8 @@ sub bits ($) {
# reason that the diagnostic message might get the
# wrong value is that Config.pm is incorrect.)
#
- if ($max <= 0 or $max >= (1 << $randbits)) { # Just in case...
- print "not ok 1\n";
+ if ($max <= 0 or $max >= (2 ** $randbits)) {# Just in case...
+ print "# max=[$max] min=[$min]\nnot ok 1\n";
print "# This perl was compiled with randbits=$randbits\n";
print "# which is _way_ off. Or maybe your system rand is broken,\n";
print "# or your C compiler can't multiply, or maybe Martians\n";
@@ -91,7 +102,7 @@ sub bits ($) {
$off = int($off) + ($off > 0); # Next more positive int
if ($off) {
$shouldbe = $Config{randbits} + $off;
- print "not ok 1\n";
+ print "# max=[$max] min=[$min]\nnot ok 1\n";
print "# This perl was compiled with randbits=$randbits on $^O.\n";
print "# Consider using randbits=$shouldbe instead.\n";
# And skip the remaining tests; they would be pointless now.
diff --git a/t/op/range.t b/t/op/range.t
index 7999b869cb..1698db4a55 100755
--- a/t/op/range.t
+++ b/t/op/range.t
@@ -1,6 +1,6 @@
#!./perl
-print "1..10\n";
+print "1..13\n";
print join(':',1..5) eq '1:2:3:4:5' ? "ok 1\n" : "not ok 1\n";
@@ -46,3 +46,21 @@ foreach ('09'..'08') {
print "not " unless join(",", @y) eq join(",", @x);
print "ok 10\n";
+# check bounds
+@a = 0x7ffffffe..0x7fffffff;
+print "not " unless "@a" eq "2147483646 2147483647";
+print "ok 11\n";
+
+@a = -0x7fffffff..-0x7ffffffe;
+print "not " unless "@a" eq "-2147483647 -2147483646";
+print "ok 12\n";
+
+# check magic
+{
+ my $bad = 0;
+ local $SIG{'__WARN__'} = sub { $bad = 1 };
+ my $x = 'a-e';
+ $x =~ s/(\w)-(\w)/join ':', $1 .. $2/e;
+ $bad = 1 unless $x eq 'a:b:c:d:e';
+ print $bad ? "not ok 13\n" : "ok 13\n";
+}
diff --git a/t/op/re_tests b/t/op/re_tests
index 7ac20c3852..b35e964dc1 100644
--- a/t/op/re_tests
+++ b/t/op/re_tests
@@ -151,8 +151,8 @@ a[bcd]+dcdcde adcdcde n - -
(bc+d$|ef*g.|h?i(j|k)) reffgz y $&-$1-$2 effgz-effgz-
((((((((((a)))))))))) a y $10 a
((((((((((a))))))))))\10 aa y $& aa
-((((((((((a))))))))))\41 aa n - -
-((((((((((a))))))))))\41 a! y $& a!
+((((((((((a))))))))))${bang} aa n - -
+((((((((((a))))))))))${bang} a! y $& a!
(((((((((a))))))))) a y $& a
multiple words of text uh-uh n - -
multiple words multiple words, yeah y $& multiple words
@@ -291,8 +291,8 @@ a[-]?c ac y $& ac
'(bc+d$|ef*g.|h?i(j|k))'i REFFGZ y $&-$1-$2 EFFGZ-EFFGZ-
'((((((((((a))))))))))'i A y $10 A
'((((((((((a))))))))))\10'i AA y $& AA
-'((((((((((a))))))))))\41'i AA n - -
-'((((((((((a))))))))))\41'i A! y $& A!
+'((((((((((a))))))))))${bang}'i AA n - -
+'((((((((((a))))))))))${bang}'i A! y $& A!
'(((((((((a)))))))))'i A y $& A
'(?:(?:(?:(?:(?:(?:(?:(?:(?:(a))))))))))'i A y $1 A
'(?:(?:(?:(?:(?:(?:(?:(?:(?:(a|b|c))))))))))'i C y $1 C
@@ -335,6 +335,9 @@ a(?:b|(c|e){1,2}?|d)+?(.) ace y $1$2 ce
^(a(?(1)\1)){4}$ aaaaaaaaaa y $1 aaaa
^(a(?(1)\1)){4}$ aaaaaaaaa n - -
^(a(?(1)\1)){4}$ aaaaaaaaaaa n - -
+((a{4})+) aaaaaaaaa y $1 aaaaaaaa
+(((aa){2})+) aaaaaaaaaa y $1 aaaaaaaa
+(((a{2}){2})+) aaaaaaaaaa y $1 aaaaaaaa
(?:(f)(o)(o)|(b)(a)(r))* foobar y $1:$2:$3:$4:$5:$6 f:o:o:b:a:r
(?<=a)b ab y $& b
(?<=a)b cb n - -
@@ -399,7 +402,7 @@ a(?{{})b - c - /a(?{{})b/: Sequence (?{...}) not terminated or not {}-balanced
a(?{}})b - c - /a(?{}})b/: Sequence (?{...}) not terminated or not {}-balanced
a(?{"{"})b - c - /a(?{"{"})b/: Sequence (?{...}) not terminated or not {}-balanced
a(?{"\{"})b cabd y $& ab
-a(?{"{"}})b - c - Unmatched right bracket
+a(?{"{"}})b - c - Unmatched right curly bracket
a(?{$bl="\{"}).b caxbd y $bl {
x(~~)*(?:(?:F)?)? x~~ y - -
^a(?#xxx){3}c aaac y $& aaac
@@ -471,15 +474,268 @@ $(?<=^(a)) a y $1 a
([[=]+) a=[b]= y $1 =[
([[.]+) a.[b]. y $1 .[
[a[:xyz: - c - /[a[:xyz:/: unmatched [] in regexp
-[a[:xyz:] - c - /[a[:xyz:]/: unmatched [] in regexp
-([a[:xyz:]b]+) pbaq y $1 ba
+[a[:xyz:] - c - Character class [:xyz:] unknown
+[a[:]b[:c] abc y $& abc
+([a[:xyz:]b]+) pbaq c - Character class [:xyz:] unknown
+[a[:]b[:c] abc y $& abc
+([[:alpha:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd
+([[:alnum:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd01Xy
+([[:ascii:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd01Xy__-- ${nulnul}
+([[:cntrl:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ${nulnul}
+([[:digit:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 01
+([[:graph:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd01Xy__--
+([[:lower:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 cd
+([[:print:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd01Xy__--
+([[:punct:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 __--
+([[:space:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1
+([[:word:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd01Xy__
+([[:upper:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 AB
+([[:xdigit:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd01
+([[:^alpha:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 01
+([[:^alnum:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 __-- ${nulnul}${ffff}
+([[:^ascii:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ${ffff}
+([[:^cntrl:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd01Xy__--
+([[:^digit:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd
+([[:^lower:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 AB
+([[:^print:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ${nulnul}${ffff}
+([[:^punct:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd01Xy
+([[:^space:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 ABcd01Xy__--
+([[:^word:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 -- ${nulnul}${ffff}
+([[:^upper:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 cd01
+([[:^xdigit:]]+) ABcd01Xy__-- ${nulnul}${ffff} y $1 Xy__-- ${nulnul}${ffff}
+[[:foo:]] - c - Character class [:foo:] unknown
+[[:^foo:]] - c - Character class [:^foo:] unknown
((?>a+)b) aaab y $1 aaab
(?>(a+))b aaab y $1 aaa
((?>[^()]+)|\([^()]*\))+ ((abc(ade)ufh()()x y $& abc(ade)ufh()()x
(?<=x+)y - c - /(?<=x+)y/: variable length lookbehind not implemented
a{37,17} - c - /a{37,17}/: Can't do {n,m} with n > m
+\Z a\nb\n y $-[0] 3
+\z a\nb\n y $-[0] 4
+$ a\nb\n y $-[0] 3
+\Z b\na\n y $-[0] 3
+\z b\na\n y $-[0] 4
+$ b\na\n y $-[0] 3
+\Z b\na y $-[0] 3
+\z b\na y $-[0] 3
+$ b\na y $-[0] 3
+'\Z'm a\nb\n y $-[0] 3
+'\z'm a\nb\n y $-[0] 4
+'$'m a\nb\n y $-[0] 1
+'\Z'm b\na\n y $-[0] 3
+'\z'm b\na\n y $-[0] 4
+'$'m b\na\n y $-[0] 1
+'\Z'm b\na y $-[0] 3
+'\z'm b\na y $-[0] 3
+'$'m b\na y $-[0] 1
a\Z a\nb\n n - -
-b\Z a\nb\n y - -
-b\z a\nb\n n - -
-b\Z a\nb y - -
-b\z a\nb y - -
+a\z a\nb\n n - -
+a$ a\nb\n n - -
+a\Z b\na\n y $-[0] 2
+a\z b\na\n n - -
+a$ b\na\n y $-[0] 2
+a\Z b\na y $-[0] 2
+a\z b\na y $-[0] 2
+a$ b\na y $-[0] 2
+'a\Z'm a\nb\n bn - -
+'a\z'm a\nb\n n - -
+'a$'m a\nb\n y $-[0] 0
+'a\Z'm b\na\n y $-[0] 2
+'a\z'm b\na\n n - -
+'a$'m b\na\n y $-[0] 2
+'a\Z'm b\na y $-[0] 2
+'a\z'm b\na y $-[0] 2
+'a$'m b\na y $-[0] 2
+aa\Z aa\nb\n n - -
+aa\z aa\nb\n n - -
+aa$ aa\nb\n n - -
+aa\Z b\naa\n y $-[0] 2
+aa\z b\naa\n n - -
+aa$ b\naa\n y $-[0] 2
+aa\Z b\naa y $-[0] 2
+aa\z b\naa y $-[0] 2
+aa$ b\naa y $-[0] 2
+'aa\Z'm aa\nb\n bn - -
+'aa\z'm aa\nb\n n - -
+'aa$'m aa\nb\n y $-[0] 0
+'aa\Z'm b\naa\n y $-[0] 2
+'aa\z'm b\naa\n n - -
+'aa$'m b\naa\n y $-[0] 2
+'aa\Z'm b\naa y $-[0] 2
+'aa\z'm b\naa y $-[0] 2
+'aa$'m b\naa y $-[0] 2
+aa\Z ac\nb\n n - -
+aa\z ac\nb\n n - -
+aa$ ac\nb\n n - -
+aa\Z b\nac\n n - -
+aa\z b\nac\n n - -
+aa$ b\nac\n n - -
+aa\Z b\nac n - -
+aa\z b\nac n - -
+aa$ b\nac n - -
+'aa\Z'm ac\nb\n n - -
+'aa\z'm ac\nb\n n - -
+'aa$'m ac\nb\n n - -
+'aa\Z'm b\nac\n n - -
+'aa\z'm b\nac\n n - -
+'aa$'m b\nac\n n - -
+'aa\Z'm b\nac n - -
+'aa\z'm b\nac n - -
+'aa$'m b\nac n - -
+aa\Z ca\nb\n n - -
+aa\z ca\nb\n n - -
+aa$ ca\nb\n n - -
+aa\Z b\nca\n n - -
+aa\z b\nca\n n - -
+aa$ b\nca\n n - -
+aa\Z b\nca n - -
+aa\z b\nca n - -
+aa$ b\nca n - -
+'aa\Z'm ca\nb\n n - -
+'aa\z'm ca\nb\n n - -
+'aa$'m ca\nb\n n - -
+'aa\Z'm b\nca\n n - -
+'aa\z'm b\nca\n n - -
+'aa$'m b\nca\n n - -
+'aa\Z'm b\nca n - -
+'aa\z'm b\nca n - -
+'aa$'m b\nca n - -
+ab\Z ab\nb\n n - -
+ab\z ab\nb\n n - -
+ab$ ab\nb\n n - -
+ab\Z b\nab\n y $-[0] 2
+ab\z b\nab\n n - -
+ab$ b\nab\n y $-[0] 2
+ab\Z b\nab y $-[0] 2
+ab\z b\nab y $-[0] 2
+ab$ b\nab y $-[0] 2
+'ab\Z'm ab\nb\n bn - -
+'ab\z'm ab\nb\n n - -
+'ab$'m ab\nb\n y $-[0] 0
+'ab\Z'm b\nab\n y $-[0] 2
+'ab\z'm b\nab\n n - -
+'ab$'m b\nab\n y $-[0] 2
+'ab\Z'm b\nab y $-[0] 2
+'ab\z'm b\nab y $-[0] 2
+'ab$'m b\nab y $-[0] 2
+ab\Z ac\nb\n n - -
+ab\z ac\nb\n n - -
+ab$ ac\nb\n n - -
+ab\Z b\nac\n n - -
+ab\z b\nac\n n - -
+ab$ b\nac\n n - -
+ab\Z b\nac n - -
+ab\z b\nac n - -
+ab$ b\nac n - -
+'ab\Z'm ac\nb\n n - -
+'ab\z'm ac\nb\n n - -
+'ab$'m ac\nb\n n - -
+'ab\Z'm b\nac\n n - -
+'ab\z'm b\nac\n n - -
+'ab$'m b\nac\n n - -
+'ab\Z'm b\nac n - -
+'ab\z'm b\nac n - -
+'ab$'m b\nac n - -
+ab\Z ca\nb\n n - -
+ab\z ca\nb\n n - -
+ab$ ca\nb\n n - -
+ab\Z b\nca\n n - -
+ab\z b\nca\n n - -
+ab$ b\nca\n n - -
+ab\Z b\nca n - -
+ab\z b\nca n - -
+ab$ b\nca n - -
+'ab\Z'm ca\nb\n n - -
+'ab\z'm ca\nb\n n - -
+'ab$'m ca\nb\n n - -
+'ab\Z'm b\nca\n n - -
+'ab\z'm b\nca\n n - -
+'ab$'m b\nca\n n - -
+'ab\Z'm b\nca n - -
+'ab\z'm b\nca n - -
+'ab$'m b\nca n - -
+abb\Z abb\nb\n n - -
+abb\z abb\nb\n n - -
+abb$ abb\nb\n n - -
+abb\Z b\nabb\n y $-[0] 2
+abb\z b\nabb\n n - -
+abb$ b\nabb\n y $-[0] 2
+abb\Z b\nabb y $-[0] 2
+abb\z b\nabb y $-[0] 2
+abb$ b\nabb y $-[0] 2
+'abb\Z'm abb\nb\n bn - -
+'abb\z'm abb\nb\n n - -
+'abb$'m abb\nb\n y $-[0] 0
+'abb\Z'm b\nabb\n y $-[0] 2
+'abb\z'm b\nabb\n n - -
+'abb$'m b\nabb\n y $-[0] 2
+'abb\Z'm b\nabb y $-[0] 2
+'abb\z'm b\nabb y $-[0] 2
+'abb$'m b\nabb y $-[0] 2
+abb\Z ac\nb\n n - -
+abb\z ac\nb\n n - -
+abb$ ac\nb\n n - -
+abb\Z b\nac\n n - -
+abb\z b\nac\n n - -
+abb$ b\nac\n n - -
+abb\Z b\nac n - -
+abb\z b\nac n - -
+abb$ b\nac n - -
+'abb\Z'm ac\nb\n n - -
+'abb\z'm ac\nb\n n - -
+'abb$'m ac\nb\n n - -
+'abb\Z'm b\nac\n n - -
+'abb\z'm b\nac\n n - -
+'abb$'m b\nac\n n - -
+'abb\Z'm b\nac n - -
+'abb\z'm b\nac n - -
+'abb$'m b\nac n - -
+abb\Z ca\nb\n n - -
+abb\z ca\nb\n n - -
+abb$ ca\nb\n n - -
+abb\Z b\nca\n n - -
+abb\z b\nca\n n - -
+abb$ b\nca\n n - -
+abb\Z b\nca n - -
+abb\z b\nca n - -
+abb$ b\nca n - -
+'abb\Z'm ca\nb\n n - -
+'abb\z'm ca\nb\n n - -
+'abb$'m ca\nb\n n - -
+'abb\Z'm b\nca\n n - -
+'abb\z'm b\nca\n n - -
+'abb$'m b\nca\n n - -
+'abb\Z'm b\nca n - -
+'abb\z'm b\nca n - -
+'abb$'m b\nca n - -
+(^|x)(c) ca y $2 c
+a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz x n - -
+a(?{$a=2;$b=3;($b)=$a})b yabz y $b 2
+round\(((?>[^()]+))\) _I(round(xs * sz),1) y $1 xs * sz
+'((?x:.) )' x y $1- x -
+'((?-x:.) )'x x y $1- x-
+foo.bart foo.bart y - -
+'^d[x][x][x]'m abcd\ndxxx y - -
+.X(.+)+X bbbbXcXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa y - -
+.X(.+)+XX bbbbXcXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa y - -
+.XX(.+)+X bbbbXXcXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa y - -
+.X(.+)+X bbbbXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa n - -
+.X(.+)+XX bbbbXXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa n - -
+.XX(.+)+X bbbbXXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa n - -
+.X(.+)+[X] bbbbXcXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa y - -
+.X(.+)+[X][X] bbbbXcXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa y - -
+.XX(.+)+[X] bbbbXXcXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa y - -
+.X(.+)+[X] bbbbXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa n - -
+.X(.+)+[X][X] bbbbXXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa n - -
+.XX(.+)+[X] bbbbXXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa n - -
+.[X](.+)+[X] bbbbXcXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa y - -
+.[X](.+)+[X][X] bbbbXcXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa y - -
+.[X][X](.+)+[X] bbbbXXcXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa y - -
+.[X](.+)+[X] bbbbXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa n - -
+.[X](.+)+[X][X] bbbbXXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa n - -
+.[X][X](.+)+[X] bbbbXXXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa n - -
+tt+$ xxxtt y - -
+[a-\w] - c - /[a-\w]/: invalid [] range in regexp
+[\w-z] - c - /[\w-z]/: invalid [] range in regexp
+[0-[:digit:]] - c - /[0-[:digit:]]/: invalid [] range in regexp
+[[:digit:]-9] - c - /[[:digit:]-9]/: invalid [] range in regexp
diff --git a/t/op/readdir.t b/t/op/readdir.t
index ca19ebc7db..aea976823a 100755
--- a/t/op/readdir.t
+++ b/t/op/readdir.t
@@ -5,6 +5,12 @@ if ($@) { print "1..0\n"; exit; }
print "1..3\n";
+for $i (1..2000) {
+ local *OP;
+ opendir(OP, "op") or die "can't opendir: $!";
+ # should auto-closedir() here
+}
+
if (opendir(OP, "op")) { print "ok 1\n"; } else { print "not ok 1\n"; }
@D = grep(/^[^\.].*\.t$/i, readdir(OP));
closedir(OP);
diff --git a/t/op/ref.t b/t/op/ref.t
index 1d70f9fd4c..a2baab8e3b 100755
--- a/t/op/ref.t
+++ b/t/op/ref.t
@@ -1,6 +1,6 @@
#!./perl
-print "1..55\n";
+print "1..56\n";
# Test glob operations.
@@ -241,11 +241,11 @@ print $$_,"\n";
package A;
sub new { bless {}, shift }
DESTROY { print "# destroying 'A'\nok 51\n" }
- package B;
+ package _B;
sub new { bless {}, shift }
- DESTROY { print "# destroying 'B'\nok 50\n"; bless shift, 'A' }
+ DESTROY { print "# destroying '_B'\nok 50\n"; bless shift, 'A' }
package main;
- my $b = B->new;
+ my $b = _B->new;
}
# test if $_[0] is properly protected in DESTROY()
@@ -271,14 +271,22 @@ print $$_,"\n";
print "# good, didn't recurse\n";
}
+# test if refgen behaves with autoviv magic
+
+{
+ my @a;
+ $a[1] = "ok 53\n";
+ print ${\$_} for @a;
+}
+
# test global destruction
package FINALE;
{
- $ref3 = bless ["ok 55\n"]; # package destruction
- my $ref2 = bless ["ok 54\n"]; # lexical destruction
- local $ref1 = bless ["ok 53\n"]; # dynamic destruction
+ $ref3 = bless ["ok 56\n"]; # package destruction
+ my $ref2 = bless ["ok 55\n"]; # lexical destruction
+ local $ref1 = bless ["ok 54\n"]; # dynamic destruction
1; # flush any temp values on stack
}
diff --git a/t/op/regexp.t b/t/op/regexp.t
index 0ec069b19a..4ffe1362c6 100755
--- a/t/op/regexp.t
+++ b/t/op/regexp.t
@@ -16,6 +16,8 @@ $ENV{PERL_DESTRUCT_LEVEL} = 0 unless $ENV{PERL_DESTRUCT_LEVEL} > 3;
# y expect a match
# n expect no match
# c expect an error
+# B test exposes a known bug in Perl, should be skipped
+# b test exposes a known bug in Perl, should be skipped if noamp
#
# Columns 4 and 5 are used only if column 3 contains C<y> or C<c>.
#
@@ -24,18 +26,16 @@ $ENV{PERL_DESTRUCT_LEVEL} = 0 unless $ENV{PERL_DESTRUCT_LEVEL} > 3;
# Column 5 contains the expected result of double-quote
# interpolating that string after the match, or start of error message.
#
-# \n in the tests are interpolated.
+# \n in the tests are interpolated, as are variables of the form ${\w+}.
#
# If you want to add a regular expression test that can't be expressed
# in this format, don't add it here: put it in op/pat.t instead.
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
-use re 'eval';
-
$iters = shift || 1; # Poor man performance suite, 10000 is OK.
open(TESTS,'op/re_tests') || open(TESTS,'t/op/re_tests') ||
@@ -46,6 +46,10 @@ $numtests = $.;
seek(TESTS,0,0);
$. = 0;
+$bang = sprintf "\\%03o", ord "!"; # \41 would not be portable.
+$ffff = chr(0xff) x 2;
+$nulnul = "\0" x 2;
+
$| = 1;
print "1..$numtests\n# $iters iterations\n";
TEST:
@@ -57,11 +61,18 @@ while (<TESTS>) {
infty_subst(\$pat);
infty_subst(\$expect);
$pat = "'$pat'" unless $pat =~ /^[:']/;
+ $pat =~ s/(\$\{\w+\})/$1/eeg;
$pat =~ s/\\n/\n/g;
+ $subject =~ s/(\$\{\w+\})/$1/eeg;
$subject =~ s/\\n/\n/g;
+ $expect =~ s/(\$\{\w+\})/$1/eeg;
$expect =~ s/\\n/\n/g;
$expect = $repl = '-' if $skip_amp and $input =~ /\$[&\`\']/;
- for $study ("", "study \$subject") {
+ $skip = ($skip_amp ? ($result =~ s/B//i) : ($result =~ s/B//));
+ # Certain tests don't work with utf8 (the re_test should be in UTF8)
+ $skip = 1 if ($^H &= ~0x00000008) && $pat =~ /\[:\^(alnum|print|word):\]/;
+ $result =~ s/B//i unless $skip;
+ for $study ('', 'study \$subject') {
$c = $iters;
eval "$study; \$match = (\$subject =~ m$pat) while \$c--; \$got = \"$repl\";";
chomp( $err = $@ );
@@ -69,6 +80,9 @@ while (<TESTS>) {
if ($err !~ m!^\Q$expect!) { print "not ok $. (compile) $input => `$err'\n"; next TEST }
last; # no need to study a syntax error
}
+ elsif ( $skip ) {
+ print "ok $. # skipped\n"; next TEST;
+ }
elsif ($@) {
print "not ok $. $input => error `$err'\n"; next TEST;
}
diff --git a/t/op/repeat.t b/t/op/repeat.t
index 54fa590836..c030ba9a12 100755
--- a/t/op/repeat.t
+++ b/t/op/repeat.t
@@ -2,7 +2,7 @@
# $RCSfile: repeat.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:21 $
-print "1..19\n";
+print "1..20\n";
# compile time
@@ -40,3 +40,59 @@ print join(':', () x 4) eq '' ? "ok 16\n" : "not ok 16\n";
print join(':', (9) x 4) eq '9:9:9:9' ? "ok 17\n" : "not ok 17\n";
print join(':', (9,9) x 4) eq '9:9:9:9:9:9:9:9' ? "ok 18\n" : "not ok 18\n";
print join('', (split(//,"123")) x 2) eq '123123' ? "ok 19\n" : "not ok 19\n";
+
+#
+# The test #20 is actually testing for Digital C compiler optimizer bug,
+# present in Dec C versions 5.* and 6.0 (used in Digital UNIX and VMS),
+# found in December 1998. The bug was reported to Digital^WCompaq as
+# DECC 2745 (21-Dec-1998)
+# GEM_BUGS 7619 (23-Dec-1998)
+# As of April 1999 the bug has been fixed in Tru64 UNIX 5.0 and is planned
+# to be fixed also in 4.0G.
+#
+# The bug was as follows: broken code was produced for util.c:repeatcpy()
+# (a utility function for the 'x' operator) in the case *all* these
+# four conditions held:
+#
+# (1) len == 1
+# (2) "from" had the 8th bit on in its single character
+# (3) count > 7 (the 'x' count > 16)
+# (4) the highest optimization level was used in compilation
+# (which is the default when compiling Perl)
+#
+# The bug looked like this (. being the eight-bit character and ? being \xff):
+#
+# 16 ................
+# 17 .........???????.
+# 18 .........???????..
+# 19 .........???????...
+# 20 .........???????....
+# 21 .........???????.....
+# 22 .........???????......
+# 23 .........???????.......
+# 24 .........???????.???????
+# 25 .........???????.???????.
+#
+# The bug was triggered in the "if (len == 1)" branch. The fix
+# was to introduce a new temporary variable. In diff -u format:
+#
+# register char *frombase = from;
+#
+# if (len == 1) {
+#- todo = *from;
+#+ register char c = *from;
+# while (count-- > 0)
+#- *to++ = todo;
+#+ *to++ = c;
+# return;
+# }
+#
+# The bug could also be (obscurely) avoided by changing "from" to
+# be an unsigned char pointer.
+#
+# This obscure bug was not found by the then test suite but instead
+# by Mark.Martinec@nsc.ijs.si while trying to install Digest-MD5-2.00.
+#
+# jhi@iki.fi
+#
+print "\xdd" x 24 eq "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" ? "ok 20\n" : "not ok 20\n";
diff --git a/t/op/runlevel.t b/t/op/runlevel.t
index 307e2a0bb5..a1551775e3 100755
--- a/t/op/runlevel.t
+++ b/t/op/runlevel.t
@@ -7,7 +7,7 @@
##
chdir 't' if -d 't';
-@INC = "../lib";
+unshift @INC, "../lib";
$Is_VMS = $^O eq 'VMS';
$Is_MSWin32 = $^O eq 'MSWin32';
$ENV{PERL5LIB} = "../lib" unless $Is_VMS;
@@ -35,7 +35,7 @@ for (@prgs){
`MCR $^X "-I[-.lib]" $switch $tmpfile` :
$Is_MSWin32 ?
`.\\perl -I../lib $switch $tmpfile 2>&1` :
- `sh -c './perl $switch $tmpfile' 2>&1`;
+ `./perl $switch $tmpfile 2>&1`;
my $status = $?;
$results =~ s/\n+$//;
# allow expected output to be written as if $prog is on STDIN
@@ -315,3 +315,23 @@ main|-|9|main::__ANON__
In DIE
main|-|10|(eval)
main|-|10|main::foo
+########
+package TEST;
+
+sub TIEARRAY {
+ return bless [qw(foo fee fie foe)], $_[0];
+}
+sub FETCH {
+ my ($s,$i) = @_;
+ if ($i) {
+ goto bbb;
+ }
+bbb:
+ return $s->[$i];
+}
+
+package main;
+tie my @bar, 'TEST';
+print join('|', @bar[0..3]), "\n";
+EXPECT
+foo|fee|fie|foe
diff --git a/t/op/sort.t b/t/op/sort.t
index a6829e01e4..f7bba3d263 100755
--- a/t/op/sort.t
+++ b/t/op/sort.t
@@ -1,25 +1,51 @@
#!./perl
-# $RCSfile: sort.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:24 $
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+print "1..38\n";
-print "1..21\n";
+# XXX known to leak scalars
+$ENV{PERL_DESTRUCT_LEVEL} = 0 unless $ENV{PERL_DESTRUCT_LEVEL} > 3;
sub backwards { $a lt $b ? 1 : $a gt $b ? -1 : 0 }
+my $upperfirst = 'A' lt 'a';
+
+# Beware: in future this may become hairier because of possible
+# collation complications: qw(A a B c) can be sorted at least as
+# any of the following
+#
+# A a B b
+# A B a b
+# a b A B
+# a A b B
+#
+# All the above orders make sense.
+#
+# That said, EBCDIC sorts all small letters first, as opposed
+# to ASCII which sorts all big letters first.
+
@harry = ('dog','cat','x','Cain','Abel');
@george = ('gone','chased','yz','punished','Axed');
$x = join('', sort @harry);
-print ($x eq 'AbelCaincatdogx' ? "ok 1\n" : "not ok 1\n");
-print "# x = '$x'\n";
+$expected = $upperfirst ? 'AbelCaincatdogx' : 'catdogxAbelCain';
+print "# 1: x = '$x', expected = '$expected'\n";
+print ($x eq $expected ? "ok 1\n" : "not ok 1\n");
$x = join('', sort( backwards @harry));
-print ($x eq 'xdogcatCainAbel' ? "ok 2\n" : "not ok 2\n");
-print "# x = '$x'\n";
+$expected = $upperfirst ? 'xdogcatCainAbel' : 'CainAbelxdogcat';
+print "# 2: x = '$x', expected = '$expected'\n";
+print ($x eq $expected ? "ok 2\n" : "not ok 2\n");
$x = join('', sort @george, 'to', @harry);
-print ($x eq 'AbelAxedCaincatchaseddoggonepunishedtoxyz'?"ok 3\n":"not ok 3\n");
-print "# x = '$x'\n";
+$expected = $upperfirst ?
+ 'AbelAxedCaincatchaseddoggonepunishedtoxyz' :
+ 'catchaseddoggonepunishedtoxyzAbelAxedCain' ;
+print "# 3: x = '$x', expected = '$expected'\n";
+print ($x eq $expected ?"ok 3\n":"not ok 3\n");
@a = ();
@b = reverse @a;
@@ -47,7 +73,9 @@ print ("@b" eq "2 3 4 10" ? "ok 9\n" : "not ok 9 (@b)\n");
$sub = 'backwards';
$x = join('', sort $sub @harry);
-print ($x eq 'xdogcatCainAbel' ? "ok 10\n" : "not ok 10\n");
+$expected = $upperfirst ? 'xdogcatCainAbel' : 'CainAbelxdogcat';
+print "# 10: x = $x, expected = '$expected'\n";
+print ($x eq $expected ? "ok 10\n" : "not ok 10\n");
# literals, combinations
@@ -102,3 +130,76 @@ eval <<'CODE';
my @result = sort 'one', 'two';
CODE
print $@ ? "not ok 21\n# $@" : "ok 21\n";
+
+{
+ my $sortsub = \&backwards;
+ my $sortglob = *backwards;
+ my $sortglobr = \*backwards;
+ my $sortname = 'backwards';
+ @b = sort $sortsub 4,1,3,2;
+ print ("@b" eq '4 3 2 1' ? "ok 22\n" : "not ok 22 |@b|\n");
+ @b = sort $sortglob 4,1,3,2;
+ print ("@b" eq '4 3 2 1' ? "ok 23\n" : "not ok 23 |@b|\n");
+ @b = sort $sortname 4,1,3,2;
+ print ("@b" eq '4 3 2 1' ? "ok 24\n" : "not ok 24 |@b|\n");
+ @b = sort $sortglobr 4,1,3,2;
+ print ("@b" eq '4 3 2 1' ? "ok 25\n" : "not ok 25 |@b|\n");
+}
+
+{
+ local $sortsub = \&backwards;
+ local $sortglob = *backwards;
+ local $sortglobr = \*backwards;
+ local $sortname = 'backwards';
+ @b = sort $sortsub 4,1,3,2;
+ print ("@b" eq '4 3 2 1' ? "ok 26\n" : "not ok 26 |@b|\n");
+ @b = sort $sortglob 4,1,3,2;
+ print ("@b" eq '4 3 2 1' ? "ok 27\n" : "not ok 27 |@b|\n");
+ @b = sort $sortname 4,1,3,2;
+ print ("@b" eq '4 3 2 1' ? "ok 28\n" : "not ok 28 |@b|\n");
+ @b = sort $sortglobr 4,1,3,2;
+ print ("@b" eq '4 3 2 1' ? "ok 29\n" : "not ok 29 |@b|\n");
+}
+
+## exercise sort builtins... ($a <=> $b already tested)
+@a = ( 5, 19, 1996, 255, 90 );
+@b = sort { $b <=> $a } @a;
+print ("@b" eq '1996 255 90 19 5' ? "ok 30\n" : "not ok 30\n");
+print "# x = '@b'\n";
+$x = join('', sort { $a cmp $b } @harry);
+$expected = $upperfirst ? 'AbelCaincatdogx' : 'catdogxAbelCain';
+print ($x eq $expected ? "ok 31\n" : "not ok 31\n");
+print "# x = '$x'; expected = '$expected'\n";
+$x = join('', sort { $b cmp $a } @harry);
+$expected = $upperfirst ? 'xdogcatCainAbel' : 'CainAbelxdogcat';
+print ($x eq $expected ? "ok 32\n" : "not ok 32\n");
+print "# x = '$x'; expected = '$expected'\n";
+{
+ use integer;
+ @b = sort { $a <=> $b } @a;
+ print ("@b" eq '5 19 90 255 1996' ? "ok 33\n" : "not ok 33\n");
+ print "# x = '@b'\n";
+ @b = sort { $b <=> $a } @a;
+ print ("@b" eq '1996 255 90 19 5' ? "ok 34\n" : "not ok 34\n");
+ print "# x = '@b'\n";
+ $x = join('', sort { $a cmp $b } @harry);
+ $expected = $upperfirst ? 'AbelCaincatdogx' : 'catdogxAbelCain';
+ print ($x eq $expected ? "ok 35\n" : "not ok 35\n");
+ print "# x = '$x'; expected = '$expected'\n";
+ $x = join('', sort { $b cmp $a } @harry);
+ $expected = $upperfirst ? 'xdogcatCainAbel' : 'CainAbelxdogcat';
+ print ($x eq $expected ? "ok 36\n" : "not ok 36\n");
+ print "# x = '$x'; expected = '$expected'\n";
+}
+
+# test that an optimized-away comparison block doesn't take any other
+# arguments away with it
+$x = join('', sort { $a <=> $b } 3, 1, 2);
+print $x eq "123" ? "ok 37\n" : "not ok 37\n";
+
+# test sorting in non-main package
+package Foo;
+@a = ( 5, 19, 1996, 255, 90 );
+@b = sort { $b <=> $a } @a;
+print ("@b" eq '1996 255 90 19 5' ? "ok 38\n" : "not ok 38\n");
+print "# x = '@b'\n";
diff --git a/t/op/sprintf.t b/t/op/sprintf.t
index 7556c80a41..ef5b94cb11 100755
--- a/t/op/sprintf.t
+++ b/t/op/sprintf.t
@@ -14,8 +14,8 @@ $SIG{__WARN__} = sub {
};
$w = 0;
-$x = sprintf("%3s %-4s%%foo %.0d%5d %#x%c%3.1f","hi",123,0,456,0,65,3.0999);
-if ($x eq ' hi 123 %foo 456 0A3.1' && $w == 0) {
+$x = sprintf("%3s %-4s%%foo %.0d%5d %#x%c%3.1f %b","hi",123,0,456,0,ord('A'),3.0999,11);
+if ($x eq ' hi 123 %foo 456 0A3.1 1011' && $w == 0) {
print "ok 1\n";
} else {
print "not ok 1 '$x'\n";
diff --git a/t/op/stat.t b/t/op/stat.t
index 03bfd8da39..0af55bbaab 100755
--- a/t/op/stat.t
+++ b/t/op/stat.t
@@ -4,7 +4,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
use Config;
@@ -13,28 +13,40 @@ print "1..58\n";
$Is_MSWin32 = $^O eq 'MSWin32';
$Is_Dos = $^O eq 'dos';
+$Is_Dosish = $Is_Dos || $^O eq 'os2' || $Is_MSWin32;
chop($cwd = ($Is_MSWin32 ? `cd` : `pwd`));
-$DEV = `ls -l /dev` unless ($Is_MSWin32 || $Is_Dos);
+$DEV = `ls -l /dev` unless $Is_Dosish;
unlink "Op.stat.tmp";
-open(FOO, ">Op.stat.tmp");
-
-# hack to make Apollo update link count:
-$junk = `ls Op.stat.tmp` unless ($Is_MSWin32 || $Is_Dos);
-
-($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
- $blksize,$blocks) = stat(FOO);
-if ($nlink == 1) {print "ok 1\n";} else {print "not ok 1\n";}
-if ($Is_MSWin32 || ($mtime && $mtime == $ctime)) {print "ok 2\n";}
-else {print "# |$mtime| vs |$ctime|\nnot ok 2\n";}
-
-print FOO "Now is the time for all good men to come to.\n";
-close(FOO);
-
-sleep 2;
+if (open(FOO, ">Op.stat.tmp")) {
+ # hack to make Apollo update link count:
+ $junk = `ls Op.stat.tmp` unless ($Is_MSWin32 || $Is_Dos);
+
+ ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
+ $blksize,$blocks) = stat(FOO);
+ if ($nlink == 1) {
+ print "ok 1\n";
+ }
+ else {
+ print "# res=$res, nlink=$nlink.\nnot ok 1\n";
+ }
+ if ($Is_MSWin32 || ($mtime && $mtime == $ctime)) {
+ print "ok 2\n";
+ }
+ else {
+ print "# |$mtime| vs |$ctime|\nnot ok 2\n";
+ }
+
+ print FOO "Now is the time for all good men to come to.\n";
+ close(FOO);
+
+ sleep 2;
+} else {
+ print "# open failed: $!\nnot ok 1\nnot ok 2\n";
+}
-if ($Is_MSWin32 || $Is_Dos) { unlink "Op.stat.tmp2" }
+if ($Is_Dosish) { unlink "Op.stat.tmp2"}
else {
`rm -f Op.stat.tmp2;ln Op.stat.tmp Op.stat.tmp2; chmod 644 Op.stat.tmp`;
}
@@ -42,15 +54,19 @@ else {
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
$blksize,$blocks) = stat('Op.stat.tmp');
-if ($Is_MSWin32 || $Is_Dos || $Config{dont_use_nlink} || $nlink == 2)
- {print "ok 3\n";} else {print "# \$nlink is |$nlink|\nnot ok 3\n";}
+if ($Is_Dosish || $Config{dont_use_nlink})
+ {print "ok 3 # skipped: no link count\n";}
+elsif ($nlink == 2)
+ {print "ok 3\n";}
+else {print "# \$nlink is |$nlink|\nnot ok 3\n";}
-if ( ($mtime && $mtime != $ctime)
- || $Is_MSWin32
- || $Is_Dos
+if ( $Is_Dosish
|| ($cwd =~ m#^/tmp# and $mtime && $mtime==$ctime) # Solaris tmpfs bug
|| $cwd =~ m#/afs/#
|| $^O eq 'amigaos') {
+ print "ok 4 # skipped: different semantic of mtime/ctime\n";
+}
+elsif ( ($mtime && $mtime != $ctime) ) {
print "ok 4\n";
}
else {
@@ -60,7 +76,7 @@ else {
}
print "#4 :$mtime: should != :$ctime:\n";
-unlink "Op.stat.tmp";
+unlink "Op.stat.tmp" or print "# unlink failed: $!\n";
if ($Is_MSWin32) { open F, '>Op.stat.tmp' and close F }
else { `touch Op.stat.tmp` }
@@ -71,7 +87,7 @@ $Is_MSWin32 ? `cmd /c echo hi > Op.stat.tmp` : `echo hi >Op.stat.tmp`;
if (! -z 'Op.stat.tmp') {print "ok 7\n";} else {print "not ok 7\n";}
if (-s 'Op.stat.tmp') {print "ok 8\n";} else {print "not ok 8\n";}
-unlink 'Op.stat.tmp';
+unlink 'Op.stat.tmp' or print "# unlink failed: $!\n";
$olduid = $>; # can't test -r if uid == 0
$Is_MSWin32 ? `cmd /c echo hi > Op.stat.tmp` : `echo hi >Op.stat.tmp`;
chmod 0,'Op.stat.tmp';
@@ -88,10 +104,15 @@ foreach ((12,13,14,15,16,17)) {
print "ok $_\n"; #deleted tests
}
+# in ms windows, Op.stat.tmp inherits owner uid from directory
+# not sure about os/2, but chown is harmless anyway
+eval { chown $>,'Op.stat.tmp'; 1 } or print "# $@" ;
chmod 0700,'Op.stat.tmp';
if (-r 'Op.stat.tmp') {print "ok 18\n";} else {print "not ok 18\n";}
if (-w 'Op.stat.tmp') {print "ok 19\n";} else {print "not ok 19\n";}
-if ($Is_MSWin32 or $Is_Dos or -x 'Op.stat.tmp') {print "ok 20\n";} else {print "not ok 20\n";}
+if ($Is_Dosish) {print "ok 20 # skipped: -x by extension\n";}
+elsif (-x 'Op.stat.tmp') {print "ok 20\n";}
+else {print "not ok 20\n";}
if (-f 'Op.stat.tmp') {print "ok 21\n";} else {print "not ok 21\n";}
if (! -d 'Op.stat.tmp') {print "ok 22\n";} else {print "not ok 22\n";}
@@ -99,7 +120,7 @@ if (! -d 'Op.stat.tmp') {print "ok 22\n";} else {print "not ok 22\n";}
if (-d '.') {print "ok 23\n";} else {print "not ok 23\n";}
if (! -f '.') {print "ok 24\n";} else {print "not ok 24\n";}
-if (!($Is_MSWin32 || $Is_Dos) and `ls -l perl` =~ /^l.*->/) {
+if (!$Is_Dosish and `ls -l perl` =~ /^l.*->/) {
if (-l 'perl') {print "ok 25\n";} else {print "not ok 25\n";}
}
else {
@@ -142,7 +163,9 @@ else
{print "not ok 33\n";}
if (! -b '.') {print "ok 34\n";} else {print "not ok 34\n";}
-if ($^O eq 'amigaos' or $Is_MSWin32 || $Is_Dos) {print "ok 35\n"; goto tty_test;}
+if ($^O eq 'amigaos' or $Is_Dosish) {
+ print "ok 35 # skipped: no -u\n"; goto tty_test;
+}
$cnt = $uid = 0;
@@ -175,14 +198,23 @@ unless($ENV{PERL_SKIP_TTY_TEST}) {
print "ok 37\n";
}
else {
- unless (open(tty,"/dev/tty")) {
- print STDERR "Can't open /dev/tty--run t/TEST outside of make.\n";
+ my $TTY = "/dev/tty";
+
+ $TTY = "/dev/ttyp0" if $^O eq 'rhapsody';
+
+ if (defined $TTY) {
+ unless (open(TTY, $TTY)) {
+ print STDERR "Can't open $TTY--run t/TEST outside of make.\n";
+ }
+ if (-t TTY) {print "ok 36\n";} else {print "not ok 36\n";}
+ if (-c TTY) {print "ok 37\n";} else {print "not ok 37\n";}
+ close(TTY);
+ } else { # if some platform completely undefines $TTY
+ print "ok 36 # skipped\n";
+ print "ok 37 # skipped\n";
}
- if (-t tty) {print "ok 36\n";} else {print "not ok 36\n";}
- if (-c tty) {print "ok 37\n";} else {print "not ok 37\n";}
- close(tty);
}
- if (! -t tty) {print "ok 38\n";} else {print "not ok 38\n";}
+ if (! -t TTY) {print "ok 38\n";} else {print "not ok 38\n";}
if (-t) {print "ok 39\n";} else {print "not ok 39\n";}
}
else {
@@ -240,4 +272,4 @@ $_ = 'Op.stat.tmp';
if (-f) {print "ok 57\n";} else {print "not ok 57\n";}
if (-f()) {print "ok 58\n";} else {print "not ok 58\n";}
-unlink 'Op.stat.tmp';
+unlink 'Op.stat.tmp' or print "# unlink failed: $!\n";
diff --git a/t/op/subst.t b/t/op/subst.t
index 2d42eeb386..2d15df4dc1 100755
--- a/t/op/subst.t
+++ b/t/op/subst.t
@@ -1,12 +1,12 @@
#!./perl
-
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
+ require Config; import Config;
}
-print "1..71\n";
+print "1..83\n";
$x = 'foo';
$_ = "x";
@@ -187,13 +187,22 @@ tr/a-z/A-Z/;
print $_ eq 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' ? "ok 52\n" : "not ok 52\n";
# same as tr/A-Z/a-z/;
-y[\101-\132][\141-\172];
+if ($Config{ebcdic} eq 'define') { # EBCDIC.
+ no utf8;
+ y[\301-\351][\201-\251];
+} else { # Ye Olde ASCII. Or something like it.
+ y[\101-\132][\141-\172];
+}
print $_ eq 'abcdefghijklmnopqrstuvwxyz0123456789' ? "ok 53\n" : "not ok 53\n";
-$_ = '+,-';
-tr/+--/a-c/;
-print $_ eq 'abc' ? "ok 54\n" : "not ok 54\n";
+if (ord("+") == ord(",") - 1 && ord(",") == ord("-") - 1 &&
+ ord("a") == ord("b") - 1 && ord("b") == ord("c") - 1) {
+ $_ = '+,-';
+ tr/+--/a-c/;
+ print "not " unless $_ eq 'abc';
+}
+print "ok 54\n";
$_ = '+,-';
tr/+\--/a\/c/;
@@ -303,6 +312,67 @@ s{ \d+ \b [,.;]? (?{ 'digits' })
print ($_ eq $foo ? "ok 70\n" : "not ok 70\n#'$_'\n#'$foo'\n");
$_ = 'x' x 20;
-s/\d*|x/<$&>/g;
+s/(\d*|x)/<$1>/g;
$foo = '<>' . ('<x><>' x 20) ;
print ($_ eq $foo ? "ok 71\n" : "not ok 71\n#'$_'\n#'$foo'\n");
+
+$t = 'aaaaaaaaa';
+
+$_ = $t;
+pos = 6;
+s/\Ga/xx/g;
+print "not " unless $_ eq 'aaaaaaxxxxxx';
+print "ok 72\n";
+
+$_ = $t;
+pos = 6;
+s/\Ga/x/g;
+print "not " unless $_ eq 'aaaaaaxxx';
+print "ok 73\n";
+
+$_ = $t;
+pos = 6;
+s/\Ga/xx/;
+print "not " unless $_ eq 'aaaaaaxxaa';
+print "ok 74\n";
+
+$_ = $t;
+pos = 6;
+s/\Ga/x/;
+print "not " unless $_ eq 'aaaaaaxaa';
+print "ok 75\n";
+
+$_ = $t;
+s/\Ga/xx/g;
+print "not " unless $_ eq 'xxxxxxxxxxxxxxxxxx';
+print "ok 76\n";
+
+$_ = $t;
+s/\Ga/x/g;
+print "not " unless $_ eq 'xxxxxxxxx';
+print "ok 77\n";
+
+$_ = $t;
+s/\Ga/xx/;
+print "not " unless $_ eq 'xxaaaaaaaa';
+print "ok 78\n";
+
+$_ = $t;
+s/\Ga/x/;
+print "not " unless $_ eq 'xaaaaaaaa';
+print "ok 79\n";
+
+$_ = 'aaaa';
+s/\ba/./g;
+print "#'$_'\nnot " unless $_ eq '.aaa';
+print "ok 80\n";
+
+eval q% s/a/"b"}/e %;
+print ($@ =~ /Bad evalled substitution/ ? "ok 81\n" : "not ok 81\n");
+eval q% ($_ = "x") =~ s/(.)/"$1 "/e %;
+print +($_ eq "x " and !length $@) ? "ok 82\n" : "not ok 82\n# \$_ eq $_, $@\n";
+$x = $x = 'interp';
+eval q% ($_ = "x") =~ s/x(($x)*)/"$1"/e %;
+print +($_ eq '' and !length $@) ? "ok 83\n" : "not ok 83\n# \$_ eq $_, $@\n";
+
+
diff --git a/t/op/subst_amp.t b/t/op/subst_amp.t
new file mode 100755
index 0000000000..e2e7c0e542
--- /dev/null
+++ b/t/op/subst_amp.t
@@ -0,0 +1,104 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib' if -d '../lib';
+ require Config; import Config;
+}
+
+print "1..13\n";
+
+$_ = 'x' x 20;
+s/\d*|x/<$&>/g;
+$foo = '<>' . ('<x><>' x 20) ;
+print ($_ eq $foo ? "ok 1\n" : "not ok 1\n#'$_'\n#'$foo'\n");
+
+$t = 'aaa';
+
+$_ = $t;
+@res = ();
+pos = 1;
+s/\Ga(?{push @res, $_, $`})/xx/g;
+print "not " unless "$_ @res" eq 'axxxx aaa a aaa aa';
+print "ok 2\n";
+
+$_ = $t;
+@res = ();
+pos = 1;
+s/\Ga(?{push @res, $_, $`})/x/g;
+print "not " unless "$_ @res" eq 'axx aaa a aaa aa';
+print "ok 3\n";
+
+$_ = $t;
+@res = ();
+pos = 1;
+s/\Ga(?{push @res, $_, $`})/xx/;
+print "not " unless "$_ @res" eq 'axxa aaa a';
+print "ok 4\n";
+
+$_ = $t;
+@res = ();
+pos = 1;
+s/\Ga(?{push @res, $_, $`})/x/;
+print "not " unless "$_ @res" eq 'axa aaa a';
+print "ok 5\n";
+
+$a = $t;
+@res = ();
+pos ($a) = 1;
+$a =~ s/\Ga(?{push @res, $_, $`})/xx/g;
+print "#'$a' '@res'\nnot " unless "$a @res" eq 'axxxx aaa a aaa aa';
+print "ok 6\n";
+
+$a = $t;
+@res = ();
+pos ($a) = 1;
+$a =~ s/\Ga(?{push @res, $_, $`})/x/g;
+print "#'$a' '@res'\nnot " unless "$a @res" eq 'axx aaa a aaa aa';
+print "ok 7\n";
+
+$a = $t;
+@res = ();
+pos ($a) = 1;
+$a =~ s/\Ga(?{push @res, $_, $`})/xx/;
+print "#'$a' '@res'\nnot " unless "$a @res" eq 'axxa aaa a';
+print "ok 8\n";
+
+$a = $t;
+@res = ();
+pos ($a) = 1;
+$a =~ s/\Ga(?{push @res, $_, $`})/x/;
+print "#'$a' '@res'\nnot " unless "$a @res" eq 'axa aaa a';
+print "ok 9\n";
+
+sub x2 {'xx'}
+sub x1 {'x'}
+
+$a = $t;
+@res = ();
+pos ($a) = 1;
+$a =~ s/\Ga(?{push @res, $_, $`})/x2/ge;
+print "#'$a' '@res'\nnot " unless "$a @res" eq 'axxxx aaa a aaa aa';
+print "ok 10\n";
+
+$a = $t;
+@res = ();
+pos ($a) = 1;
+$a =~ s/\Ga(?{push @res, $_, $`})/x1/ge;
+print "#'$a' '@res'\nnot " unless "$a @res" eq 'axx aaa a aaa aa';
+print "ok 11\n";
+
+$a = $t;
+@res = ();
+pos ($a) = 1;
+$a =~ s/\Ga(?{push @res, $_, $`})/x2/e;
+print "#'$a' '@res'\nnot " unless "$a @res" eq 'axxa aaa a';
+print "ok 12\n";
+
+$a = $t;
+@res = ();
+pos ($a) = 1;
+$a =~ s/\Ga(?{push @res, $_, $`})/x1/e;
+print "#'$a' '@res'\nnot " unless "$a @res" eq 'axa aaa a';
+print "ok 13\n";
+
diff --git a/t/op/subst_wamp.t b/t/op/subst_wamp.t
new file mode 100755
index 0000000000..b716b30915
--- /dev/null
+++ b/t/op/subst_wamp.t
@@ -0,0 +1,11 @@
+#!./perl
+
+$dummy = defined $&; # Now we have it...
+for $file ('op/subst.t', 't/op/subst.t') {
+ if (-r $file) {
+ do $file;
+ exit;
+ }
+}
+die "Cannot find op/subst.t or t/op/subst.t\n";
+
diff --git a/t/op/sysio.t b/t/op/sysio.t
index 826cf383ae..22e60e30fc 100755
--- a/t/op/sysio.t
+++ b/t/op/sysio.t
@@ -1,12 +1,13 @@
#!./perl
-print "1..36\n";
+print "1..39\n";
chdir('op') || die "sysio.t: cannot look for myself: $!";
open(I, 'sysio.t') || die "sysio.t: cannot find myself: $!";
-$reopen = ($^O eq 'VMS' || $^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'dos');
+$reopen = ($^O eq 'VMS' || $^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'dos' ||
+ $^O eq 'mpeix');
$x = 'abc';
@@ -151,6 +152,21 @@ if ($reopen) { # must close file to update EOF marker for stat
print 'not ' unless (-s $outfile == 7);
print "ok 28\n";
+# with implicit length argument
+print 'not ' unless (syswrite(O, $x) == 3);
+print "ok 29\n";
+
+# $a still intact
+print 'not ' unless ($x eq "abc");
+print "ok 30\n";
+
+# $outfile should have grown now
+if ($reopen) { # must close file to update EOF marker for stat
+ close O; open(O, ">>$outfile") || die "sysio.t: cannot write $outfile: $!";
+}
+print 'not ' unless (-s $outfile == 10);
+print "ok 31\n";
+
close(O);
open(I, $outfile) || die "sysio.t: cannot read $outfile: $!";
@@ -158,30 +174,30 @@ open(I, $outfile) || die "sysio.t: cannot read $outfile: $!";
$b = 'xyz';
# reading too much only return as much as available
-print 'not ' unless (sysread(I, $b, 100) == 7);
-print "ok 29\n";
+print 'not ' unless (sysread(I, $b, 100) == 10);
+print "ok 32\n";
# this we should have
-print 'not ' unless ($b eq '#!ererl');
-print "ok 30\n";
+print 'not ' unless ($b eq '#!ererlabc');
+print "ok 33\n";
# test sysseek
print 'not ' unless sysseek(I, 2, 0) == 2;
-print "ok 31\n";
+print "ok 34\n";
sysread(I, $b, 3);
print 'not ' unless $b eq 'ere';
-print "ok 32\n";
+print "ok 35\n";
print 'not ' unless sysseek(I, -2, 1) == 3;
-print "ok 33\n";
+print "ok 36\n";
sysread(I, $b, 4);
print 'not ' unless $b eq 'rerl';
-print "ok 34\n";
+print "ok 37\n";
print 'not ' unless sysseek(I, 0, 0) eq '0 but true';
-print "ok 35\n";
+print "ok 38\n";
print 'not ' if defined sysseek(I, -1, 1);
-print "ok 36\n";
+print "ok 39\n";
close(I);
diff --git a/t/op/taint.t b/t/op/taint.t
index f2181d82fd..fdd1c79b83 100755
--- a/t/op/taint.t
+++ b/t/op/taint.t
@@ -9,12 +9,23 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
use strict;
use Config;
+# We do not want the whole taint.t to fail
+# just because Errno possibly failing.
+eval { require Errno; import Errno };
+
+BEGIN {
+ if ($^O eq 'VMS' && !defined($Config{d_setenv})) {
+ $ENV{PATH} = $ENV{PATH};
+ $ENV{TERM} = $ENV{TERM} ne ''? $ENV{TERM} : 'dummy';
+ }
+}
+
my $Is_VMS = $^O eq 'VMS';
my $Is_MSWin32 = $^O eq 'MSWin32';
my $Is_Dos = $^O eq 'dos';
@@ -29,9 +40,9 @@ if ($Is_VMS) {
}
eval <<EndOfCleanup;
END {
- \$ENV{PATH} = '';
+ \$ENV{PATH} = '' if $Config{d_setenv};
warn "# Note: logical name 'PATH' may have been deleted\n";
- @ENV{keys %old} = values %old;
+ \@ENV{keys %old} = values %old;
}
EndOfCleanup
}
@@ -360,7 +371,12 @@ else {
test 71, eval { open FOO, $foo } eq '', 'open for read';
test 72, $@ eq '', $@; # NB: This should be allowed
- test 73, $! == 2 || ($Is_Dos && $! == 22); # File not found
+
+ # Try first new style but allow also old style.
+ test 73, $!{ENOENT} ||
+ $! == 2 || # File not found
+ ($Is_Dos && $! == 22) ||
+ ($^O eq 'mint' && $! == 33);
test 74, eval { open FOO, "> $foo" } eq '', 'open for write';
test 75, $@ =~ /^Insecure dependency/, $@;
@@ -374,10 +390,10 @@ else {
for (76..79) { print "ok $_ # Skipped: open('|') is not available\n" }
}
else {
- test 76, eval { open FOO, "| $foo" } eq '', 'popen to';
+ test 76, eval { open FOO, "| x$foo" } eq '', 'popen to';
test 77, $@ =~ /^Insecure dependency/, $@;
- test 78, eval { open FOO, "$foo |" } eq '', 'popen from';
+ test 78, eval { open FOO, "x$foo |" } eq '', 'popen from';
test 79, $@ =~ /^Insecure dependency/, $@;
}
diff --git a/t/op/tie.t b/t/op/tie.t
index 77e74db4e2..105b1d6f18 100755
--- a/t/op/tie.t
+++ b/t/op/tie.t
@@ -6,7 +6,7 @@
# Currently it only tests the untie warning
chdir 't' if -d 't';
-@INC = "../lib";
+unshift @INC, "../lib";
$ENV{PERL5LIB} = "../lib";
$|=1;
@@ -77,8 +77,8 @@ EXPECT
########
# strict behaviour, without any extra references
-#use warning 'untie';
-local $^W = 1 ;
+use warnings 'untie';
+#local $^W = 1 ;
use Tie::Hash ;
tie %h, Tie::StdHash;
untie %h;
@@ -86,8 +86,8 @@ EXPECT
########
# strict behaviour, with 1 extra references generating an error
-#use warning 'untie';
-local $^W = 1 ;
+use warnings 'untie';
+#local $^W = 1 ;
use Tie::Hash ;
$a = tie %h, Tie::StdHash;
untie %h;
@@ -96,8 +96,8 @@ untie attempted while 1 inner references still exist
########
# strict behaviour, with 1 extra references via tied generating an error
-#use warning 'untie';
-local $^W = 1 ;
+use warnings 'untie';
+#local $^W = 1 ;
use Tie::Hash ;
tie %h, Tie::StdHash;
$a = tied %h;
@@ -107,8 +107,8 @@ untie attempted while 1 inner references still exist
########
# strict behaviour, with 1 extra references which are destroyed
-#use warning 'untie';
-local $^W = 1 ;
+use warnings 'untie';
+#local $^W = 1 ;
use Tie::Hash ;
$a = tie %h, Tie::StdHash;
$a = 0 ;
@@ -117,8 +117,8 @@ EXPECT
########
# strict behaviour, with extra 1 references via tied which are destroyed
-#use warning 'untie';
-local $^W = 1 ;
+use warnings 'untie';
+#local $^W = 1 ;
use Tie::Hash ;
tie %h, Tie::StdHash;
$a = tied %h;
@@ -128,8 +128,8 @@ EXPECT
########
# strict error behaviour, with 2 extra references
-#use warning 'untie';
-local $^W = 1 ;
+use warnings 'untie';
+#local $^W = 1 ;
use Tie::Hash ;
$a = tie %h, Tie::StdHash;
$b = tied %h ;
@@ -139,17 +139,42 @@ untie attempted while 2 inner references still exist
########
# strict behaviour, check scope of strictness.
-#no warning 'untie';
-local $^W = 0 ;
+no warnings 'untie';
+#local $^W = 0 ;
use Tie::Hash ;
$A = tie %H, Tie::StdHash;
$C = $B = tied %H ;
{
- #use warning 'untie';
- local $^W = 1 ;
+ use warnings 'untie';
+ #local $^W = 1 ;
use Tie::Hash ;
tie %h, Tie::StdHash;
untie %h;
}
untie %H;
EXPECT
+########
+
+# verify no leak when underlying object is selfsame tied variable
+my ($a, $b);
+sub Self::TIEHASH { bless $_[1], $_[0] }
+sub Self::DESTROY { $b = $_[0] + 0; }
+{
+ my %b5;
+ $a = \%b5 + 0;
+ tie %b5, 'Self', \%b5;
+}
+die unless $a == $b;
+EXPECT
+########
+# Interaction of tie and vec
+
+my ($a, $b);
+use Tie::Scalar;
+tie $a,Tie::StdScalar or die;
+vec($b,1,1)=1;
+$a = $b;
+vec($a,1,1)=0;
+vec($b,1,1)=0;
+die unless $a eq $b;
+EXPECT
diff --git a/t/op/tiearray.t b/t/op/tiearray.t
index 8e78b2f76b..25fda3fb03 100755
--- a/t/op/tiearray.t
+++ b/t/op/tiearray.t
@@ -3,7 +3,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
my %seen;
diff --git a/t/op/tiehandle.t b/t/op/tiehandle.t
index e3d24723a9..6ae3faaaec 100755
--- a/t/op/tiehandle.t
+++ b/t/op/tiehandle.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
my @expect;
@@ -64,7 +64,7 @@ sub READ {
sub WRITE {
compare(WRITE => @_);
$data = substr($_[1],$_[3] || 0, $_[2]);
- 4;
+ length($data);
}
sub CLOSE {
@@ -77,7 +77,7 @@ package main;
use Symbol;
-print "1..23\n";
+print "1..29\n";
my $fh = gensym;
@@ -132,6 +132,20 @@ $r = syswrite $fh,$buf,4,1;
ok($r == 4);
ok($data eq "wert");
+$buf = "qwerty";
+@expect = (WRITE => $ob, $buf, 4);
+$data = "";
+$r = syswrite $fh,$buf,4;
+ok($r == 4);
+ok($data eq "qwer");
+
+$buf = "qwerty";
+@expect = (WRITE => $ob, $buf, 6);
+$data = "";
+$r = syswrite $fh,$buf;
+ok($r == 6);
+ok($data eq "qwerty");
+
@expect = (CLOSE => $ob);
$r = close $fh;
ok($r == 5);
diff --git a/t/op/time.t b/t/op/time.t
index 1bec442fe2..658f9f35b9 100755
--- a/t/op/time.t
+++ b/t/op/time.t
@@ -2,7 +2,7 @@
# $RCSfile: time.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:32 $
-if ($does_gmtime = gmtime(time)) { print "1..5\n" }
+if ($does_gmtime = gmtime(time)) { print "1..6\n" }
else { print "1..3\n" }
($beguser,$begsys) = times;
@@ -45,3 +45,9 @@ if (index(" :0:1:-1:364:365:-364:-365:",':' . ($localyday - $yday) . ':') > 0)
{print "ok 5\n";}
else
{print "not ok 5\n";}
+
+# This could be stricter.
+if (gmtime() =~ /^(Sun|Mon|Tue|Wed|Thu|Fri|Sat) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Nov|Dec) ([ \d]\d) (\d\d):(\d\d):(\d\d) (\d\d\d\d)$/)
+ {print "ok 6\n";}
+else
+ {print "not ok 6\n";}
diff --git a/t/op/tr.t b/t/op/tr.t
new file mode 100755
index 0000000000..4e6667cd7f
--- /dev/null
+++ b/t/op/tr.t
@@ -0,0 +1,39 @@
+# tr.t
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, "../lib";
+}
+
+print "1..4\n";
+
+$_ = "abcdefghijklmnopqrstuvwxyz";
+
+tr/a-z/A-Z/;
+
+print "not " unless $_ eq "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+print "ok 1\n";
+
+tr/A-Z/a-z/;
+
+print "not " unless $_ eq "abcdefghijklmnopqrstuvwxyz";
+print "ok 2\n";
+
+tr/b-y/B-Y/;
+
+print "not " unless $_ eq "aBCDEFGHIJKLMNOPQRSTUVWXYz";
+print "ok 3\n";
+
+# In EBCDIC 'I' is \xc9 and 'J' is \0xd1, 'i' is \x89 and 'j' is \x91.
+# Yes, discontinuities. Regardless, the \xca in the below should stay
+# untouched (and not became \x8a).
+{
+ no utf8;
+ $_ = "I\xcaJ";
+
+ tr/I-J/i-j/;
+
+ print "not " unless $_ eq "i\xcaj";
+ print "ok 4\n";
+}
+#
diff --git a/t/op/undef.t b/t/op/undef.t
index 8ab2ec421f..8944ee3976 100755
--- a/t/op/undef.t
+++ b/t/op/undef.t
@@ -1,8 +1,11 @@
#!./perl
-# $RCSfile: undef.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:34 $
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
-print "1..21\n";
+print "1..27\n";
print defined($a) ? "not ok 1\n" : "ok 1\n";
@@ -54,3 +57,25 @@ sub foo { print "ok 19\n"; }
print defined &foo ? "ok 20\n" : "not ok 20\n";
undef &foo;
print defined(&foo) ? "not ok 21\n" : "ok 21\n";
+
+eval { undef $1 };
+print $@ =~ /^Modification of a read/ ? "ok 22\n" : "not ok 22\n";
+
+eval { $1 = undef };
+print $@ =~ /^Modification of a read/ ? "ok 23\n" : "not ok 23\n";
+
+{
+ require Tie::Hash;
+ tie my %foo, 'Tie::StdHash';
+ print defined %foo ? "ok 24\n" : "not ok 24\n";
+ %foo = ( a => 1 );
+ print defined %foo ? "ok 25\n" : "not ok 25\n";
+}
+
+{
+ require Tie::Array;
+ tie my @foo, 'Tie::StdArray';
+ print defined @foo ? "ok 26\n" : "not ok 26\n";
+ @foo = ( a => 1 );
+ print defined @foo ? "ok 27\n" : "not ok 27\n";
+}
diff --git a/t/op/universal.t b/t/op/universal.t
index bd6c73afe9..eb6ec3ce97 100755
--- a/t/op/universal.t
+++ b/t/op/universal.t
@@ -5,7 +5,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
print "1..72\n";
@@ -75,7 +75,11 @@ test ! (eval { $a->VERSION(2.719) }) &&
test (eval { $a->VERSION(2.718) }) && ! $@;
my $subs = join ' ', sort grep { defined &{"UNIVERSAL::$_"} } keys %UNIVERSAL::;
-test $subs eq "VERSION can isa";
+if ('a' lt 'A') {
+ test $subs eq "can isa VERSION";
+} else {
+ test $subs eq "VERSION can isa";
+}
test $a->isa("UNIVERSAL");
@@ -86,7 +90,11 @@ test $a->isa("UNIVERSAL");
my $sub2 = join ' ', sort grep { defined &{"UNIVERSAL::$_"} } keys %UNIVERSAL::;
# XXX import being here is really a bug
-test $sub2 eq "VERSION can import isa";
+if ('a' lt 'A') {
+ test $sub2 eq "can import isa VERSION";
+} else {
+ test $sub2 eq "VERSION can import isa";
+}
eval 'sub UNIVERSAL::sleep {}';
test $a->can("sleep");
diff --git a/t/op/write.t b/t/op/write.t
index 705fa7977b..9918b2f57f 100755
--- a/t/op/write.t
+++ b/t/op/write.t
@@ -2,7 +2,7 @@
# $RCSfile: write.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:38 $
-print "1..5\n";
+print "1..6\n";
my $CAT = ($^O eq 'MSWin32') ? 'type' : 'cat';
@@ -167,3 +167,26 @@ for (0..10) {
print $was1 eq $mustbe ? "ok 4\n" : "not ok 4\n";
print $was2 eq $mustbe ? "ok 5\n" : "not ok 5\n";
+$^A = '';
+
+# more test
+
+format OUT3 =
+^<<<<<<...
+$foo
+.
+
+open(OUT3, '>Op_write.tmp') || die "Can't create Op_write.tmp";
+
+$foo = 'fit ';
+write(OUT3);
+close OUT3;
+
+$right =
+"fit\n";
+
+if (`$CAT Op_write.tmp` eq $right)
+ { print "ok 6\n"; unlink 'Op_write.tmp'; }
+else
+ { print "not ok 6\n"; }
+
diff --git a/t/pod/emptycmd.t b/t/pod/emptycmd.t
new file mode 100755
index 0000000000..59e395ea04
--- /dev/null
+++ b/t/pod/emptycmd.t
@@ -0,0 +1,21 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testp2pt.pl";
+ import TestPodIncPlainText;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodplaintext \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+__END__
+
+=pod
+
+= this is a test
+of the emergency
+broadcast system
+
+=cut
diff --git a/t/pod/emptycmd.xr b/t/pod/emptycmd.xr
new file mode 100644
index 0000000000..f06d2dbb09
--- /dev/null
+++ b/t/pod/emptycmd.xr
@@ -0,0 +1,2 @@
+ = this is a test of the emergency broadcast system
+
diff --git a/t/pod/for.t b/t/pod/for.t
new file mode 100755
index 0000000000..44af44f17d
--- /dev/null
+++ b/t/pod/for.t
@@ -0,0 +1,59 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testp2pt.pl";
+ import TestPodIncPlainText;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodplaintext \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+
+__END__
+
+
+=pod
+
+This is a test
+
+=for theloveofpete
+You shouldn't see this
+or this
+or this
+
+=for text
+pod2text should see this
+and this
+and this
+
+and everything should see this!
+
+=begin text
+
+Similarly, this line ...
+
+and this one ...
+
+as well this one,
+
+should all be in pod2text output
+
+=end text
+
+Tweedley-deedley-dee, Im as happy as can be!
+Tweedley-deedley-dum, cuz youre my honey sugar plum!
+
+=begin atthebeginning
+
+But I expect to see neither hide ...
+
+nor tail ...
+
+of this text
+
+=end atthebeginning
+
+The rest of this should show up in everything.
+
diff --git a/t/pod/for.xr b/t/pod/for.xr
new file mode 100644
index 0000000000..25794ab0fe
--- /dev/null
+++ b/t/pod/for.xr
@@ -0,0 +1,19 @@
+ This is a test
+
+ pod2text should see this and this and this
+
+ and everything should see this!
+
+ Similarly, this line ...
+
+ and this one ...
+
+ as well this one,
+
+ should all be in pod2text output
+
+ Tweedley-deedley-dee, Im as happy as can be! Tweedley-deedley-
+ dum, cuz youre my honey sugar plum!
+
+ The rest of this should show up in everything.
+
diff --git a/t/pod/headings.t b/t/pod/headings.t
new file mode 100755
index 0000000000..78608d0fd9
--- /dev/null
+++ b/t/pod/headings.t
@@ -0,0 +1,140 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testp2pt.pl";
+ import TestPodIncPlainText;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodplaintext \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+
+__END__
+
+
+#################################################################
+ use Pod::Usage;
+ pod2usage( VERBOSE => 2, EXIT => 1 );
+
+=pod
+
+=head1 NAME
+
+B<rdb2pg> - insert an rdb table into a PostgreSQL database
+
+=head1 SYNOPSIS
+
+B<rdb2pg> [I<param>=I<value> ...]
+
+=head1 PARAMETERS
+
+B<rdb2pg> uses an IRAF-compatible parameter interface.
+A template parameter file is in F</proj/axaf/simul/lib/uparm/rdb2pg.par>.
+
+=over 4
+
+=item B<input> I<file>
+
+The B<RDB> file to insert into the database. If the given name
+is the string C<stdin>, it reads from the UNIX standard input stream.
+
+
+=back
+
+=head1 DESCRIPTION
+
+B<rdb2pg> will enter the data from an B<RDB> database into a
+PostgreSQL database table, optionally creating the database and the
+table if they do not exist. It automatically determines the
+PostgreSQL data type from the column definition in the B<RDB> file,
+but may be overriden via a series of definition files or directly
+via one of its parameters.
+
+The target database and table are specified by the C<db> and C<table>
+parameters. If they do not exist, and the C<createdb> parameter is
+set, they will be created. Table field definitions are determined
+in the following order:
+
+=cut
+
+#################################################################
+
+results in:
+
+
+#################################################################
+
+ rdb2pg - insert an rdb table into a PostgreSQL database
+
+ rdb2pg [*param*=*value* ...]
+
+ rdb2pg uses an IRAF-compatible parameter interface. A template
+ parameter file is in /proj/axaf/simul/lib/uparm/rdb2pg.par.
+
+ The RDB file to insert into the database. If the given name is
+ the string `stdin', it reads from the UNIX standard input
+ stream.
+
+ rdb2pg will enter the data from an RDB database into a
+ PostgreSQL database table, optionally creating the database and
+ the table if they do not exist. It automatically determines the
+ PostgreSQL data type from the column definition in the RDB file,
+ but may be overriden via a series of definition files or
+ directly via one of its parameters.
+
+ The target database and table are specified by the `db' and
+ `table' parameters. If they do not exist, and the `createdb'
+ parameter is set, they will be created. Table field definitions
+ are determined in the following order:
+
+
+#################################################################
+
+while the original version of Text (using pod2text) gives
+
+#################################################################
+
+NAME
+ rdb2pg - insert an rdb table into a PostgreSQL database
+
+SYNOPSIS
+ rdb2pg [*param*=*value* ...]
+
+PARAMETERS
+ rdb2pg uses an IRAF-compatible parameter interface. A template
+ parameter file is in /proj/axaf/simul/lib/uparm/rdb2pg.par.
+
+ input *file*
+ The RDB file to insert into the database. If the given name
+ is the string `stdin', it reads from the UNIX standard input
+ stream.
+
+DESCRIPTION
+ rdb2pg will enter the data from an RDB database into a
+ PostgreSQL database table, optionally creating the database and
+ the table if they do not exist. It automatically determines the
+ PostgreSQL data type from the column definition in the RDB file,
+ but may be overriden via a series of definition files or
+ directly via one of its parameters.
+
+ The target database and table are specified by the `db' and
+ `table' parameters. If they do not exist, and the `createdb'
+ parameter is set, they will be created. Table field definitions
+ are determined in the following order:
+
+
+#################################################################
+
+
+Thanks for any help. If, as your email indicates, you've not much
+time to look at this, I can work around things by calling pod2text()
+directly using the official Text.pm.
+
+Diab
+
+-------------
+Diab Jerius
+djerius@cfa.harvard.edu
+
diff --git a/t/pod/headings.xr b/t/pod/headings.xr
new file mode 100644
index 0000000000..e1277b7e37
--- /dev/null
+++ b/t/pod/headings.xr
@@ -0,0 +1,29 @@
+NAME
+ rdb2pg - insert an rdb table into a PostgreSQL database
+
+SYNOPSIS
+ rdb2pg [*param*=*value* ...]
+
+PARAMETERS
+ rdb2pg uses an IRAF-compatible parameter interface. A template
+ parameter file is in /proj/axaf/simul/lib/uparm/rdb2pg.par.
+
+ input *file*
+ The RDB file to insert into the database. If the given name
+ is the string `stdin', it reads from the UNIX standard input
+ stream.
+
+
+DESCRIPTION
+ rdb2pg will enter the data from an RDB database into a
+ PostgreSQL database table, optionally creating the database and
+ the table if they do not exist. It automatically determines the
+ PostgreSQL data type from the column definition in the RDB file,
+ but may be overriden via a series of definition files or
+ directly via one of its parameters.
+
+ The target database and table are specified by the `db' and
+ `table' parameters. If they do not exist, and the `createdb'
+ parameter is set, they will be created. Table field definitions
+ are determined in the following order:
+
diff --git a/t/pod/include.t b/t/pod/include.t
new file mode 100755
index 0000000000..4e73b78356
--- /dev/null
+++ b/t/pod/include.t
@@ -0,0 +1,36 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testp2pt.pl";
+ import TestPodIncPlainText;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodplaintext \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+
+__END__
+
+
+=pod
+
+This file tries to demonstrate a simple =include directive
+for pods. It is used as follows:
+
+ =include filename
+
+where "filename" is expected to be an absolute pathname, or else
+reside be relative to the directory in which the current processed
+podfile resides, or be relative to the current directory.
+
+Lets try it out with the file "included.t" shall we.
+
+***THIS TEXT IS IMMEDIATELY BEFORE THE INCLUDE***
+
+=include included.t
+
+***THIS TEXT IS IMMEDIATELY AFTER THE INCLUDE***
+
+So how did we do???
diff --git a/t/pod/include.xr b/t/pod/include.xr
new file mode 100644
index 0000000000..1bac06adb1
--- /dev/null
+++ b/t/pod/include.xr
@@ -0,0 +1,23 @@
+ This file tries to demonstrate a simple =include directive for
+ pods. It is used as follows:
+
+ =include filename
+
+ where "filename" is expected to be an absolute pathname, or else
+ reside be relative to the directory in which the current
+ processed podfile resides, or be relative to the current
+ directory.
+
+ Lets try it out with the file "included.t" shall we.
+
+ ***THIS TEXT IS IMMEDIATELY BEFORE THE INCLUDE***
+
+###### begin =include included.t #####
+ This is the text of the included file named "included.t". It
+ should appear in the final pod document from pod2xxx
+
+###### end =include included.t #####
+ ***THIS TEXT IS IMMEDIATELY AFTER THE INCLUDE***
+
+ So how did we do???
+
diff --git a/t/pod/included.t b/t/pod/included.t
new file mode 100755
index 0000000000..4f171c454b
--- /dev/null
+++ b/t/pod/included.t
@@ -0,0 +1,35 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testp2pt.pl";
+ import TestPodIncPlainText;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodplaintext \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+
+__END__
+
+
+##------------------------------------------------------------
+# This file is =included by "include.t"
+#
+# This text should NOT be in the resultant pod document
+# because we havent seen an =xxx pod directive in this file!
+##------------------------------------------------------------
+
+=pod
+
+This is the text of the included file named "included.t".
+It should appear in the final pod document from pod2xxx
+
+=cut
+
+##------------------------------------------------------------
+# This text should NOT be in the resultant pod document
+# because it is *after* an =cut an no other pod directives
+# proceed it!
+##------------------------------------------------------------
diff --git a/t/pod/included.xr b/t/pod/included.xr
new file mode 100644
index 0000000000..f0bc03bf09
--- /dev/null
+++ b/t/pod/included.xr
@@ -0,0 +1,3 @@
+ This is the text of the included file named "included.t". It
+ should appear in the final pod document from pod2xxx
+
diff --git a/t/pod/lref.t b/t/pod/lref.t
new file mode 100755
index 0000000000..02e2c9e307
--- /dev/null
+++ b/t/pod/lref.t
@@ -0,0 +1,66 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testp2pt.pl";
+ import TestPodIncPlainText;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodplaintext \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+
+__END__
+
+
+=pod
+
+Try out I<LOTS> of different ways of specifying references:
+
+Reference the L<manpage/section>
+
+Reference the L<manpage / section>
+
+Reference the L<manpage/ section>
+
+Reference the L<manpage /section>
+
+Reference the L<"manpage/section">
+
+Reference the L<"manpage"/section>
+
+Reference the L<manpage/"section">
+
+Reference the L<manpage/
+section>
+
+Reference the L<manpage
+/section>
+
+Now try it using the new "|" stuff ...
+
+Reference the L<thistext|manpage/section>
+
+Reference the L<thistext | manpage / section>
+
+Reference the L<thistext| manpage/ section>
+
+Reference the L<thistext |manpage /section>
+
+Reference the L<thistext|
+"manpage/section">
+
+Reference the L<thistext
+|"manpage"/section>
+
+Reference the L<thistext|manpage/"section">
+
+Reference the L<thistext|
+manpage/
+section>
+
+Reference the L<thistext
+|manpage
+/section>
+
diff --git a/t/pod/lref.xr b/t/pod/lref.xr
new file mode 100644
index 0000000000..d8455e3874
--- /dev/null
+++ b/t/pod/lref.xr
@@ -0,0 +1,40 @@
+ Try out *LOTS* of different ways of specifying references:
+
+ Reference the the "section" entry in the manpage manpage
+
+ Reference the the "section" entry in the manpage manpage
+
+ Reference the the "section" entry in the manpage manpage
+
+ Reference the the "section" entry in the manpage manpage
+
+ Reference the the section on "manpage/section"
+
+ Reference the the "section" entry in the "manpage" manpage
+
+ Reference the the section on "section" in the manpage manpage
+
+ Reference the the "section" entry in the manpage manpage
+
+ Reference the the "section" entry in the manpage manpage
+
+ Now try it using the new "|" stuff ...
+
+ Reference the thistext
+
+ Reference the thistext
+
+ Reference the thistext
+
+ Reference the thistext
+
+ Reference the thistext
+
+ Reference the thistext
+
+ Reference the thistext
+
+ Reference the thistext
+
+ Reference the thistext
+
diff --git a/t/pod/nested_items.t b/t/pod/nested_items.t
new file mode 100755
index 0000000000..c8e9b22427
--- /dev/null
+++ b/t/pod/nested_items.t
@@ -0,0 +1,64 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testp2pt.pl";
+ import TestPodIncPlainText;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodplaintext \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+
+__END__
+
+
+=head1 Test nested item lists
+
+This is a test to ensure the nested =item paragraphs
+get indented appropriately.
+
+=over 2
+
+=item 1
+
+First section.
+
+=over 2
+
+=item a
+
+this is item a
+
+=item b
+
+this is item b
+
+=back
+
+=item 2
+
+Second section.
+
+=over 2
+
+=item a
+
+this is item a
+
+=item b
+
+this is item b
+
+=item c
+
+=item d
+
+This is item c & d.
+
+=back
+
+=back
+
+=cut
diff --git a/t/pod/nested_items.xr b/t/pod/nested_items.xr
new file mode 100644
index 0000000000..7d72bbe890
--- /dev/null
+++ b/t/pod/nested_items.xr
@@ -0,0 +1,19 @@
+Test nested item lists
+ This is a test to ensure the nested =item paragraphs get
+ indented appropriately.
+
+ 1 First section.
+
+ a this is item a
+
+ b this is item b
+
+ 2 Second section.
+
+ a this is item a
+
+ b this is item b
+
+ c
+ d This is item c & d.
+
diff --git a/t/pod/nested_seqs.t b/t/pod/nested_seqs.t
new file mode 100755
index 0000000000..8559f1f25f
--- /dev/null
+++ b/t/pod/nested_seqs.t
@@ -0,0 +1,23 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testp2pt.pl";
+ import TestPodIncPlainText;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodplaintext \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+
+__END__
+
+
+=pod
+
+The statement: C<This is dog kind's I<finest> hour!> is a parody of a
+quotation from Winston Churchill.
+
+=cut
+
diff --git a/t/pod/nested_seqs.xr b/t/pod/nested_seqs.xr
new file mode 100644
index 0000000000..5a008c17e9
--- /dev/null
+++ b/t/pod/nested_seqs.xr
@@ -0,0 +1,3 @@
+ The statement: `This is dog kind's *finest* hour!' is a parody
+ of a quotation from Winston Churchill.
+
diff --git a/t/pod/oneline_cmds.t b/t/pod/oneline_cmds.t
new file mode 100755
index 0000000000..28bd1d09e5
--- /dev/null
+++ b/t/pod/oneline_cmds.t
@@ -0,0 +1,46 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testp2pt.pl";
+ import TestPodIncPlainText;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodplaintext \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+
+__END__
+
+
+==head1 NAME
+B<rdb2pg> - insert an rdb table into a PostgreSQL database
+
+==head1 SYNOPSIS
+B<rdb2pg> [I<param>=I<value> ...]
+
+==head1 PARAMETERS
+B<rdb2pg> uses an IRAF-compatible parameter interface.
+A template parameter file is in F</proj/axaf/simul/lib/uparm/rdb2pg.par>.
+
+==over 4
+==item B<input> I<file>
+The B<RDB> file to insert into the database. If the given name
+is the string C<stdin>, it reads from the UNIX standard input stream.
+
+==back
+
+==head1 DESCRIPTION
+B<rdb2pg> will enter the data from an B<RDB> database into a
+PostgreSQL database table, optionally creating the database and the
+table if they do not exist. It automatically determines the
+PostgreSQL data type from the column definition in the B<RDB> file,
+but may be overriden via a series of definition files or directly
+via one of its parameters.
+
+The target database and table are specified by the C<db> and C<table>
+parameters. If they do not exist, and the C<createdb> parameter is
+set, they will be created. Table field definitions are determined
+in the following order:
+
diff --git a/t/pod/oneline_cmds.xr b/t/pod/oneline_cmds.xr
new file mode 100644
index 0000000000..e1277b7e37
--- /dev/null
+++ b/t/pod/oneline_cmds.xr
@@ -0,0 +1,29 @@
+NAME
+ rdb2pg - insert an rdb table into a PostgreSQL database
+
+SYNOPSIS
+ rdb2pg [*param*=*value* ...]
+
+PARAMETERS
+ rdb2pg uses an IRAF-compatible parameter interface. A template
+ parameter file is in /proj/axaf/simul/lib/uparm/rdb2pg.par.
+
+ input *file*
+ The RDB file to insert into the database. If the given name
+ is the string `stdin', it reads from the UNIX standard input
+ stream.
+
+
+DESCRIPTION
+ rdb2pg will enter the data from an RDB database into a
+ PostgreSQL database table, optionally creating the database and
+ the table if they do not exist. It automatically determines the
+ PostgreSQL data type from the column definition in the RDB file,
+ but may be overriden via a series of definition files or
+ directly via one of its parameters.
+
+ The target database and table are specified by the `db' and
+ `table' parameters. If they do not exist, and the `createdb'
+ parameter is set, they will be created. Table field definitions
+ are determined in the following order:
+
diff --git a/t/pod/poderrs.t b/t/pod/poderrs.t
new file mode 100755
index 0000000000..591bd2a86d
--- /dev/null
+++ b/t/pod/poderrs.t
@@ -0,0 +1,39 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testpchk.pl";
+ import TestPodChecker;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodchecker \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+
+__END__
+
+
+=head1 NAME
+
+poderrors.t - test Pod::Checker on some pod syntax errors
+
+=unknown1 this is an unknown command with two N<unknownA>
+and D<unknownB> interior sequences.
+
+This is some paragraph text with some unknown interior sequences,
+such as Q<unknown2>,
+A<unknown3>,
+and Y<unknown4 V<unknown5>>.
+
+Now try some unterminated sequences like
+I<hello mudda!
+B<hello fadda!
+
+Here I am at C<camp granada!
+
+Camps is very,
+entertaining.
+And they say we'll have some fun if it stops raining!
+
+=cut
diff --git a/t/pod/poderrs.xr b/t/pod/poderrs.xr
new file mode 100644
index 0000000000..a7bc42d956
--- /dev/null
+++ b/t/pod/poderrs.xr
@@ -0,0 +1,11 @@
+*** ERROR: Unknown command "unknown1" at line 21 of file t/poderrs.t
+*** ERROR: Unknown interior-sequence "N" at line 21 of file t/poderrs.t
+*** ERROR: Unknown interior-sequence "D" at line 22 of file t/poderrs.t
+*** ERROR: Unknown interior-sequence "Q" at line 25 of file t/poderrs.t
+*** ERROR: Unknown interior-sequence "A" at line 26 of file t/poderrs.t
+*** ERROR: Unknown interior-sequence "V" at line 27 of file t/poderrs.t
+*** ERROR: Unknown interior-sequence "Y" at line 27 of file t/poderrs.t
+** Unterminated B<...> at t/poderrs.t line 31
+** Unterminated I<...> at t/poderrs.t line 30
+** Unterminated C<...> at t/poderrs.t line 33
+t/poderrs.t has 10 pod syntax errors.
diff --git a/t/pod/special_seqs.t b/t/pod/special_seqs.t
new file mode 100755
index 0000000000..1b31387dd3
--- /dev/null
+++ b/t/pod/special_seqs.t
@@ -0,0 +1,32 @@
+BEGIN {
+ use File::Basename;
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testp2pt.pl";
+ import TestPodIncPlainText;
+}
+
+my %options = map { $_ => 1 } @ARGV; ## convert cmdline to options-hash
+my $passed = testpodplaintext \%options, $0;
+exit( ($passed == 1) ? 0 : -1 ) unless $ENV{HARNESS_ACTIVE};
+
+
+__END__
+
+
+=pod
+
+This is a test to see if I can do not only C<$self> and C<method()>, but
+also C<$self->method()> and C<$self->{FIELDNAME}> and C<{FOO=>BAR}> without
+resorting to escape sequences.
+
+Now for the grand finale of C<$self->method()->{FIELDNAME} = {FOO=>BAR}>.
+
+Of course I should still be able to do all this I<with> escape sequences
+too: C<$self-E<gt>method()> and C<$self-E<gt>{FIELDNAME}> and C<{FOO=E<gt>BAR}>.
+
+Dont forget C<$self-E<gt>method()-E<gt>{FIELDNAME} = {FOO=E<gt>BAR}>.
+
+And make sure that C<0> works too!
+
+=cut
diff --git a/t/pod/special_seqs.xr b/t/pod/special_seqs.xr
new file mode 100644
index 0000000000..6795de0490
--- /dev/null
+++ b/t/pod/special_seqs.xr
@@ -0,0 +1,15 @@
+ This is a test to see if I can do not only `$self' and
+ `method()', but also `$self->method()' and `$self->{FIELDNAME}'
+ and `{FOO=>BAR}' without resorting to escape sequences.
+
+ Now for the grand finale of `$self->method()->{FIELDNAME} =
+ {FOO=>BAR}'.
+
+ Of course I should still be able to do all this *with* escape
+ sequences too: `$self->method()' and `$self->{FIELDNAME}' and
+ `{FOO=>BAR}'.
+
+ Dont forget `$self->method()->{FIELDNAME} = {FOO=>BAR}'.
+
+ And make sure that `0' works too!
+
diff --git a/t/pod/testcmp.pl b/t/pod/testcmp.pl
new file mode 100644
index 0000000000..d61bbff3a2
--- /dev/null
+++ b/t/pod/testcmp.pl
@@ -0,0 +1,90 @@
+package TestCompare;
+
+use vars qw(@ISA @EXPORT $MYPKG);
+#use strict;
+#use diagnostics;
+use Carp;
+use Exporter;
+use File::Basename;
+use File::Spec;
+
+@ISA = qw(Exporter);
+@EXPORT = qw(&testcmp);
+$MYPKG = eval { (caller)[0] };
+
+##--------------------------------------------------------------------------
+
+=head1 NAME
+
+testcmp -- compare two files line-by-line
+
+=head1 SYNOPSIS
+
+ $is_diff = testcmp($file1, $file2);
+
+or
+
+ $is_diff = testcmp({-cmplines => \&mycmp}, $file1, $file2);
+
+=head2 DESCRIPTION
+
+Compare two text files line-by-line and return 0 if they are the
+same, 1 if they differ. Each of $file1 and $file2 may be a filenames,
+or a filehandles (in which case it must already be open for reading).
+
+If the first argument is a hashref, then the B<-cmplines> key in the
+hash may have a subroutine reference as its corresponding value.
+The referenced user-defined subroutine should be a line-comparator
+function that takes two pre-chomped text-lines as its arguments
+(the first is from $file1 and the second is from $file2). It should
+return 0 if it considers the two lines equivalent, and non-zero
+otherwise.
+
+=cut
+
+##--------------------------------------------------------------------------
+
+sub testcmp( $ $ ; $) {
+ my %opts = ref($_[0]) eq 'HASH' ? %{shift()} : ();
+ my ($file1, $file2) = @_;
+ my ($fh1, $fh2) = ($file1, $file2);
+ unless (ref $fh1) {
+ $fh1 = FileHandle->new($file1, "r") or die "Can't open $file1: $!";
+ }
+ unless (ref $fh2) {
+ $fh2 = FileHandle->new($file2, "r") or die "Can't open $file2: $!";
+ }
+
+ my $cmplines = $opts{'-cmplines'} || undef;
+ my ($f1text, $f2text) = ("", "");
+ my ($line, $diffs) = (0, 0);
+
+ while ( defined($f1text) and defined($f2text) ) {
+ defined($f1text = <$fh1>) and chomp($f1text);
+ defined($f2text = <$fh2>) and chomp($f2text);
+ ++$line;
+ last unless ( defined($f1text) and defined($f2text) );
+ $diffs = (ref $cmplines) ? &$cmplines($f1text, $f2text)
+ : ($f1text ne $f2text);
+ last if $diffs;
+ }
+ close($fh1) unless (ref $file1);
+ close($fh2) unless (ref $file2);
+
+ $diffs = 1 if (defined($f1text) or defined($f2text));
+ if ( defined($f1text) and defined($f2text) ) {
+ ## these two lines must be different
+ warn "$file1 and $file2 differ at line $line\n";
+ }
+ elsif (defined($f1text) and (! defined($f1text))) {
+ ## file1 must be shorter
+ warn "$file1 is shorter than $file2\n";
+ }
+ elsif (defined $f2text) {
+ ## file2 must be longer
+ warn "$file1 is shorter than $file2\n";
+ }
+ return $diffs;
+}
+
+1;
diff --git a/t/pod/testp2pt.pl b/t/pod/testp2pt.pl
new file mode 100644
index 0000000000..9df5b9f2ed
--- /dev/null
+++ b/t/pod/testp2pt.pl
@@ -0,0 +1,178 @@
+package TestPodIncPlainText;
+
+BEGIN {
+ use File::Basename;
+ use File::Spec;
+ use Cwd qw(abs_path);
+ push @INC, '..';
+ my $THISDIR = abs_path(dirname $0);
+ unshift @INC, $THISDIR;
+ require "testcmp.pl";
+ import TestCompare;
+ my $PARENTDIR = dirname $THISDIR;
+ push @INC, map { File::Spec->catfile($_, 'lib') } ($PARENTDIR, $THISDIR);
+}
+
+use Pod::PlainText;
+use vars qw(@ISA @EXPORT $MYPKG);
+#use strict;
+#use diagnostics;
+use Carp;
+use Exporter;
+#use File::Compare;
+#use Cwd qw(abs_path);
+
+@ISA = qw(Pod::PlainText);
+@EXPORT = qw(&testpodplaintext);
+$MYPKG = eval { (caller)[0] };
+
+## Hardcode settings for TERMCAP and COLUMNS so we can try to get
+## reproducible results between environments
+@ENV{qw(TERMCAP COLUMNS)} = ('co=72:do=^J', 72);
+
+sub catfile(@) { File::Spec->catfile(@_); }
+
+my $INSTDIR = abs_path(dirname $0);
+$INSTDIR = (dirname $INSTDIR) if (basename($INSTDIR) eq 'xtra');
+$INSTDIR = (dirname $INSTDIR) if (basename($INSTDIR) eq 'pod');
+$INSTDIR = (dirname $INSTDIR) if (basename($INSTDIR) eq 't');
+my @PODINCDIRS = ( catfile($INSTDIR, 'lib', 'Pod'),
+ catfile($INSTDIR, 'scripts'),
+ catfile($INSTDIR, 't', 'pod'),
+ catfile($INSTDIR, 't', 'pod', 'xtra')
+ );
+
+## Find the path to the file to =include
+sub findinclude {
+ my $self = shift;
+ my $incname = shift;
+
+ ## See if its already found w/out any "searching;
+ return $incname if (-r $incname);
+
+ ## Need to search for it. Look in the following directories ...
+ ## 1. the directory containing this pod file
+ my $thispoddir = dirname $self->input_file;
+ ## 2. the parent directory of the above
+ my $parentdir = dirname $thispoddir;
+ my @podincdirs = ($thispoddir, $parentdir, @PODINCDIRS);
+
+ for (@podincdirs) {
+ my $incfile = catfile($_, $incname);
+ return $incfile if (-r $incfile);
+ }
+ warn("*** Can't find =include file $incname in @podincdirs\n");
+ return "";
+}
+
+sub command {
+ my $self = shift;
+ my ($cmd, $text, $line_num, $pod_para) = @_;
+ $cmd = '' unless (defined $cmd);
+ local $_ = $text || '';
+ my $out_fh = $self->output_handle;
+
+ ## Defer to the superclass for everything except '=include'
+ return $self->SUPER::command(@_) unless ($cmd eq "include");
+
+ ## We have an '=include' command
+ my $incdebug = 1; ## debugging
+ my @incargs = split;
+ if (@incargs == 0) {
+ warn("*** No filename given for '=include'\n");
+ return;
+ }
+ my $incfile = $self->findinclude(shift @incargs) or return;
+ my $incbase = basename $incfile;
+ print $out_fh "###### begin =include $incbase #####\n" if ($incdebug);
+ $self->parse_from_file( {-cutting => 1}, $incfile );
+ print $out_fh "###### end =include $incbase #####\n" if ($incdebug);
+}
+
+sub podinc2plaintext( $ $ ) {
+ my ($infile, $outfile) = @_;
+ local $_;
+ my $text_parser = $MYPKG->new;
+ $text_parser->parse_from_file($infile, $outfile);
+}
+
+sub testpodinc2plaintext( @ ) {
+ my %args = @_;
+ my $infile = $args{'-In'} || croak "No input file given!";
+ my $outfile = $args{'-Out'} || croak "No output file given!";
+ my $cmpfile = $args{'-Cmp'} || croak "No compare-result file given!";
+
+ my $different = '';
+ my $testname = basename $cmpfile, '.t', '.xr';
+
+ unless (-e $cmpfile) {
+ my $msg = "*** Can't find comparison file $cmpfile for testing $infile";
+ warn "$msg\n";
+ return $msg;
+ }
+
+ print "+ Running testpodinc2plaintext for '$testname'...\n";
+ ## Compare the output against the expected result
+ podinc2plaintext($infile, $outfile);
+ if ( testcmp($outfile, $cmpfile) ) {
+ $different = "$outfile is different from $cmpfile";
+ }
+ else {
+ unlink($outfile);
+ }
+ return $different;
+}
+
+sub testpodplaintext( @ ) {
+ my %opts = (ref $_[0] eq 'HASH') ? %{shift()} : ();
+ my @testpods = @_;
+ my ($testname, $testdir) = ("", "");
+ my ($podfile, $cmpfile) = ("", "");
+ my ($outfile, $errfile) = ("", "");
+ my $passes = 0;
+ my $failed = 0;
+ local $_;
+
+ print "1..", scalar @testpods, "\n" unless ($opts{'-xrgen'});
+
+ for $podfile (@testpods) {
+ ($testname, $_) = fileparse($podfile);
+ $testdir ||= $_;
+ $testname =~ s/\.t$//;
+ $cmpfile = $testdir . $testname . '.xr';
+ $outfile = $testdir . $testname . '.OUT';
+
+ if ($opts{'-xrgen'}) {
+ if ($opts{'-force'} or ! -e $cmpfile) {
+ ## Create the comparison file
+ print "+ Creating expected result for \"$testname\"" .
+ " pod2plaintext test ...\n";
+ podinc2plaintext($podfile, $cmpfile);
+ }
+ else {
+ print "+ File $cmpfile already exists" .
+ " (use '-force' to regenerate it).\n";
+ }
+ next;
+ }
+
+ my $failmsg = testpodinc2plaintext
+ -In => $podfile,
+ -Out => $outfile,
+ -Cmp => $cmpfile;
+ if ($failmsg) {
+ ++$failed;
+ print "+\tFAILED. ($failmsg)\n";
+ print "not ok ", $failed+$passes, "\n";
+ }
+ else {
+ ++$passes;
+ unlink($outfile);
+ print "+\tPASSED.\n";
+ print "ok ", $failed+$passes, "\n";
+ }
+ }
+ return $passes;
+}
+
+1;
diff --git a/t/pod/testpchk.pl b/t/pod/testpchk.pl
new file mode 100644
index 0000000000..cd3c13816d
--- /dev/null
+++ b/t/pod/testpchk.pl
@@ -0,0 +1,129 @@
+package TestPodChecker;
+
+BEGIN {
+ use File::Basename;
+ use File::Spec;
+ push @INC, '..';
+ my $THISDIR = dirname $0;
+ unshift @INC, $THISDIR;
+ require "testcmp.pl";
+ import TestCompare;
+ my $PARENTDIR = dirname $THISDIR;
+ push @INC, map { File::Spec->catfile($_, 'lib') } ($PARENTDIR, $THISDIR);
+}
+
+use Pod::Checker;
+use vars qw(@ISA @EXPORT $MYPKG);
+#use strict;
+#use diagnostics;
+use Carp;
+use Exporter;
+#use File::Compare;
+
+@ISA = qw(Exporter);
+@EXPORT = qw(&testpodchecker);
+$MYPKG = eval { (caller)[0] };
+
+sub stripname( $ ) {
+ local $_ = shift;
+ return /(\w[.\w]*)\s*$/ ? $1 : $_;
+}
+
+sub msgcmp( $ $ ) {
+ ## filter out platform-dependent aspects of error messages
+ my ($line1, $line2) = @_;
+ for ($line1, $line2) {
+ if ( /^#*\s*(\S.*?)\s+(?:has \d+\s*)?pod syntax (?:error|OK)/ ) {
+ my $fname = $1;
+ s/^#*\s*// if ($^O eq 'MacOS');
+ s/^\s*\Q$fname\E/stripname($fname)/e;
+ }
+ elsif ( /^#*\s*\*+\s*(?:ERROR|Unterminated)/ ) {
+ s/^#*\s*// if ($^O eq 'MacOS');
+ s/of file\s+(\S.*?)\s*$/"of file ".stripname($1)/e;
+ s/at\s+(\S.*?)\s+line/"at ".stripname($1)." line"/e;
+ }
+ }
+ return $line1 ne $line2;
+}
+
+sub testpodcheck( @ ) {
+ my %args = @_;
+ my $infile = $args{'-In'} || croak "No input file given!";
+ my $outfile = $args{'-Out'} || croak "No output file given!";
+ my $cmpfile = $args{'-Cmp'} || croak "No compare-result file given!";
+
+ my $different = '';
+ my $testname = basename $cmpfile, '.t', '.xr';
+
+ unless (-e $cmpfile) {
+ my $msg = "*** Can't find comparison file $cmpfile for testing $infile";
+ warn "$msg\n";
+ return $msg;
+ }
+
+ print "+ Running podchecker for '$testname'...\n";
+ ## Compare the output against the expected result
+ podchecker($infile, $outfile);
+ if ( testcmp({'-cmplines' => \&msgcmp}, $outfile, $cmpfile) ) {
+ $different = "$outfile is different from $cmpfile";
+ }
+ else {
+ unlink($outfile);
+ }
+ return $different;
+}
+
+sub testpodchecker( @ ) {
+ my %opts = (ref $_[0] eq 'HASH') ? %{shift()} : ();
+ my @testpods = @_;
+ my ($testname, $testdir) = ("", "");
+ my ($podfile, $cmpfile) = ("", "");
+ my ($outfile, $errfile) = ("", "");
+ my $passes = 0;
+ my $failed = 0;
+ local $_;
+
+ print "1..", scalar @testpods, "\n" unless ($opts{'-xrgen'});
+
+ for $podfile (@testpods) {
+ ($testname, $_) = fileparse($podfile);
+ $testdir ||= $_;
+ $testname =~ s/\.t$//;
+ $cmpfile = $testdir . $testname . '.xr';
+ $outfile = $testdir . $testname . '.OUT';
+
+ if ($opts{'-xrgen'}) {
+ if ($opts{'-force'} or ! -e $cmpfile) {
+ ## Create the comparison file
+ print "+ Creating expected result for \"$testname\"" .
+ " podchecker test ...\n";
+ podchecker($podfile, $cmpfile);
+ }
+ else {
+ print "+ File $cmpfile already exists" .
+ " (use '-force' to regenerate it).\n";
+ }
+ next;
+ }
+
+ my $failmsg = testpodcheck
+ -In => $podfile,
+ -Out => $outfile,
+ -Cmp => $cmpfile;
+ if ($failmsg) {
+ ++$failed;
+ print "+\tFAILED. ($failmsg)\n";
+ print "not ok ", $failed+$passes, "\n";
+ }
+ else {
+ ++$passes;
+ unlink($outfile);
+ print "+\tPASSED.\n";
+ print "ok ", $failed+$passes, "\n";
+ }
+ }
+ return $passes;
+}
+
+1;
diff --git a/t/pragma/constant.t b/t/pragma/constant.t
index 0095f3b627..15ce319c02 100755
--- a/t/pragma/constant.t
+++ b/t/pragma/constant.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib' if -d '../lib';
+ unshift @INC, '../lib' if -d '../lib';
}
BEGIN {$^W |= 1} # Insist upon warnings
@@ -14,7 +14,7 @@ END { print @warnings }
######################### We start with some black magic to print on failure.
-BEGIN { $| = 1; print "1..39\n"; }
+BEGIN { $| = 1; print "1..46\n"; }
END {print "not ok 1\n" unless $loaded;}
use constant;
$loaded = 1;
@@ -81,7 +81,7 @@ test 18, (COUNTLIST)[1] == 4;
use constant ABC => 'ABC';
test 19, "abc${\( ABC )}abc" eq "abcABCabc";
-use constant DEF => 'D', "\x45", chr 70;
+use constant DEF => 'D', 'E', chr ord 'F';
test 20, "d e f @{[ DEF ]} d e f" eq "d e f D E F d e f";
use constant SINGLE => "'";
@@ -139,3 +139,19 @@ test 37, @warnings &&
test 38, @warnings == 0, "unexpected warning";
test 39, $^W & 1, "Who disabled the warnings?";
+
+use constant CSCALAR => \"ok 40\n";
+use constant CHASH => { foo => "ok 41\n" };
+use constant CARRAY => [ undef, "ok 42\n" ];
+use constant CPHASH => [ { foo => 1 }, "ok 43\n" ];
+use constant CCODE => sub { "ok $_[0]\n" };
+
+print ${+CSCALAR};
+print CHASH->{foo};
+print CARRAY->[1];
+print CPHASH->{foo};
+eval q{ CPHASH->{bar} };
+test 44, scalar($@ =~ /^No such array/);
+print CCODE->(45);
+eval q{ CCODE->{foo} };
+test 46, scalar($@ =~ /^Constant is not a HASH/);
diff --git a/t/pragma/locale.t b/t/pragma/locale.t
index 00baa6645e..82adcf3fb8 100755
--- a/t/pragma/locale.t
+++ b/t/pragma/locale.t
@@ -2,7 +2,8 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
+ unshift @INC, '.';
require Config; import Config;
if (!$Config{d_setlocale} || $Config{ccflags} =~ /\bD?NO_LOCALE\b/) {
print "1..0\n";
@@ -12,6 +13,16 @@ BEGIN {
use strict;
+my $debug = 1;
+
+sub debug {
+ print @_ if $debug;
+}
+
+sub debugf {
+ printf @_ if $debug;
+}
+
my $have_setlocale = 0;
eval {
require POSIX;
@@ -23,14 +34,11 @@ eval {
# and mingw32 uses said silly CRT
$have_setlocale = 0 if $^O eq 'MSWin32' && $Config{cc} =~ /^(cl|gcc)/i;
-print "1..", ($have_setlocale ? 102 : 98), "\n";
+print "1..", ($have_setlocale ? 115 : 98), "\n";
-use vars qw($a
- $English $German $French $Spanish
- @C @English @German @French @Spanish
- $Locale @Locale %iLocale %UPPER %lower @Neoalpha);
+use vars qw(&LC_ALL);
-$a = 'abc %';
+my $a = 'abc %';
sub ok {
my ($n, $result) = @_;
@@ -216,268 +224,481 @@ check_taint_not 98, $a;
# I think we've seen quite enough of taint.
# Let us do some *real* locale work now,
-# unless setlocale() is missing (i.e. minitest).
+# unless setlocale() is missing (i.e. minitest).
exit unless $have_setlocale;
-sub getalnum {
+# Find locales.
+
+debug "# Scanning for locales...\n";
+
+# Note that it's okay that some languages have their native names
+# capitalized here even though that's not "right". They are lowercased
+# anyway later during the scanning process (and besides, some clueless
+# vendor might have them capitalized errorneously anyway).
+
+my $locales = <<EOF;
+Afrikaans:af:za:1 15
+Arabic:ar:dz eg sa:6 arabic8
+Brezhoneg Breton:br:fr:1 15
+Bulgarski Bulgarian:bg:bg:5
+Chinese:zh:cn tw:cn.EUC eucCN eucTW euc.CN euc.TW GB2312 tw.EUC
+Hrvatski Croatian:hr:hr:2
+Cymraeg Welsh:cy:cy:1 14 15
+Czech:cs:cz:2
+Dansk Danish:dk:da:1 15
+Nederlands Dutch:nl:be nl:1 15
+English American British:en:au ca gb ie nz us uk:1 15 cp850
+Esperanto:eo:eo:3
+Eesti Estonian:et:ee:4 6 13
+Suomi Finnish:fi:fi:1 15
+Flamish::fl:1 15
+Deutsch German:de:at be ch de lu:1 15
+Euskaraz Basque:eu:es fr:1 15
+Galego Galician:gl:es:1 15
+Ellada Greek:el:gr:7 g8
+Frysk:fy:nl:1 15
+Greenlandic:kl:gl:4 6
+Hebrew:iw:il:8 hebrew8
+Hungarian:hu:hu:2
+Indonesian:in:id:1 15
+Gaeilge Irish:ga:IE:1 14 15
+Italiano Italian:it:ch it:1 15
+Nihongo Japanese:ja:jp:euc eucJP jp.EUC sjis
+Korean:ko:kr:
+Latine Latin:la:va:1 15
+Latvian:lv:lv:4 6 13
+Lithuanian:lt:lt:4 6 13
+Macedonian:mk:mk:1 15
+Maltese:mt:mt:3
+Norsk Norwegian:no:no:1 15
+Occitan:oc:es:1 15
+Polski Polish:pl:pl:2
+Rumanian:ro:ro:2
+Russki Russian:ru:ru su ua:5 koi8 koi8r koi8u cp1251
+Serbski Serbian:sr:yu:5
+Slovak:sk:sk:2
+Slovene Slovenian:sl:si:2
+Sqhip Albanian:sq:sq:1 15
+Svenska Swedish:sv:fi se:1 15
+Thai:th:th:11 tis620
+Turkish:tr:tr:9 turkish8
+Yiddish:::1 15
+EOF
+
+sub in_utf8 () { $^H & 0x08 }
+
+if (in_utf8) {
+ require "pragma/locale/utf8";
+} else {
+ require "pragma/locale/latin1";
+}
+
+my @Locale;
+my $Locale;
+my @Alnum_;
+
+sub getalnum_ {
sort grep /\w/, map { chr } 0..255
}
-sub locatelocale ($$@) {
- my ($lcall, $alnum, @try) = @_;
+sub trylocale {
+ my $locale = shift;
+ if (setlocale(LC_ALL, $locale)) {
+ push @Locale, $locale;
+ }
+}
- undef $$lcall;
+sub decode_encodings {
+ my @enc;
- for (@try) {
- local $^W = 0; # suppress "Subroutine LC_ALL redefined"
- if (setlocale(&LC_ALL, $_)) {
- $$lcall = $_;
- @$alnum = &getalnum;
- last;
+ foreach (split(/ /, shift)) {
+ if (/^(\d+)$/) {
+ push @enc, "ISO8859-$1";
+ push @enc, "iso8859$1"; # HP
+ if ($1 eq '1') {
+ push @enc, "roman8"; # HP
+ }
+ } else {
+ push @enc, $_;
}
}
- @$alnum = () unless (defined $$lcall);
+ return @enc;
}
-# Find some default locale
-
-locatelocale(\$Locale, \@Locale, qw(C POSIX));
-
-# Find some English locale
-
-locatelocale(\$English, \@English,
- qw(en_US.ISO8859-1 en_GB.ISO8859-1
- en en_US en_UK en_IE en_CA en_AU en_NZ
- english english.iso88591
- american american.iso88591
- british british.iso88591
- ));
-
-# Find some German locale
-
-locatelocale(\$German, \@German,
- qw(de_DE.ISO8859-1 de_AT.ISO8859-1 de_CH.ISO8859-1
- de de_DE de_AT de_CH
- german german.iso88591));
-
-# Find some French locale
-
-locatelocale(\$French, \@French,
- qw(fr_FR.ISO8859-1 fr_BE.ISO8859-1 fr_CA.ISO8859-1 fr_CH.ISO8859-1
- fr fr_FR fr_BE fr_CA fr_CH
- french french.iso88591));
-
-# Find some Spanish locale
-
-locatelocale(\$Spanish, \@Spanish,
- qw(es_AR.ISO8859-1 es_BO.ISO8859-1 es_CL.ISO8859-1
- es_CO.ISO8859-1 es_CR.ISO8859-1 es_EC.ISO8859-1
- es_ES.ISO8859-1 es_GT.ISO8859-1 es_MX.ISO8859-1
- es_NI.ISO8859-1 es_PA.ISO8859-1 es_PE.ISO8859-1
- es_PY.ISO8859-1 es_SV.ISO8859-1 es_UY.ISO8859-1 es_VE.ISO8859-1
- es es_AR es_BO es_CL
- es_CO es_CR es_EC
- es_ES es_GT es_MX
- es_NI es_PA es_PE
- es_PY es_SV es_UY es_VE
- spanish spanish.iso88591));
-
-# Select the largest of the alpha(num)bets.
-
-($Locale, @Locale) = ($English, @English)
- if (@English > @Locale);
-($Locale, @Locale) = ($German, @German)
- if (@German > @Locale);
-($Locale, @Locale) = ($French, @French)
- if (@French > @Locale);
-($Locale, @Locale) = ($Spanish, @Spanish)
- if (@Spanish > @Locale);
-
-{
- local $^W = 0;
- setlocale(&LC_ALL, $Locale);
+trylocale("C");
+trylocale("POSIX");
+foreach (0..15) {
+ trylocale("ISO8859-$_");
+ trylocale("iso8859$_");
+ trylocale("iso8859-$_");
+ trylocale("iso_8859_$_");
+ trylocale("isolatin$_");
+ trylocale("isolatin-$_");
+ trylocale("iso_latin_$_");
}
-# Sort it now that LC_ALL has been set.
+foreach my $locale (split(/\n/, $locales)) {
+ my ($locale_name, $language_codes, $country_codes, $encodings) =
+ split(/:/, $locale);
+ my @enc = decode_encodings($encodings);
+ foreach my $loc (split(/ /, $locale_name)) {
+ trylocale($loc);
+ foreach my $enc (@enc) {
+ trylocale("$loc.$enc");
+ }
+ $loc = lc $loc;
+ foreach my $enc (@enc) {
+ trylocale("$loc.$enc");
+ }
+ }
+ foreach my $lang (split(/ /, $language_codes)) {
+ trylocale($lang);
+ foreach my $country (split(/ /, $country_codes)) {
+ my $lc = "${lang}_${country}";
+ trylocale($lc);
+ foreach my $enc (@enc) {
+ trylocale("$lc.$enc");
+ }
+ my $lC = "${lang}_\U${country}";
+ trylocale($lC);
+ foreach my $enc (@enc) {
+ trylocale("$lC.$enc");
+ }
+ }
+ }
+}
+
+setlocale(LC_ALL, "C");
@Locale = sort @Locale;
-print "# Locale = $Locale\n";
-print "# Alnum_ = @Locale\n";
+debug "# Locales = @Locale\n";
+
+my %Problem;
+my %Okay;
+my %Testing;
+my @Neoalpha;
+
+sub tryneoalpha {
+ my ($Locale, $i, $test) = @_;
+ debug "# testing $i with locale '$Locale'\n"
+ unless $Testing{$i}{$Locale}++;
+ unless ($test) {
+ $Problem{$i}{$Locale} = 1;
+ debug "# failed $i with locale '$Locale'\n";
+ } else {
+ push @{$Okay{$i}}, $Locale;
+ }
+}
-{
- my $i = 0;
+foreach $Locale (@Locale) {
+ debug "# Locale = $Locale\n";
+ @Alnum_ = getalnum_();
+ debug "# \\w = @Alnum_\n";
- for (@Locale) {
- $iLocale{$_} = $i++;
+ unless (setlocale(LC_ALL, $Locale)) {
+ foreach (99..103) {
+ $Problem{$_}{$Locale} = -1;
+ }
+ next;
}
-}
-# Sieve the uppercase and the lowercase.
+ # Sieve the uppercase and the lowercase.
+
+ my %UPPER = ();
+ my %lower = ();
+ my %BoThCaSe = ();
+ for (@Alnum_) {
+ if (/[^\d_]/) { # skip digits and the _
+ if (uc($_) eq $_) {
+ $UPPER{$_} = $_;
+ }
+ if (lc($_) eq $_) {
+ $lower{$_} = $_;
+ }
+ }
+ }
+ foreach (keys %UPPER) {
+ $BoThCaSe{$_}++ if exists $lower{$_};
+ }
+ foreach (keys %lower) {
+ $BoThCaSe{$_}++ if exists $UPPER{$_};
+ }
+ foreach (keys %BoThCaSe) {
+ delete $UPPER{$_};
+ delete $lower{$_};
+ }
-for (@Locale) {
- if (/[^\d_]/) { # skip digits and the _
- if (lc eq $_) {
- $UPPER{$_} = uc;
- } else {
- $lower{$_} = lc;
+ debug "# UPPER = ", join(" ", sort keys %UPPER ), "\n";
+ debug "# lower = ", join(" ", sort keys %lower ), "\n";
+ debug "# BoThCaSe = ", join(" ", sort keys %BoThCaSe), "\n";
+
+ # Find the alphabets that are not alphabets in the default locale.
+
+ {
+ no locale;
+
+ @Neoalpha = ();
+ for (keys %UPPER, keys %lower) {
+ push(@Neoalpha, $_) if (/\W/);
}
}
-}
-# Find the alphabets that are not alphabets in the default locale.
+ @Neoalpha = sort @Neoalpha;
-{
- no locale;
+ debug "# Neoalpha = @Neoalpha\n";
+
+ if (@Neoalpha == 0) {
+ # If we have no Neoalphas the remaining tests are no-ops.
+ debug "# no Neoalpha, skipping tests 99..102 for locale '$Locale'\n";
+ foreach (99..102) {
+ push @{$Okay{$_}}, $Locale;
+ }
+ } else {
+
+ # Test \w.
- for (keys %UPPER, keys %lower) {
- push(@Neoalpha, $_) if (/\W/);
+ {
+ my $word = join('', @Neoalpha);
+
+ $word =~ /^(\w+)$/;
+
+ tryneoalpha($Locale, 99, $1 eq $word);
+ }
+
+ # Cross-check the whole 8-bit character set.
+
+ for (map { chr } 0..255) {
+ tryneoalpha($Locale, 100,
+ (/\w/ xor /\W/) ||
+ (/\d/ xor /\D/) ||
+ (/\s/ xor /\S/));
+ }
+
+ # Test for read-only scalars' locale vs non-locale comparisons.
+
+ {
+ no locale;
+ $a = "qwerty";
+ {
+ use locale;
+ tryneoalpha($Locale, 101, ($a cmp "qwerty") == 0);
+ }
+ }
+
+ {
+ my ($from, $to, $lesser, $greater,
+ @test, %test, $test, $yes, $no, $sign);
+
+ for (0..9) {
+ # Select a slice.
+ $from = int(($_*@Alnum_)/10);
+ $to = $from + int(@Alnum_/10);
+ $to = $#Alnum_ if ($to > $#Alnum_);
+ $lesser = join('', @Alnum_[$from..$to]);
+ # Select a slice one character on.
+ $from++; $to++;
+ $to = $#Alnum_ if ($to > $#Alnum_);
+ $greater = join('', @Alnum_[$from..$to]);
+ ($yes, $no, $sign) = ($lesser lt $greater
+ ? (" ", "not ", 1)
+ : ("not ", " ", -1));
+ # all these tests should FAIL (return 0).
+ # Exact lt or gt cannot be tested because
+ # in some locales, say, eacute and E may test equal.
+ @test =
+ (
+ $no.' ($lesser le $greater)', # 1
+ 'not ($lesser ne $greater)', # 2
+ ' ($lesser eq $greater)', # 3
+ $yes.' ($lesser ge $greater)', # 4
+ $yes.' ($lesser ge $greater)', # 5
+ $yes.' ($greater le $lesser )', # 7
+ 'not ($greater ne $lesser )', # 8
+ ' ($greater eq $lesser )', # 9
+ $no.' ($greater ge $lesser )', # 10
+ 'not (($lesser cmp $greater) == -$sign)' # 12
+ );
+ @test{@test} = 0 x @test;
+ $test = 0;
+ for my $ti (@test) {
+ $test{$ti} = eval $ti;
+ $test ||= $test{$ti}
+ }
+ tryneoalpha($Locale, 102, $test == 0);
+ if ($test) {
+ debug "# lesser = '$lesser'\n";
+ debug "# greater = '$greater'\n";
+ debug "# lesser cmp greater = ",
+ $lesser cmp $greater, "\n";
+ debug "# greater cmp lesser = ",
+ $greater cmp $lesser, "\n";
+ debug "# (greater) from = $from, to = $to\n";
+ for my $ti (@test) {
+ debugf("# %-40s %-4s", $ti,
+ $test{$ti} ? 'FAIL' : 'ok');
+ if ($ti =~ /\(\.*(\$.+ +cmp +\$[^\)]+)\.*\)/) {
+ debugf("(%s == %4d)", $1, eval $1);
+ }
+ debug "\n#";
+ }
+
+ last;
+ }
+ }
+ }
}
-}
-@Neoalpha = sort @Neoalpha;
+ use locale;
-# Test \w.
+ my ($x, $y) = (1.23, 1.23);
-{
- my $word = join('', @Neoalpha);
+ my $a = "$x";
+ printf ''; # printf used to reset locale to "C"
+ my $b = "$y";
- $word =~ /^(\w*)$/;
+ debug "# 103..107: a = $a, b = $b, Locale = $Locale\n";
- print 'not ' if ($1 ne $word);
-}
-print "ok 99\n";
+ tryneoalpha($Locale, 103, $a eq $b);
+
+ my $c = "$x";
+ my $z = sprintf ''; # sprintf used to reset locale to "C"
+ my $d = "$y";
-# Find places where the collation order differs from the default locale.
+ debug "# 104..107: c = $c, d = $d, Locale = $Locale\n";
-print "# testing 100\n";
-{
- my (@k, $i, $j, @d);
+ tryneoalpha($Locale, 104, $c eq $d);
{
- no locale;
+ my $w = 0;
+ local $SIG{__WARN__} = sub { $w++ };
+ local $^W = 1;
- @k = sort (keys %UPPER, keys %lower);
- }
+ # the == (among other ops) used to warn for locales
+ # that had something else than "." as the radix character
- for ($i = 0; $i < @k; $i++) {
- for ($j = $i + 1; $j < @k; $j++) {
- if ($iLocale{$k[$j]} < $iLocale{$k[$i]}) {
- push(@d, [$k[$j], $k[$i]]);
- }
+ tryneoalpha($Locale, 105, $c == 1.23);
+
+ tryneoalpha($Locale, 106, $c == $x);
+
+ tryneoalpha($Locale, 107, $c == $d);
+
+ {
+ no locale;
+
+ my $e = "$x";
+
+ debug "# 108..110: e = $e, Locale = $Locale\n";
+
+ tryneoalpha($Locale, 108, $e == 1.23);
+
+ tryneoalpha($Locale, 109, $e == $x);
+
+ tryneoalpha($Locale, 110, $e == $c);
}
+
+ tryneoalpha($Locale, 111, $w == 0);
+
+ my $f = "1.23";
+
+ debug "# 112..114: f = $f, locale = $Locale\n";
+
+ tryneoalpha($Locale, 112, $f == 1.23);
+
+ tryneoalpha($Locale, 113, $f == $x);
+
+ tryneoalpha($Locale, 114, $f == $c);
}
- # Cross-check those places.
+ debug "# testing 115 with locale '$Locale'\n";
+ {
+ use locale;
+
+ sub lcA {
+ my $lc0 = lc $_[0];
+ my $lc1 = lc $_[1];
+ return $lc0 cmp $lc1;
+ }
- for (@d) {
- ($i, $j) = @$_;
- if ($i gt $j) {
- print "# failed 100 at:\n";
- print "# i = $i, j = $j, i ",
- $i le $j ? 'le' : 'gt', " j\n";
- print 'not ';
- last;
+ sub lcB {
+ return lc($_[0]) cmp lc($_[1]);
}
+
+ my $x = "ab";
+ my $y = "aa";
+ my $z = "AB";
+
+ tryneoalpha($Locale, 115,
+ lcA($x, $y) == 1 && lcB($x, $y) == 1 ||
+ lcA($x, $z) == 0 && lcB($x, $z) == 0);
}
}
-print "ok 100\n";
-
-# Cross-check whole character set.
-
-print "# testing 101\n";
-for (map { chr } 0..255) {
- if (/\w/ and /\W/) { print 'not '; last }
- if (/\d/ and /\D/) { print 'not '; last }
- if (/\s/ and /\S/) { print 'not '; last }
- if (/\w/ and /\D/ and not /_/ and
- not (exists $UPPER{$_} or exists $lower{$_})) {
- print "# failed 101 at:\n";
- print "# ", ord($_), " '$_'\n";
- print 'not ';
- last;
+
+# Recount the errors.
+
+foreach (99..115) {
+ if ($Problem{$_} || !defined $Okay{$_} || !@{$Okay{$_}}) {
+ if ($_ == 102) {
+ print "# The failure of test 102 is not necessarily fatal.\n";
+ print "# It usually indicates a problem in the enviroment,\n";
+ print "# not in Perl itself.\n";
+ }
+ print "not ";
}
+ print "ok $_\n";
}
-print "ok 101\n";
-# Test for read-onlys.
-
-{
- no locale;
- $a = "qwerty";
- {
- use locale;
- print "not " if $a cmp "qwerty";
+# Give final advice.
+
+my $didwarn = 0;
+
+foreach (99..115) {
+ if ($Problem{$_}) {
+ my @f = sort keys %{ $Problem{$_} };
+ my $f = join(" ", @f);
+ $f =~ s/(.{50,60}) /$1\n#\t/g;
+ print
+ "#\n",
+ "# The locale ", (@f == 1 ? "definition" : "definitions"), "\n#\n",
+ "#\t", $f, "\n#\n",
+ "# on your system may have errors because the locale test $_\n",
+ "# failed in ", (@f == 1 ? "that locale" : "those locales"),
+ ".\n";
+ print <<EOW;
+#
+# If your users are not using these locales you are safe for the moment,
+# but please report this failure first to perlbug\@perl.com using the
+# perlbug script (as described in the INSTALL file) so that the exact
+# details of the failures can be sorted out first and then your operating
+# system supplier can be alerted about these anomalies.
+#
+EOW
+ $didwarn = 1;
}
}
-print "ok 102\n";
-
-# This test must be the last one because its failure is not fatal.
-# The @Locale should be internally consistent.
-# Thanks to Hallvard Furuseth <h.b.furuseth@usit.uio.no>
-# for inventing a way to test for ordering consistency
-# without requiring any particular order.
-# ++$jhi;#@iki.fi
-
-print "# testing 103\n";
-{
- my ($from, $to, $lesser, $greater, @test, %test, $test, $yes, $no, $sign);
-
- for (0..9) {
- # Select a slice.
- $from = int(($_*@Locale)/10);
- $to = $from + int(@Locale/10);
- $to = $#Locale if ($to > $#Locale);
- $lesser = join('', @Locale[$from..$to]);
- # Select a slice one character on.
- $from++; $to++;
- $to = $#Locale if ($to > $#Locale);
- $greater = join('', @Locale[$from..$to]);
- ($yes, $no, $sign) = ($lesser lt $greater
- ? (" ", "not ", 1)
- : ("not ", " ", -1));
- # all these tests should FAIL (return 0).
- @test =
- (
- $no.' ($lesser lt $greater)', # 0
- $no.' ($lesser le $greater)', # 1
- 'not ($lesser ne $greater)', # 2
- ' ($lesser eq $greater)', # 3
- $yes.' ($lesser ge $greater)', # 4
- $yes.' ($lesser gt $greater)', # 5
- $yes.' ($greater lt $lesser )', # 6
- $yes.' ($greater le $lesser )', # 7
- 'not ($greater ne $lesser )', # 8
- ' ($greater eq $lesser )', # 9
- $no.' ($greater ge $lesser )', # 10
- $no.' ($greater gt $lesser )', # 11
- 'not (($lesser cmp $greater) == -$sign)' # 12
- );
- @test{@test} = 0 x @test;
- $test = 0;
- for my $ti (@test) { $test{$ti} = eval $ti ; $test ||= $test{$ti} }
- if ($test) {
- print "# failed 103 at:\n";
- print "# lesser = '$lesser'\n";
- print "# greater = '$greater'\n";
- print "# lesser cmp greater = ", $lesser cmp $greater, "\n";
- print "# greater cmp lesser = ", $greater cmp $lesser, "\n";
- print "# (greater) from = $from, to = $to\n";
- for my $ti (@test) {
- printf("# %-40s %-4s", $ti,
- $test{$ti} ? 'FAIL' : 'ok');
- if ($ti =~ /\(\.*(\$.+ +cmp +\$[^\)]+)\.*\)/) {
- printf("(%s == %4d)", $1, eval $1);
- }
- print "\n";
- }
- warn "The locale definition on your system may have errors.\n";
- last;
+# Tell which locales ere okay.
+
+if ($didwarn) {
+ my @s;
+
+ foreach my $l (@Locale) {
+ my $p = 0;
+ foreach my $t (102..102) {
+ $p++ if $Problem{$t}{$l};
}
+ push @s, $l if $p == 0;
}
+
+ my $s = join(" ", @s);
+ $s =~ s/(.{50,60}) /$1\n#\t/g;
+
+ warn
+ "# The following locales\n#\n",
+ "#\t", $s, "\n#\n",
+ "# tested okay.\n#\n",
}
# eof
diff --git a/t/pragma/locale/latin1 b/t/pragma/locale/latin1
new file mode 100644
index 0000000000..f40f7325e0
--- /dev/null
+++ b/t/pragma/locale/latin1
@@ -0,0 +1,10 @@
+$locales .= <<EOF;
+Català Catalan:ca:es:1 15
+Français French:fr:be ca ch fr lu:1 15
+Gáidhlig Gaelic:gd:gb uk:1 14 15
+Føroyskt Faroese:fo:fo:1 15
+Íslensku Icelandic:is:is:1 15
+Sámi Lappish:::4 6 13
+Português Portuguese:po:po br:1 15
+Espanõl Spanish:es:ar bo cl co cr do ec es gt hn mx ni pa pe py sv uy ve:1 15
+EOF
diff --git a/t/pragma/locale/utf8 b/t/pragma/locale/utf8
new file mode 100644
index 0000000000..fbbe94fb51
--- /dev/null
+++ b/t/pragma/locale/utf8
@@ -0,0 +1,10 @@
+$locales .= <<EOF;
+Català Catalan:ca:es:1 15
+Français French:fr:be ca ch fr lu:1 15
+Gáidhlig Gaelic:gd:gb uk:1 14 15
+Føroyskt Faroese:fo:fo:1 15
+Ãslensku Icelandic:is:is:1 15
+Sámi Lappish:::4 6 13
+Português Portuguese:po:po br:1 15
+Espanõl Spanish:es:ar bo cl co cr do ec es gt hn mx ni pa pe py sv uy ve:1 15
+EOF
diff --git a/t/pragma/overload.t b/t/pragma/overload.t
index 05035c612d..ff8d8059f1 100755
--- a/t/pragma/overload.t
+++ b/t/pragma/overload.t
@@ -2,11 +2,9 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
}
-use Config;
-
package Oscalar;
use overload (
# Anonymous subroutines:
@@ -436,6 +434,487 @@ test($b, "_<oups1
>_"); # 134
test($c, "bareword"); # 135
+{
+ package symbolic; # Primitive symbolic calculator
+ use overload nomethod => \&wrap, '""' => \&str, '0+' => \&num,
+ '=' => \&cpy, '++' => \&inc, '--' => \&dec;
+
+ sub new { shift; bless ['n', @_] }
+ sub cpy {
+ my $self = shift;
+ bless [@$self], ref $self;
+ }
+ sub inc { $_[0] = bless ['++', $_[0], 1]; }
+ sub dec { $_[0] = bless ['--', $_[0], 1]; }
+ sub wrap {
+ my ($obj, $other, $inv, $meth) = @_;
+ if ($meth eq '++' or $meth eq '--') {
+ @$obj = ($meth, (bless [@$obj]), 1); # Avoid circular reference
+ return $obj;
+ }
+ ($obj, $other) = ($other, $obj) if $inv;
+ bless [$meth, $obj, $other];
+ }
+ sub str {
+ my ($meth, $a, $b) = @{+shift};
+ $a = 'u' unless defined $a;
+ if (defined $b) {
+ "[$meth $a $b]";
+ } else {
+ "[$meth $a]";
+ }
+ }
+ my %subr = ( 'n' => sub {$_[0]} );
+ foreach my $op (split " ", $overload::ops{with_assign}) {
+ $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}";
+ }
+ my @bins = qw(binary 3way_comparison num_comparison str_comparison);
+ foreach my $op (split " ", "@overload::ops{ @bins }") {
+ $subr{$op} = eval "sub {shift() $op shift()}";
+ }
+ foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
+ $subr{$op} = eval "sub {$op shift()}";
+ }
+ $subr{'++'} = $subr{'+'};
+ $subr{'--'} = $subr{'-'};
+
+ sub num {
+ my ($meth, $a, $b) = @{+shift};
+ my $subr = $subr{$meth}
+ or die "Do not know how to ($meth) in symbolic";
+ $a = $a->num if ref $a eq __PACKAGE__;
+ $b = $b->num if ref $b eq __PACKAGE__;
+ $subr->($a,$b);
+ }
+ sub TIESCALAR { my $pack = shift; $pack->new(@_) }
+ sub FETCH { shift }
+ sub nop { } # Around a bug
+ sub vars { my $p = shift; tie($_, $p), $_->nop foreach @_; }
+ sub STORE {
+ my $obj = shift;
+ $#$obj = 1;
+ @$obj->[0,1] = ('=', shift);
+ }
+}
+
+{
+ my $foo = new symbolic 11;
+ my $baz = $foo++;
+ test( (sprintf "%d", $foo), '12');
+ test( (sprintf "%d", $baz), '11');
+ my $bar = $foo;
+ $baz = ++$foo;
+ test( (sprintf "%d", $foo), '13');
+ test( (sprintf "%d", $bar), '12');
+ test( (sprintf "%d", $baz), '13');
+ my $ban = $foo;
+ $baz = ($foo += 1);
+ test( (sprintf "%d", $foo), '14');
+ test( (sprintf "%d", $bar), '12');
+ test( (sprintf "%d", $baz), '14');
+ test( (sprintf "%d", $ban), '13');
+ $baz = 0;
+ $baz = $foo++;
+ test( (sprintf "%d", $foo), '15');
+ test( (sprintf "%d", $baz), '14');
+ test( "$foo", '[++ [+= [++ [++ [n 11] 1] 1] 1] 1]');
+}
+
+{
+ my $iter = new symbolic 2;
+ my $side = new symbolic 1;
+ my $cnt = $iter;
+
+ while ($cnt) {
+ $cnt = $cnt - 1; # The "simple" way
+ $side = (sqrt(1 + $side**2) - 1)/$side;
+ }
+ my $pi = $side*(2**($iter+2));
+ test "$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]';
+ test( (sprintf "%f", $pi), '3.182598');
+}
+
+{
+ my $iter = new symbolic 2;
+ my $side = new symbolic 1;
+ my $cnt = $iter;
+
+ while ($cnt--) {
+ $side = (sqrt(1 + $side**2) - 1)/$side;
+ }
+ my $pi = $side*(2**($iter+2));
+ test "$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]';
+ test( (sprintf "%f", $pi), '3.182598');
+}
+
+{
+ my ($a, $b);
+ symbolic->vars($a, $b);
+ my $c = sqrt($a**2 + $b**2);
+ $a = 3; $b = 4;
+ test( (sprintf "%d", $c), '5');
+ $a = 12; $b = 5;
+ test( (sprintf "%d", $c), '13');
+}
+
+{
+ package symbolic1; # Primitive symbolic calculator
+ # Mutator inc/dec
+ use overload nomethod => \&wrap, '""' => \&str, '0+' => \&num, '=' => \&cpy;
+
+ sub new { shift; bless ['n', @_] }
+ sub cpy {
+ my $self = shift;
+ bless [@$self], ref $self;
+ }
+ sub wrap {
+ my ($obj, $other, $inv, $meth) = @_;
+ if ($meth eq '++' or $meth eq '--') {
+ @$obj = ($meth, (bless [@$obj]), 1); # Avoid circular reference
+ return $obj;
+ }
+ ($obj, $other) = ($other, $obj) if $inv;
+ bless [$meth, $obj, $other];
+ }
+ sub str {
+ my ($meth, $a, $b) = @{+shift};
+ $a = 'u' unless defined $a;
+ if (defined $b) {
+ "[$meth $a $b]";
+ } else {
+ "[$meth $a]";
+ }
+ }
+ my %subr = ( 'n' => sub {$_[0]} );
+ foreach my $op (split " ", $overload::ops{with_assign}) {
+ $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}";
+ }
+ my @bins = qw(binary 3way_comparison num_comparison str_comparison);
+ foreach my $op (split " ", "@overload::ops{ @bins }") {
+ $subr{$op} = eval "sub {shift() $op shift()}";
+ }
+ foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
+ $subr{$op} = eval "sub {$op shift()}";
+ }
+ $subr{'++'} = $subr{'+'};
+ $subr{'--'} = $subr{'-'};
+
+ sub num {
+ my ($meth, $a, $b) = @{+shift};
+ my $subr = $subr{$meth}
+ or die "Do not know how to ($meth) in symbolic";
+ $a = $a->num if ref $a eq __PACKAGE__;
+ $b = $b->num if ref $b eq __PACKAGE__;
+ $subr->($a,$b);
+ }
+ sub TIESCALAR { my $pack = shift; $pack->new(@_) }
+ sub FETCH { shift }
+ sub nop { } # Around a bug
+ sub vars { my $p = shift; tie($_, $p), $_->nop foreach @_; }
+ sub STORE {
+ my $obj = shift;
+ $#$obj = 1;
+ @$obj->[0,1] = ('=', shift);
+ }
+}
+
+{
+ my $foo = new symbolic1 11;
+ my $baz = $foo++;
+ test( (sprintf "%d", $foo), '12');
+ test( (sprintf "%d", $baz), '11');
+ my $bar = $foo;
+ $baz = ++$foo;
+ test( (sprintf "%d", $foo), '13');
+ test( (sprintf "%d", $bar), '12');
+ test( (sprintf "%d", $baz), '13');
+ my $ban = $foo;
+ $baz = ($foo += 1);
+ test( (sprintf "%d", $foo), '14');
+ test( (sprintf "%d", $bar), '12');
+ test( (sprintf "%d", $baz), '14');
+ test( (sprintf "%d", $ban), '13');
+ $baz = 0;
+ $baz = $foo++;
+ test( (sprintf "%d", $foo), '15');
+ test( (sprintf "%d", $baz), '14');
+ test( "$foo", '[++ [+= [++ [++ [n 11] 1] 1] 1] 1]');
+}
+
+{
+ my $iter = new symbolic1 2;
+ my $side = new symbolic1 1;
+ my $cnt = $iter;
+
+ while ($cnt) {
+ $cnt = $cnt - 1; # The "simple" way
+ $side = (sqrt(1 + $side**2) - 1)/$side;
+ }
+ my $pi = $side*(2**($iter+2));
+ test "$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]';
+ test( (sprintf "%f", $pi), '3.182598');
+}
+
+{
+ my $iter = new symbolic1 2;
+ my $side = new symbolic1 1;
+ my $cnt = $iter;
+
+ while ($cnt--) {
+ $side = (sqrt(1 + $side**2) - 1)/$side;
+ }
+ my $pi = $side*(2**($iter+2));
+ test "$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]';
+ test( (sprintf "%f", $pi), '3.182598');
+}
+
+{
+ my ($a, $b);
+ symbolic1->vars($a, $b);
+ my $c = sqrt($a**2 + $b**2);
+ $a = 3; $b = 4;
+ test( (sprintf "%d", $c), '5');
+ $a = 12; $b = 5;
+ test( (sprintf "%d", $c), '13');
+}
+
+{
+ package two_face; # Scalars with separate string and
+ # numeric values.
+ sub new { my $p = shift; bless [@_], $p }
+ use overload '""' => \&str, '0+' => \&num, fallback => 1;
+ sub num {shift->[1]}
+ sub str {shift->[0]}
+}
+
+{
+ my $seven = new two_face ("vii", 7);
+ test( (sprintf "seven=$seven, seven=%d, eight=%d", $seven, $seven+1),
+ 'seven=vii, seven=7, eight=8');
+ test( scalar ($seven =~ /i/), '1')
+}
+
+{
+ package sorting;
+ use overload 'cmp' => \&comp;
+ sub new { my ($p, $v) = @_; bless \$v, $p }
+ sub comp { my ($x,$y) = @_; ($$x * 3 % 10) <=> ($$y * 3 % 10) or $$x cmp $$y }
+}
+{
+ my @arr = map sorting->new($_), 0..12;
+ my @sorted1 = sort @arr;
+ my @sorted2 = map $$_, @sorted1;
+ test "@sorted2", '0 10 7 4 1 11 8 5 12 2 9 6 3';
+}
+{
+ package iterator;
+ use overload '<>' => \&iter;
+ sub new { my ($p, $v) = @_; bless \$v, $p }
+ sub iter { my ($x) = @_; return undef if $$x < 0; return $$x--; }
+}
+{
+ my $iter = iterator->new(5);
+ my $acc = '';
+ my $out;
+ $acc .= " $out" while $out = <${iter}>;
+ test $acc, ' 5 4 3 2 1 0'; # 175
+ $iter = iterator->new(5);
+ test scalar <${iter}>, '5'; # 176
+ $acc = '';
+ $acc .= " $out" while $out = <$iter>;
+ test $acc, ' 4 3 2 1 0'; # 177
+}
+{
+ package deref;
+ use overload '%{}' => \&hderef, '&{}' => \&cderef,
+ '*{}' => \&gderef, '${}' => \&sderef, '@{}' => \&aderef;
+ sub new { my ($p, $v) = @_; bless \$v, $p }
+ sub deref {
+ my ($self, $key) = (shift, shift);
+ my $class = ref $self;
+ bless $self, 'deref::dummy'; # Disable overloading of %{}
+ my $out = $self->{$key};
+ bless $self, $class; # Restore overloading
+ $out;
+ }
+ sub hderef {shift->deref('h')}
+ sub aderef {shift->deref('a')}
+ sub cderef {shift->deref('c')}
+ sub gderef {shift->deref('g')}
+ sub sderef {shift->deref('s')}
+}
+{
+ my $deref = bless { h => { foo => 5 , fake => 23 },
+ c => sub {return shift() + 34},
+ 's' => \123,
+ a => [11..13],
+ g => \*srt,
+ }, 'deref';
+ # Hash:
+ my @cont = sort %$deref;
+ test "@cont", '23 5 fake foo'; # 178
+ my @keys = sort keys %$deref;
+ test "@keys", 'fake foo'; # 179
+ my @val = sort values %$deref;
+ test "@val", '23 5'; # 180
+ test $deref->{foo}, 5; # 181
+ test defined $deref->{bar}, ''; # 182
+ my $key;
+ @keys = ();
+ push @keys, $key while $key = each %$deref;
+ @keys = sort @keys;
+ test "@keys", 'fake foo'; # 183
+ test exists $deref->{bar}, ''; # 184
+ test exists $deref->{foo}, 1; # 185
+ # Code:
+ test $deref->(5), 39; # 186
+ test &$deref(6), 40; # 187
+ sub xxx_goto { goto &$deref }
+ test xxx_goto(7), 41; # 188
+ my $srt = bless { c => sub {$b <=> $a}
+ }, 'deref';
+ *srt = \&$srt;
+ my @sorted = sort srt 11, 2, 5, 1, 22;
+ test "@sorted", '22 11 5 2 1'; # 189
+ # Scalar
+ test $$deref, 123; # 190
+ # Code
+ @sorted = sort $srt 11, 2, 5, 1, 22;
+ test "@sorted", '22 11 5 2 1'; # 191
+ # Array
+ test "@$deref", '11 12 13'; # 192
+ test $#$deref, '2'; # 193
+ my $l = @$deref;
+ test $l, 3; # 194
+ test $deref->[2], '13'; # 195
+ $l = pop @$deref;
+ test $l, 13; # 196
+ $l = 1;
+ test $deref->[$l], '12'; # 197
+ # Repeated dereference
+ my $double = bless { h => $deref,
+ }, 'deref';
+ test $double->{foo}, 5; # 198
+}
+
+{
+ package two_refs;
+ use overload '%{}' => \&gethash, '@{}' => sub { ${shift()} };
+ sub new {
+ my $p = shift;
+ bless \ [@_], $p;
+ }
+ sub gethash {
+ my %h;
+ my $self = shift;
+ tie %h, ref $self, $self;
+ \%h;
+ }
+
+ sub TIEHASH { my $p = shift; bless \ shift, $p }
+ my %fields;
+ my $i = 0;
+ $fields{$_} = $i++ foreach qw{zero one two three};
+ sub STORE {
+ my $self = ${shift()};
+ my $key = $fields{shift()};
+ defined $key or die "Out of band access";
+ $$self->[$key] = shift;
+ }
+ sub FETCH {
+ my $self = ${shift()};
+ my $key = $fields{shift()};
+ defined $key or die "Out of band access";
+ $$self->[$key];
+ }
+}
+
+my $bar = new two_refs 3,4,5,6;
+$bar->[2] = 11;
+test $bar->{two}, 11; # 199
+$bar->{three} = 13;
+test $bar->[3], 13; # 200
+
+{
+ package two_refs_o;
+ @ISA = ('two_refs');
+}
+
+$bar = new two_refs_o 3,4,5,6;
+$bar->[2] = 11;
+test $bar->{two}, 11; # 201
+$bar->{three} = 13;
+test $bar->[3], 13; # 202
+
+{
+ package two_refs1;
+ use overload '%{}' => sub { ${shift()}->[1] },
+ '@{}' => sub { ${shift()}->[0] };
+ sub new {
+ my $p = shift;
+ my $a = [@_];
+ my %h;
+ tie %h, $p, $a;
+ bless \ [$a, \%h], $p;
+ }
+ sub gethash {
+ my %h;
+ my $self = shift;
+ tie %h, ref $self, $self;
+ \%h;
+ }
+
+ sub TIEHASH { my $p = shift; bless \ shift, $p }
+ my %fields;
+ my $i = 0;
+ $fields{$_} = $i++ foreach qw{zero one two three};
+ sub STORE {
+ my $a = ${shift()};
+ my $key = $fields{shift()};
+ defined $key or die "Out of band access";
+ $a->[$key] = shift;
+ }
+ sub FETCH {
+ my $a = ${shift()};
+ my $key = $fields{shift()};
+ defined $key or die "Out of band access";
+ $a->[$key];
+ }
+}
+
+$bar = new two_refs_o 3,4,5,6;
+$bar->[2] = 11;
+test $bar->{two}, 11; # 203
+$bar->{three} = 13;
+test $bar->[3], 13; # 204
+
+{
+ package two_refs1_o;
+ @ISA = ('two_refs1');
+}
+
+$bar = new two_refs1_o 3,4,5,6;
+$bar->[2] = 11;
+test $bar->{two}, 11; # 205
+$bar->{three} = 13;
+test $bar->[3], 13; # 206
+
+{
+ package B;
+ use overload bool => sub { ${+shift} };
+}
+
+my $aaa;
+{ my $bbbb = 0; $aaa = bless \$bbbb, B }
+
+test !$aaa, 1;
+
+unless ($aaa) {
+ test 'ok', 'ok';
+} else {
+ test 'is not', 'ok';
+}
+
# Last test is:
-sub last {135}
+sub last {208}
diff --git a/t/pragma/strict-subs b/t/pragma/strict-subs
index 61ec286eb6..deeb381473 100644
--- a/t/pragma/strict-subs
+++ b/t/pragma/strict-subs
@@ -277,3 +277,25 @@ my $a = Fred ;
EXPECT
Bareword "Fred" not allowed while "strict subs" in use at - line 8.
Execution of - aborted due to compilation errors.
+########
+
+# see if Foo->Bar(...) etc work under strictures
+use strict;
+package Foo; sub Bar { print "@_\n" }
+Foo->Bar('a',1);
+Bar Foo ('b',2);
+Foo->Bar(qw/c 3/);
+Bar Foo (qw/d 4/);
+Foo::->Bar('A',1);
+Bar Foo:: ('B',2);
+Foo::->Bar(qw/C 3/);
+Bar Foo:: (qw/D 4/);
+EXPECT
+Foo a 1
+Foo b 2
+Foo c 3
+Foo d 4
+Foo A 1
+Foo B 2
+Foo C 3
+Foo D 4
diff --git a/t/pragma/strict.t b/t/pragma/strict.t
index fc3282089f..2b8c58735f 100755
--- a/t/pragma/strict.t
+++ b/t/pragma/strict.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
$ENV{PERL5LIB} = '../lib';
}
@@ -69,7 +69,7 @@ for (@prgs){
`MCR $^X $switch $tmpfile` :
$Is_MSWin32 ?
`.\\perl -I../lib $switch $tmpfile 2>&1` :
- `sh -c './perl $switch $tmpfile' 2>&1`;
+ `./perl $switch $tmpfile 2>&1`;
my $status = $?;
$results =~ s/\n+$//;
# allow expected output to be written as if $prog is on STDIN
diff --git a/t/pragma/sub_lval.t b/t/pragma/sub_lval.t
new file mode 100755
index 0000000000..c382ad52ae
--- /dev/null
+++ b/t/pragma/sub_lval.t
@@ -0,0 +1,429 @@
+print "1..46\n";
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+}
+
+sub a {use attrs 'lvalue'; my $a = 34; bless \$a} # Return a temporary
+sub b {use attrs 'lvalue'; shift}
+
+my $out = a(b()); # Check that temporaries are allowed.
+print "# `$out'\nnot " unless ref $out eq 'main'; # Not reached if error.
+print "ok 1\n";
+
+my @out = grep /main/, a(b()); # Check that temporaries are allowed.
+print "# `@out'\nnot " unless @out==1; # Not reached if error.
+print "ok 2\n";
+
+my $in;
+
+# Check that we can return localized values from subroutines:
+
+sub in {use attrs 'lvalue'; $in = shift;}
+sub neg {use attrs 'lvalue'; #(num_str) return num_str
+ local $_ = shift;
+ s/^\+/-/;
+ $_;
+}
+in(neg("+2"));
+
+
+print "# `$in'\nnot " unless $in eq '-2';
+print "ok 3\n";
+
+sub get_lex {use attrs 'lvalue'; $in}
+sub get_st {use attrs 'lvalue'; $blah}
+sub id {use attrs 'lvalue'; shift}
+sub id1 {use attrs 'lvalue'; $_[0]}
+sub inc {use attrs 'lvalue'; ++$_[0]}
+
+$in = 5;
+$blah = 3;
+
+get_st = 7;
+
+print "# `$blah' ne 7\nnot " unless $blah eq 7;
+print "ok 4\n";
+
+get_lex = 7;
+
+print "# `$in' ne 7\nnot " unless $in eq 7;
+print "ok 5\n";
+
+++get_st;
+
+print "# `$blah' ne 8\nnot " unless $blah eq 8;
+print "ok 6\n";
+
+++get_lex;
+
+print "# `$in' ne 8\nnot " unless $in eq 8;
+print "ok 7\n";
+
+id(get_st) = 10;
+
+print "# `$blah' ne 10\nnot " unless $blah eq 10;
+print "ok 8\n";
+
+id(get_lex) = 10;
+
+print "# `$in' ne 10\nnot " unless $in eq 10;
+print "ok 9\n";
+
+++id(get_st);
+
+print "# `$blah' ne 11\nnot " unless $blah eq 11;
+print "ok 10\n";
+
+++id(get_lex);
+
+print "# `$in' ne 11\nnot " unless $in eq 11;
+print "ok 11\n";
+
+id1(get_st) = 20;
+
+print "# `$blah' ne 20\nnot " unless $blah eq 20;
+print "ok 12\n";
+
+id1(get_lex) = 20;
+
+print "# `$in' ne 20\nnot " unless $in eq 20;
+print "ok 13\n";
+
+++id1(get_st);
+
+print "# `$blah' ne 21\nnot " unless $blah eq 21;
+print "ok 14\n";
+
+++id1(get_lex);
+
+print "# `$in' ne 21\nnot " unless $in eq 21;
+print "ok 15\n";
+
+inc(get_st);
+
+print "# `$blah' ne 22\nnot " unless $blah eq 22;
+print "ok 16\n";
+
+inc(get_lex);
+
+print "# `$in' ne 22\nnot " unless $in eq 22;
+print "ok 17\n";
+
+inc(id(get_st));
+
+print "# `$blah' ne 23\nnot " unless $blah eq 23;
+print "ok 18\n";
+
+inc(id(get_lex));
+
+print "# `$in' ne 23\nnot " unless $in eq 23;
+print "ok 19\n";
+
+++inc(id1(id(get_st)));
+
+print "# `$blah' ne 25\nnot " unless $blah eq 25;
+print "ok 20\n";
+
+++inc(id1(id(get_lex)));
+
+print "# `$in' ne 25\nnot " unless $in eq 25;
+print "ok 21\n";
+
+@a = (1) x 3;
+@b = (undef) x 2;
+$#c = 3; # These slots are not fillable.
+
+# Explanation: empty slots contain &sv_undef.
+
+=for disabled constructs
+
+sub a3 {use attrs 'lvalue'; @a}
+sub b2 {use attrs 'lvalue'; @b}
+sub c4 {use attrs 'lvalue'; @c}
+
+$_ = '';
+
+eval <<'EOE' or $_ = $@;
+ ($x, a3, $y, b2, $z, c4, $t) = (34 .. 78);
+ 1;
+EOE
+
+#@out = ($x, a3, $y, b2, $z, c4, $t);
+#@in = (34 .. 41, (undef) x 4, 46);
+#print "# `@out' ne `@in'\nnot " unless "@out" eq "@in";
+
+print "# '$_'.\nnot "
+ unless /Can\'t return an uninitialized value from lvalue subroutine/;
+=cut
+
+print "ok 22\n";
+
+my $var;
+
+sub a::var {use attrs 'lvalue'; $var}
+
+"a"->var = 45;
+
+print "# `$var' ne 45\nnot " unless $var eq 45;
+print "ok 23\n";
+
+my $oo;
+$o = bless \$oo, "a";
+
+$o->var = 47;
+
+print "# `$var' ne 47\nnot " unless $var eq 47;
+print "ok 24\n";
+
+sub o {use attrs 'lvalue'; $o}
+
+o->var = 49;
+
+print "# `$var' ne 49\nnot " unless $var eq 49;
+print "ok 25\n";
+
+sub nolv () { $x0, $x1 } # Not lvalue
+
+$_ = '';
+
+eval <<'EOE' or $_ = $@;
+ nolv = (2,3);
+ 1;
+EOE
+
+print "not "
+ unless /Can\'t modify non-lvalue subroutine call in scalar assignment/;
+print "ok 26\n";
+
+$_ = '';
+
+eval <<'EOE' or $_ = $@;
+ nolv = (2,3) if $_;
+ 1;
+EOE
+
+print "not "
+ unless /Can\'t modify non-lvalue subroutine call in scalar assignment/;
+print "ok 27\n";
+
+$_ = '';
+
+eval <<'EOE' or $_ = $@;
+ &nolv = (2,3) if $_;
+ 1;
+EOE
+
+print "not "
+ unless /Can\'t modify non-lvalue subroutine call in scalar assignment/;
+print "ok 28\n";
+
+$x0 = $x1 = $_ = undef;
+$nolv = \&nolv;
+
+eval <<'EOE' or $_ = $@;
+ $nolv->() = (2,3) if $_;
+ 1;
+EOE
+
+print "# '$_', '$x0', '$x1'.\nnot " if defined $_;
+print "ok 29\n";
+
+$x0 = $x1 = $_ = undef;
+$nolv = \&nolv;
+
+eval <<'EOE' or $_ = $@;
+ $nolv->() = (2,3);
+ 1;
+EOE
+
+print "# '$_', '$x0', '$x1'.\nnot "
+ unless /Can\'t modify non-lvalue subroutine call/;
+print "ok 30\n";
+
+sub lv0 {use attrs 'lvalue';} # Converted to lv10 in scalar context
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ lv0 = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot "
+ unless /Can\'t return a readonly value from lvalue subroutine/;
+print "ok 31\n";
+
+sub lv10 {use attrs 'lvalue';}
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ (lv0) = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot " if defined $_;
+print "ok 32\n";
+
+sub lv1u {use attrs 'lvalue'; undef }
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ lv1u = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot "
+ unless /Can\'t return a readonly value from lvalue subroutine/;
+print "ok 33\n";
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ (lv1u) = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot "
+ unless /Can\'t return an uninitialized value from lvalue subroutine/;
+print "ok 34\n";
+
+$x = '1234567';
+sub lv1t {use attrs 'lvalue'; index $x, 2 }
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ lv1t = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot "
+ unless /Can\'t return a temporary from lvalue subroutine/;
+print "ok 35\n";
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ (lv1t) = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot "
+ unless /Can\'t return a temporary from lvalue subroutine/;
+print "ok 36\n";
+
+$xxx = 'xxx';
+sub xxx () { $xxx } # Not lvalue
+sub lv1tmp {use attrs 'lvalue'; xxx } # is it a TEMP?
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ lv1tmp = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot "
+ unless /Can\'t return a temporary from lvalue subroutine/;
+print "ok 37\n";
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ (lv1tmp) = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot "
+ unless /Can\'t return a temporary from lvalue subroutine/;
+print "ok 38\n";
+
+sub xxx () { 'xxx' } # Not lvalue
+sub lv1tmpr {use attrs 'lvalue'; xxx } # is it a TEMP?
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ lv1tmpr = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot "
+ unless /Can\'t return a readonly value from lvalue subroutine/;
+print "ok 39\n";
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ (lv1tmpr) = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot "
+ unless /Can\'t return a readonly value from lvalue subroutine/;
+print "ok 40\n";
+
+=for disabled constructs
+
+sub lva {use attrs 'lvalue';@a}
+
+$_ = undef;
+@a = ();
+$a[1] = 12;
+eval <<'EOE' or $_ = $@;
+ (lva) = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot "
+ unless /Can\'t return an uninitialized value from lvalue subroutine/;
+print "ok 41\n";
+
+$_ = undef;
+@a = ();
+$a[0] = undef;
+$a[1] = 12;
+eval <<'EOE' or $_ = $@;
+ (lva) = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot " unless "'@a' $_" eq "'2 3' ";
+print "ok 42\n";
+
+$_ = undef;
+@a = ();
+$a[0] = undef;
+$a[1] = 12;
+eval <<'EOE' or $_ = $@;
+ (lva) = (2,3);
+ 1;
+EOE
+
+print "# '$_'.\nnot " unless "'@a' $_" eq "'2 3' ";
+print "ok 43\n";
+
+=cut
+
+print "ok $_\n" for 41..43;
+
+sub lv1n {use attrs 'lvalue'; $newvar }
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ lv1n = (3,4);
+ 1;
+EOE
+
+print "# '$_', '$newvar'.\nnot " unless "'$newvar' $_" eq "'4' ";
+print "ok 44\n";
+
+sub lv1nn {use attrs 'lvalue'; $nnewvar }
+
+$_ = undef;
+eval <<'EOE' or $_ = $@;
+ (lv1nn) = (3,4);
+ 1;
+EOE
+
+print "# '$_'.\nnot " unless "'$nnewvar' $_" eq "'3' ";
+print "ok 45\n";
+
+$a = \&lv1nn;
+$a->() = 8;
+print "# '$nnewvar'.\nnot " unless $nnewvar eq '8';
+print "ok 46\n";
diff --git a/t/pragma/subs.t b/t/pragma/subs.t
index 056c4bd7cf..c8eb2c087f 100755
--- a/t/pragma/subs.t
+++ b/t/pragma/subs.t
@@ -2,7 +2,7 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
$ENV{PERL5LIB} = '../lib';
}
@@ -49,12 +49,15 @@ for (@prgs){
`MCR $^X $switch $tmpfile` :
$Is_MSWin32 ?
`.\\perl -I../lib $switch $tmpfile 2>&1` :
- `sh -c './perl $switch $tmpfile' 2>&1`;
+ `./perl $switch $tmpfile 2>&1`;
my $status = $?;
$results =~ s/\n+$//;
# allow expected output to be written as if $prog is on STDIN
$results =~ s/tmp\d+/-/g;
$results =~ s/\n%[A-Z]+-[SIWEF]-.*$// if $Is_VMS; # clip off DCL status msg
+# bison says 'parse error' instead of 'syntax error',
+# various yaccs may or may not capitalize 'syntax'.
+ $results =~ s/^(syntax|parse) error/syntax error/mig;
$expected =~ s/\n+$//;
my $prefix = ($results =~ s/^PREFIX\n//) ;
if ( $results =~ s/^SKIPPED\n//) {
diff --git a/t/pragma/utf8.t b/t/pragma/utf8.t
new file mode 100755
index 0000000000..01b0f0529c
--- /dev/null
+++ b/t/pragma/utf8.t
@@ -0,0 +1,82 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ unshift @INC, '../lib';
+ $ENV{PERL5LIB} = '../lib';
+}
+
+print "1..12\n";
+
+my $test = 1;
+
+sub ok {
+ my ($got,$expect) = @_;
+ print "# expected [$expect], got [$got]\nnot " if $got ne $expect;
+ print "ok $test\n";
+}
+
+{
+ use utf8;
+ $_ = ">\x{263A}<";
+ s/([\x{80}-\x{10ffff}])/"&#".ord($1).";"/eg;
+ ok $_, '>&#9786;<';
+ $test++;
+
+ $_ = ">\x{263A}<";
+ my $rx = "\x{80}-\x{10ffff}";
+ s/([$rx])/"&#".ord($1).";"/eg;
+ ok $_, '>&#9786;<';
+ $test++;
+
+ $_ = ">\x{263A}<";
+ my $rx = "\\x{80}-\\x{10ffff}";
+ s/([$rx])/"&#".ord($1).";"/eg;
+ ok $_, '>&#9786;<';
+ $test++;
+
+ $_ = "alpha,numeric";
+ m/([[:alpha:]]+)/;
+ ok $1, 'alpha';
+ $test++;
+
+ $_ = "alphaNUMERICstring";
+ m/([[:^lower:]]+)/;
+ ok $1, 'NUMERIC';
+ $test++;
+
+ $_ = "alphaNUMERICstring";
+ m/(\p{Ll}+)/;
+ ok $1, 'alpha';
+ $test++;
+
+ $_ = "alphaNUMERICstring";
+ m/(\p{Lu}+)/;
+ ok $1, 'NUMERIC';
+ $test++;
+
+ $_ = "alpha,numeric";
+ m/([\p{IsAlpha}]+)/;
+ ok $1, 'alpha';
+ $test++;
+
+ $_ = "alphaNUMERICstring";
+ m/([^\p{IsLower}]+)/;
+ ok $1, 'NUMERIC';
+ $test++;
+
+ $_ = "alpha123numeric456";
+ m/([\p{IsDigit}]+)/;
+ ok $1, '123';
+ $test++;
+
+ $_ = "alpha123numeric456";
+ m/([^\p{IsDigit}]+)/;
+ ok $1, 'alpha';
+ $test++;
+
+ $_ = ",123alpha,456numeric";
+ m/([\p{IsAlnum}]+)/;
+ ok $1, '123alpha';
+ $test++;
+}
diff --git a/t/pragma/warn-1global b/t/pragma/warn/1global
index 07b5bc8eb9..836b7f513f 100644
--- a/t/pragma/warn-1global
+++ b/t/pragma/warn/1global
@@ -1,5 +1,6 @@
Check existing $^W functionality
+
__END__
# warnable code, warnings disabled
@@ -12,12 +13,14 @@ EXPECT
$a =+ 3 ;
EXPECT
Reversed += operator at - line 3.
+Name "main::a" used only once: possible typo at - line 3.
########
#! perl -w
# warnable code, warnings enabled via #! line
$a =+ 3 ;
EXPECT
Reversed += operator at - line 3.
+Name "main::a" used only once: possible typo at - line 3.
########
# warnable code, warnings enabled via compile time $^W
@@ -25,6 +28,7 @@ BEGIN { $^W = 1 }
$a =+ 3 ;
EXPECT
Reversed += operator at - line 4.
+Name "main::a" used only once: possible typo at - line 4.
########
# compile-time warnable code, warnings enabled via runtime $^W
@@ -110,22 +114,24 @@ Use of uninitialized value at - line 3.
########
$^W = 1;
-eval "my $b ; chop $b ;" ;
+eval 'my $b ; chop $b ;' ;
+print $@ ;
EXPECT
-Use of uninitialized value at - line 3.
-Use of uninitialized value at - line 3.
+Use of uninitialized value at (eval 1) line 1.
########
-eval "$^W = 1;" ;
+eval '$^W = 1;' ;
+print $@ ;
my $b ; chop $b ;
EXPECT
-
+Use of uninitialized value at - line 4.
########
eval {$^W = 1;} ;
+print $@ ;
my $b ; chop $b ;
EXPECT
-Use of uninitialized value at - line 3.
+Use of uninitialized value at - line 4.
########
{
@@ -149,3 +155,35 @@ Use of uninitialized value at - line 5.
-e undef
EXPECT
Use of uninitialized value at - line 2.
+########
+
+$^W = 1 + 2 ;
+EXPECT
+
+########
+
+$^W = $a ;
+EXPECT
+
+########
+
+sub fred {}
+$^W = fred() ;
+EXPECT
+
+########
+
+sub fred { my $b ; chop $b ;}
+{ local $^W = 0 ;
+ fred() ;
+}
+EXPECT
+
+########
+
+sub fred { my $b ; chop $b ;}
+{ local $^W = 1 ;
+ fred() ;
+}
+EXPECT
+Use of uninitialized value at - line 2.
diff --git a/t/pragma/warn/2use b/t/pragma/warn/2use
new file mode 100644
index 0000000000..4ec4da0a77
--- /dev/null
+++ b/t/pragma/warn/2use
@@ -0,0 +1,308 @@
+Check lexical warnings functionality
+
+TODO
+ check that the warning hierarchy works.
+
+__END__
+
+# check illegal category is caught
+use warnings 'blah' ;
+EXPECT
+unknown warning category 'blah' at - line 3
+BEGIN failed--compilation aborted at - line 3.
+########
+
+# Check compile time scope of pragma
+use warnings 'deprecated' ;
+{
+ no warnings ;
+ 1 if $a EQ $b ;
+}
+1 if $a EQ $b ;
+EXPECT
+Use of EQ is deprecated at - line 8.
+########
+
+# Check compile time scope of pragma
+no warnings;
+{
+ use warnings 'deprecated' ;
+ 1 if $a EQ $b ;
+}
+1 if $a EQ $b ;
+EXPECT
+Use of EQ is deprecated at - line 6.
+########
+
+# Check runtime scope of pragma
+use warnings 'uninitialized' ;
+{
+ no warnings ;
+ my $b ; chop $b ;
+}
+my $b ; chop $b ;
+EXPECT
+Use of uninitialized value at - line 8.
+########
+
+# Check runtime scope of pragma
+no warnings ;
+{
+ use warnings 'uninitialized' ;
+ my $b ; chop $b ;
+}
+my $b ; chop $b ;
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+# Check runtime scope of pragma
+no warnings ;
+{
+ use warnings 'uninitialized' ;
+ $a = sub { my $b ; chop $b ; }
+}
+&$a ;
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+use warnings 'deprecated' ;
+1 if $a EQ $b ;
+EXPECT
+Use of EQ is deprecated at - line 3.
+########
+
+--FILE-- abc
+1 if $a EQ $b ;
+1;
+--FILE--
+use warnings 'deprecated' ;
+require "./abc";
+EXPECT
+
+########
+
+--FILE-- abc
+use warnings 'deprecated' ;
+1;
+--FILE--
+require "./abc";
+1 if $a EQ $b ;
+EXPECT
+
+########
+
+--FILE-- abc
+use warnings 'deprecated' ;
+1 if $a EQ $b ;
+1;
+--FILE--
+use warnings 'uninitialized' ;
+require "./abc";
+my $a ; chop $a ;
+EXPECT
+Use of EQ is deprecated at ./abc line 2.
+Use of uninitialized value at - line 3.
+########
+
+--FILE-- abc.pm
+use warnings 'deprecated' ;
+1 if $a EQ $b ;
+1;
+--FILE--
+use warnings 'uninitialized' ;
+use abc;
+my $a ; chop $a ;
+EXPECT
+Use of EQ is deprecated at abc.pm line 2.
+Use of uninitialized value at - line 3.
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval {
+ my $b ; chop $b ;
+}; print STDERR $@ ;
+my $b ; chop $b ;
+EXPECT
+
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval {
+ use warnings 'uninitialized' ;
+ my $b ; chop $b ;
+}; print STDERR $@ ;
+my $b ; chop $b ;
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+# Check scope of pragma with eval
+use warnings 'uninitialized' ;
+eval {
+ my $b ; chop $b ;
+}; print STDERR $@ ;
+my $b ; chop $b ;
+EXPECT
+Use of uninitialized value at - line 5.
+Use of uninitialized value at - line 7.
+########
+
+# Check scope of pragma with eval
+use warnings 'uninitialized' ;
+eval {
+ no warnings ;
+ my $b ; chop $b ;
+}; print STDERR $@ ;
+my $b ; chop $b ;
+EXPECT
+Use of uninitialized value at - line 8.
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval {
+ 1 if $a EQ $b ;
+}; print STDERR $@ ;
+1 if $a EQ $b ;
+EXPECT
+
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval {
+ use warnings 'deprecated' ;
+ 1 if $a EQ $b ;
+}; print STDERR $@ ;
+1 if $a EQ $b ;
+EXPECT
+Use of EQ is deprecated at - line 6.
+########
+
+# Check scope of pragma with eval
+use warnings 'deprecated' ;
+eval {
+ 1 if $a EQ $b ;
+}; print STDERR $@ ;
+1 if $a EQ $b ;
+EXPECT
+Use of EQ is deprecated at - line 5.
+Use of EQ is deprecated at - line 7.
+########
+
+# Check scope of pragma with eval
+use warnings 'deprecated' ;
+eval {
+ no warnings ;
+ 1 if $a EQ $b ;
+}; print STDERR $@ ;
+1 if $a EQ $b ;
+EXPECT
+Use of EQ is deprecated at - line 8.
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval '
+ my $b ; chop $b ;
+'; print STDERR $@ ;
+my $b ; chop $b ;
+EXPECT
+
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval q[
+ use warnings 'uninitialized' ;
+ my $b ; chop $b ;
+]; print STDERR $@;
+my $b ; chop $b ;
+EXPECT
+Use of uninitialized value at (eval 1) line 3.
+########
+
+# Check scope of pragma with eval
+use warnings 'uninitialized' ;
+eval '
+ my $b ; chop $b ;
+'; print STDERR $@ ;
+my $b ; chop $b ;
+EXPECT
+Use of uninitialized value at (eval 1) line 2.
+Use of uninitialized value at - line 7.
+########
+
+# Check scope of pragma with eval
+use warnings 'uninitialized' ;
+eval '
+ no warnings ;
+ my $b ; chop $b ;
+'; print STDERR $@ ;
+my $b ; chop $b ;
+EXPECT
+Use of uninitialized value at - line 8.
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval '
+ 1 if $a EQ $b ;
+'; print STDERR $@ ;
+1 if $a EQ $b ;
+EXPECT
+
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval q[
+ use warnings 'deprecated' ;
+ 1 if $a EQ $b ;
+]; print STDERR $@;
+1 if $a EQ $b ;
+EXPECT
+Use of EQ is deprecated at (eval 1) line 3.
+########
+
+# Check scope of pragma with eval
+use warnings 'deprecated' ;
+eval '
+ 1 if $a EQ $b ;
+'; print STDERR $@;
+1 if $a EQ $b ;
+EXPECT
+Use of EQ is deprecated at - line 7.
+Use of EQ is deprecated at (eval 1) line 2.
+########
+
+# Check scope of pragma with eval
+use warnings 'deprecated' ;
+eval '
+ no warnings ;
+ 1 if $a EQ $b ;
+'; print STDERR $@;
+1 if $a EQ $b ;
+EXPECT
+Use of EQ is deprecated at - line 8.
+########
+
+# Check the additive nature of the pragma
+1 if $a EQ $b ;
+my $a ; chop $a ;
+use warnings 'deprecated' ;
+1 if $a EQ $b ;
+my $b ; chop $b ;
+use warnings 'uninitialized' ;
+my $c ; chop $c ;
+no warnings 'deprecated' ;
+1 if $a EQ $b ;
+EXPECT
+Use of EQ is deprecated at - line 6.
+Use of uninitialized value at - line 9.
+Use of uninitialized value at - line 11.
+Use of uninitialized value at - line 11.
diff --git a/t/pragma/warn/3both b/t/pragma/warn/3both
new file mode 100644
index 0000000000..592724ad73
--- /dev/null
+++ b/t/pragma/warn/3both
@@ -0,0 +1,197 @@
+Check interaction of $^W and lexical
+
+__END__
+
+# Check interaction of $^W and use warnings
+sub fred {
+ use warnings ;
+ my $b ;
+ chop $b ;
+}
+{ local $^W = 0 ;
+ fred() ;
+}
+
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+# Check interaction of $^W and use warnings
+sub fred {
+ use warnings ;
+ my $b ;
+ chop $b ;
+}
+{ $^W = 0 ;
+ fred() ;
+}
+
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+# Check interaction of $^W and use warnings
+sub fred {
+ no warnings ;
+ my $b ;
+ chop $b ;
+}
+{ local $^W = 1 ;
+ fred() ;
+}
+
+EXPECT
+
+########
+
+# Check interaction of $^W and use warnings
+sub fred {
+ no warnings ;
+ my $b ;
+ chop $b ;
+}
+{ $^W = 1 ;
+ fred() ;
+}
+
+EXPECT
+
+########
+
+# Check interaction of $^W and use warnings
+use warnings ;
+$^W = 1 ;
+my $b ;
+chop $b ;
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+# Check interaction of $^W and use warnings
+$^W = 1 ;
+use warnings ;
+my $b ;
+chop $b ;
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+# Check interaction of $^W and use warnings
+$^W = 1 ;
+no warnings ;
+my $b ;
+chop $b ;
+EXPECT
+
+########
+
+# Check interaction of $^W and use warnings
+no warnings ;
+$^W = 1 ;
+my $b ;
+chop $b ;
+EXPECT
+
+########
+-w
+# Check interaction of $^W and use warnings
+no warnings ;
+my $b ;
+chop $b ;
+EXPECT
+
+########
+-w
+# Check interaction of $^W and use warnings
+use warnings ;
+my $b ;
+chop $b ;
+EXPECT
+Use of uninitialized value at - line 5.
+########
+
+# Check interaction of $^W and use warnings
+sub fred {
+ use warnings ;
+ my $b ;
+ chop $b ;
+}
+BEGIN { $^W = 0 }
+fred() ;
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+# Check interaction of $^W and use warnings
+sub fred {
+ no warnings ;
+ my $b ;
+ chop $b ;
+}
+BEGIN { $^W = 1 }
+fred() ;
+
+EXPECT
+
+########
+
+# Check interaction of $^W and use warnings
+use warnings ;
+BEGIN { $^W = 1 }
+my $b ;
+chop $b ;
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+# Check interaction of $^W and use warnings
+BEGIN { $^W = 1 }
+use warnings ;
+my $b ;
+chop $b ;
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+# Check interaction of $^W and use warnings
+BEGIN { $^W = 1 }
+no warnings ;
+my $b ;
+chop $b ;
+EXPECT
+
+########
+
+# Check interaction of $^W and use warnings
+no warnings ;
+BEGIN { $^W = 1 }
+my $b ;
+chop $b ;
+EXPECT
+
+########
+
+# Check interaction of $^W and use warnings
+BEGIN { $^W = 1 }
+{
+ no warnings ;
+ my $b ;
+ chop $b ;
+}
+my $b ;
+chop $b ;
+EXPECT
+Use of uninitialized value at - line 10.
+########
+
+# Check interaction of $^W and use warnings
+BEGIN { $^W = 0 }
+{
+ use warnings ;
+ my $b ;
+ chop $b ;
+}
+my $b ;
+chop $b ;
+EXPECT
+Use of uninitialized value at - line 7.
diff --git a/t/pragma/warn/4lint b/t/pragma/warn/4lint
new file mode 100644
index 0000000000..6a08409bb2
--- /dev/null
+++ b/t/pragma/warn/4lint
@@ -0,0 +1,112 @@
+Check lint
+
+__END__
+-W
+# lint: check compile time $^W is zapped
+BEGIN { $^W = 0 ;}
+$a = $b = 1 ;
+$a = 1 if $a EQ $b ;
+close STDIN ; print STDIN "abc" ;
+EXPECT
+Use of EQ is deprecated at - line 5.
+print on closed filehandle main::STDIN at - line 6.
+########
+-W
+# lint: check runtime $^W is zapped
+$^W = 0 ;
+close STDIN ; print STDIN "abc" ;
+EXPECT
+print on closed filehandle main::STDIN at - line 4.
+########
+-W
+# lint: check runtime $^W is zapped
+{
+ $^W = 0 ;
+ close STDIN ; print STDIN "abc" ;
+}
+EXPECT
+print on closed filehandle main::STDIN at - line 5.
+########
+-W
+# lint: check "no warnings" is zapped
+no warnings ;
+$a = $b = 1 ;
+$a = 1 if $a EQ $b ;
+close STDIN ; print STDIN "abc" ;
+EXPECT
+Use of EQ is deprecated at - line 5.
+print on closed filehandle main::STDIN at - line 6.
+########
+-W
+# lint: check "no warnings" is zapped
+{
+ no warnings ;
+ close STDIN ; print STDIN "abc" ;
+}
+EXPECT
+print on closed filehandle main::STDIN at - line 5.
+########
+-Ww
+# lint: check combination of -w and -W
+{
+ $^W = 0 ;
+ close STDIN ; print STDIN "abc" ;
+}
+EXPECT
+print on closed filehandle main::STDIN at - line 5.
+########
+-W
+--FILE-- abc.pm
+no warnings 'deprecated' ;
+my ($a, $b) = (0,0);
+1 if $a EQ $b ;
+1;
+--FILE--
+no warnings 'uninitialized' ;
+use abc;
+my $a ; chop $a ;
+EXPECT
+Use of EQ is deprecated at abc.pm line 3.
+Use of uninitialized value at - line 3.
+########
+-W
+--FILE-- abc
+no warnings 'deprecated' ;
+my ($a, $b) = (0,0);
+1 if $a EQ $b ;
+1;
+--FILE--
+no warnings 'uninitialized' ;
+require "./abc";
+my $a ; chop $a ;
+EXPECT
+Use of EQ is deprecated at ./abc line 3.
+Use of uninitialized value at - line 3.
+########
+-W
+--FILE-- abc.pm
+BEGIN {$^W = 0}
+my ($a, $b) = (0,0);
+1 if $a EQ $b ;
+1;
+--FILE--
+$^W = 0 ;
+use abc;
+my $a ; chop $a ;
+EXPECT
+Use of EQ is deprecated at abc.pm line 3.
+Use of uninitialized value at - line 3.
+########
+-W
+--FILE-- abc
+BEGIN {$^W = 0}
+my ($a, $b) = (0,0);
+1 if $a EQ $b ;
+1;
+--FILE--
+$^W = 0 ;
+require "./abc";
+my $a ; chop $a ;
+EXPECT
+Use of EQ is deprecated at ./abc line 3.
+Use of uninitialized value at - line 3.
diff --git a/t/pragma/warn/5nolint b/t/pragma/warn/5nolint
new file mode 100644
index 0000000000..994190a855
--- /dev/null
+++ b/t/pragma/warn/5nolint
@@ -0,0 +1,96 @@
+Check anti-lint
+
+__END__
+-X
+# nolint: check compile time $^W is zapped
+BEGIN { $^W = 1 ;}
+$a = $b = 1 ;
+$a = 1 if $a EQ $b ;
+close STDIN ; print STDIN "abc" ;
+EXPECT
+########
+-X
+# nolint: check runtime $^W is zapped
+$^W = 1 ;
+close STDIN ; print STDIN "abc" ;
+EXPECT
+########
+-X
+# nolint: check runtime $^W is zapped
+{
+ $^W = 1 ;
+ close STDIN ; print STDIN "abc" ;
+}
+EXPECT
+########
+-X
+# nolint: check "no warnings" is zapped
+use warnings ;
+$a = $b = 1 ;
+$a = 1 if $a EQ $b ;
+close STDIN ; print STDIN "abc" ;
+EXPECT
+########
+-X
+# nolint: check "no warnings" is zapped
+{
+ use warnings ;
+ close STDIN ; print STDIN "abc" ;
+}
+EXPECT
+########
+-Xw
+# nolint: check combination of -w and -X
+{
+ $^W = 1 ;
+ close STDIN ; print STDIN "abc" ;
+}
+EXPECT
+########
+-X
+--FILE-- abc.pm
+use warnings 'deprecated' ;
+my ($a, $b) = (0,0);
+1 if $a EQ $b ;
+1;
+--FILE--
+use warnings 'uninitialized' ;
+use abc;
+my $a ; chop $a ;
+EXPECT
+########
+-X
+--FILE-- abc
+use warnings 'deprecated' ;
+my ($a, $b) = (0,0);
+1 if $a EQ $b ;
+1;
+--FILE--
+use warnings 'uninitialized' ;
+require "./abc";
+my $a ; chop $a ;
+EXPECT
+########
+-X
+--FILE-- abc.pm
+BEGIN {$^W = 1}
+my ($a, $b) = (0,0);
+1 if $a EQ $b ;
+1;
+--FILE--
+$^W = 1 ;
+use abc;
+my $a ; chop $a ;
+EXPECT
+########
+-X
+--FILE-- abc
+BEGIN {$^W = 1}
+my ($a, $b) = (0,0);
+1 if $a EQ $b ;
+1;
+--FILE--
+$^W = 1 ;
+require "./abc";
+my $a ; chop $a ;
+EXPECT
diff --git a/t/pragma/warn/6default b/t/pragma/warn/6default
new file mode 100644
index 0000000000..dd3d1825f4
--- /dev/null
+++ b/t/pragma/warn/6default
@@ -0,0 +1,53 @@
+Check default warnings
+
+__END__
+# default warnings should be displayed if you don't add anything
+# optional shouldn't
+my $a = oct "7777777777777777777777777777777777779" ;
+EXPECT
+Integer overflow in octal number at - line 3.
+########
+# no warnings should be displayed
+no warnings ;
+my $a = oct "7777777777777777777777777777777777778" ;
+EXPECT
+########
+# all warnings should be displayed
+use warnings ;
+my $a = oct "7777777777777777777777777777777777778" ;
+EXPECT
+Integer overflow in octal number at - line 3.
+Illegal octal digit '8' ignored at - line 3.
+Octal number > 037777777777 non-portable at - line 3.
+########
+# check scope
+use warnings ;
+my $a = oct "7777777777777777777777777777777777778" ;
+{
+ no warnings ;
+ my $a = oct "7777777777777777777777777777777777778" ;
+}
+my $c = oct "7777777777777777777777777777777777778" ;
+EXPECT
+Integer overflow in octal number at - line 3.
+Illegal octal digit '8' ignored at - line 3.
+Octal number > 037777777777 non-portable at - line 3.
+Integer overflow in octal number at - line 8.
+Illegal octal digit '8' ignored at - line 8.
+Octal number > 037777777777 non-portable at - line 8.
+########
+# all warnings should be displayed
+use warnings ;
+my $a = oct "0xfffffffffffffffffg" ;
+EXPECT
+Integer overflow in hexadecimal number at - line 3.
+Illegal hexadecimal digit 'g' ignored at - line 3.
+Hexadecimal number > 0xffffffff non-portable at - line 3.
+########
+# all warnings should be displayed
+use warnings ;
+my $a = oct "0b111111111111111111111111111111111111111111111111111111111111111112";
+EXPECT
+Integer overflow in binary number at - line 3.
+Illegal binary digit '2' ignored at - line 3.
+Binary number > 0b11111111111111111111111111111111 non-portable at - line 3.
diff --git a/t/pragma/warn/7fatal b/t/pragma/warn/7fatal
new file mode 100644
index 0000000000..fe94511f3e
--- /dev/null
+++ b/t/pragma/warn/7fatal
@@ -0,0 +1,242 @@
+Check FATAL functionality
+
+__END__
+
+# Check compile time warning
+use warnings FATAL => 'deprecated' ;
+{
+ no warnings ;
+ 1 if $a EQ $b ;
+}
+1 if $a EQ $b ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of EQ is deprecated at - line 8.
+########
+
+# Check runtime scope of pragma
+use warnings FATAL => 'uninitialized' ;
+{
+ no warnings ;
+ my $b ; chop $b ;
+}
+my $b ; chop $b ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of uninitialized value at - line 8.
+########
+
+# Check runtime scope of pragma
+no warnings ;
+{
+ use warnings FATAL => 'uninitialized' ;
+ $a = sub { my $b ; chop $b ; }
+}
+&$a ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of uninitialized value at - line 6.
+########
+
+--FILE-- abc
+1 if $a EQ $b ;
+1;
+--FILE--
+use warnings FATAL => 'deprecated' ;
+require "./abc";
+EXPECT
+
+########
+
+--FILE-- abc
+use warnings FATAL => 'deprecated' ;
+1;
+--FILE--
+require "./abc";
+1 if $a EQ $b ;
+EXPECT
+
+########
+
+--FILE-- abc
+use warnings 'deprecated' ;
+1 if $a EQ $b ;
+1;
+--FILE--
+use warnings FATAL => 'uninitialized' ;
+require "./abc";
+my $a ; chop $a ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of EQ is deprecated at ./abc line 2.
+Use of uninitialized value at - line 3.
+########
+
+--FILE-- abc.pm
+use warnings 'deprecated' ;
+1 if $a EQ $b ;
+1;
+--FILE--
+use warnings FATAL => 'uninitialized' ;
+use abc;
+my $a ; chop $a ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of EQ is deprecated at abc.pm line 2.
+Use of uninitialized value at - line 3.
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval {
+ use warnings FATAL => 'uninitialized' ;
+ my $b ; chop $b ;
+}; print STDERR "-- $@" ;
+my $b ; chop $b ;
+print STDERR "The End.\n" ;
+EXPECT
+-- Use of uninitialized value at - line 6.
+The End.
+########
+
+# Check scope of pragma with eval
+use warnings FATAL => 'uninitialized' ;
+eval {
+ my $b ; chop $b ;
+}; print STDERR "-- $@" ;
+my $b ; chop $b ;
+print STDERR "The End.\n" ;
+EXPECT
+-- Use of uninitialized value at - line 5.
+Use of uninitialized value at - line 7.
+########
+
+# Check scope of pragma with eval
+use warnings FATAL => 'uninitialized' ;
+eval {
+ no warnings ;
+ my $b ; chop $b ;
+}; print STDERR $@ ;
+my $b ; chop $b ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of uninitialized value at - line 8.
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval {
+ use warnings FATAL => 'deprecated' ;
+ 1 if $a EQ $b ;
+}; print STDERR "-- $@" ;
+1 if $a EQ $b ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of EQ is deprecated at - line 6.
+########
+
+# Check scope of pragma with eval
+use warnings FATAL => 'deprecated' ;
+eval {
+ 1 if $a EQ $b ;
+}; print STDERR "-- $@" ;
+1 if $a EQ $b ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of EQ is deprecated at - line 5.
+########
+
+# Check scope of pragma with eval
+use warnings FATAL => 'deprecated' ;
+eval {
+ no warnings ;
+ 1 if $a EQ $b ;
+}; print STDERR $@ ;
+1 if $a EQ $b ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of EQ is deprecated at - line 8.
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval {
+ use warnings FATAL => 'deprecated' ;
+}; print STDERR $@ ;
+1 if $a EQ $b ;
+print STDERR "The End.\n" ;
+EXPECT
+The End.
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval q[
+ use warnings FATAL => 'uninitialized' ;
+ my $b ; chop $b ;
+]; print STDERR "-- $@";
+my $b ; chop $b ;
+print STDERR "The End.\n" ;
+EXPECT
+-- Use of uninitialized value at (eval 1) line 3.
+The End.
+########
+
+# Check scope of pragma with eval
+use warnings FATAL => 'uninitialized' ;
+eval '
+ my $b ; chop $b ;
+'; print STDERR "-- $@" ;
+my $b ; chop $b ;
+print STDERR "The End.\n" ;
+EXPECT
+-- Use of uninitialized value at (eval 1) line 2.
+Use of uninitialized value at - line 7.
+########
+
+# Check scope of pragma with eval
+use warnings FATAL => 'uninitialized' ;
+eval '
+ no warnings ;
+ my $b ; chop $b ;
+'; print STDERR $@ ;
+my $b ; chop $b ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of uninitialized value at - line 8.
+########
+
+# Check scope of pragma with eval
+no warnings ;
+eval q[
+ use warnings FATAL => 'deprecated' ;
+ 1 if $a EQ $b ;
+]; print STDERR "-- $@";
+1 if $a EQ $b ;
+print STDERR "The End.\n" ;
+EXPECT
+-- Use of EQ is deprecated at (eval 1) line 3.
+The End.
+########
+
+# Check scope of pragma with eval
+use warnings FATAL => 'deprecated' ;
+eval '
+ 1 if $a EQ $b ;
+'; print STDERR "-- $@";
+print STDERR "The End.\n" ;
+EXPECT
+-- Use of EQ is deprecated at (eval 1) line 2.
+The End.
+########
+
+# Check scope of pragma with eval
+use warnings FATAL => 'deprecated' ;
+eval '
+ no warnings ;
+ 1 if $a EQ $b ;
+'; print STDERR "-- $@";
+1 if $a EQ $b ;
+print STDERR "The End.\n" ;
+EXPECT
+Use of EQ is deprecated at - line 8.
diff --git a/t/pragma/warn/8signal b/t/pragma/warn/8signal
new file mode 100644
index 0000000000..0be2d13cc0
--- /dev/null
+++ b/t/pragma/warn/8signal
@@ -0,0 +1,18 @@
+Check interaction of __WARN__, __DIE__ & lexical Warnings
+
+TODO
+
+__END__
+# 8signal
+BEGIN { $SIG{__WARN__} = sub { print "WARN -- @_" } }
+BEGIN { $SIG{__DIE__} = sub { print "DIE -- @_" } }
+1 if 1 EQ 2 ;
+use warnings qw(deprecated) ;
+1 if 1 EQ 2 ;
+use warnings FATAL => qw(deprecated) ;
+1 if 1 EQ 2 ;
+print "The End.\n" ;
+EXPECT
+Use of EQ is deprecated at - line 8.
+WARN -- Use of EQ is deprecated at - line 6.
+DIE -- Use of EQ is deprecated at - line 8.
diff --git a/t/pragma/warn/av b/t/pragma/warn/av
new file mode 100644
index 0000000000..79bd3b7600
--- /dev/null
+++ b/t/pragma/warn/av
@@ -0,0 +1,9 @@
+ av.c
+
+ Mandatory Warnings ALL TODO
+ ------------------
+ av_reify called on tied array [av_reify]
+
+ Attempt to clear deleted array [av_clear]
+
+__END__
diff --git a/t/pragma/warn/doio b/t/pragma/warn/doio
new file mode 100644
index 0000000000..5101bdef80
--- /dev/null
+++ b/t/pragma/warn/doio
@@ -0,0 +1,191 @@
+ doio.c
+
+ Can't do bidirectional pipe [Perl_do_open9]
+ open(F, "| true |");
+
+ Missing command in piped open [Perl_do_open9]
+ open(F, "| ");
+
+ Missing command in piped open [Perl_do_open9]
+ open(F, " |");
+
+ warn(warn_nl, "open"); [Perl_do_open9]
+ open(F, "true\ncd")
+
+ Close on unopened file <%s> [Perl_do_close] <<TODO
+ $a = "fred";close("$a")
+
+ tell() on unopened file [Perl_do_tell]
+ $a = "fred";$a = tell($a)
+
+ seek() on unopened file [Perl_do_seek]
+ $a = "fred";$a = seek($a,1,1)
+
+ sysseek() on unopened file [Perl_do_sysseek]
+ $a = "fred";$a = seek($a,1,1)
+
+ warn(warn_uninit); [Perl_do_print]
+ print $a ;
+
+ Stat on unopened file <%s> [Perl_my_stat]
+ close STDIN ; -x STDIN ;
+
+ warn(warn_nl, "stat"); [Perl_my_stat]
+ stat "ab\ncd"
+
+ warn(warn_nl, "lstat"); [Perl_my_lstat]
+ lstat "ab\ncd"
+
+ Can't exec \"%s\": %s [Perl_do_aexec5]
+
+ Can't exec \"%s\": %s [Perl_do_exec3]
+
+ Filehandle %s opened only for output [Perl_do_eof]
+ my $a = eof STDOUT
+
+ Mandatory Warnings ALL TODO
+ ------------------
+ Can't do inplace edit: %s is not a regular file [Perl_nextargv]
+ edit a directory
+
+ Can't do inplace edit: %s would not be unique [Perl_nextargv]
+ Can't rename %s to %s: %s, skipping file [Perl_nextargv]
+ Can't rename %s to %s: %s, skipping file [Perl_nextargv]
+ Can't remove %s: %s, skipping file [Perl_nextargv]
+ Can't do inplace edit on %s: %s [Perl_nextargv]
+
+
+__END__
+# doio.c [Perl_do_open9]
+use warnings 'io' ;
+open(F, '|'.($^O eq 'VMS' ? 'mcr ':'')."$^X -e 1|");
+close(F);
+no warnings 'io' ;
+open(G, '|'.($^O eq 'VMS' ? 'mcr ':'')."$^X -e 1|");
+close(G);
+EXPECT
+Can't do bidirectional pipe at - line 3.
+########
+# doio.c [Perl_do_open9]
+use warnings 'io' ;
+open(F, "| ");
+no warnings 'io' ;
+open(G, "| ");
+EXPECT
+Missing command in piped open at - line 3.
+########
+# doio.c [Perl_do_open9]
+use warnings 'io' ;
+open(F, " |");
+no warnings 'io' ;
+open(G, " |");
+EXPECT
+Missing command in piped open at - line 3.
+########
+# doio.c [Perl_do_open9]
+use warnings 'io' ;
+open(F, "<true\ncd");
+no warnings 'io' ;
+open(G, "<true\ncd");
+EXPECT
+Unsuccessful open on filename containing newline at - line 3.
+########
+# doio.c [Perl_do_close] <<TODO
+use warnings 'unopened' ;
+close "fred" ;
+no warnings 'unopened' ;
+close "joe" ;
+EXPECT
+Close on unopened file <fred> at - line 3.
+########
+# doio.c [Perl_do_tell Perl_do_seek Perl_do_sysseek Perl_my_stat]
+use warnings 'io' ;
+close STDIN ;
+tell(STDIN);
+$a = seek(STDIN,1,1);
+$a = sysseek(STDIN,1,1);
+-x STDIN ;
+no warnings 'io' ;
+close STDIN ;
+tell(STDIN);
+$a = seek(STDIN,1,1);
+$a = sysseek(STDIN,1,1);
+-x STDIN ;
+EXPECT
+tell() on unopened file at - line 4.
+seek() on unopened file at - line 5.
+sysseek() on unopened file at - line 6.
+Stat on unopened file <STDIN> at - line 7.
+########
+# doio.c [Perl_do_print]
+use warnings 'uninitialized' ;
+print $a ;
+no warnings 'uninitialized' ;
+print $b ;
+EXPECT
+Use of uninitialized value at - line 3.
+########
+# doio.c [Perl_my_stat Perl_my_lstat]
+use warnings 'io' ;
+stat "ab\ncd";
+lstat "ab\ncd";
+no warnings 'io' ;
+stat "ab\ncd";
+lstat "ab\ncd";
+EXPECT
+Unsuccessful stat on filename containing newline at - line 3.
+Unsuccessful stat on filename containing newline at - line 4.
+########
+# doio.c [Perl_do_aexec5]
+use warnings 'io' ;
+exec "lskdjfalksdjfdjfkls","" ;
+no warnings 'io' ;
+exec "lskdjfalksdjfdjfkls","" ;
+EXPECT
+OPTION regex
+Can't exec "lskdjfalksdjfdjfkls": .+
+########
+# doio.c [Perl_do_exec3]
+use warnings 'io' ;
+exec "lskdjfalksdjfdjfkls", "abc" ;
+no warnings 'io' ;
+exec "lskdjfalksdjfdjfkls", "abc" ;
+EXPECT
+OPTION regex
+Can't exec "lskdjfalksdjfdjfkls(:? abc)?": .+
+########
+# doio.c [Perl_nextargv]
+$^W = 0 ;
+my $filename = "./temp" ;
+mkdir $filename, 0777
+ or die "Cannot create directory $filename: $!\n" ;
+{
+ local (@ARGV) = ($filename) ;
+ local ($^I) = "" ;
+ my $x = <> ;
+}
+{
+ no warnings 'inplace' ;
+ local (@ARGV) = ($filename) ;
+ local ($^I) = "" ;
+ my $x = <> ;
+}
+{
+ use warnings 'inplace' ;
+ local (@ARGV) = ($filename) ;
+ local ($^I) = "" ;
+ my $x = <> ;
+}
+rmdir $filename ;
+EXPECT
+Can't do inplace edit: ./temp is not a regular file at - line 9.
+Can't do inplace edit: ./temp is not a regular file at - line 21.
+
+########
+# doio.c [Perl_do_eof]
+use warnings 'io' ;
+my $a = eof STDOUT ;
+no warnings 'io' ;
+$a = eof STDOUT ;
+EXPECT
+Filehandle main::STDOUT opened only for output at - line 3.
diff --git a/t/pragma/warn/doop b/t/pragma/warn/doop
new file mode 100644
index 0000000000..961d157502
--- /dev/null
+++ b/t/pragma/warn/doop
@@ -0,0 +1,25 @@
+ doop.c AOK
+
+ Malformed UTF-8 character
+
+
+__END__
+# doop.c
+use utf8 ;
+$_ = "\x80 \xff" ;
+chop ;
+EXPECT
+Malformed UTF-8 character at - line 4.
+########
+# doop.c
+use warnings 'utf8' ;
+use utf8 ;
+$_ = "\x80 \xff" ;
+chop ;
+no warnings 'utf8' ;
+$_ = "\x80 \xff" ;
+chop ;
+EXPECT
+\x80 will produce malformed UTF-8 character; use \x{80} for that at - line 4.
+\xff will produce malformed UTF-8 character; use \x{ff} for that at - line 4.
+Malformed UTF-8 character at - line 5.
diff --git a/t/pragma/warn/gv b/t/pragma/warn/gv
new file mode 100644
index 0000000000..5ed4eca018
--- /dev/null
+++ b/t/pragma/warn/gv
@@ -0,0 +1,54 @@
+ gv.c AOK
+
+ Can't locate package %s for @%s::ISA
+ @ISA = qw(Fred); joe()
+
+ Use of inherited AUTOLOAD for non-method %s::%.*s() is deprecated
+ sub Other::AUTOLOAD { 1 } sub Other::fred {}
+ @ISA = qw(Other) ;
+ fred() ;
+
+ Use of $# is deprecated
+ Use of $* is deprecated
+
+ $a = ${"#"} ;
+ $a = ${"*"} ;
+
+ Mandatory Warnings ALL TODO
+ ------------------
+
+ Had to create %s unexpectedly [gv_fetchpv]
+ Attempt to free unreferenced glob pointers [gp_free]
+
+__END__
+# gv.c
+use warnings 'misc' ;
+@ISA = qw(Fred); joe()
+EXPECT
+Can't locate package Fred for @main::ISA at - line 3.
+Undefined subroutine &main::joe called at - line 3.
+########
+# gv.c
+no warnings 'misc' ;
+@ISA = qw(Fred); joe()
+EXPECT
+Undefined subroutine &main::joe called at - line 3.
+########
+# gv.c
+sub Other::AUTOLOAD { 1 } sub Other::fred {}
+@ISA = qw(Other) ;
+use warnings 'deprecated' ;
+fred() ;
+EXPECT
+Use of inherited AUTOLOAD for non-method main::fred() is deprecated at - line 5.
+########
+# gv.c
+use warnings 'deprecated' ;
+$a = ${"#"};
+$a = ${"*"};
+no warnings 'deprecated' ;
+$a = ${"#"};
+$a = ${"*"};
+EXPECT
+Use of $# is deprecated at - line 3.
+Use of $* is deprecated at - line 4.
diff --git a/t/pragma/warn/hv b/t/pragma/warn/hv
new file mode 100644
index 0000000000..c9eec028f1
--- /dev/null
+++ b/t/pragma/warn/hv
@@ -0,0 +1,8 @@
+ hv.c
+
+
+ Mandatory Warnings ALL TODO
+ ------------------
+ Attempt to free non-existent shared string [unsharepvn]
+
+__END__
diff --git a/t/pragma/warn/malloc b/t/pragma/warn/malloc
new file mode 100644
index 0000000000..2f8b096a51
--- /dev/null
+++ b/t/pragma/warn/malloc
@@ -0,0 +1,9 @@
+ malloc.c
+
+
+ Mandatory Warnings ALL TODO
+ ------------------
+ %s free() ignored [Perl_mfree]
+ %s", "Bad free() ignored [Perl_mfree]
+
+__END__
diff --git a/t/pragma/warn/mg b/t/pragma/warn/mg
new file mode 100644
index 0000000000..a8f9dbc338
--- /dev/null
+++ b/t/pragma/warn/mg
@@ -0,0 +1,44 @@
+ mg.c AOK
+
+ No such signal: SIG%s
+ $SIG{FRED} = sub {}
+
+ SIG%s handler \"%s\" not defined.
+ $SIG{"INT"} = "ok3"; kill "INT",$$;
+
+ Mandatory Warnings TODO
+ ------------------
+ Can't break at that line [magic_setdbline]
+
+__END__
+# mg.c
+use warnings 'signal' ;
+$SIG{FRED} = sub {};
+EXPECT
+No such signal: SIGFRED at - line 3.
+########
+# mg.c
+no warnings 'signal' ;
+$SIG{FRED} = sub {};
+EXPECT
+
+########
+# mg.c
+use warnings 'signal' ;
+if ($^O eq 'MSWin32' || $^O eq 'VMS') {
+ print "SKIPPED\n# $^O, can't kill() to raise()\n"; exit;
+}
+$|=1;
+$SIG{"INT"} = "fred"; kill "INT",$$;
+EXPECT
+SIGINT handler "fred" not defined.
+########
+# mg.c
+no warnings 'signal' ;
+if ($^O eq 'MSWin32' || $^O eq 'VMS') {
+ print "SKIPPED\n# win32, can't kill() to raise()\n"; exit;
+}
+$|=1;
+$SIG{"INT"} = "fred"; kill "INT",$$;
+EXPECT
+
diff --git a/t/pragma/warn/op b/t/pragma/warn/op
new file mode 100644
index 0000000000..e50420a8f6
--- /dev/null
+++ b/t/pragma/warn/op
@@ -0,0 +1,810 @@
+ op.c AOK
+
+ "my" variable %s masks earlier declaration in same scope
+ my $x;
+ my $x ;
+
+ Variable "%s" may be unavailable
+ sub x {
+ my $x;
+ sub y {
+ $x
+ }
+ }
+
+ Variable "%s" will not stay shared
+ sub x {
+ my $x;
+ sub y {
+ sub { $x }
+ }
+ }
+
+ Found = in conditional, should be ==
+ 1 if $a = 1 ;
+
+ Use of implicit split to @_ is deprecated
+ split ;
+
+ Use of implicit split to @_ is deprecated
+ $a = split ;
+
+ Useless use of time in void context
+ Useless use of a variable in void context
+ Useless use of a constant in void context
+ time ;
+ $a ;
+ "abc"
+
+ Applying %s to %s will act on scalar(%s)
+ my $a ; my @a = () ; my %a = () ; my $b = \@a ; my $c = \%a ;
+ @a =~ /abc/ ;
+ @a =~ s/a/b/ ;
+ @a =~ tr/a/b/ ;
+ @$b =~ /abc/ ;
+ @$b =~ s/a/b/ ;
+ @$b =~ tr/a/b/ ;
+ %a =~ /abc/ ;
+ %a =~ s/a/b/ ;
+ %a =~ tr/a/b/ ;
+ %$c =~ /abc/ ;
+ %$c =~ s/a/b/ ;
+ %$c =~ tr/a/b/ ;
+
+
+ Parentheses missing around "my" list at -e line 1.
+ my $a, $b = (1,2);
+
+ Parentheses missing around "local" list at -e line 1.
+ local $a, $b = (1,2);
+
+ Probable precedence problem on logical or at -e line 1.
+ use warnings 'syntax'; my $x = print(ABC || 1);
+
+ Value of %s may be \"0\"; use \"defined\"
+ $x = 1 if $x = <FH> ;
+ $x = 1 while $x = <FH> ;
+
+ Subroutine fred redefined at -e line 1.
+ sub fred{1;} sub fred{1;}
+
+ Constant subroutine %s redefined
+ sub fred() {1;} sub fred() {1;}
+
+ Format FRED redefined at /tmp/x line 5.
+ format FRED =
+ .
+ format FRED =
+ .
+
+ Array @%s missing the @ in argument %d of %s()
+ push fred ;
+
+ Hash %%%s missing the %% in argument %d of %s()
+ keys joe ;
+
+ Statement unlikely to be reached
+ (Maybe you meant system() when you said exec()?
+ exec "true" ; my $a
+
+ defined(@array) is deprecated
+ (Maybe you should just omit the defined()?)
+ my @a ; defined @a ;
+ defined (@a = (1,2,3)) ;
+
+ defined(%hash) is deprecated
+ (Maybe you should just omit the defined()?)
+ my %h ; defined %h ;
+
+ /---/ should probably be written as "---"
+ join(/---/, @foo);
+
+ %s() called too early to check prototype [Perl_peep]
+ fred() ; sub fred ($$) {}
+
+
+ Mandatory Warnings
+ ------------------
+ Prototype mismatch: [cv_ckproto]
+ sub fred() ;
+ sub fred($) {}
+
+ %s never introduced [pad_leavemy] TODO
+ Runaway prototype [newSUB] TODO
+ oops: oopsAV [oopsAV] TODO
+ oops: oopsHV [oopsHV] TODO
+
+
+__END__
+# op.c
+use warnings 'unsafe' ;
+my $x ;
+my $x ;
+no warnings 'unsafe' ;
+my $x ;
+EXPECT
+"my" variable $x masks earlier declaration in same scope at - line 4.
+########
+# op.c
+use warnings 'unsafe' ;
+sub x {
+ my $x;
+ sub y {
+ $x
+ }
+ }
+EXPECT
+Variable "$x" will not stay shared at - line 7.
+########
+# op.c
+no warnings 'unsafe' ;
+sub x {
+ my $x;
+ sub y {
+ $x
+ }
+ }
+EXPECT
+
+########
+# op.c
+use warnings 'unsafe' ;
+sub x {
+ my $x;
+ sub y {
+ sub { $x }
+ }
+ }
+EXPECT
+Variable "$x" may be unavailable at - line 6.
+########
+# op.c
+no warnings 'unsafe' ;
+sub x {
+ my $x;
+ sub y {
+ sub { $x }
+ }
+ }
+EXPECT
+
+########
+# op.c
+use warnings 'syntax' ;
+1 if $a = 1 ;
+no warnings 'syntax' ;
+1 if $a = 1 ;
+EXPECT
+Found = in conditional, should be == at - line 3.
+########
+# op.c
+use warnings 'deprecated' ;
+split ;
+no warnings 'deprecated' ;
+split ;
+EXPECT
+Use of implicit split to @_ is deprecated at - line 3.
+########
+# op.c
+use warnings 'deprecated' ;
+$a = split ;
+no warnings 'deprecated' ;
+$a = split ;
+EXPECT
+Use of implicit split to @_ is deprecated at - line 3.
+########
+# op.c
+use warnings 'void' ; close STDIN ;
+1 x 3 ; # OP_REPEAT
+ # OP_GVSV
+wantarray ; # OP_WANTARRAY
+ # OP_GV
+ # OP_PADSV
+ # OP_PADAV
+ # OP_PADHV
+ # OP_PADANY
+ # OP_AV2ARYLEN
+ref ; # OP_REF
+\@a ; # OP_REFGEN
+\$a ; # OP_SREFGEN
+defined $a ; # OP_DEFINED
+hex $a ; # OP_HEX
+oct $a ; # OP_OCT
+length $a ; # OP_LENGTH
+substr $a,1 ; # OP_SUBSTR
+vec $a,1,2 ; # OP_VEC
+index $a,1,2 ; # OP_INDEX
+rindex $a,1,2 ; # OP_RINDEX
+sprintf $a ; # OP_SPRINTF
+$a[0] ; # OP_AELEM
+ # OP_AELEMFAST
+@a[0] ; # OP_ASLICE
+#values %a ; # OP_VALUES
+#keys %a ; # OP_KEYS
+$a{0} ; # OP_HELEM
+@a{0} ; # OP_HSLICE
+unpack "a", "a" ; # OP_UNPACK
+pack $a,"" ; # OP_PACK
+join "" ; # OP_JOIN
+(@a)[0,1] ; # OP_LSLICE
+ # OP_ANONLIST
+ # OP_ANONHASH
+sort(1,2) ; # OP_SORT
+reverse(1,2) ; # OP_REVERSE
+ # OP_RANGE
+ # OP_FLIP
+(1 ..2) ; # OP_FLOP
+caller ; # OP_CALLER
+fileno STDIN ; # OP_FILENO
+eof STDIN ; # OP_EOF
+tell STDIN ; # OP_TELL
+readlink 1; # OP_READLINK
+time ; # OP_TIME
+localtime ; # OP_LOCALTIME
+gmtime ; # OP_GMTIME
+eval { getgrnam 1 }; # OP_GGRNAM
+eval { getgrgid 1 }; # OP_GGRGID
+eval { getpwnam 1 }; # OP_GPWNAM
+eval { getpwuid 1 }; # OP_GPWUID
+EXPECT
+Useless use of repeat in void context at - line 3.
+Useless use of wantarray in void context at - line 5.
+Useless use of reference-type operator in void context at - line 12.
+Useless use of reference constructor in void context at - line 13.
+Useless use of single ref constructor in void context at - line 14.
+Useless use of defined operator in void context at - line 15.
+Useless use of hex in void context at - line 16.
+Useless use of oct in void context at - line 17.
+Useless use of length in void context at - line 18.
+Useless use of substr in void context at - line 19.
+Useless use of vec in void context at - line 20.
+Useless use of index in void context at - line 21.
+Useless use of rindex in void context at - line 22.
+Useless use of sprintf in void context at - line 23.
+Useless use of array element in void context at - line 24.
+Useless use of array slice in void context at - line 26.
+Useless use of hash elem in void context at - line 29.
+Useless use of hash slice in void context at - line 30.
+Useless use of unpack in void context at - line 31.
+Useless use of pack in void context at - line 32.
+Useless use of join in void context at - line 33.
+Useless use of list slice in void context at - line 34.
+Useless use of sort in void context at - line 37.
+Useless use of reverse in void context at - line 38.
+Useless use of range (or flop) in void context at - line 41.
+Useless use of caller in void context at - line 42.
+Useless use of fileno in void context at - line 43.
+Useless use of eof in void context at - line 44.
+Useless use of tell in void context at - line 45.
+Useless use of readlink in void context at - line 46.
+Useless use of time in void context at - line 47.
+Useless use of localtime in void context at - line 48.
+Useless use of gmtime in void context at - line 49.
+Useless use of getgrnam in void context at - line 50.
+Useless use of getgrgid in void context at - line 51.
+Useless use of getpwnam in void context at - line 52.
+Useless use of getpwuid in void context at - line 53.
+########
+# op.c
+no warnings 'void' ; close STDIN ;
+1 x 3 ; # OP_REPEAT
+ # OP_GVSV
+wantarray ; # OP_WANTARRAY
+ # OP_GV
+ # OP_PADSV
+ # OP_PADAV
+ # OP_PADHV
+ # OP_PADANY
+ # OP_AV2ARYLEN
+ref ; # OP_REF
+\@a ; # OP_REFGEN
+\$a ; # OP_SREFGEN
+defined $a ; # OP_DEFINED
+hex $a ; # OP_HEX
+oct $a ; # OP_OCT
+length $a ; # OP_LENGTH
+substr $a,1 ; # OP_SUBSTR
+vec $a,1,2 ; # OP_VEC
+index $a,1,2 ; # OP_INDEX
+rindex $a,1,2 ; # OP_RINDEX
+sprintf $a ; # OP_SPRINTF
+$a[0] ; # OP_AELEM
+ # OP_AELEMFAST
+@a[0] ; # OP_ASLICE
+#values %a ; # OP_VALUES
+#keys %a ; # OP_KEYS
+$a{0} ; # OP_HELEM
+@a{0} ; # OP_HSLICE
+unpack "a", "a" ; # OP_UNPACK
+pack $a,"" ; # OP_PACK
+join "" ; # OP_JOIN
+(@a)[0,1] ; # OP_LSLICE
+ # OP_ANONLIST
+ # OP_ANONHASH
+sort(1,2) ; # OP_SORT
+reverse(1,2) ; # OP_REVERSE
+ # OP_RANGE
+ # OP_FLIP
+(1 ..2) ; # OP_FLOP
+caller ; # OP_CALLER
+fileno STDIN ; # OP_FILENO
+eof STDIN ; # OP_EOF
+tell STDIN ; # OP_TELL
+readlink 1; # OP_READLINK
+time ; # OP_TIME
+localtime ; # OP_LOCALTIME
+gmtime ; # OP_GMTIME
+eval { getgrnam 1 }; # OP_GGRNAM
+eval { getgrgid 1 }; # OP_GGRGID
+eval { getpwnam 1 }; # OP_GPWNAM
+eval { getpwuid 1 }; # OP_GPWUID
+EXPECT
+########
+# op.c
+use warnings 'void' ;
+for (@{[0]}) { "$_" } # check warning isn't duplicated
+no warnings 'void' ;
+for (@{[0]}) { "$_" } # check warning isn't duplicated
+EXPECT
+Useless use of string in void context at - line 3.
+########
+# op.c
+use warnings 'void' ;
+use Config ;
+BEGIN {
+ if ( ! $Config{d_telldir}) {
+ print <<EOM ;
+SKIPPED
+# telldir not present
+EOM
+ exit
+ }
+}
+telldir 1 ; # OP_TELLDIR
+no warnings 'void' ;
+telldir 1 ; # OP_TELLDIR
+EXPECT
+Useless use of telldir in void context at - line 13.
+########
+# op.c
+use warnings 'void' ;
+use Config ;
+BEGIN {
+ if ( ! $Config{d_getppid}) {
+ print <<EOM ;
+SKIPPED
+# getppid not present
+EOM
+ exit
+ }
+}
+getppid ; # OP_GETPPID
+no warnings 'void' ;
+getppid ; # OP_GETPPID
+EXPECT
+Useless use of getppid in void context at - line 13.
+########
+# op.c
+use warnings 'void' ;
+use Config ;
+BEGIN {
+ if ( ! $Config{d_getpgrp}) {
+ print <<EOM ;
+SKIPPED
+# getpgrp not present
+EOM
+ exit
+ }
+}
+getpgrp ; # OP_GETPGRP
+no warnings 'void' ;
+getpgrp ; # OP_GETPGRP
+EXPECT
+Useless use of getpgrp in void context at - line 13.
+########
+# op.c
+use warnings 'void' ;
+use Config ;
+BEGIN {
+ if ( ! $Config{d_times}) {
+ print <<EOM ;
+SKIPPED
+# times not present
+EOM
+ exit
+ }
+}
+times ; # OP_TMS
+no warnings 'void' ;
+times ; # OP_TMS
+EXPECT
+Useless use of times in void context at - line 13.
+########
+# op.c
+use warnings 'void' ;
+use Config ;
+BEGIN {
+ if ( ! $Config{d_getprior} or $^O eq 'os2') { # Locks before fixpak22
+ print <<EOM ;
+SKIPPED
+# getpriority not present
+EOM
+ exit
+ }
+}
+getpriority 1,2; # OP_GETPRIORITY
+no warnings 'void' ;
+getpriority 1,2; # OP_GETPRIORITY
+EXPECT
+Useless use of getpriority in void context at - line 13.
+########
+# op.c
+use warnings 'void' ;
+use Config ;
+BEGIN {
+ if ( ! $Config{d_getlogin}) {
+ print <<EOM ;
+SKIPPED
+# getlogin not present
+EOM
+ exit
+ }
+}
+getlogin ; # OP_GETLOGIN
+no warnings 'void' ;
+getlogin ; # OP_GETLOGIN
+EXPECT
+Useless use of getlogin in void context at - line 13.
+########
+# op.c
+use warnings 'void' ;
+use Config ; BEGIN {
+if ( ! $Config{d_socket}) {
+ print <<EOM ;
+SKIPPED
+# getsockname not present
+# getpeername not present
+# gethostbyname not present
+# gethostbyaddr not present
+# gethostent not present
+# getnetbyname not present
+# getnetbyaddr not present
+# getnetent not present
+# getprotobyname not present
+# getprotobynumber not present
+# getprotoent not present
+# getservbyname not present
+# getservbyport not present
+# getservent not present
+EOM
+ exit
+} }
+getsockname STDIN ; # OP_GETSOCKNAME
+getpeername STDIN ; # OP_GETPEERNAME
+gethostbyname 1 ; # OP_GHBYNAME
+gethostbyaddr 1,2; # OP_GHBYADDR
+gethostent ; # OP_GHOSTENT
+getnetbyname 1 ; # OP_GNBYNAME
+getnetbyaddr 1,2 ; # OP_GNBYADDR
+getnetent ; # OP_GNETENT
+getprotobyname 1; # OP_GPBYNAME
+getprotobynumber 1; # OP_GPBYNUMBER
+getprotoent ; # OP_GPROTOENT
+getservbyname 1,2; # OP_GSBYNAME
+getservbyport 1,2; # OP_GSBYPORT
+getservent ; # OP_GSERVENT
+
+no warnings 'void' ;
+getsockname STDIN ; # OP_GETSOCKNAME
+getpeername STDIN ; # OP_GETPEERNAME
+gethostbyname 1 ; # OP_GHBYNAME
+gethostbyaddr 1,2; # OP_GHBYADDR
+gethostent ; # OP_GHOSTENT
+getnetbyname 1 ; # OP_GNBYNAME
+getnetbyaddr 1,2 ; # OP_GNBYADDR
+getnetent ; # OP_GNETENT
+getprotobyname 1; # OP_GPBYNAME
+getprotobynumber 1; # OP_GPBYNUMBER
+getprotoent ; # OP_GPROTOENT
+getservbyname 1,2; # OP_GSBYNAME
+getservbyport 1,2; # OP_GSBYPORT
+getservent ; # OP_GSERVENT
+INIT {
+ # some functions may not be there, so we exit without running
+ exit;
+}
+EXPECT
+Useless use of getsockname in void context at - line 24.
+Useless use of getpeername in void context at - line 25.
+Useless use of gethostbyname in void context at - line 26.
+Useless use of gethostbyaddr in void context at - line 27.
+Useless use of gethostent in void context at - line 28.
+Useless use of getnetbyname in void context at - line 29.
+Useless use of getnetbyaddr in void context at - line 30.
+Useless use of getnetent in void context at - line 31.
+Useless use of getprotobyname in void context at - line 32.
+Useless use of getprotobynumber in void context at - line 33.
+Useless use of getprotoent in void context at - line 34.
+Useless use of getservbyname in void context at - line 35.
+Useless use of getservbyport in void context at - line 36.
+Useless use of getservent in void context at - line 37.
+########
+# op.c
+use warnings 'void' ;
+*a ; # OP_RV2GV
+$a ; # OP_RV2SV
+@a ; # OP_RV2AV
+%a ; # OP_RV2HV
+no warnings 'void' ;
+*a ; # OP_RV2GV
+$a ; # OP_RV2SV
+@a ; # OP_RV2AV
+%a ; # OP_RV2HV
+EXPECT
+Useless use of a variable in void context at - line 3.
+Useless use of a variable in void context at - line 4.
+Useless use of a variable in void context at - line 5.
+Useless use of a variable in void context at - line 6.
+########
+# op.c
+use warnings 'void' ;
+"abc"; # OP_CONST
+7 ; # OP_CONST
+no warnings 'void' ;
+"abc"; # OP_CONST
+7 ; # OP_CONST
+EXPECT
+Useless use of a constant in void context at - line 3.
+Useless use of a constant in void context at - line 4.
+########
+# op.c
+$ENV{PERL_DESTRUCT_LEVEL} = 0 unless $ENV{PERL_DESTRUCT_LEVEL} > 3; # known scalar leak
+use warnings 'unsafe' ;
+my $a ; my @a = () ; my %a = () ; my $b = \@a ; my $c = \%a ;
+@a =~ /abc/ ;
+@a =~ s/a/b/ ;
+@a =~ tr/a/b/ ;
+@$b =~ /abc/ ;
+@$b =~ s/a/b/ ;
+@$b =~ tr/a/b/ ;
+%a =~ /abc/ ;
+%a =~ s/a/b/ ;
+%a =~ tr/a/b/ ;
+%$c =~ /abc/ ;
+%$c =~ s/a/b/ ;
+%$c =~ tr/a/b/ ;
+{
+no warnings 'unsafe' ;
+my $a ; my @a = () ; my %a = () ; my $b = \@a ; my $c = \%a ;
+@a =~ /abc/ ;
+@a =~ s/a/b/ ;
+@a =~ tr/a/b/ ;
+@$b =~ /abc/ ;
+@$b =~ s/a/b/ ;
+@$b =~ tr/a/b/ ;
+%a =~ /abc/ ;
+%a =~ s/a/b/ ;
+%a =~ tr/a/b/ ;
+%$c =~ /abc/ ;
+%$c =~ s/a/b/ ;
+%$c =~ tr/a/b/ ;
+}
+EXPECT
+Applying pattern match to @array will act on scalar(@array) at - line 5.
+Applying substitution to @array will act on scalar(@array) at - line 6.
+Can't modify private array in substitution at - line 6, near "s/a/b/ ;"
+Applying character translation to @array will act on scalar(@array) at - line 7.
+Applying pattern match to @array will act on scalar(@array) at - line 8.
+Applying substitution to @array will act on scalar(@array) at - line 9.
+Applying character translation to @array will act on scalar(@array) at - line 10.
+Applying pattern match to %hash will act on scalar(%hash) at - line 11.
+Applying substitution to %hash will act on scalar(%hash) at - line 12.
+Applying character translation to %hash will act on scalar(%hash) at - line 13.
+Applying pattern match to %hash will act on scalar(%hash) at - line 14.
+Applying substitution to %hash will act on scalar(%hash) at - line 15.
+Applying character translation to %hash will act on scalar(%hash) at - line 16.
+BEGIN not safe after errors--compilation aborted at - line 18.
+########
+# op.c
+use warnings 'syntax' ;
+my $a, $b = (1,2);
+no warnings 'syntax' ;
+my $c, $d = (1,2);
+EXPECT
+Parentheses missing around "my" list at - line 3.
+########
+# op.c
+use warnings 'syntax' ;
+local $a, $b = (1,2);
+no warnings 'syntax' ;
+local $c, $d = (1,2);
+EXPECT
+Parentheses missing around "local" list at - line 3.
+########
+# op.c
+use warnings 'syntax' ;
+print (ABC || 1) ;
+no warnings 'syntax' ;
+print (ABC || 1) ;
+EXPECT
+Probable precedence problem on logical or at - line 3.
+########
+--FILE-- abc
+
+--FILE--
+# op.c
+use warnings 'unsafe' ;
+open FH, "<abc" ;
+$x = 1 if $x = <FH> ;
+no warnings 'unsafe' ;
+$x = 1 if $x = <FH> ;
+EXPECT
+Value of <HANDLE> construct can be "0"; test with defined() at - line 4.
+########
+# op.c
+use warnings 'unsafe' ;
+opendir FH, "." ;
+$x = 1 if $x = readdir FH ;
+no warnings 'unsafe' ;
+$x = 1 if $x = readdir FH ;
+closedir FH ;
+EXPECT
+Value of readdir() operator can be "0"; test with defined() at - line 4.
+########
+# op.c
+use warnings 'unsafe' ;
+$x = 1 if $x = <*> ;
+no warnings 'unsafe' ;
+$x = 1 if $x = <*> ;
+EXPECT
+Value of glob construct can be "0"; test with defined() at - line 3.
+########
+# op.c
+use warnings 'unsafe' ;
+%a = (1,2,3,4) ;
+$x = 1 if $x = each %a ;
+no warnings 'unsafe' ;
+$x = 1 if $x = each %a ;
+EXPECT
+Value of each() operator can be "0"; test with defined() at - line 4.
+########
+# op.c
+use warnings 'unsafe' ;
+$x = 1 while $x = <*> and 0 ;
+no warnings 'unsafe' ;
+$x = 1 while $x = <*> and 0 ;
+EXPECT
+Value of glob construct can be "0"; test with defined() at - line 3.
+########
+# op.c
+use warnings 'unsafe' ;
+opendir FH, "." ;
+$x = 1 while $x = readdir FH and 0 ;
+no warnings 'unsafe' ;
+$x = 1 while $x = readdir FH and 0 ;
+closedir FH ;
+EXPECT
+Value of readdir() operator can be "0"; test with defined() at - line 4.
+########
+# op.c
+use warnings 'redefine' ;
+sub fred {}
+sub fred {}
+no warnings 'redefine' ;
+sub fred {}
+EXPECT
+Subroutine fred redefined at - line 4.
+########
+# op.c
+use warnings 'redefine' ;
+sub fred () { 1 }
+sub fred () { 1 }
+no warnings 'redefine' ;
+sub fred () { 1 }
+EXPECT
+Constant subroutine fred redefined at - line 4.
+########
+# op.c
+use warnings 'redefine' ;
+format FRED =
+.
+format FRED =
+.
+no warnings 'redefine' ;
+format FRED =
+.
+EXPECT
+Format FRED redefined at - line 5.
+########
+# op.c
+use warnings 'syntax' ;
+push FRED;
+no warnings 'syntax' ;
+push FRED;
+EXPECT
+Array @FRED missing the @ in argument 1 of push() at - line 3.
+########
+# op.c
+use warnings 'syntax' ;
+@a = keys FRED ;
+no warnings 'syntax' ;
+@a = keys FRED ;
+EXPECT
+Hash %FRED missing the % in argument 1 of keys() at - line 3.
+########
+# op.c
+use warnings 'syntax' ;
+exec "$^X -e 1" ;
+my $a
+EXPECT
+Statement unlikely to be reached at - line 4.
+(Maybe you meant system() when you said exec()?)
+########
+# op.c
+use warnings 'deprecated' ;
+my @a; defined(@a);
+EXPECT
+defined(@array) is deprecated at - line 3.
+(Maybe you should just omit the defined()?)
+########
+# op.c
+use warnings 'deprecated' ;
+defined(@a = (1,2,3));
+EXPECT
+defined(@array) is deprecated at - line 3.
+(Maybe you should just omit the defined()?)
+########
+# op.c
+use warnings 'deprecated' ;
+my %h; defined(%h);
+EXPECT
+defined(%hash) is deprecated at - line 3.
+(Maybe you should just omit the defined()?)
+########
+# op.c
+no warnings 'syntax' ;
+exec "$^X -e 1" ;
+my $a
+EXPECT
+
+########
+# op.c
+sub fred();
+sub fred($) {}
+EXPECT
+Prototype mismatch: sub main::fred () vs ($) at - line 3.
+########
+# op.c
+$^W = 0 ;
+sub fred() ;
+sub fred($) {}
+{
+ no warnings 'unsafe' ;
+ sub Fred() ;
+ sub Fred($) {}
+ use warnings 'unsafe' ;
+ sub freD() ;
+ sub freD($) {}
+}
+sub FRED() ;
+sub FRED($) {}
+EXPECT
+Prototype mismatch: sub main::fred () vs ($) at - line 4.
+Prototype mismatch: sub main::freD () vs ($) at - line 11.
+Prototype mismatch: sub main::FRED () vs ($) at - line 14.
+########
+# op.c
+use warnings 'syntax' ;
+join /---/, 'x', 'y', 'z';
+EXPECT
+/---/ should probably be written as "---" at - line 3.
+########
+# op.c [Perl_peep]
+use warnings 'unsafe' ;
+fred() ;
+sub fred ($$) {}
+no warnings 'unsafe' ;
+joe() ;
+sub joe ($$) {}
+EXPECT
+main::fred() called too early to check prototype at - line 3.
diff --git a/t/pragma/warn/perl b/t/pragma/warn/perl
new file mode 100644
index 0000000000..45807499d6
--- /dev/null
+++ b/t/pragma/warn/perl
@@ -0,0 +1,57 @@
+ perl.c AOK
+
+ gv_check(defstash)
+ Name \"%s::%s\" used only once: possible typo
+
+ Mandatory Warnings All TODO
+ ------------------
+ Recompile perl with -DDEBUGGING to use -D switch [moreswitches]
+ Unbalanced scopes: %ld more ENTERs than LEAVEs [perl_destruct]
+ Unbalanced saves: %ld more saves than restores [perl_destruct]
+ Unbalanced tmps: %ld more allocs than frees [perl_destruct]
+ Unbalanced context: %ld more PUSHes than POPs [perl_destruct]
+ Unbalanced string table refcount: (%d) for \"%s\" [perl_destruct]
+ Scalars leaked: %ld [perl_destruct]
+
+
+__END__
+# perl.c
+no warnings 'once' ;
+$x = 3 ;
+use warnings 'once' ;
+$z = 3 ;
+EXPECT
+Name "main::z" used only once: possible typo at - line 5.
+########
+-w
+# perl.c
+$x = 3 ;
+no warnings 'once' ;
+$z = 3
+EXPECT
+Name "main::x" used only once: possible typo at - line 3.
+########
+# perl.c
+BEGIN { $^W =1 ; }
+$x = 3 ;
+no warnings 'once' ;
+$z = 3
+EXPECT
+Name "main::x" used only once: possible typo at - line 3.
+########
+-W
+# perl.c
+no warnings 'once' ;
+$x = 3 ;
+use warnings 'once' ;
+$z = 3 ;
+EXPECT
+Name "main::x" used only once: possible typo at - line 4.
+Name "main::z" used only once: possible typo at - line 6.
+########
+-X
+# perl.c
+use warnings 'once' ;
+$x = 3 ;
+EXPECT
+
diff --git a/t/pragma/warn/perlio b/t/pragma/warn/perlio
new file mode 100644
index 0000000000..18c0dfa89f
--- /dev/null
+++ b/t/pragma/warn/perlio
@@ -0,0 +1,10 @@
+ perlio.c
+
+
+ Mandatory Warnings ALL TODO
+ ------------------
+ Setting cnt to %d
+ Setting ptr %p > end+1 %p
+ Setting cnt to %d, ptr implies %d
+
+__END__
diff --git a/t/pragma/warn/perly b/t/pragma/warn/perly
new file mode 100644
index 0000000000..afc5dccc72
--- /dev/null
+++ b/t/pragma/warn/perly
@@ -0,0 +1,31 @@
+ perly.y AOK
+
+ dep() => deprecate("\"do\" to call subroutines")
+ Use of "do" to call subroutines is deprecated
+
+ sub fred {} do fred()
+ sub fred {} do fred(1)
+ sub fred {} $a = "fred" ; do $a()
+ sub fred {} $a = "fred" ; do $a(1)
+
+
+__END__
+# perly.y
+use warnings 'deprecated' ;
+sub fred {}
+do fred() ;
+do fred(1) ;
+$a = "fred" ;
+do $a() ;
+do $a(1) ;
+no warnings 'deprecated' ;
+do fred() ;
+do fred(1) ;
+$a = "fred" ;
+do $a() ;
+do $a(1) ;
+EXPECT
+Use of "do" to call subroutines is deprecated at - line 4.
+Use of "do" to call subroutines is deprecated at - line 5.
+Use of "do" to call subroutines is deprecated at - line 7.
+Use of "do" to call subroutines is deprecated at - line 8.
diff --git a/t/pragma/warn/pp b/t/pragma/warn/pp
new file mode 100644
index 0000000000..48b5ec86b5
--- /dev/null
+++ b/t/pragma/warn/pp
@@ -0,0 +1,125 @@
+ pp.c TODO
+
+ substr outside of string
+ $a = "ab" ; $a = substr($a, 4,5)
+
+ Attempt to use reference as lvalue in substr
+ $a = "ab" ; $b = \$a ; substr($b, 1,1) = $b
+
+ uninitialized in pp_rv2gv()
+ my *b = *{ undef()}
+
+ uninitialized in pp_rv2sv()
+ my $a = undef ; my $b = $$a
+
+ Odd number of elements in hash list
+ my $a = { 1,2,3 } ;
+
+ Invalid type in unpack: '%c
+ my $A = pack ("A,A", 1,2) ;
+ my @A = unpack ("A,A", "22") ;
+
+ Attempt to pack pointer to temporary value
+ pack("p", "abc") ;
+
+ Explicit blessing to '' (assuming package main)
+ bless \[], "";
+
+ Constant subroutine %s undefined <<<TODO
+ Constant subroutine (anonymous) undefined <<<TODO
+
+ Mandatory Warnings
+ ------------------
+ Malformed UTF-8 character
+
+__END__
+# pp.c
+use warnings 'substr' ;
+$a = "ab" ;
+$a = substr($a, 4,5);
+no warnings 'substr' ;
+$a = "ab" ;
+$a = substr($a, 4,5);
+EXPECT
+substr outside of string at - line 4.
+########
+# pp.c
+use warnings 'substr' ;
+$a = "ab" ;
+$b = \$a ;
+substr($b, 1,1) = "ab" ;
+no warnings 'substr' ;
+substr($b, 1,1) = "ab" ;
+EXPECT
+Attempt to use reference as lvalue in substr at - line 5.
+########
+# pp.c
+use warnings 'uninitialized' ;
+# TODO
+EXPECT
+
+########
+# pp.c
+use warnings 'unsafe' ;
+my $a = { 1,2,3};
+no warnings 'unsafe' ;
+my $b = { 1,2,3};
+EXPECT
+Odd number of elements in hash assignment at - line 3.
+########
+# pp.c
+use warnings 'unsafe' ;
+my @a = unpack ("A,A", "22") ;
+my $a = pack ("A,A", 1,2) ;
+no warnings 'unsafe' ;
+my @b = unpack ("A,A", "22") ;
+my $b = pack ("A,A", 1,2) ;
+EXPECT
+Invalid type in unpack: ',' at - line 3.
+Invalid type in pack: ',' at - line 4.
+########
+# pp.c
+use warnings 'uninitialized' ;
+my $a = undef ;
+my $b = $$a;
+no warnings 'uninitialized' ;
+my $c = $$a;
+EXPECT
+Use of uninitialized value at - line 4.
+########
+# pp.c
+use warnings 'unsafe' ;
+sub foo { my $a = "a"; return $a . $a++ . $a++ }
+my $a = pack("p", &foo) ;
+no warnings 'unsafe' ;
+my $b = pack("p", &foo) ;
+EXPECT
+Attempt to pack pointer to temporary value at - line 4.
+########
+# pp.c
+use warnings 'unsafe' ;
+bless \[], "" ;
+no warnings 'unsafe' ;
+bless \[], "" ;
+EXPECT
+Explicit blessing to '' (assuming package main) at - line 3.
+########
+# pp.c
+use utf8 ;
+$_ = "\x80 \xff" ;
+reverse ;
+EXPECT
+Malformed UTF-8 character at - line 4.
+########
+# pp.c
+use warnings 'utf8' ;
+use utf8 ;
+$_ = "\x80 \xff" ;
+reverse ;
+no warnings 'utf8' ;
+$_ = "\x80 \xff" ;
+reverse ;
+EXPECT
+\x80 will produce malformed UTF-8 character; use \x{80} for that at - line 4.
+\xff will produce malformed UTF-8 character; use \x{ff} for that at - line 4.
+Malformed UTF-8 character at - line 5.
diff --git a/t/pragma/warn/pp_ctl b/t/pragma/warn/pp_ctl
new file mode 100644
index 0000000000..70e6d60e8d
--- /dev/null
+++ b/t/pragma/warn/pp_ctl
@@ -0,0 +1,217 @@
+ pp_ctl.c AOK
+
+ Not enough format arguments
+ format STDOUT =
+ @<<< @<<<
+ $a
+ .
+ write;
+
+
+ Exiting substitution via %s
+ $_ = "abc" ;
+ while ($i ++ == 0)
+ {
+ s/ab/last/e ;
+ }
+
+ Exiting subroutine via %s
+ sub fred { last }
+ { fred() }
+
+ Exiting eval via %s
+ { eval "last" }
+
+ Exiting pseudo-block via %s
+ @a = (1,2) ; @b = sort { last } @a ;
+
+ Exiting substitution via %s
+ $_ = "abc" ;
+ last fred:
+ while ($i ++ == 0)
+ {
+ s/ab/last fred/e ;
+ }
+
+
+ Exiting subroutine via %s
+ sub fred { last joe }
+ joe: { fred() }
+
+ Exiting eval via %s
+ fred: { eval "last fred" }
+
+ Exiting pseudo-block via %s
+ @a = (1,2) ; fred: @b = sort { last fred } @a ;
+
+
+ Deep recursion on subroutine \"%s\"
+ sub fred
+ {
+ fred() if $a++ < 200
+ }
+
+ fred()
+
+ (in cleanup) foo bar
+ package Foo;
+ DESTROY { die "foo bar" }
+ { bless [], 'Foo' for 1..10 }
+
+__END__
+# pp_ctl.c
+use warnings 'syntax' ;
+format STDOUT =
+@<<< @<<<
+1
+.
+write;
+EXPECT
+Not enough format arguments at - line 5.
+1
+########
+# pp_ctl.c
+no warnings 'syntax' ;
+format =
+@<<< @<<<
+1
+.
+write ;
+EXPECT
+1
+########
+# pp_ctl.c
+use warnings 'unsafe' ;
+$_ = "abc" ;
+
+while ($i ++ == 0)
+{
+ s/ab/last/e ;
+}
+no warnings 'unsafe' ;
+while ($i ++ == 0)
+{
+ s/ab/last/e ;
+}
+EXPECT
+Exiting substitution via last at - line 7.
+########
+# pp_ctl.c
+use warnings 'unsafe' ;
+sub fred { last }
+{ fred() }
+no warnings 'unsafe' ;
+sub joe { last }
+{ joe() }
+EXPECT
+Exiting subroutine via last at - line 3.
+########
+# pp_ctl.c
+{
+ eval "use warnings 'unsafe' ; last;"
+}
+print STDERR $@ ;
+{
+ eval "no warnings 'unsafe' ;last;"
+}
+print STDERR $@ ;
+EXPECT
+Exiting eval via last at (eval 1) line 1.
+########
+# pp_ctl.c
+use warnings 'unsafe' ;
+@a = (1,2) ;
+@b = sort { last } @a ;
+no warnings 'unsafe' ;
+@b = sort { last } @a ;
+EXPECT
+Exiting pseudo-block via last at - line 4.
+Can't "last" outside a block at - line 4.
+########
+# pp_ctl.c
+use warnings 'unsafe' ;
+$_ = "abc" ;
+fred:
+while ($i ++ == 0)
+{
+ s/ab/last fred/e ;
+}
+no warnings 'unsafe' ;
+while ($i ++ == 0)
+{
+ s/ab/last fred/e ;
+}
+EXPECT
+Exiting substitution via last at - line 7.
+########
+# pp_ctl.c
+use warnings 'unsafe' ;
+sub fred { last joe }
+joe: { fred() }
+no warnings 'unsafe' ;
+sub Fred { last Joe }
+Joe: { Fred() }
+EXPECT
+Exiting subroutine via last at - line 3.
+########
+# pp_ctl.c
+joe:
+{ eval "use warnings 'unsafe' ; last joe;" }
+print STDERR $@ ;
+Joe:
+{ eval "no warnings 'unsafe' ; last Joe;" }
+print STDERR $@ ;
+EXPECT
+Exiting eval via last at (eval 1) line 1.
+########
+# pp_ctl.c
+use warnings 'unsafe' ;
+@a = (1,2) ;
+fred: @b = sort { last fred } @a ;
+no warnings 'unsafe' ;
+Fred: @b = sort { last Fred } @a ;
+EXPECT
+Exiting pseudo-block via last at - line 4.
+Label not found for "last fred" at - line 4.
+########
+# pp_ctl.c
+use warnings 'recursion' ;
+BEGIN { warn "PREFIX\n" ;}
+sub fred
+{
+ fred() if $a++ < 200
+}
+
+fred()
+EXPECT
+Deep recursion on subroutine "main::fred" at - line 6.
+########
+# pp_ctl.c
+no warnings 'recursion' ;
+BEGIN { warn "PREFIX\n" ;}
+sub fred
+{
+ fred() if $a++ < 200
+}
+
+fred()
+EXPECT
+########
+# pp_ctl.c
+use warnings 'unsafe' ;
+package Foo;
+DESTROY { die "@{$_[0]} foo bar" }
+{ bless ['A'], 'Foo' for 1..10 }
+{ bless ['B'], 'Foo' for 1..10 }
+EXPECT
+ (in cleanup) A foo bar at - line 4.
+ (in cleanup) B foo bar at - line 4.
+########
+# pp_ctl.c
+no warnings 'unsafe' ;
+package Foo;
+DESTROY { die "@{$_[0]} foo bar" }
+{ bless ['A'], 'Foo' for 1..10 }
+{ bless ['B'], 'Foo' for 1..10 }
+EXPECT
+
diff --git a/t/pragma/warn/pp_hot b/t/pragma/warn/pp_hot
new file mode 100644
index 0000000000..6bd315148f
--- /dev/null
+++ b/t/pragma/warn/pp_hot
@@ -0,0 +1,192 @@
+ pp_hot.c
+
+ Filehandle %s never opened [pp_print]
+ $f = $a = "abc" ; print $f $a
+
+ Filehandle %s opened only for input [pp_print]
+ print STDIN "abc" ;
+
+ Filehandle %s opened only for output [pp_print]
+ print <STDOUT> ;
+
+ print on closed filehandle %s [pp_print]
+ close STDIN ; print STDIN "abc" ;
+
+ uninitialized [pp_rv2av]
+ my $a = undef ; my @b = @$a
+
+ uninitialized [pp_rv2hv]
+ my $a = undef ; my %b = %$a
+
+ Odd number of elements in hash list [pp_aassign]
+ %X = (1,2,3) ;
+
+ Reference found where even-sized list expected [pp_aassign]
+ $X = [ 1 ..3 ];
+
+ Filehandle %s opened only for output [Perl_do_readline]
+ open (FH, ">./xcv") ;
+ my $a = <FH> ;
+
+ glob failed (can't start child: %s) [Perl_do_readline] <<TODO
+
+ Read on closed filehandle %s [Perl_do_readline]
+ close STDIN ; $a = <STDIN>;
+
+ glob failed (child exited with status %d%s) [Perl_do_readline] <<TODO
+
+ Deep recursion on subroutine \"%s\" [Perl_sub_crush_depth]
+ sub fred { fred() if $a++ < 200} fred()
+
+ Deep recursion on anonymous subroutine [Perl_sub_crush_depth]
+ $a = sub { &$a if $a++ < 200} &$a
+
+
+__END__
+# pp_hot.c [pp_print]
+use warnings 'unopened' ;
+$f = $a = "abc" ;
+print $f $a;
+no warnings 'unopened' ;
+print $f $a;
+EXPECT
+Filehandle main::abc never opened at - line 4.
+########
+# pp_hot.c [pp_print]
+use warnings 'io' ;
+print STDIN "anc";
+print <STDOUT>;
+print <STDERR>;
+open(FOO, ">&STDOUT") and print <FOO>;
+print getc(STDERR);
+print getc(FOO);
+####################################################################
+# The next test is known to fail on some systems (Linux/BSD+glibc, #
+# NeXT among others. glibc should be fixed in the next version, #
+# but it appears other platforms have little hope. We skip it for #
+# now (on the grounds that it is "just" a warning). #
+####################################################################
+#read(FOO,$_,1);
+no warnings 'io' ;
+print STDIN "anc";
+EXPECT
+Filehandle main::STDIN opened only for input at - line 3.
+Filehandle main::STDOUT opened only for output at - line 4.
+Filehandle main::STDERR opened only for output at - line 5.
+Filehandle main::FOO opened only for output at - line 6.
+Filehandle main::STDERR opened only for output at - line 7.
+Filehandle main::FOO opened only for output at - line 8.
+########
+# pp_hot.c [pp_print]
+use warnings 'closed' ;
+close STDIN ;
+print STDIN "anc";
+no warnings 'closed' ;
+print STDIN "anc";
+EXPECT
+print on closed filehandle main::STDIN at - line 4.
+########
+# pp_hot.c [pp_rv2av]
+use warnings 'uninitialized' ;
+my $a = undef ;
+my @b = @$a;
+no warnings 'uninitialized' ;
+my @c = @$a;
+EXPECT
+Use of uninitialized value at - line 4.
+########
+# pp_hot.c [pp_rv2hv]
+use warnings 'uninitialized' ;
+my $a = undef ;
+my %b = %$a;
+no warnings 'uninitialized' ;
+my %c = %$a;
+EXPECT
+Use of uninitialized value at - line 4.
+########
+# pp_hot.c [pp_aassign]
+use warnings 'unsafe' ;
+my %X ; %X = (1,2,3) ;
+no warnings 'unsafe' ;
+my %Y ; %Y = (1,2,3) ;
+EXPECT
+Odd number of elements in hash assignment at - line 3.
+########
+# pp_hot.c [pp_aassign]
+use warnings 'unsafe' ;
+my %X ; %X = [1 .. 3] ;
+no warnings 'unsafe' ;
+my %Y ; %Y = [1 .. 3] ;
+EXPECT
+Reference found where even-sized list expected at - line 3.
+########
+# pp_hot.c [Perl_do_readline]
+use warnings 'closed' ;
+close STDIN ; $a = <STDIN> ;
+no warnings 'closed' ;
+$a = <STDIN> ;
+EXPECT
+Read on closed filehandle main::STDIN at - line 3.
+########
+# pp_hot.c [Perl_do_readline]
+use warnings 'io' ;
+my $file = "./xcv" ; unlink $file ;
+open (FH, ">./xcv") ;
+my $a = <FH> ;
+no warnings 'io' ;
+$a = <FH> ;
+unlink $file ;
+EXPECT
+Filehandle main::FH opened only for output at - line 5.
+########
+# pp_hot.c [Perl_sub_crush_depth]
+use warnings 'recursion' ;
+sub fred
+{
+ fred() if $a++ < 200
+}
+{
+ local $SIG{__WARN__} = sub {
+ die "ok\n" if $_[0] =~ /^Deep recursion on subroutine "main::fred"/
+ };
+ fred();
+}
+EXPECT
+ok
+########
+# pp_hot.c [Perl_sub_crush_depth]
+no warnings 'recursion' ;
+sub fred
+{
+ fred() if $a++ < 200
+}
+{
+ local $SIG{__WARN__} = sub {
+ die "ok\n" if $_[0] =~ /^Deep recursion on subroutine "main::fred"/
+ };
+ fred();
+}
+EXPECT
+
+########
+# pp_hot.c [Perl_sub_crush_depth]
+use warnings 'recursion' ;
+$b = sub
+{
+ &$b if $a++ < 200
+} ;
+
+&$b ;
+EXPECT
+Deep recursion on anonymous subroutine at - line 5.
+########
+# pp_hot.c [Perl_sub_crush_depth]
+no warnings 'recursion' ;
+$b = sub
+{
+ &$b if $a++ < 200
+} ;
+
+&$b ;
+EXPECT
+
diff --git a/t/pragma/warn/pp_sys b/t/pragma/warn/pp_sys
new file mode 100644
index 0000000000..651cdf9515
--- /dev/null
+++ b/t/pragma/warn/pp_sys
@@ -0,0 +1,259 @@
+ pp_sys.c AOK
+
+ untie attempted while %d inner references still exist [pp_untie]
+ sub TIESCALAR { bless [] } ; tie $a, 'main'; untie $a ;
+
+ Filehandle %s opened only for input [pp_leavewrite]
+ format STDIN =
+ .
+ write STDIN;
+
+ Write on closed filehandle %s [pp_leavewrite]
+ format STDIN =
+ .
+ close STDIN;
+ write STDIN ;
+
+ page overflow [pp_leavewrite]
+
+ Filehandle %s never opened [pp_prtf]
+ $a = "abc"; printf $a "fred"
+
+ Filehandle %s opened only for input [pp_prtf]
+ $a = "abc";
+ printf $a "fred"
+
+ printf on closed filehandle %s [pp_prtf]
+ close STDIN ;
+ printf STDIN "fred"
+
+ Syswrite on closed filehandle [pp_send]
+ close STDIN;
+ syswrite STDIN, "fred", 1;
+
+ Send on closed socket [pp_send]
+ close STDIN;
+ send STDIN, "fred", 1
+
+ bind() on closed fd [pp_bind]
+ close STDIN;
+ bind STDIN, "fred" ;
+
+
+ connect() on closed fd [pp_connect]
+ close STDIN;
+ connect STDIN, "fred" ;
+
+ listen() on closed fd [pp_listen]
+ close STDIN;
+ listen STDIN, 2;
+
+ accept() on closed fd [pp_accept]
+ close STDIN;
+ accept STDIN, "fred" ;
+
+ shutdown() on closed fd [pp_shutdown]
+ close STDIN;
+ shutdown STDIN, 0;
+
+ [gs]etsockopt() on closed fd [pp_ssockopt]
+ close STDIN;
+ setsockopt STDIN, 1,2,3;
+ getsockopt STDIN, 1,2;
+
+ get{sock, peer}name() on closed fd [pp_getpeername]
+ close STDIN;
+ getsockname STDIN;
+ getpeername STDIN;
+
+ warn(warn_nl, "stat"); [pp_stat]
+
+ Test on unopened file <%s>
+ close STDIN ; -T STDIN ;
+
+ warn(warn_nl, "open"); [pp_fttext]
+ -T "abc\ndef" ;
+
+ Filehandle %s opened only for output [pp_sysread]
+ my $file = "./xcv" ;
+ open(F, ">$file") ;
+ my $a = sysread(F, $a,10) ;
+
+
+
+__END__
+# pp_sys.c [pp_untie]
+use warnings 'untie' ;
+sub TIESCALAR { bless [] } ;
+$b = tie $a, 'main';
+untie $a ;
+no warnings 'untie' ;
+$c = tie $d, 'main';
+untie $d ;
+EXPECT
+untie attempted while 1 inner references still exist at - line 5.
+########
+# pp_sys.c [pp_leavewrite]
+use warnings 'io' ;
+format STDIN =
+.
+write STDIN;
+no warnings 'io' ;
+write STDIN;
+EXPECT
+Filehandle main::STDIN opened only for input at - line 5.
+########
+# pp_sys.c [pp_leavewrite]
+use warnings 'closed' ;
+format STDIN =
+.
+close STDIN;
+write STDIN;
+no warnings 'closed' ;
+write STDIN;
+EXPECT
+Write on closed filehandle main::STDIN at - line 6.
+########
+# pp_sys.c [pp_leavewrite]
+use warnings 'io' ;
+format STDOUT_TOP =
+abc
+.
+format STDOUT =
+def
+ghi
+.
+$= = 1 ;
+$- =1 ;
+open STDOUT, ">".($^O eq 'VMS'? 'NL:' : '/dev/null') ;
+write ;
+no warnings 'io' ;
+write ;
+EXPECT
+page overflow at - line 13.
+########
+# pp_sys.c [pp_prtf]
+use warnings 'unopened' ;
+$a = "abc";
+printf $a "fred";
+no warnings 'unopened' ;
+printf $a "fred";
+EXPECT
+Filehandle main::abc never opened at - line 4.
+########
+# pp_sys.c [pp_prtf]
+use warnings 'closed' ;
+close STDIN ;
+printf STDIN "fred";
+no warnings 'closed' ;
+printf STDIN "fred";
+EXPECT
+printf on closed filehandle main::STDIN at - line 4.
+########
+# pp_sys.c [pp_prtf]
+use warnings 'io' ;
+printf STDIN "fred";
+no warnings 'io' ;
+printf STDIN "fred";
+EXPECT
+Filehandle main::STDIN opened only for input at - line 3.
+########
+# pp_sys.c [pp_send]
+use warnings 'closed' ;
+close STDIN;
+syswrite STDIN, "fred", 1;
+no warnings 'closed' ;
+syswrite STDIN, "fred", 1;
+EXPECT
+Syswrite on closed filehandle at - line 4.
+########
+# pp_sys.c [pp_prtf pp_send pp_bind pp_connect pp_listen pp_accept pp_shutdown pp_ssockopt ppp_getpeername]
+use warnings 'io' ;
+use Config;
+BEGIN {
+ if ( $^O ne 'VMS' and ! $Config{d_socket}) {
+ print <<EOM ;
+SKIPPED
+# send not present
+# bind not present
+# connect not present
+# accept not present
+# shutdown not present
+# setsockopt not present
+# getsockopt not present
+# getsockname not present
+# getpeername not present
+EOM
+ exit ;
+ }
+}
+close STDIN;
+send STDIN, "fred", 1;
+bind STDIN, "fred" ;
+connect STDIN, "fred" ;
+listen STDIN, 2;
+accept STDIN, "fred" ;
+shutdown STDIN, 0;
+setsockopt STDIN, 1,2,3;
+getsockopt STDIN, 1,2;
+getsockname STDIN;
+getpeername STDIN;
+no warnings 'io' ;
+send STDIN, "fred", 1;
+bind STDIN, "fred" ;
+connect STDIN, "fred" ;
+listen STDIN, 2;
+accept STDIN, "fred" ;
+shutdown STDIN, 0;
+setsockopt STDIN, 1,2,3;
+getsockopt STDIN, 1,2;
+getsockname STDIN;
+getpeername STDIN;
+EXPECT
+Send on closed socket at - line 22.
+bind() on closed fd at - line 23.
+connect() on closed fd at - line 24.
+listen() on closed fd at - line 25.
+accept() on closed fd at - line 26.
+shutdown() on closed fd at - line 27.
+[gs]etsockopt() on closed fd at - line 28.
+[gs]etsockopt() on closed fd at - line 29.
+get{sock, peer}name() on closed fd at - line 30.
+get{sock, peer}name() on closed fd at - line 31.
+########
+# pp_sys.c [pp_stat]
+use warnings 'newline' ;
+stat "abc\ndef";
+no warnings 'newline' ;
+stat "abc\ndef";
+EXPECT
+Unsuccessful stat on filename containing newline at - line 3.
+########
+# pp_sys.c [pp_fttext]
+use warnings 'unopened' ;
+close STDIN ;
+-T STDIN ;
+no warnings 'unopened' ;
+-T STDIN ;
+EXPECT
+Test on unopened file <STDIN> at - line 4.
+########
+# pp_sys.c [pp_fttext]
+use warnings 'newline' ;
+-T "abc\ndef" ;
+no warnings 'newline' ;
+-T "abc\ndef" ;
+EXPECT
+Unsuccessful open on filename containing newline at - line 3.
+########
+# pp_sys.c [pp_sysread]
+use warnings 'io' ;
+my $file = "./xcv" ;
+open(F, ">$file") ;
+my $a = sysread(F, $a,10) ;
+no warnings 'io' ;
+my $a = sysread(F, $a,10) ;
+close F ;
+unlink $file ;
+EXPECT
+Filehandle main::F opened only for output at - line 5.
diff --git a/t/pragma/warn/regcomp b/t/pragma/warn/regcomp
new file mode 100644
index 0000000000..9c3677ee10
--- /dev/null
+++ b/t/pragma/warn/regcomp
@@ -0,0 +1,75 @@
+ regcomp.c AOK
+
+ Strange *+?{} on zero-length expression [S_study_chunk]
+ /(?=a)?/
+
+ %.*s matches null string many times [S_regpiece]
+ $a = "ABC123" ; $a =~ /(?=a)*/'
+
+ /%.127s/: Unrecognized escape \\%c passed through" [S_regatom]
+ /\m/
+
+ Character class syntax [. .] is reserved for future extensions [S_regpposixcc]
+
+ Character class syntax [= =] is reserved for future extensions [S_checkposixcc]
+
+ Character class syntax [%c %c] belongs inside character classes [S_checkposixcc]
+
+
+
+
+__END__
+# regcomp.c [S_regpiece]
+use warnings 'unsafe' ;
+my $a = "ABC123" ;
+$a =~ /(?=a)*/ ;
+no warnings 'unsafe' ;
+$a =~ /(?=a)*/ ;
+EXPECT
+(?=a)* matches null string many times at - line 4.
+########
+# regcomp.c [S_study_chunk]
+use warnings 'unsafe' ;
+$_ = "" ;
+/(?=a)?/;
+no warnings 'unsafe' ;
+/(?=a)?/;
+EXPECT
+Strange *+?{} on zero-length expression at - line 4.
+########
+# regcomp.c [S_regatom]
+use warnings 'unsafe' ;
+$a =~ /\m/ ;
+no warnings 'unsafe' ;
+EXPECT
+Unrecognized escape \m passed through at - line 3.
+########
+# regcomp.c [S_regpposixcc S_checkposixcc]
+use warnings 'unsafe' ;
+$_ = "" ;
+/[:alpha:]/;
+/[.bar.]/;
+/[=zog=]/;
+/[[:alpha:]]/;
+/[[.foo.]]/;
+/[[=bar=]]/;
+/[:zog:]/;
+no warnings 'unsafe' ;
+/[:alpha:]/;
+/[.foo.]/;
+/[=bar=]/;
+/[[:alpha:]]/;
+/[[.foo.]]/;
+/[[=bar=]]/;
+/[:zog:]/;
+/[[:zog:]]/;
+EXPECT
+Character class syntax [: :] belongs inside character classes at - line 4.
+Character class syntax [. .] belongs inside character classes at - line 5.
+Character class syntax [. .] is reserved for future extensions at - line 5.
+Character class syntax [= =] belongs inside character classes at - line 6.
+Character class syntax [= =] is reserved for future extensions at - line 6.
+Character class syntax [. .] is reserved for future extensions at - line 8.
+Character class syntax [= =] is reserved for future extensions at - line 9.
+Character class syntax [: :] belongs inside character classes at - line 10.
+Character class [:zog:] unknown at - line 19.
diff --git a/t/pragma/warn/regexec b/t/pragma/warn/regexec
new file mode 100644
index 0000000000..b9ba790832
--- /dev/null
+++ b/t/pragma/warn/regexec
@@ -0,0 +1,119 @@
+ regexec.c
+
+ This test generates "bad free" warnings when run under
+ PERL_DESTRUCT_LEVEL. This file merely serves as a placeholder
+ for investigation.
+
+ Complex regular subexpression recursion limit (%d) exceeded
+
+ $_ = 'a' x (2**15+1); /^()(a\1)*$/ ;
+ Complex regular subexpression recursion limit (%d) exceeded
+
+ $_ = 'a' x (2**15+1); /^()(a\1)*?$/ ;
+
+ (The actual value substituted for %d is masked in the tests so that
+ REG_INFTY configuration variable value does not affect outcome.)
+__END__
+# regexec.c
+print("SKIPPED\n# most systems run into stacksize limits\n"),exit;
+use warnings 'unsafe' ;
+$SIG{__WARN__} = sub{local ($m) = shift;
+ $m =~ s/\(\d+\)/(*MASKED*)/;
+ print STDERR $m};
+$_ = 'a' x (2**15+1);
+/^()(a\1)*$/ ;
+#
+# If this test fails with a segmentation violation or similar,
+# you may have to increase the default stacksize limit in your
+# shell. You may need superuser privileges.
+#
+# Under the sh, ksh, zsh:
+# $ ulimit -s
+# 8192
+# $ ulimit -s 16000
+#
+# Under the csh:
+# % limit stacksize
+# stacksize 8192 kbytes
+# % limit stacksize 16000
+#
+EXPECT
+Complex regular subexpression recursion limit (*MASKED*) exceeded at - line 9.
+########
+# regexec.c
+print("SKIPPED\n# most systems run into stacksize limits\n"),exit;
+no warnings 'unsafe' ;
+$SIG{__WARN__} = sub{local ($m) = shift;
+ $m =~ s/\(\d+\)/(*MASKED*)/;
+ print STDERR $m};
+$_ = 'a' x (2**15+1);
+/^()(a\1)*$/ ;
+#
+# If this test fails with a segmentation violation or similar,
+# you may have to increase the default stacksize limit in your
+# shell. You may need superuser privileges.
+#
+# Under the sh, ksh, zsh:
+# $ ulimit -s
+# 8192
+# $ ulimit -s 16000
+#
+# Under the csh:
+# % limit stacksize
+# stacksize 8192 kbytes
+# % limit stacksize 16000
+#
+EXPECT
+
+########
+# regexec.c
+print("SKIPPED\n# most systems run into stacksize limits\n"),exit;
+use warnings 'unsafe' ;
+$SIG{__WARN__} = sub{local ($m) = shift;
+ $m =~ s/\(\d+\)/(*MASKED*)/;
+ print STDERR $m};
+$_ = 'a' x (2**15+1);
+/^()(a\1)*?$/ ;
+#
+# If this test fails with a segmentation violation or similar,
+# you may have to increase the default stacksize limit in your
+# shell. You may need superuser privileges.
+#
+# Under the sh, ksh, zsh:
+# $ ulimit -s
+# 8192
+# $ ulimit -s 16000
+#
+# Under the csh:
+# % limit stacksize
+# stacksize 8192 kbytes
+# % limit stacksize 16000
+#
+EXPECT
+Complex regular subexpression recursion limit (*MASKED*) exceeded at - line 9.
+########
+# regexec.c
+print("SKIPPED\n# most systems run into stacksize limits\n"),exit;
+no warnings 'unsafe' ;
+$SIG{__WARN__} = sub{local ($m) = shift;
+ $m =~ s/\(\d+\)/(*MASKED*)/;
+ print STDERR $m};
+$_ = 'a' x (2**15+1);
+/^()(a\1)*?$/ ;
+#
+# If this test fails with a segmentation violation or similar,
+# you may have to increase the default stacksize limit in your
+# shell. You may need superuser privileges.
+#
+# Under the sh, ksh, zsh:
+# $ ulimit -s
+# 8192
+# $ ulimit -s 16000
+#
+# Under the csh:
+# % limit stacksize
+# stacksize 8192 kbytes
+# % limit stacksize 16000
+#
+EXPECT
+
diff --git a/t/pragma/warn/run b/t/pragma/warn/run
new file mode 100644
index 0000000000..7a4be20e70
--- /dev/null
+++ b/t/pragma/warn/run
@@ -0,0 +1,8 @@
+ run.c
+
+
+ Mandatory Warnings ALL TODO
+ ------------------
+ NULL OP IN RUN
+
+__END__
diff --git a/t/pragma/warn/sv b/t/pragma/warn/sv
new file mode 100644
index 0000000000..bac2c42545
--- /dev/null
+++ b/t/pragma/warn/sv
@@ -0,0 +1,282 @@
+ sv.c
+
+ warn(warn_uninit);
+
+ warn(warn_uninit);
+
+ warn(warn_uninit);
+
+ warn(warn_uninit);
+
+ not_a_number(sv);
+
+ not_a_number(sv);
+
+ warn(warn_uninit);
+
+ not_a_number(sv);
+
+ warn(warn_uninit);
+
+ not_a_number(sv);
+
+ not_a_number(sv);
+
+ warn(warn_uninit);
+
+ warn(warn_uninit);
+
+ Subroutine %s redefined
+
+ Invalid conversion in %s:
+
+ Undefined value assigned to typeglob
+
+ Reference is already weak [Perl_sv_rvweaken] <<TODO
+
+ Mandatory Warnings
+ ------------------
+ Malformed UTF-8 character [sv_pos_b2u]
+ my $a = rindex "a\xff bc ", "bc" ;
+
+ Mandatory Warnings TODO
+ ------------------
+ Attempt to free non-arena SV: 0x%lx [del_sv]
+ Reference miscount in sv_replace() [sv_replace]
+ Attempt to free unreferenced scalar [sv_free]
+ Attempt to free temp prematurely: SV 0x%lx [sv_free]
+ semi-panic: attempt to dup freed string [newSVsv]
+
+
+__END__
+# sv.c
+use integer ;
+use warnings 'uninitialized' ;
+$x = 1 + $a[0] ; # a
+no warnings 'uninitialized' ;
+$x = 1 + $b[0] ; # a
+EXPECT
+Use of uninitialized value at - line 4.
+########
+# sv.c (sv_2iv)
+package fred ;
+sub TIESCALAR { my $x ; bless \$x}
+sub FETCH { return undef }
+sub STORE { return 1 }
+package main ;
+tie $A, 'fred' ;
+use integer ;
+use warnings 'uninitialized' ;
+$A *= 2 ;
+no warnings 'uninitialized' ;
+$A *= 2 ;
+EXPECT
+Use of uninitialized value at - line 10.
+########
+# sv.c
+use integer ;
+use warnings 'uninitialized' ;
+my $x *= 2 ; #b
+no warnings 'uninitialized' ;
+my $y *= 2 ; #b
+EXPECT
+Use of uninitialized value at - line 4.
+########
+# sv.c (sv_2uv)
+package fred ;
+sub TIESCALAR { my $x ; bless \$x}
+sub FETCH { return undef }
+sub STORE { return 1 }
+package main ;
+tie $A, 'fred' ;
+use warnings 'uninitialized' ;
+$B = 0 ;
+$B |= $A ;
+no warnings 'uninitialized' ;
+$B = 0 ;
+$B |= $A ;
+EXPECT
+Use of uninitialized value at - line 10.
+########
+# sv.c
+use warnings 'uninitialized' ;
+my $Y = 1 ;
+my $x = 1 | $a[$Y] ;
+no warnings 'uninitialized' ;
+my $Y = 1 ;
+$x = 1 | $b[$Y] ;
+EXPECT
+Use of uninitialized value at - line 4.
+########
+# sv.c
+use warnings 'uninitialized' ;
+my $x *= 1 ; # d
+no warnings 'uninitialized' ;
+my $y *= 1 ; # d
+EXPECT
+Use of uninitialized value at - line 3.
+########
+# sv.c
+use warnings 'uninitialized' ;
+$x = 1 + $a[0] ; # e
+no warnings 'uninitialized' ;
+$x = 1 + $b[0] ; # e
+EXPECT
+Use of uninitialized value at - line 3.
+########
+# sv.c (sv_2nv)
+package fred ;
+sub TIESCALAR { my $x ; bless \$x}
+sub FETCH { return undef }
+sub STORE { return 1 }
+package main ;
+tie $A, 'fred' ;
+use warnings 'uninitialized' ;
+$A *= 2 ;
+no warnings 'uninitialized' ;
+$A *= 2 ;
+EXPECT
+Use of uninitialized value at - line 9.
+########
+# sv.c
+use warnings 'uninitialized' ;
+$x = $y + 1 ; # f
+no warnings 'uninitialized' ;
+$x = $z + 1 ; # f
+EXPECT
+Use of uninitialized value at - line 3.
+########
+# sv.c
+use warnings 'uninitialized' ;
+$x = chop undef ; # g
+no warnings 'uninitialized' ;
+$x = chop undef ; # g
+EXPECT
+Modification of a read-only value attempted at - line 3.
+########
+# sv.c
+use warnings 'uninitialized' ;
+$x = chop $y ; # h
+no warnings 'uninitialized' ;
+$x = chop $z ; # h
+EXPECT
+Use of uninitialized value at - line 3.
+########
+# sv.c (sv_2pv)
+package fred ;
+sub TIESCALAR { my $x ; bless \$x}
+sub FETCH { return undef }
+sub STORE { return 1 }
+package main ;
+tie $A, 'fred' ;
+use warnings 'uninitialized' ;
+$B = "" ;
+$B .= $A ;
+no warnings 'uninitialized' ;
+$C = "" ;
+$C .= $A ;
+EXPECT
+Use of uninitialized value at - line 10.
+########
+# sv.c
+use warnings 'numeric' ;
+sub TIESCALAR{bless[]} ;
+sub FETCH {"def"} ;
+tie $a,"main" ;
+my $b = 1 + $a;
+no warnings 'numeric' ;
+my $c = 1 + $a;
+EXPECT
+Argument "def" isn't numeric in add at - line 6.
+########
+# sv.c
+use warnings 'numeric' ;
+my $x = 1 + "def" ;
+no warnings 'numeric' ;
+my $z = 1 + "def" ;
+EXPECT
+Argument "def" isn't numeric in add at - line 3.
+########
+# sv.c
+use warnings 'numeric' ;
+my $a = "def" ;
+my $x = 1 + $a ;
+no warnings 'numeric' ;
+my $y = 1 + $a ;
+EXPECT
+Argument "def" isn't numeric in add at - line 4.
+########
+# sv.c
+use warnings 'numeric' ; use integer ;
+my $a = "def" ;
+my $x = 1 + $a ;
+no warnings 'numeric' ;
+my $z = 1 + $a ;
+EXPECT
+Argument "def" isn't numeric in i_add at - line 4.
+########
+# sv.c
+use warnings 'numeric' ;
+my $x = 1 & "def" ;
+no warnings 'numeric' ;
+my $z = 1 & "def" ;
+EXPECT
+Argument "def" isn't numeric in bit_and at - line 3.
+########
+# sv.c
+use warnings 'redefine' ;
+sub fred {}
+sub joe {}
+*fred = \&joe ;
+no warnings 'redefine' ;
+sub jim {}
+*jim = \&joe ;
+EXPECT
+Subroutine fred redefined at - line 5.
+########
+# sv.c
+use warnings 'printf' ;
+open F, ">".($^O eq 'VMS'? 'NL:' : '/dev/null') ;
+printf F "%z\n" ;
+my $a = sprintf "%z" ;
+printf F "%" ;
+$a = sprintf "%" ;
+printf F "%\x02" ;
+$a = sprintf "%\x02" ;
+no warnings 'printf' ;
+printf F "%z\n" ;
+$a = sprintf "%z" ;
+printf F "%" ;
+$a = sprintf "%" ;
+printf F "%\x02" ;
+$a = sprintf "%\x02" ;
+EXPECT
+Invalid conversion in sprintf: "%z" at - line 5.
+Invalid conversion in sprintf: end of string at - line 7.
+Invalid conversion in sprintf: "%\002" at - line 9.
+Invalid conversion in printf: "%z" at - line 4.
+Invalid conversion in printf: end of string at - line 6.
+Invalid conversion in printf: "%\002" at - line 8.
+########
+# sv.c
+use warnings 'unsafe' ;
+*a = undef ;
+no warnings 'unsafe' ;
+*b = undef ;
+EXPECT
+Undefined value assigned to typeglob at - line 3.
+########
+# sv.c
+use utf8 ;
+$^W =0 ;
+{
+ use warnings 'utf8' ;
+ my $a = rindex "a\xff bc ", "bc" ;
+ no warnings 'utf8' ;
+ $a = rindex "a\xff bc ", "bc" ;
+}
+my $a = rindex "a\xff bc ", "bc" ;
+EXPECT
+\xff will produce malformed UTF-8 character; use \x{ff} for that at - line 6.
+Malformed UTF-8 character at - line 6.
+Malformed UTF-8 character at - line 10.
diff --git a/t/pragma/warn/taint b/t/pragma/warn/taint
new file mode 100644
index 0000000000..fd6deed60f
--- /dev/null
+++ b/t/pragma/warn/taint
@@ -0,0 +1,49 @@
+ taint.c AOK
+
+ Insecure %s%s while running with -T switch
+
+__END__
+-T
+--FILE-- abc
+def
+--FILE--
+# taint.c
+open(FH, "<abc") ;
+$a = <FH> ;
+close FH ;
+chdir $a ;
+print "xxx\n" ;
+EXPECT
+Insecure dependency in chdir while running with -T switch at - line 5.
+########
+-TU
+--FILE-- abc
+def
+--FILE--
+# taint.c
+open(FH, "<abc") ;
+$a = <FH> ;
+close FH ;
+chdir $a ;
+print "xxx\n" ;
+EXPECT
+xxx
+########
+-TU
+--FILE-- abc
+def
+--FILE--
+# taint.c
+open(FH, "<abc") ;
+$a = <FH> ;
+close FH ;
+use warnings 'taint' ;
+chdir $a ;
+print "xxx\n" ;
+no warnings 'taint' ;
+chdir $a ;
+print "yyy\n" ;
+EXPECT
+Insecure dependency in chdir while running with -T switch at - line 6.
+xxx
+yyy
diff --git a/t/pragma/warn/toke b/t/pragma/warn/toke
new file mode 100644
index 0000000000..ee02efa813
--- /dev/null
+++ b/t/pragma/warn/toke
@@ -0,0 +1,611 @@
+toke.c AOK
+
+ we seem to have lost a few ambiguous warnings!!
+
+
+ 1 if $a EQ $b ;
+ 1 if $a NE $b ;
+ 1 if $a LT $b ;
+ 1 if $a GT $b ;
+ 1 if $a GE $b ;
+ 1 if $a LE $b ;
+ $a = <<;
+ Use of comma-less variable list is deprecated
+ (called 3 times via depcom)
+
+ \1 better written as $1
+ use warnings 'syntax' ;
+ s/(abc)/\1/;
+
+ warn(warn_nosemi)
+ Semicolon seems to be missing
+ $a = 1
+ &time ;
+
+
+ Reversed %c= operator
+ my $a =+ 2 ;
+ $a =- 2 ;
+ $a =* 2 ;
+ $a =% 2 ;
+ $a =& 2 ;
+ $a =. 2 ;
+ $a =^ 2 ;
+ $a =| 2 ;
+ $a =< 2 ;
+ $a =/ 2 ;
+
+ Multidimensional syntax %.*s not supported
+ my $a = $a[1,2] ;
+
+ You need to quote \"%s\""
+ sub fred {} ; $SIG{TERM} = fred;
+
+ Scalar value %.*s better written as $%.*s"
+ @a[3] = 2;
+ @a{3} = 2;
+
+ Can't use \\%c to mean $%c in expression
+ $_ = "ab" ; s/(ab)/\1/e;
+
+ Unquoted string "abc" may clash with future reserved word at - line 3.
+ warn(warn_reserved
+ $a = abc;
+
+ chmod: mode argument is missing initial 0
+ chmod 3;
+
+ Possible attempt to separate words with commas
+ @a = qw(a, b, c) ;
+
+ Possible attempt to put comments in qw() list
+ @a = qw(a b # c) ;
+
+ umask: argument is missing initial 0
+ umask 3;
+
+ %s (...) interpreted as function
+ print ("")
+ printf ("")
+ sort ("")
+
+ Ambiguous use of %c{%s%s} resolved to %c%s%s
+ $a = ${time[2]}
+ $a = ${time{2}}
+
+
+ Ambiguous use of %c{%s} resolved to %c%s
+ $a = ${time}
+ sub fred {} $a = ${fred}
+
+ Misplaced _ in number
+ $a = 1_2;
+ $a = 1_2345_6;
+
+ Bareword \"%s\" refers to nonexistent package
+ $a = FRED:: ;
+
+ Ambiguous call resolved as CORE::%s(), qualify as such or use &
+ sub time {}
+ my $a = time()
+
+ Use of \\x{} without utf8 declaration
+ $_ = " \x{123} " ;
+
+
+ \x%.*s will produce malformed UTF-8 character; use \x{%.*s} for that
+ use utf8 ;
+ $_ = "\xffe"
+
+ Unrecognized escape \\%c passed through
+ $a = "\m" ;
+
+ %s number > %s non-portable
+ my $a = 0b011111111111111111111111111111110 ;
+ $a = 0b011111111111111111111111111111111 ;
+ $a = 0b111111111111111111111111111111111 ;
+ $a = 0x0fffffffe ;
+ $a = 0x0ffffffff ;
+ $a = 0x1ffffffff ;
+ $a = 0037777777776 ;
+ $a = 0037777777777 ;
+ $a = 0047777777777 ;
+
+ Integer overflow in binary number
+ my $a = 0b011111111111111111111111111111110 ;
+ $a = 0b011111111111111111111111111111111 ;
+ $a = 0b111111111111111111111111111111111 ;
+ $a = 0x0fffffffe ;
+ $a = 0x0ffffffff ;
+ $a = 0x1ffffffff ;
+ $a = 0037777777776 ;
+ $a = 0037777777777 ;
+ $a = 0047777777777 ;
+
+ Mandatory Warnings
+ ------------------
+ Use of "%s" without parentheses is ambiguous [check_uni]
+ rand + 4
+
+ Ambiguous use of -%s resolved as -&%s() [yylex]
+ sub fred {} ; - fred ;
+
+ Precedence problem: open %.*s should be open(%.*s) [yylex]
+ open FOO || die;
+
+ Operator or semicolon missing before %c%s [yylex]
+ Ambiguous use of %c resolved as operator %c
+ *foo *foo
+
+__END__
+# toke.c
+use warnings 'deprecated' ;
+1 if $a EQ $b ;
+1 if $a NE $b ;
+1 if $a GT $b ;
+1 if $a LT $b ;
+1 if $a GE $b ;
+1 if $a LE $b ;
+no warnings 'deprecated' ;
+1 if $a EQ $b ;
+1 if $a NE $b ;
+1 if $a GT $b ;
+1 if $a LT $b ;
+1 if $a GE $b ;
+1 if $a LE $b ;
+EXPECT
+Use of EQ is deprecated at - line 3.
+Use of NE is deprecated at - line 4.
+Use of GT is deprecated at - line 5.
+Use of LT is deprecated at - line 6.
+Use of GE is deprecated at - line 7.
+Use of LE is deprecated at - line 8.
+########
+# toke.c
+use warnings 'deprecated' ;
+format STDOUT =
+@<<< @||| @>>> @>>>
+$a $b "abc" 'def'
+.
+no warnings 'deprecated' ;
+format STDOUT =
+@<<< @||| @>>> @>>>
+$a $b "abc" 'def'
+.
+EXPECT
+Use of comma-less variable list is deprecated at - line 5.
+Use of comma-less variable list is deprecated at - line 5.
+Use of comma-less variable list is deprecated at - line 5.
+########
+# toke.c
+use warnings 'deprecated' ;
+$a = <<;
+
+no warnings 'deprecated' ;
+$a = <<;
+
+EXPECT
+Use of bare << to mean <<"" is deprecated at - line 3.
+########
+# toke.c
+use warnings 'syntax' ;
+s/(abc)/\1/;
+no warnings 'syntax' ;
+s/(abc)/\1/;
+EXPECT
+\1 better written as $1 at - line 3.
+########
+# toke.c
+use warnings 'semicolon' ;
+$a = 1
+&time ;
+no warnings 'semicolon' ;
+$a = 1
+&time ;
+EXPECT
+Semicolon seems to be missing at - line 3.
+########
+# toke.c
+BEGIN {
+ # Scalars leaked: due to syntax errors
+ $ENV{PERL_DESTRUCT_LEVEL} = 0 unless $ENV{PERL_DESTRUCT_LEVEL} > 3;
+}
+use warnings 'syntax' ;
+my $a =+ 2 ;
+$a =- 2 ;
+$a =* 2 ;
+$a =% 2 ;
+$a =& 2 ;
+$a =. 2 ;
+$a =^ 2 ;
+$a =| 2 ;
+$a =< 2 ;
+$a =/ 2 ;
+EXPECT
+Reversed += operator at - line 7.
+Reversed -= operator at - line 8.
+Reversed *= operator at - line 9.
+Reversed %= operator at - line 10.
+Reversed &= operator at - line 11.
+Reversed .= operator at - line 12.
+syntax error at - line 12, near "=."
+Reversed ^= operator at - line 13.
+syntax error at - line 13, near "=^"
+Reversed |= operator at - line 14.
+syntax error at - line 14, near "=|"
+Reversed <= operator at - line 15.
+Unterminated <> operator at - line 15.
+########
+# toke.c
+BEGIN {
+ # Scalars leaked: due to syntax errors
+ $ENV{PERL_DESTRUCT_LEVEL} = 0 unless $ENV{PERL_DESTRUCT_LEVEL} > 3;
+}
+no warnings 'syntax' ;
+my $a =+ 2 ;
+$a =- 2 ;
+$a =* 2 ;
+$a =% 2 ;
+$a =& 2 ;
+$a =. 2 ;
+$a =^ 2 ;
+$a =| 2 ;
+$a =< 2 ;
+$a =/ 2 ;
+EXPECT
+syntax error at - line 12, near "=."
+syntax error at - line 13, near "=^"
+syntax error at - line 14, near "=|"
+Unterminated <> operator at - line 15.
+########
+# toke.c
+use warnings 'syntax' ;
+my $a = $a[1,2] ;
+no warnings 'syntax' ;
+my $a = $a[1,2] ;
+EXPECT
+Multidimensional syntax $a[1,2] not supported at - line 3.
+########
+# toke.c
+use warnings 'syntax' ;
+sub fred {} ; $SIG{TERM} = fred;
+no warnings 'syntax' ;
+$SIG{TERM} = fred;
+EXPECT
+You need to quote "fred" at - line 3.
+########
+# toke.c
+use warnings 'syntax' ;
+@a[3] = 2;
+@a{3} = 2;
+no warnings 'syntax' ;
+@a[3] = 2;
+@a{3} = 2;
+EXPECT
+Scalar value @a[3] better written as $a[3] at - line 3.
+Scalar value @a{3} better written as $a{3} at - line 4.
+########
+# toke.c
+use warnings 'syntax' ;
+$_ = "ab" ;
+s/(ab)/\1/e;
+no warnings 'syntax' ;
+$_ = "ab" ;
+s/(ab)/\1/e;
+EXPECT
+Can't use \1 to mean $1 in expression at - line 4.
+########
+# toke.c
+use warnings 'reserved' ;
+$a = abc;
+no warnings 'reserved' ;
+$a = abc;
+EXPECT
+Unquoted string "abc" may clash with future reserved word at - line 3.
+########
+# toke.c
+use warnings 'octal' ;
+chmod 3;
+no warnings 'octal' ;
+chmod 3;
+EXPECT
+chmod: mode argument is missing initial 0 at - line 3.
+########
+# toke.c
+use warnings 'syntax' ;
+@a = qw(a, b, c) ;
+no warnings 'syntax' ;
+@a = qw(a, b, c) ;
+EXPECT
+Possible attempt to separate words with commas at - line 3.
+########
+# toke.c
+use warnings 'syntax' ;
+@a = qw(a b #) ;
+no warnings 'syntax' ;
+@a = qw(a b #) ;
+EXPECT
+Possible attempt to put comments in qw() list at - line 3.
+########
+# toke.c
+use warnings 'octal' ;
+umask 3;
+no warnings 'octal' ;
+umask 3;
+EXPECT
+umask: argument is missing initial 0 at - line 3.
+########
+# toke.c
+use warnings 'syntax' ;
+print ("")
+EXPECT
+print (...) interpreted as function at - line 3.
+########
+# toke.c
+no warnings 'syntax' ;
+print ("")
+EXPECT
+
+########
+# toke.c
+use warnings 'syntax' ;
+printf ("")
+EXPECT
+printf (...) interpreted as function at - line 3.
+########
+# toke.c
+no warnings 'syntax' ;
+printf ("")
+EXPECT
+
+########
+# toke.c
+use warnings 'syntax' ;
+sort ("")
+EXPECT
+sort (...) interpreted as function at - line 3.
+########
+# toke.c
+no warnings 'syntax' ;
+sort ("")
+EXPECT
+
+########
+# toke.c
+use warnings 'ambiguous' ;
+$a = ${time[2]};
+no warnings 'ambiguous' ;
+$a = ${time[2]};
+EXPECT
+Ambiguous use of ${time[...]} resolved to $time[...] at - line 3.
+########
+# toke.c
+use warnings 'ambiguous' ;
+$a = ${time{2}};
+EXPECT
+Ambiguous use of ${time{...}} resolved to $time{...} at - line 3.
+########
+# toke.c
+no warnings 'ambiguous' ;
+$a = ${time{2}};
+EXPECT
+
+########
+# toke.c
+use warnings 'ambiguous' ;
+$a = ${time} ;
+no warnings 'ambiguous' ;
+$a = ${time} ;
+EXPECT
+Ambiguous use of ${time} resolved to $time at - line 3.
+########
+# toke.c
+use warnings 'ambiguous' ;
+sub fred {}
+$a = ${fred} ;
+no warnings 'ambiguous' ;
+$a = ${fred} ;
+EXPECT
+Ambiguous use of ${fred} resolved to $fred at - line 4.
+########
+# toke.c
+use warnings 'syntax' ;
+$a = 1_2;
+$a = 1_2345_6;
+no warnings 'syntax' ;
+$a = 1_2;
+$a = 1_2345_6;
+EXPECT
+Misplaced _ in number at - line 3.
+Misplaced _ in number at - line 4.
+Misplaced _ in number at - line 4.
+########
+# toke.c
+use warnings 'unsafe' ;
+#line 25 "bar"
+$a = FRED:: ;
+no warnings 'unsafe' ;
+#line 25 "bar"
+$a = FRED:: ;
+EXPECT
+Bareword "FRED::" refers to nonexistent package at bar line 25.
+########
+# toke.c
+use warnings 'ambiguous' ;
+sub time {}
+my $a = time() ;
+no warnings 'ambiguous' ;
+my $b = time() ;
+EXPECT
+Ambiguous call resolved as CORE::time(), qualify as such or use & at - line 4.
+########
+# toke.c
+use warnings 'utf8' ;
+eval <<'EOE';
+{
+#line 30 "foo"
+ $_ = " \x{123} " ;
+}
+EOE
+EXPECT
+Use of \x{} without utf8 declaration at foo line 30.
+########
+# toke.c
+no warnings 'utf8' ;
+eval <<'EOE';
+{
+#line 30 "foo"
+ $_ = " \x{123} " ;
+}
+EOE
+EXPECT
+
+########
+# toke.c
+use warnings 'utf8' ;
+use utf8 ;
+$_ = " \xffe " ;
+no warnings 'utf8' ;
+$_ = " \xffe " ;
+EXPECT
+\xff will produce malformed UTF-8 character; use \x{ff} for that at - line 4.
+########
+# toke.c
+my $a = rand + 4 ;
+EXPECT
+Warning: Use of "rand" without parens is ambiguous at - line 2.
+########
+# toke.c
+$^W = 0 ;
+my $a = rand + 4 ;
+{
+ no warnings 'ambiguous' ;
+ $a = rand + 4 ;
+ use warnings 'ambiguous' ;
+ $a = rand + 4 ;
+}
+$a = rand + 4 ;
+EXPECT
+Warning: Use of "rand" without parens is ambiguous at - line 3.
+Warning: Use of "rand" without parens is ambiguous at - line 8.
+Warning: Use of "rand" without parens is ambiguous at - line 10.
+########
+# toke.c
+sub fred {};
+-fred ;
+EXPECT
+Ambiguous use of -fred resolved as -&fred() at - line 3.
+########
+# toke.c
+$^W = 0 ;
+sub fred {} ;
+-fred ;
+{
+ no warnings 'ambiguous' ;
+ -fred ;
+ use warnings 'ambiguous' ;
+ -fred ;
+}
+-fred ;
+EXPECT
+Ambiguous use of -fred resolved as -&fred() at - line 4.
+Ambiguous use of -fred resolved as -&fred() at - line 9.
+Ambiguous use of -fred resolved as -&fred() at - line 11.
+########
+# toke.c
+open FOO || time;
+EXPECT
+Precedence problem: open FOO should be open(FOO) at - line 2.
+########
+# toke.c
+$^W = 0 ;
+open FOO || time;
+{
+ no warnings 'ambiguous' ;
+ open FOO || time;
+ use warnings 'ambiguous' ;
+ open FOO || time;
+}
+open FOO || time;
+EXPECT
+Precedence problem: open FOO should be open(FOO) at - line 3.
+Precedence problem: open FOO should be open(FOO) at - line 8.
+Precedence problem: open FOO should be open(FOO) at - line 10.
+########
+# toke.c
+$^W = 0 ;
+*foo *foo ;
+{
+ no warnings 'ambiguous' ;
+ *foo *foo ;
+ use warnings 'ambiguous' ;
+ *foo *foo ;
+}
+*foo *foo ;
+EXPECT
+Operator or semicolon missing before *foo at - line 3.
+Ambiguous use of * resolved as operator * at - line 3.
+Operator or semicolon missing before *foo at - line 8.
+Ambiguous use of * resolved as operator * at - line 8.
+Operator or semicolon missing before *foo at - line 10.
+Ambiguous use of * resolved as operator * at - line 10.
+########
+# toke.c
+use warnings 'unsafe' ;
+my $a = "\m" ;
+no warnings 'unsafe' ;
+$a = "\m" ;
+EXPECT
+Unrecognized escape \m passed through at - line 3.
+########
+# toke.c
+use warnings 'portable' ;
+my $a = 0b011111111111111111111111111111110 ;
+ $a = 0b011111111111111111111111111111111 ;
+ $a = 0b111111111111111111111111111111111 ;
+ $a = 0x0fffffffe ;
+ $a = 0x0ffffffff ;
+ $a = 0x1ffffffff ;
+ $a = 0037777777776 ;
+ $a = 0037777777777 ;
+ $a = 0047777777777 ;
+no warnings 'portable' ;
+ $a = 0b011111111111111111111111111111110 ;
+ $a = 0b011111111111111111111111111111111 ;
+ $a = 0b111111111111111111111111111111111 ;
+ $a = 0x0fffffffe ;
+ $a = 0x0ffffffff ;
+ $a = 0x1ffffffff ;
+ $a = 0037777777776 ;
+ $a = 0037777777777 ;
+ $a = 0047777777777 ;
+EXPECT
+Binary number > 0b11111111111111111111111111111111 non-portable at - line 5.
+Hexadecimal number > 0xffffffff non-portable at - line 8.
+Octal number > 037777777777 non-portable at - line 11.
+########
+# toke.c
+use warnings 'overflow' ;
+my $a = 0b011111111111111111111111111111110 ;
+ $a = 0b011111111111111111111111111111111 ;
+ $a = 0b10000000000000000000000000000000000000000000000000000000000000000 ;
+ $a = 0x0fffffffe ;
+ $a = 0x0ffffffff ;
+ $a = 0x10000000000000000 ;
+ $a = 0037777777776 ;
+ $a = 0037777777777 ;
+ $a = 002000000000000000000000;
+no warnings 'overflow' ;
+ $a = 0b011111111111111111111111111111110 ;
+ $a = 0b011111111111111111111111111111111 ;
+ $a = 0b10000000000000000000000000000000000000000000000000000000000000000 ;
+ $a = 0x0fffffffe ;
+ $a = 0x0ffffffff ;
+ $a = 0x10000000000000000 ;
+ $a = 0037777777776 ;
+ $a = 0037777777777 ;
+ $a = 002000000000000000000000;
+EXPECT
+Integer overflow in binary number at - line 5.
+Integer overflow in hexadecimal number at - line 8.
+Integer overflow in octal number at - line 11.
diff --git a/t/pragma/warn/universal b/t/pragma/warn/universal
new file mode 100644
index 0000000000..6dbb1be4e0
--- /dev/null
+++ b/t/pragma/warn/universal
@@ -0,0 +1,16 @@
+ universal.c AOK
+
+ Can't locate package %s for @%s::ISA [S_isa_lookup]
+
+
+
+__END__
+# universal.c [S_isa_lookup]
+use warnings 'misc' ;
+@ISA = qw(Joe) ;
+my $a = bless [] ;
+UNIVERSAL::isa $a, Jim ;
+EXPECT
+Can't locate package Joe for @main::ISA at - line 5.
+Can't locate package Joe for @main::ISA.
+Can't locate package Joe for @main::ISA.
diff --git a/t/pragma/warn/utf8 b/t/pragma/warn/utf8
new file mode 100644
index 0000000000..b11514d826
--- /dev/null
+++ b/t/pragma/warn/utf8
@@ -0,0 +1,56 @@
+
+ utf8.c AOK
+
+ All Mandatory warnings
+
+ [utf8_to_uv]
+ Malformed UTF-8 character
+ my $a = ord "\x80" ;
+
+ Malformed UTF-8 character
+ my $a = ord "\xf080" ;
+
+ [utf16_to_utf8]
+ Malformed UTF-16 surrogate
+ <<<<<< Add a test when somethig actually calls utf16_to_utf8
+
+__END__
+# utf8.c [utf8_to_uv]
+use utf8 ;
+my $a = ord "\x80" ;
+EXPECT
+Malformed UTF-8 character at - line 3.
+########
+# utf8.c [utf8_to_uv]
+use utf8 ;
+my $a = ord "\x80" ;
+{
+ use warnings 'utf8' ;
+ my $a = ord "\x80" ;
+ no warnings 'utf8' ;
+ my $a = ord "\x80" ;
+}
+EXPECT
+Malformed UTF-8 character at - line 3.
+\x80 will produce malformed UTF-8 character; use \x{80} for that at - line 6.
+Malformed UTF-8 character at - line 6.
+########
+# utf8.c [utf8_to_uv]
+use utf8 ;
+my $a = ord "\xf080" ;
+EXPECT
+Malformed UTF-8 character at - line 3.
+########
+# utf8.c [utf8_to_uv]
+use utf8 ;
+my $a = ord "\xf080" ;
+{
+ use warnings 'utf8' ;
+ my $a = ord "\xf080" ;
+ no warnings 'utf8' ;
+ my $a = ord "\xf080" ;
+}
+EXPECT
+Malformed UTF-8 character at - line 3.
+\xf0 will produce malformed UTF-8 character; use \x{f0} for that at - line 6.
+Malformed UTF-8 character at - line 6.
diff --git a/t/pragma/warn/util b/t/pragma/warn/util
new file mode 100644
index 0000000000..6c9bc8c696
--- /dev/null
+++ b/t/pragma/warn/util
@@ -0,0 +1,108 @@
+ util.c AOK
+
+ Illegal octal digit ignored
+ my $a = oct "029" ;
+
+ Illegal hex digit ignored
+ my $a = hex "0xv9" ;
+
+ Illegal binary digit ignored
+ my $a = oct "0b9" ;
+
+ Integer overflow in binary number
+ my $a = oct "0b111111111111111111111111111111111111111111" ;
+ Binary number > 0b11111111111111111111111111111111 non-portable
+ $a = oct "0b111111111111111111111111111111111" ;
+ Integer overflow in octal number
+ my $a = oct "0777777777777777777777777777777777777777777777777" ;
+ Octal number > 037777777777 non-portable
+ $a = oct "0047777777777" ;
+ Integer overflow in hexadecimal number
+ my $a = hex "0xffffffffffffffffffff" ;
+ Hexadecimal number > 0xffffffff non-portable
+ $a = hex "0x1ffffffff" ;
+
+__END__
+# util.c
+use warnings 'digit' ;
+my $a = oct "029" ;
+no warnings 'digit' ;
+$a = oct "029" ;
+EXPECT
+Illegal octal digit '9' ignored at - line 3.
+########
+# util.c
+use warnings 'digit' ;
+my $a = hex "0xv9" ;
+no warnings 'digit' ;
+$a = hex "0xv9" ;
+EXPECT
+Illegal hexadecimal digit 'v' ignored at - line 3.
+########
+# util.c
+use warnings 'digit' ;
+my $a = oct "0b9" ;
+no warnings 'digit' ;
+$a = oct "0b9" ;
+EXPECT
+Illegal binary digit '9' ignored at - line 3.
+########
+# util.c
+use warnings 'overflow' ;
+my $a = oct "0b11111111111111111111111111111111111111111111111111111111111111111";
+no warnings 'overflow' ;
+$a = oct "0b11111111111111111111111111111111111111111111111111111111111111111";
+EXPECT
+Integer overflow in binary number at - line 3.
+########
+# util.c
+use warnings 'overflow' ;
+my $a = hex "0xffffffffffffffffffff" ;
+no warnings 'overflow' ;
+$a = hex "0xffffffffffffffffffff" ;
+EXPECT
+Integer overflow in hexadecimal number at - line 3.
+########
+# util.c
+use warnings 'overflow' ;
+my $a = oct "0777777777777777777777777777777777777777777777777" ;
+no warnings 'overflow' ;
+$a = oct "0777777777777777777777777777777777777777777777777" ;
+EXPECT
+Integer overflow in octal number at - line 3.
+########
+# util.c
+use warnings 'portable' ;
+my $a = oct "0b011111111111111111111111111111110" ;
+ $a = oct "0b011111111111111111111111111111111" ;
+ $a = oct "0b111111111111111111111111111111111" ;
+no warnings 'portable' ;
+ $a = oct "0b011111111111111111111111111111110" ;
+ $a = oct "0b011111111111111111111111111111111" ;
+ $a = oct "0b111111111111111111111111111111111" ;
+EXPECT
+Binary number > 0b11111111111111111111111111111111 non-portable at - line 5.
+########
+# util.c
+use warnings 'portable' ;
+my $a = hex "0x0fffffffe" ;
+ $a = hex "0x0ffffffff" ;
+ $a = hex "0x1ffffffff" ;
+no warnings 'portable' ;
+ $a = hex "0x0fffffffe" ;
+ $a = hex "0x0ffffffff" ;
+ $a = hex "0x1ffffffff" ;
+EXPECT
+Hexadecimal number > 0xffffffff non-portable at - line 5.
+########
+# util.c
+use warnings 'portable' ;
+my $a = oct "0037777777776" ;
+ $a = oct "0037777777777" ;
+ $a = oct "0047777777777" ;
+no warnings 'portable' ;
+ $a = oct "0037777777776" ;
+ $a = oct "0037777777777" ;
+ $a = oct "0047777777777" ;
+EXPECT
+Octal number > 037777777777 non-portable at - line 5.
diff --git a/t/pragma/warning.t b/t/pragma/warnings.t
index fa0301ea6a..73e4c8d1a8 100755..100644
--- a/t/pragma/warning.t
+++ b/t/pragma/warnings.t
@@ -2,13 +2,14 @@
BEGIN {
chdir 't' if -d 't';
- @INC = '../lib';
+ unshift @INC, '../lib';
$ENV{PERL5LIB} = '../lib';
+ require Config; import Config;
}
$| = 1;
-my $Is_VMS = $^O eq 'VMS';
+my $Is_VMS = $^O eq 'VMS';
my $Is_MSWin32 = $^O eq 'MSWin32';
my $tmpfile = "tmp0000";
my $i = 0 ;
@@ -16,8 +17,16 @@ my $i = 0 ;
END { if ($tmpfile) { 1 while unlink $tmpfile} }
my @prgs = () ;
+my @w_files = () ;
-foreach (sort glob("pragma/warn-*")) {
+if (@ARGV)
+ { print "ARGV = [@ARGV]\n" ; @w_files = map { s#^#./pragma/warn/#; $_ } @ARGV }
+else
+ { @w_files = sort glob("pragma/warn/*") }
+
+foreach (@w_files) {
+
+ next if /\.orig$/ ;
next if /(~|\.orig)$/;
@@ -43,7 +52,7 @@ for (@prgs){
my @temps = () ;
if (s/^\s*-\w+//){
$switch = $&;
- $switch =~ s/(-\S*[A-Z]\S*)/"-$1"/ if $Is_VMS; # protect uc switches
+ $switch =~ s/(-\S*[A-Z]\S*)/"$1"/ if $Is_VMS; # protect uc switches
}
my($prog,$expected) = split(/\nEXPECT\n/, $_);
if ( $prog =~ /--FILE--/) {
@@ -70,19 +79,35 @@ for (@prgs){
`MCR $^X $switch $tmpfile` :
$Is_MSWin32 ?
`.\\perl -I../lib $switch $tmpfile 2>&1` :
- `sh -c './perl $switch $tmpfile' 2>&1`;
+ `./perl -I../lib $switch $tmpfile 2>&1`;
my $status = $?;
$results =~ s/\n+$//;
# allow expected output to be written as if $prog is on STDIN
$results =~ s/tmp\d+/-/g;
$results =~ s/\n%[A-Z]+-[SIWEF]-.*$// if $Is_VMS; # clip off DCL status msg
+# bison says 'parse error' instead of 'syntax error',
+# various yaccs may or may not capitalize 'syntax'.
+ $results =~ s/^(syntax|parse) error/syntax error/mig;
$expected =~ s/\n+$//;
my $prefix = ($results =~ s/^PREFIX\n//) ;
+ # any special options? (OPTIONS foo bar zap)
+ my $option_regex = 0;
+ if ($expected =~ s/^OPTIONS? (.+)\n//) {
+ foreach my $option (split(' ', $1)) {
+ if ($option eq 'regex') { # allow regular expressions
+ $option_regex = 1;
+ } else {
+ die "$0: Unknown OPTION '$option'\n";
+ }
+ }
+ }
if ( $results =~ s/^SKIPPED\n//) {
print "$results\n" ;
}
- elsif (($prefix and $results !~ /^\Q$expected/) or
- (!$prefix and $results ne $expected)){
+ elsif (($prefix && (( $option_regex && $results !~ /^$expected/) ||
+ (!$option_regex && $results !~ /^\Q$expected/))) or
+ (!$prefix && (( $option_regex && $results !~ /^$expected/) ||
+ (!$option_regex && $results ne $expected)))) {
print STDERR "PROG: $switch\n$prog\n";
print STDERR "EXPECTED:\n$expected\n";
print STDERR "GOT:\n$results\n";