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
|
#!perl
use strict;
BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } }
select(STDERR); $|=1;
select(STDOUT); $|=1;
use Test::More;
use lib 't/lib';
use Helper;
use Frontend;
use Config;
use File::Temp ();
use Capture::Tiny qw/capture/;
use Probe::Perl ();
#--------------------------------------------------------------------------#
# fixtures
#--------------------------------------------------------------------------#
my $perl = Probe::Perl->find_perl_interpreter();
$perl = qq{"$perl"};
my $quote = $^O eq 'MSWin32' || $^O eq 'MSDOS' ? q{"} : q{'};
#--------------------------------------------------------------------------#
# Test planning
#--------------------------------------------------------------------------#
my @cases = (
{
label => "Exit with 0",
program => 'print qq{foo\n}; exit 0',
args => '',
output => [ "foo\n" ],
exit_code => 0,
},
{
label => "Exit with 1",
program => 'print qq{foo\n}; exit 1',
args => '',
output => [ "foo\n" ],
exit_code => 1 << 8,
},
{
label => "Exit with 2",
program => 'print qq{foo\n}; exit 2',
args => '',
output => [ "foo\n" ],
exit_code => 2 << 8,
},
{
label => "Exit with args in shell quotes",
program => 'print qq{foo $ARGV[0]\n}; exit 0',
args => "${quote}apples oranges bananas${quote}",
output => [ "foo apples oranges bananas\n" ],
exit_code => 0,
},
{
label => "Exit with args and pipe",
program => 'print qq{foo @ARGV\n}; exit 1',
args => "bar=1 | $perl -pe 0",
output => [ "foo bar=1\n" ],
exit_code => 1 << 8,
},
{
label => "Timeout kills process",
program => '$now=time(); 1 while( time() - $now < 60); print qq{foo\n}; exit 0',
args => '',
output => [],
delay => 60,
timeout => 5,
exit_code => 9,
},
{
label => "Timeout not reached",
program => '$now=time(); 1 while( time() - $now < 2); print qq{foo\n}; exit 0',
args => '',
output => ["foo\n"],
delay => 2,
timeout => 30,
exit_code => 0,
},
{
label => "Timeout not reached (quoted args)",
program => '$now=time(); 1 while( time() - $now < 2); print qq{foo $ARGV[0]\n}; exit 0',
args => "${quote}apples oranges bananas${quote}",
output => [ "foo apples oranges bananas\n" ],
delay => 2,
timeout => 30,
exit_code => 0,
},
);
my $tests_per_case = 4;
plan tests => 1 + $tests_per_case * @cases;
#--------------------------------------------------------------------------#
# tests
#--------------------------------------------------------------------------#
require_ok( "CPAN::Reporter" );
for my $c ( @cases ) {
SKIP: {
if ( $^O eq 'MSWin32' && $c->{timeout} ) {
skip "\$ENV{PERL_AUTHOR_TESTING} required for Win32 timeout testing",
$tests_per_case
unless $ENV{PERL_AUTHOR_TESTING};
eval "use Win32::Job ()";
skip "Win32::Job needed for timeout testing", $tests_per_case
if $@;
}
my $fh = File::Temp->new()
or die "Couldn't create a temporary file: $!\nIs your temp drive full?";
print {$fh} $c->{program}, "\n";
$fh->flush;
my ($output, $exit);
my ($stdout, $stderr);
my $start_time = time();
my $cmd = $perl;
warn "# sleeping for timeout test\n" if $c->{timeout};
eval {
($stdout, $stderr) = capture {
($output, $exit) = CPAN::Reporter::record_command(
"$cmd $fh $c->{args}", $c->{timeout}
);
};
};
sleep 1; # pad the run time into the next second
my $run_time = time() - $start_time;
diag $@ if $@;
if ( $c->{timeout} ) {
my ($time_ok, $verb, $range);
if ( $c->{timeout} < $c->{delay} ) { # if process should time out
$time_ok = $run_time <= $c->{delay};
$verb = "stopped";
$range = sprintf( "timeout (%d) : ran (%d) : sleep (%d)",
$c->{timeout}, $run_time, $c->{delay}
);
}
else { # process should exit before timeout
$time_ok = $run_time <= $c->{timeout};
$verb = "didn't stop";
$range = sprintf( "sleep (%d) : ran (%d) : timeout (%d)",
$c->{delay}, $run_time, $c->{timeout}
);
}
ok( $time_ok, "$c->{label}: timeout $verb process") or diag $range;
}
else {
pass "$c->{label}: No timeout requested";
}
like( $stdout, "/" . quotemeta(join(q{},@$output)) . "/",
"$c->{label}: captured stdout"
);
is_deeply( $output, $c->{output}, "$c->{label}: output as expected" )
or diag "STDOUT:\n$stdout\n\nSTDERR:\n$stderr\n";
is( $exit, $c->{exit_code}, "$c->{label}: exit code correct" );
} # SKIP
}
|