/t/CORE/io/pipe.t

https://github.com/gitpan/B-C · Perl · 250 lines · 188 code · 40 blank · 22 comment · 29 complexity · 59d753e1e1a6996f9c2f31711beba18e MD5 · raw file

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