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