Acme-Sort-Sleep
view release on metacpan or search on metacpan
local/lib/perl5/IO/Async/LoopTests.pm view on Meta::CPAN
=cut
sub run_in_child(&)
{
my $kid = fork;
defined $kid or die "Cannot fork() - $!";
return $kid if $kid;
shift->();
die "Fell out of run_in_child!\n";
}
use constant count_tests_child => 7;
sub run_tests_child
{
my $kid = run_in_child {
exit( 3 );
};
my $exitcode;
$loop->watch_child( $kid => sub { ( undef, $exitcode ) = @_; } );
is_oneref( $loop, '$loop has refcount 1 after watch_child' );
ok( !defined $exitcode, '$exitcode not defined before ->loop_once' );
undef $exitcode;
wait_for { defined $exitcode };
ok( ($exitcode & 0x7f) == 0, 'WIFEXITED($exitcode) after child exit' );
is( ($exitcode >> 8), 3, 'WEXITSTATUS($exitcode) after child exit' );
SKIP: {
skip "This OS does not have signals", 1 unless IO::Async::OS->HAVE_SIGNALS;
# We require that SIGTERM perform its default action; i.e. terminate the
# process. Ensure this definitely happens, in case the test harness has it
# ignored or handled elsewhere.
local $SIG{TERM} = "DEFAULT";
$kid = run_in_child {
sleep( 10 );
# Just in case the parent died already and didn't kill us
exit( 0 );
};
$loop->watch_child( $kid => sub { ( undef, $exitcode ) = @_; } );
kill SIGTERM, $kid;
undef $exitcode;
wait_for { defined $exitcode };
is( ($exitcode & 0x7f), SIGTERM, 'WTERMSIG($exitcode) after SIGTERM' );
}
my %kids;
$loop->watch_child( 0 => sub { my ( $kid ) = @_; delete $kids{$kid} } );
%kids = map { run_in_child { exit 0 } => 1 } 1 .. 3;
is( scalar keys %kids, 3, 'Waiting for 3 child processes' );
wait_for { !keys %kids };
ok( !keys %kids, 'All child processes reclaimed' );
}
=head2 control
Tests that the C<run>, C<stop>, C<loop_once> and C<loop_forever> methods
behave correctly
=cut
use constant count_tests_control => 8;
sub run_tests_control
{
time_between { $loop->loop_once( 0 ) } 0, 0.1, 'loop_once(0) when idle';
time_between { $loop->loop_once( 2 * AUT ) } 1.5, 2.5, 'loop_once(2) when idle';
$loop->watch_time( after => 0.1, code => sub { $loop->stop( result => "here" ) } );
local $SIG{ALRM} = sub { die "Test timed out before ->stop" };
alarm( 1 );
my @result = $loop->run;
alarm( 0 );
is_deeply( \@result, [ result => "here" ], '->stop arguments returned by ->run' );
$loop->watch_time( after => 0.1, code => sub { $loop->stop( result => "here" ) } );
my $result = $loop->run;
is( $result, "result", 'First ->stop argument returned by ->run in scalar context' );
$loop->watch_time( after => 0.1, code => sub {
$loop->watch_time( after => 0.1, code => sub { $loop->stop( "inner" ) } );
my @result = $loop->run;
$loop->stop( @result, "outer" );
} );
@result = $loop->run;
is_deeply( \@result, [ "inner", "outer" ], '->run can be nested properly' );
$loop->watch_time( after => 0.1, code => sub { $loop->loop_stop } );
local $SIG{ALRM} = sub { die "Test timed out before ->loop_stop" };
alarm( 1 );
$loop->loop_forever;
alarm( 0 );
ok( 1, '$loop->loop_forever interruptable by ->loop_stop' );
}
( run in 1.067 second using v1.01-cache-2.11-cpan-39bf76dae61 )