#!/usr/bin/env perl use strict; use warnings; use Test::More; use File::Temp 'tempdir'; use File::Spec; use IO::Pty::Easy; use IO::Select; use POSIX (); my $dir = tempdir(CLEANUP => 1); my $readp = File::Spec->catfile($dir, 'read'); my $writep = File::Spec->catfile($dir, 'write'); POSIX::mkfifo($readp, 0700) or die "mkfifo failed: $!"; POSIX::mkfifo($writep, 0700) or die "mkfifo failed: $!"; my $script = <', '$writep' or die "can't open pipe (child): \$!"; my \$term = Term::Filter::Callback->new( callbacks => { setup => sub { my (\$t) = \@_; \$t->add_input_handle(\$readfh); }, read => sub { my (\$t, \$fh) = \@_; if (\$fh == \$readfh) { my \$buf; sysread(\$fh, \$buf, 4096); if (defined(\$buf) && length(\$buf)) { print "1read from pipe: \$buf\\n"; } else { print "2pipe error (read)!\\n"; \$t->remove_input_handle(\$readfh); } } }, read_error => sub { my (\$t, \$fh) = \@_; if (\$fh == \$readfh) { print "3pipe error (exception)!\\n"; \$t->remove_input_handle(\$readfh); } }, munge_output => sub { my (\$t, \$buf) = \@_; syswrite(\$writefh, "4read from term: \$buf"); \$buf; }, } ); \$term->run(\$^X, '-ple', q[last if /^\$/]); print "5done\\n"; SCRIPT my $crlf = "\x0d\x0a"; # just in case alarm 60; { my $pty = IO::Pty::Easy->new(handle_pty_size => 0); $pty->spawn($^X, (map {; '-I', $_ } @INC), '-e', $script); open my $readfh, '>', $readp or die "can't open pipe (parent): $!"; open my $writefh, '<', $writep or die "can't open pipe (parent): $!"; $pty->write("foo\n"); is(full_read($pty), "foo${crlf}foo${crlf}"); { my $got_pipe = full_read($writefh); like($got_pipe, qr/4read from term: /); $got_pipe =~ s/4read from term: //g; is($got_pipe, "foo${crlf}foo${crlf}"); } syswrite($readfh, "bar"); { my $got_pty = full_read($pty); like($got_pty, qr/1read from pipe: /); $got_pty =~ s/1read from pipe: //g; is($got_pty, "bar\n"); } close($readfh); close($writefh); is(full_read($pty), "2pipe error (read)!\n"); } sub full_read { my ($fh) = @_; my $select = IO::Select->new($fh); return if $select->has_exception(0.1); 1 while !$select->can_read(1); my $ret; while ($select->can_read(1)) { my $new; sysread($fh, $new, 4096); last unless defined($new) && length($new); $ret .= $new; return $ret if $select->has_exception(0.1); } return $ret; } done_testing;