#################################################################################################################################### # ConfigCommonTest.pm - Common code for Config unit tests #################################################################################################################################### package pgBackRestTest::Env::ConfigEnvTest; 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; use pgBackRest::Config::Data; use constant CONFIGENVTEST => 'ConfigEnvTest'; sub optionTestSet { my $self = shift; my $iOptionId = shift; my $strValue = shift; $self->{&CONFIGENVTEST}{option}{cfgOptionName($iOptionId)} = $strValue; } sub optionTestSetBool { my $self = shift; my $iOptionId = shift; my $bValue = shift; $self->{&CONFIGENVTEST}{boolean}{cfgOptionName($iOptionId)} = defined($bValue) ? $bValue : true; } sub optionTestClear { my $self = shift; my $iOptionId = shift; delete($self->{&CONFIGENVTEST}{option}{cfgOptionName($iOptionId)}); delete($self->{&CONFIGENVTEST}{boolean}{cfgOptionName($iOptionId)}); } sub configTestClear { my $self = shift; my $rhConfig = $self->{&CONFIGENVTEST}; delete($self->{&CONFIGENVTEST}); return $rhConfig; } sub configTestSet { my $self = shift; my $rhConfig = shift; $self->{&CONFIGENVTEST} = $rhConfig; } sub commandTestWrite { my $self = shift; my $strCommand = shift; my $rhConfig = shift; my @szyParam = (); if (defined($rhConfig->{boolean})) { foreach my $strOption (sort(keys(%{$rhConfig->{boolean}}))) { if ($rhConfig->{boolean}{$strOption}) { push(@szyParam, "--${strOption}"); } else { push(@szyParam, "--no-${strOption}"); } } } if (defined($rhConfig->{option})) { foreach my $strOption (sort(keys(%{$rhConfig->{option}}))) { push(@szyParam, "--${strOption}=$rhConfig->{option}{$strOption}"); } } push(@szyParam, $strCommand); return @szyParam; } 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)); } #################################################################################################################################### # 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 { my $self = shift; my $strCommand = shift; my $iExpectedError = shift; my $strErrorParam1 = shift; my $strErrorParam2 = shift; my $strErrorParam3 = shift; my $oOptionRuleExpected = cfgdefRuleIndex(); @ARGV = $self->commandTestWrite($strCommand, $self->{&CONFIGENVTEST}); $self->configTestClear(); &log(INFO, " command line: " . join(" ", @ARGV)); my $bErrorFound = false; eval { configLoad(false); return true; } or do { my $oException = $EVAL_ERROR; if (!defined($iExpectedError)) { confess $oException; } $bErrorFound = true; if (isException(\$oException)) { 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"; } } #################################################################################################################################### # configTestExpect - used only by config unit tests #################################################################################################################################### sub optionTestExpect { my $self = shift; my $iOptionId = shift; my $strExpectedValue = shift; my $strExpectedKey = shift; my $strOption = cfgOptionName($iOptionId); if (defined($strExpectedValue)) { my $strActualValue = cfgOption($iOptionId); 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"; } elsif (cfgOptionTest(cfgOptionId($strOption))) { confess "expected option ${strOption} to be [undef], but " . cfgOption(cfgOptionId($strOption)) . ' found instead'; } } 1;