mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-14 10:13:05 +02:00
39744a4f1d
Reported by Leonardo Avellar.
394 lines
14 KiB
Perl
394 lines
14 KiB
Perl
####################################################################################################################################
|
|
# RunTest.pm - All tests are inherited from this object
|
|
####################################################################################################################################
|
|
package pgBackRestTest::Common::RunTest;
|
|
|
|
####################################################################################################################################
|
|
# Perl includes
|
|
####################################################################################################################################
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
use English '-no_match_vars';
|
|
|
|
use Exporter qw(import);
|
|
our @EXPORT = qw();
|
|
|
|
use pgBackRest::Common::Exception;
|
|
use pgBackRest::Common::Log;
|
|
|
|
use pgBackRestTest::Common::LogTest;
|
|
use pgBackRestTest::Common::DefineTest;
|
|
|
|
####################################################################################################################################
|
|
# Constant to use when bogus data is required
|
|
####################################################################################################################################
|
|
use constant BOGUS => 'bogus';
|
|
push @EXPORT, qw(BOGUS);
|
|
|
|
|
|
####################################################################################################################################
|
|
# The current test run that is executung. Only a single run should ever occur in a process to prevent various cleanup issues from
|
|
# affecting the next run. Of course multiple subtests can be executed in a single run.
|
|
####################################################################################################################################
|
|
my $oTestRun;
|
|
|
|
####################################################################################################################################
|
|
# new
|
|
####################################################################################################################################
|
|
sub new
|
|
{
|
|
my $class = shift; # Class name
|
|
|
|
# Create the class hash
|
|
my $self = {};
|
|
bless $self, $class;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
my ($strOperation) = logDebugParam(__PACKAGE__ . '->new');
|
|
|
|
# Initialize run counter
|
|
$self->{iRun} = 0;
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'self', value => $self, trace => true}
|
|
);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# init
|
|
#
|
|
# Empty init sub in case the ancestor class does not delare one.
|
|
####################################################################################################################################
|
|
sub init {}
|
|
|
|
####################################################################################################################################
|
|
# final
|
|
#
|
|
# Empty final sub in case the ancestor class does not delare one.
|
|
####################################################################################################################################
|
|
sub final {}
|
|
|
|
####################################################################################################################################
|
|
# process
|
|
####################################################################################################################################
|
|
sub process
|
|
{
|
|
my $self = shift;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
(
|
|
my $strOperation,
|
|
$self->{strVm},
|
|
$self->{iVmId},
|
|
$self->{strBasePath},
|
|
$self->{strTestPath},
|
|
$self->{strBackRestExe},
|
|
$self->{strPgBinPath},
|
|
$self->{strPgVersion},
|
|
$self->{strModule},
|
|
$self->{strModuleTest},
|
|
$self->{iyModuleTestRun},
|
|
$self->{iProcessMax},
|
|
$self->{bOutput},
|
|
$self->{bDryRun},
|
|
$self->{bCleanup},
|
|
$self->{bLogForce},
|
|
$self->{strPgUser},
|
|
$self->{strBackRestUser},
|
|
$self->{strGroup},
|
|
) =
|
|
logDebugParam
|
|
(
|
|
__PACKAGE__ . '->process', \@_,
|
|
{name => 'strVm'},
|
|
{name => 'iVmId'},
|
|
{name => 'strBasePath'},
|
|
{name => 'strTestPath'},
|
|
{name => 'strBackRestExe'},
|
|
{name => 'strPgBinPath', required => false},
|
|
{name => 'strPgVersion', required => false},
|
|
{name => 'strModule'},
|
|
{name => 'strModuleTest'},
|
|
{name => 'iModuleTestRun', required => false},
|
|
{name => 'iProcessMax'},
|
|
{name => 'bOutput'},
|
|
{name => 'bDryRun'},
|
|
{name => 'bCleanup'},
|
|
{name => 'bLogForce'},
|
|
{name => 'strPgUser'},
|
|
{name => 'strBackRestUser'},
|
|
{name => 'strGroup'},
|
|
);
|
|
|
|
# Init, run, and end the test(s)
|
|
$self->init();
|
|
$self->run();
|
|
$self->final();
|
|
$self->end();
|
|
|
|
# Make sure the correct number of tests ran
|
|
my $hModule = testDefModuleGet($self->{strModule});
|
|
my $hModuleTest = testDefModuleTestGet($hModule, $self->{strModuleTest});
|
|
|
|
if ($hModuleTest->{&TESTDEF_TEST_TOTAL} != $self->runCurrent())
|
|
{
|
|
confess &log(ASSERT, "expected $hModuleTest->{&TESTDEF_TEST_TOTAL} tests to run but $self->{iRun} ran");
|
|
}
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'self', value => $self, trace => true}
|
|
);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# begin
|
|
####################################################################################################################################
|
|
sub begin
|
|
{
|
|
my $self = shift;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$strDescription,
|
|
$bExpect,
|
|
) =
|
|
logDebugParam
|
|
(
|
|
__PACKAGE__ . '->begin', \@_,
|
|
{name => 'strDescription'},
|
|
{name => 'bExpect', required => false},
|
|
);
|
|
|
|
# Save the previous expect log
|
|
$self->end();
|
|
|
|
# If bExpect is defined then it is an override of the default
|
|
if (defined($bExpect))
|
|
{
|
|
$self->{bExpect} = $bExpect;
|
|
}
|
|
# Else get the default expect setting
|
|
else
|
|
{
|
|
my $hModule = testDefModuleGet($self->{strModule});
|
|
my $hModuleTest = testDefModuleTestGet($hModule, $self->{strModuleTest});
|
|
$self->{bExpect} =
|
|
defined($hModuleTest->{&TESTDEF_EXPECT}) ?
|
|
($hModuleTest->{&TESTDEF_EXPECT} ? true : false) :
|
|
(defined($hModule->{&TESTDEF_EXPECT}) ?
|
|
($hModule->{&TESTDEF_EXPECT} ? true : false) :
|
|
false);
|
|
}
|
|
|
|
# Increment the run counter;
|
|
$self->{iRun}++;
|
|
|
|
# Return if this test should not be run
|
|
if (@{$self->{iyModuleTestRun}} != 0 && !grep(/^$self->{iRun}$/i, @{$self->{iyModuleTestRun}}))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
# Output information about test to run
|
|
&log(INFO, 'run ' . sprintf('%03d', $self->runCurrent()) . ' - ' . $strDescription);
|
|
|
|
if ($self->isDryRun())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
# If the module is defined then create a ExpectTest object
|
|
if ($self->doExpect())
|
|
{
|
|
$self->{oExpect} = new pgBackRestTest::Common::LogTest(
|
|
$self->module(), $self->moduleTest(), $self->runCurrent(), $self->doLogForce(), $strDescription, $self->backrestExe(),
|
|
$self->pgBinPath(), $self->testPath());
|
|
|
|
&log(INFO, ' expect log: ' . $self->{oExpect}->{strFileName});
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# end
|
|
####################################################################################################################################
|
|
sub end
|
|
{
|
|
my $self = shift;
|
|
|
|
# Save the previous test log
|
|
if (defined($self->expect()))
|
|
{
|
|
$self->expect()->logWrite($self->basePath(), $self->testPath());
|
|
delete($self->{oExpect});
|
|
}
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# testResult
|
|
####################################################################################################################################
|
|
sub testResult
|
|
{
|
|
my $self = shift;
|
|
my $fnSub = shift;
|
|
my $strExpected = shift;
|
|
|
|
my $strActual = $fnSub->();
|
|
|
|
if (!defined($strExpected) && defined($strActual) || defined($strExpected) && !defined($strActual) ||
|
|
$strActual ne $strExpected)
|
|
{
|
|
confess
|
|
'expected ' . (defined($strExpected) ? "\"${strExpected}\"" : '[undef]') .
|
|
" but actual was " . (defined($strActual) ? "\"${strActual}\"" : '[undef]');
|
|
}
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# testException
|
|
####################################################################################################################################
|
|
sub testException
|
|
{
|
|
my $self = shift;
|
|
my $fnSub = shift;
|
|
my $iCodeExpected = shift;
|
|
my $strMessageExpected = shift;
|
|
|
|
my $bError = false;
|
|
my $strError = "exception ${iCodeExpected}, \"${strMessageExpected}\" was expected";
|
|
|
|
eval
|
|
{
|
|
$fnSub->();
|
|
return true;
|
|
}
|
|
or do
|
|
{
|
|
if (!isException($EVAL_ERROR))
|
|
{
|
|
confess "${strError} but actual was standard Perl exception";
|
|
}
|
|
|
|
if (!($EVAL_ERROR->code() == $iCodeExpected && $EVAL_ERROR->message() eq $strMessageExpected))
|
|
{
|
|
confess "${strError} but actual was " . $EVAL_ERROR->code() . ", \"" . $EVAL_ERROR->message() . "\"";
|
|
}
|
|
|
|
$bError = true;
|
|
};
|
|
|
|
if (!$bError)
|
|
{
|
|
confess "${strError} but no exception was thrown";
|
|
}
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# testRunName
|
|
#
|
|
# Create module/test names by upper-casing the first letter and then inserting capitals after each -.
|
|
####################################################################################################################################
|
|
sub testRunName
|
|
{
|
|
my $strName = shift;
|
|
|
|
my @stryName = split('\-', $strName);
|
|
$strName = undef;
|
|
|
|
foreach my $strPart (@stryName)
|
|
{
|
|
$strName .= ucfirst($strPart);
|
|
}
|
|
|
|
return $strName;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# testRun
|
|
####################################################################################################################################
|
|
sub testRun
|
|
{
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$strModule,
|
|
$strModuleTest,
|
|
) =
|
|
logDebugParam
|
|
(
|
|
__PACKAGE__ . '::testRun', \@_,
|
|
{name => 'strModule', trace => true},
|
|
{name => 'strModuleTest', trace => true},
|
|
);
|
|
|
|
# Error if the test run is already defined - only one run per process is allowed
|
|
if (defined($oTestRun))
|
|
{
|
|
confess &log(ASSERT, 'a test run has already been created in this process');
|
|
}
|
|
|
|
my $strModuleName =
|
|
'pgBackRestTest::' . testRunName($strModule) . '::' . testRunName($strModule) . testRunName($strModuleTest) . 'Test';
|
|
|
|
$oTestRun = eval( ## no critic (BuiltinFunctions::ProhibitStringyEval)
|
|
"require ${strModuleName}; ${strModuleName}->import(); return new ${strModuleName}();")
|
|
or do {confess $EVAL_ERROR};
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'oRun', value => $oTestRun, trace => true}
|
|
);
|
|
}
|
|
|
|
push @EXPORT, qw(testRun);
|
|
|
|
####################################################################################################################################
|
|
# testRunGet
|
|
####################################################################################################################################
|
|
sub testRunGet
|
|
{
|
|
return $oTestRun;
|
|
}
|
|
|
|
push @EXPORT, qw(testRunGet);
|
|
|
|
####################################################################################################################################
|
|
# Getters
|
|
####################################################################################################################################
|
|
sub backrestExe {return shift->{strBackRestExe}}
|
|
sub backrestUser {return shift->{strBackRestUser}}
|
|
sub basePath {return shift->{strBasePath}}
|
|
sub dataPath {return shift->basePath() . '/test/data'}
|
|
sub doCleanup {return shift->{bCleanup}}
|
|
sub doExpect {return shift->{bExpect}}
|
|
sub doLogForce {return shift->{bLogForce}}
|
|
sub group {return shift->{strGroup}}
|
|
sub isDryRun {return shift->{bDryRun}}
|
|
sub expect {return shift->{oExpect}}
|
|
sub module {return shift->{strModule}}
|
|
sub moduleTest {return shift->{strModuleTest}}
|
|
sub pgBinPath {return shift->{strPgBinPath}}
|
|
sub pgUser {return shift->{strPgUser}}
|
|
sub pgVersion {return shift->{strPgVersion}}
|
|
sub processMax {return shift->{iProcessMax}}
|
|
sub runCurrent {return shift->{iRun}}
|
|
sub stanza {return 'db'}
|
|
sub testPath {return shift->{strTestPath}}
|
|
sub vm {return shift->{strVm}}
|
|
sub vmId {return shift->{iVmId}}
|
|
|
|
1;
|