2016-12-23 15:22:59 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# ConfigCommonTest.pm - Common code for Config unit tests
|
|
|
|
####################################################################################################################################
|
2017-05-12 22:43:04 +02:00
|
|
|
package pgBackRestTest::Env::ConfigEnvTest;
|
2016-12-23 15:22:59 +02:00
|
|
|
use parent 'pgBackRestTest::Common::RunTest';
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# Perl includes
|
|
|
|
####################################################################################################################################
|
|
|
|
use strict;
|
|
|
|
use warnings FATAL => qw(all);
|
|
|
|
use Carp qw(confess);
|
|
|
|
use English '-no_match_vars';
|
|
|
|
|
|
|
|
use pgBackRest::Common::Exception;
|
|
|
|
use pgBackRest::Common::Log;
|
|
|
|
use pgBackRest::Config::Config;
|
2017-08-25 22:47:47 +02:00
|
|
|
use pgBackRest::Config::Data;
|
2016-12-23 15:22:59 +02:00
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
use constant CONFIGENVTEST => 'ConfigEnvTest';
|
|
|
|
|
|
|
|
sub optionTestSet
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
|
|
|
my $self = shift;
|
2017-08-25 22:47:47 +02:00
|
|
|
my $iOptionId = shift;
|
2016-12-23 15:22:59 +02:00
|
|
|
my $strValue = shift;
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
$self->{&CONFIGENVTEST}{option}{cfgOptionName($iOptionId)} = $strValue;
|
2016-12-23 15:22:59 +02:00
|
|
|
}
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
sub optionTestSetBool
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
|
|
|
my $self = shift;
|
2017-08-25 22:47:47 +02:00
|
|
|
my $iOptionId = shift;
|
2016-12-23 15:22:59 +02:00
|
|
|
my $bValue = shift;
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
$self->{&CONFIGENVTEST}{boolean}{cfgOptionName($iOptionId)} = defined($bValue) ? $bValue : true;
|
2016-12-23 15:22:59 +02:00
|
|
|
}
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
sub optionTestClear
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
|
|
|
my $self = shift;
|
2017-08-25 22:47:47 +02:00
|
|
|
my $iOptionId = shift;
|
|
|
|
|
|
|
|
delete($self->{&CONFIGENVTEST}{option}{cfgOptionName($iOptionId)});
|
|
|
|
delete($self->{&CONFIGENVTEST}{boolean}{cfgOptionName($iOptionId)});
|
|
|
|
}
|
|
|
|
|
|
|
|
sub configTestClear
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
my $rhConfig = $self->{&CONFIGENVTEST};
|
2016-12-23 15:22:59 +02:00
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
delete($self->{&CONFIGENVTEST});
|
|
|
|
|
|
|
|
return $rhConfig;
|
2016-12-23 15:22:59 +02:00
|
|
|
}
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
sub configTestSet
|
2017-01-27 16:42:30 +02:00
|
|
|
{
|
|
|
|
my $self = shift;
|
2017-08-25 22:47:47 +02:00
|
|
|
my $rhConfig = shift;
|
2017-01-27 16:42:30 +02:00
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
$self->{&CONFIGENVTEST} = $rhConfig;
|
2017-01-27 16:42:30 +02:00
|
|
|
}
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
sub commandTestWrite
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
|
|
|
my $self = shift;
|
2017-08-25 22:47:47 +02:00
|
|
|
my $strCommand = shift;
|
|
|
|
my $rhConfig = shift;
|
2016-12-23 15:22:59 +02:00
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
my @szyParam = ();
|
2016-12-23 15:22:59 +02:00
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
if (defined($rhConfig->{boolean}))
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
2017-08-25 22:47:47 +02:00
|
|
|
foreach my $strOption (sort(keys(%{$rhConfig->{boolean}})))
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
2017-08-25 22:47:47 +02:00
|
|
|
if ($rhConfig->{boolean}{$strOption})
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
2017-08-25 22:47:47 +02:00
|
|
|
push(@szyParam, "--${strOption}");
|
2016-12-23 15:22:59 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-08-25 22:47:47 +02:00
|
|
|
push(@szyParam, "--no-${strOption}");
|
2016-12-23 15:22:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
if (defined($rhConfig->{option}))
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
2017-08-25 22:47:47 +02:00
|
|
|
foreach my $strOption (sort(keys(%{$rhConfig->{option}})))
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
2017-08-25 22:47:47 +02:00
|
|
|
push(@szyParam, "--${strOption}=$rhConfig->{option}{$strOption}");
|
2016-12-23 15:22:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
push(@szyParam, $strCommand);
|
2016-12-23 15:22:59 +02:00
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
return @szyParam;
|
|
|
|
}
|
2016-12-23 15:22:59 +02:00
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
sub configTestLoad
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my $iCommandId = shift;
|
|
|
|
|
|
|
|
@ARGV = $self->commandTestWrite(cfgCommandName($iCommandId), $self->{&CONFIGENVTEST});
|
|
|
|
$self->testResult(sub {configLoad(false)}, true, 'config load: ' . join(" ", @ARGV));
|
2016-12-23 15:22:59 +02:00
|
|
|
}
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# optionTestSetByName - used only by config unit tests, general option set should be done with optionTestSet
|
|
|
|
####################################################################################################################################
|
|
|
|
sub optionTestSetByName
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my $strOption = shift;
|
|
|
|
my $strValue = shift;
|
|
|
|
|
|
|
|
$self->{&CONFIGENVTEST}{option}{$strOption} = $strValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# configTestLoadExpect - used only by config unit tests, for general config load use configTestLoad()
|
|
|
|
####################################################################################################################################
|
|
|
|
sub configTestLoadExpect
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my $strCommand = shift;
|
|
|
|
my $iExpectedError = shift;
|
|
|
|
my $strErrorParam1 = shift;
|
|
|
|
my $strErrorParam2 = shift;
|
|
|
|
my $strErrorParam3 = shift;
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
my $oOptionRuleExpected = cfgdefRuleIndex();
|
2016-12-23 15:22:59 +02:00
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
@ARGV = $self->commandTestWrite($strCommand, $self->{&CONFIGENVTEST});
|
|
|
|
$self->configTestClear();
|
|
|
|
&log(INFO, " command line: " . join(" ", @ARGV));
|
2016-12-23 15:22:59 +02:00
|
|
|
|
|
|
|
my $bErrorFound = false;
|
|
|
|
|
|
|
|
eval
|
|
|
|
{
|
|
|
|
configLoad(false);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
or do
|
|
|
|
{
|
|
|
|
my $oException = $EVAL_ERROR;
|
|
|
|
|
|
|
|
if (!defined($iExpectedError))
|
|
|
|
{
|
|
|
|
confess $oException;
|
|
|
|
}
|
|
|
|
|
|
|
|
$bErrorFound = true;
|
|
|
|
|
2017-10-16 16:47:31 +02:00
|
|
|
if (isException(\$oException))
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
|
|
|
if ($oException->code() != $iExpectedError)
|
|
|
|
{
|
|
|
|
confess "expected error ${iExpectedError} from configLoad but got [" . $oException->code() .
|
|
|
|
"] '" . $oException->message() . "'";
|
|
|
|
}
|
|
|
|
|
|
|
|
my $strError;
|
|
|
|
|
|
|
|
if ($iExpectedError == ERROR_OPTION_REQUIRED)
|
|
|
|
{
|
|
|
|
$strError = "${strCommand} command requires option: ${strErrorParam1}" .
|
|
|
|
(defined($strErrorParam2) ? "\nHINT: ${strErrorParam2}" : '');
|
|
|
|
}
|
|
|
|
elsif ($iExpectedError == ERROR_COMMAND_REQUIRED)
|
|
|
|
{
|
|
|
|
$strError = "command must be specified";
|
|
|
|
}
|
|
|
|
elsif ($iExpectedError == ERROR_OPTION_INVALID)
|
|
|
|
{
|
|
|
|
$strError = "option '${strErrorParam1}' not valid without option '${strErrorParam2}'";
|
|
|
|
|
|
|
|
if (defined($strErrorParam3))
|
|
|
|
{
|
|
|
|
$strError .= @{$strErrorParam3} == 1 ? " = '$$strErrorParam3[0]'" :
|
|
|
|
" in ('" . join("', '",@{ $strErrorParam3}) . "')";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elsif ($iExpectedError == ERROR_OPTION_COMMAND)
|
|
|
|
{
|
|
|
|
$strError = "option '${strErrorParam1}' not valid for command '${strErrorParam2}'";
|
|
|
|
}
|
|
|
|
elsif ($iExpectedError == ERROR_OPTION_INVALID_VALUE)
|
|
|
|
{
|
|
|
|
$strError = "'${strErrorParam1}' is not valid for '${strErrorParam2}' option" .
|
|
|
|
(defined($strErrorParam3) ? "\nHINT: ${strErrorParam3}." : '');
|
|
|
|
}
|
|
|
|
elsif ($iExpectedError == ERROR_OPTION_MULTIPLE_VALUE)
|
|
|
|
{
|
|
|
|
$strError = "option '${strErrorParam1}' cannot be specified multiple times";
|
|
|
|
}
|
|
|
|
elsif ($iExpectedError == ERROR_OPTION_INVALID_RANGE)
|
|
|
|
{
|
|
|
|
$strError = "'${strErrorParam1}' is not valid for '${strErrorParam2}' option";
|
|
|
|
}
|
|
|
|
elsif ($iExpectedError == ERROR_OPTION_INVALID_PAIR)
|
|
|
|
{
|
|
|
|
$strError = "'${strErrorParam1}' not valid key/value for '${strErrorParam2}' option";
|
|
|
|
}
|
|
|
|
elsif ($iExpectedError == ERROR_OPTION_NEGATE)
|
|
|
|
{
|
|
|
|
$strError = "option '${strErrorParam1}' cannot be both set and negated";
|
|
|
|
}
|
|
|
|
elsif ($iExpectedError == ERROR_FILE_INVALID)
|
|
|
|
{
|
|
|
|
$strError = "'${strErrorParam1}' is not a file";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
confess
|
|
|
|
"must construct message for error ${iExpectedError}, use this as an example: '" . $oException->message() . "'";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($oException->message() ne $strError)
|
|
|
|
{
|
|
|
|
confess "expected error message \"${strError}\" from configLoad but got \"" . $oException->message() . "\"";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
confess "configLoad should throw pgBackRest::Common::Exception:\n$oException";
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!$bErrorFound && defined($iExpectedError))
|
|
|
|
{
|
|
|
|
confess "expected error ${iExpectedError} from configLoad but got success";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# configTestExpect - used only by config unit tests
|
|
|
|
####################################################################################################################################
|
2016-12-23 15:22:59 +02:00
|
|
|
sub optionTestExpect
|
|
|
|
{
|
|
|
|
my $self = shift;
|
2017-08-25 22:47:47 +02:00
|
|
|
my $iOptionId = shift;
|
2016-12-23 15:22:59 +02:00
|
|
|
my $strExpectedValue = shift;
|
|
|
|
my $strExpectedKey = shift;
|
|
|
|
|
2017-08-25 22:47:47 +02:00
|
|
|
my $strOption = cfgOptionName($iOptionId);
|
|
|
|
|
2016-12-23 15:22:59 +02:00
|
|
|
if (defined($strExpectedValue))
|
|
|
|
{
|
2017-08-25 22:47:47 +02:00
|
|
|
my $strActualValue = cfgOption($iOptionId);
|
2016-12-23 15:22:59 +02:00
|
|
|
|
|
|
|
if (defined($strExpectedKey))
|
|
|
|
{
|
|
|
|
$strActualValue = $$strActualValue{$strExpectedKey};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!defined($strActualValue))
|
|
|
|
{
|
|
|
|
confess "expected option ${strOption} to have value ${strExpectedValue} but [undef] found instead";
|
|
|
|
}
|
|
|
|
|
|
|
|
$strActualValue eq $strExpectedValue
|
|
|
|
or confess "expected option ${strOption} to have value ${strExpectedValue} but ${strActualValue} found instead";
|
|
|
|
}
|
2017-08-25 22:47:47 +02:00
|
|
|
elsif (cfgOptionTest(cfgOptionId($strOption)))
|
2016-12-23 15:22:59 +02:00
|
|
|
{
|
2017-08-25 22:47:47 +02:00
|
|
|
confess "expected option ${strOption} to be [undef], but " . cfgOption(cfgOptionId($strOption)) . ' found instead';
|
2016-12-23 15:22:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|