Revision control

Copy as Markdown

#!/usr/bin/env perl
use strict;
use warnings;
package TestReliableExe;
use Capture::Tiny qw( capture );
use English qw( -no_match_vars );
use Env::Path;
use File::Spec::Functions;
use File::Temp qw( tempdir );
use FindBin;
use Readonly;
use Test::Exception;
use Test::More;
use File::Basename qw( basename );
use lib catfile( $FindBin::Bin, qw(..) x 2 );
use QtQA::Proc::Reliable::TESTDATA qw( %TESTDATA );
use QtQA::Test::More qw( :all );
use base 'QtQA::TestScript';
=head1 NAME
30-testscript-reliable-exe.t - system test of exe's `reliable' feature
=head1 DESCRIPTION
This test runs various commands with simulated error cases and verifies that
exe automatically recovers from certain errors.
=cut
sub new
{
my ($class) = @_;
my $self = $class->SUPER::new( );
bless( $self, $class );
return $self;
}
sub run_one_test
{
my ($self, $testname, $testdata) = @_;
my $tempdir = tempdir( basename($0).'.XXXXXX', TMPDIR => 1, CLEANUP => 1 );
my $command = $testdata->{ command };
my %mock_command = %{$testdata->{ mock_command }};
my $reliable = $testdata->{ reliable } // 1;
my $expected_stderr = $testdata->{ expected_exe_stderr }
// $testdata->{ expected_raw_stderr }
// q{};
my $expected_stdout = $testdata->{ expected_exe_stdout }
// $testdata->{ expected_raw_stdout }
// q{};
my $expected_status = $testdata->{ expected_status } // 0;
$mock_command{ directory } = $tempdir;
if (! exists $mock_command{ name }) {
$mock_command{ name } = $command->[0];
}
create_mock_command( %mock_command );
# Put our mock command first in PATH
local $ENV{ PATH } = $ENV{ PATH };
Env::Path->PATH->Prepend( $tempdir );
# Usually, we just pass our command to exe ...
my @exe_args = @{$command};
# ... but, for a non-auto `reliable', we pass options too.
if (ref($reliable) || $reliable != 1) {
@exe_args = ( { reliable => $reliable }, @exe_args );
}
my ($lives_or_dies_text, $lives_or_dies_ok)
= ($expected_status == 0) ? ('exits successfully', \&lives_ok)
: ('fails as expected', \&dies_ok )
;
my ($stdout, $stderr) = capture {
$lives_or_dies_ok->(
sub { $self->exe( @exe_args ) },
"$testname $lives_or_dies_text",
);
};
# exe() should have set $? to the expected value
is( $?, $expected_status, "$testname \$? set as expected" );
# Immediately prior to stdout should always be the command;
# Prior to that may be either CWD or PATH lines.
my $prefix = quotemeta( '+ '.join(' ', @{$command}) );
$prefix = qr{
\A
(?:\+\ CWD:\ [^\n]+\n)?
(?:\+\ PATH:\ [^\n]+\n)?
$prefix \n
}xms;
like( $stdout, $prefix, "$testname stdout first line looks correct" );
# Remove prefix for subsequent comparison
$stdout =~ s{$prefix}{}xms;
is_or_like( $stdout, $expected_stdout, "$testname stdout looks correct" );
is_or_like( $stderr, $expected_stderr, "$testname stderr looks correct" );
return;
}
sub run
{
my ($self) = @_;
while (my ($testname, $testdata) = each %TESTDATA) {
$self->run_one_test($testname, $testdata);
}
done_testing( );
return;
}
TestReliableExe->new( )->run( ) if (!caller);
1;