1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
#!./perl
BEGIN {
chdir 't' if -d 't';
@INC = '../lib';
require Config; import Config;
require './test.pl';
if (!$Config{'d_fork'}) {
skip_all("fork required to pipe");
}
else {
plan(tests => 24);
}
}
my $Perl = which_perl();
$| = 1;
open(PIPE, "|-") || exec $Perl, '-pe', 'tr/YX/ko/';
printf PIPE "Xk %d - open |- || exec\n", curr_test();
next_test();
printf PIPE "oY %d - again\n", curr_test();
next_test();
close PIPE;
{
if (open(PIPE, "-|")) {
while(<PIPE>) {
s/^not //;
print;
}
close PIPE; # avoid zombies
}
else {
printf STDOUT "not ok %d - open -|\n", curr_test();
next_test();
my $tnum = curr_test;
next_test();
exec $Perl, '-le', "print q{not ok $tnum - again}";
}
# This has to be *outside* the fork
next_test() for 1..2;
my $raw = "abc\nrst\rxyz\r\nfoo\n";
if (open(PIPE, "-|")) {
$_ = join '', <PIPE>;
(my $raw1 = $_) =~ s/not ok \d+ - //;
my @r = map ord, split //, $raw;
my @r1 = map ord, split //, $raw1;
if ($raw1 eq $raw) {
s/^not (ok \d+ -) .*/$1 '@r1' passes through '-|'\n/s;
} else {
s/^(not ok \d+ -) .*/$1 expect '@r', got '@r1'\n/s;
}
print;
close PIPE; # avoid zombies
}
else {
printf STDOUT "not ok %d - $raw", curr_test();
exec $Perl, '-e0'; # Do not run END()...
}
# This has to be *outside* the fork
next_test();
if (open(PIPE, "|-")) {
printf PIPE "not ok %d - $raw", curr_test();
close PIPE; # avoid zombies
}
else {
$_ = join '', <STDIN>;
(my $raw1 = $_) =~ s/not ok \d+ - //;
my @r = map ord, split //, $raw;
my @r1 = map ord, split //, $raw1;
if ($raw1 eq $raw) {
s/^not (ok \d+ -) .*/$1 '@r1' passes through '|-'\n/s;
} else {
s/^(not ok \d+ -) .*/$1 expect '@r', got '@r1'\n/s;
}
print;
exec $Perl, '-e0'; # Do not run END()...
}
# This has to be *outside* the fork
next_test();
SKIP: {
skip "fork required", 2 unless $Config{d_fork};
pipe(READER,WRITER) || die "Can't open pipe";
if ($pid = fork) {
close WRITER;
while(<READER>) {
s/^not //;
y/A-Z/a-z/;
print;
}
close READER; # avoid zombies
}
else {
die "Couldn't fork" unless defined $pid;
close READER;
printf WRITER "not ok %d - pipe & fork\n", curr_test;
next_test;
open(STDOUT,">&WRITER") || die "Can't dup WRITER to STDOUT";
close WRITER;
my $tnum = curr_test;
next_test;
exec $Perl, '-le', "print q{not ok $tnum - with fh dup }";
}
# This has to be done *outside* the fork.
next_test() for 1..2;
}
}
wait; # Collect from $pid
pipe(READER,WRITER) || die "Can't open pipe";
close READER;
$SIG{'PIPE'} = 'broken_pipe';
sub broken_pipe {
$SIG{'PIPE'} = 'IGNORE'; # loop preventer
printf "ok %d - SIGPIPE\n", curr_test;
}
printf WRITER "not ok %d - SIGPIPE\n", curr_test;
close WRITER;
sleep 1;
next_test;
pass();
# VMS doesn't like spawning subprocesses that are still connected to
# STDOUT. Someone should modify these tests to work with VMS.
SKIP: {
skip "doesn't like spawning subprocesses that are still connected", 10
if $^O eq 'VMS';
SKIP: {
# POSIX-BC doesn't report failure when closing a broken pipe
# that has pending output. Go figure.
skip "Won't report failure on broken pipe", 1
if $^O eq 'posix-bc';
local $SIG{PIPE} = 'IGNORE';
open NIL, qq{|$Perl -e "exit 0"} or die "open failed: $!";
sleep 5;
if (print NIL 'foo') {
# If print was allowed we had better get an error on close
ok( !close NIL, 'close error on broken pipe' );
}
else {
ok(close NIL, 'print failed on broken pipe');
}
}
{
# check that errno gets forced to 0 if the piped program exited
# non-zero
open NIL, qq{|$Perl -e "exit 23";} or die "fork failed: $!";
$! = 1;
ok(!close NIL, 'close failure on non-zero piped exit');
is($!, '', ' errno');
isnt($?, 0, ' status');
# Former skip block:
{
# check that status for the correct process is collected
my $zombie;
unless( $zombie = fork ) {
$NO_ENDING=1;
exit 37;
}
my $pipe = open *FH, "sleep 2;exit 13|" or die "Open: $!\n";
$SIG{ALRM} = sub { return };
alarm(1);
is( close FH, '', 'close failure for... umm, something' );
is( $?, 13*256, ' status' );
is( $!, '', ' errno');
my $wait = wait;
is( $?, 37*256, 'status correct after wait' );
is( $wait, $zombie, ' wait pid' );
is( $!, '', ' errno');
}
}
}
# Test new semantics for missing command in piped open
# 19990114 M-J. Dominus mjd@plover.com
{ local *P;
no warnings 'pipe';
ok( !open(P, "| "), 'missing command in piped open input' );
ok( !open(P, " |"), ' output');
}
# check that status is unaffected by implicit close
{
local(*NIL);
open NIL, qq{|$Perl -e "exit 23"} or die "fork failed: $!";
$? = 42;
# NIL implicitly closed here
}
is($?, 42, 'status unaffected by implicit close');
$? = 0;
# check that child is reaped if the piped program can't be executed
SKIP: {
skip "/no_such_process exists", 1 if -e "/no_such_process";
open NIL, '/no_such_process |';
close NIL;
my $child = 0;
eval {
local $SIG{ALRM} = sub { die; };
alarm 2;
$child = wait;
alarm 0;
};
is($child, -1, 'child reaped if piped program cannot be executed');
}
|