1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2026-05-22 10:15:16 +02:00

Major refactor of the test suite.

* Make the code more modular and object-oriented.
* Multiple Docker containers can now be created for a single test to simulate more realistic environments.
This commit is contained in:
David Steele
2016-06-24 08:12:58 -04:00
parent 23a3911830
commit c8f806a293
68 changed files with 9216 additions and 9446 deletions
@@ -0,0 +1,105 @@
####################################################################################################################################
# BackupCommonTest.pm - Common code for backup unit tests
####################################################################################################################################
package pgBackRestTest::Backup::BackupCommonTest;
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Config::Config;
use pgBackRestTest::Backup::Common::HostBackupTest;
use pgBackRestTest::Backup::Common::HostBaseTest;
use pgBackRestTest::Backup::Common::HostDbCommonTest;
use pgBackRestTest::Backup::Common::HostDbTest;
use pgBackRestTest::Backup::Common::HostDbSyntheticTest;
use pgBackRestTest::Common::HostGroupTest;
use pgBackRestTest::CommonTest;
####################################################################################################################################
# backupTestSetup
####################################################################################################################################
sub backupTestSetup
{
my $bRemote = shift;
my $bSynthetic = shift;
my $oLogTest = shift;
my $oConfigParam = shift;
# Get host group
my $oHostGroup = hostGroupGet();
# Create the backup container
my $oHostBackup = undef;
if ($bRemote)
{
$oHostBackup = new pgBackRestTest::Backup::Common::HostBackupTest(
{strDbMaster => HOST_DB_MASTER, bSynthetic => $bSynthetic, oLogTest => $bSynthetic ? $oLogTest : undef});
$oHostGroup->hostAdd($oHostBackup);
}
# Create the db-master container
my $oHostDbMaster = undef;
if ($bSynthetic)
{
$oHostDbMaster = new pgBackRestTest::Backup::Common::HostDbSyntheticTest(
{oHostBackup => $oHostBackup, oLogTest => $oLogTest});
}
else
{
$oHostDbMaster = new pgBackRestTest::Backup::Common::HostDbTest({oHostBackup => $oHostBackup});
}
$oHostGroup->hostAdd($oHostDbMaster);
$oHostBackup = defined($oHostBackup) ? $oHostBackup : $oHostDbMaster;
# Create the local file object
my $oFile =
new pgBackRest::File
(
$oHostDbMaster->stanza(),
$oHostDbMaster->repoPath(),
undef,
new pgBackRest::Protocol::Common
(
OPTION_DEFAULT_BUFFER_SIZE, # Buffer size
OPTION_DEFAULT_COMPRESS_LEVEL, # Compress level
OPTION_DEFAULT_COMPRESS_LEVEL_NETWORK, # Compress network level
HOST_PROTOCOL_TIMEOUT # Protocol timeout
)
);
# Create db master config
$oHostDbMaster->configCreate(
($bRemote ? $oHostBackup : undef),
$$oConfigParam{bCompress},
$bRemote ? undef : $$oConfigParam{bHardLink}, # hardlink
undef, # thread-max
$$oConfigParam{bArchiveAsync},
undef);
# Create backup config
if ($bRemote)
{
$oHostBackup->configCreate(
$oHostDbMaster,
$$oConfigParam{bCompress}, # compress
$$oConfigParam{bHardLink}, # hardlink
$$oConfigParam{iThreadMax}); # thread-max
}
return $oHostDbMaster, $oHostBackup, $oFile;
}
push @EXPORT, qw(backupTestSetup);
1;
File diff suppressed because it is too large Load Diff
@@ -1,7 +1,7 @@
####################################################################################################################################
# ExpireCommonTest.pm - Common code for expire tests
####################################################################################################################################
package pgBackRestTest::ExpireCommonTest;
package pgBackRestTest::Backup::Common::ExpireCommonTest;
####################################################################################################################################
# Perl includes
@@ -10,9 +10,6 @@ use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use File::Basename qw(dirname);
use lib dirname($0) . '/../lib';
use pgBackRest::BackupCommon;
use pgBackRest::BackupInfo;
use pgBackRest::Common::Ini;
@@ -20,9 +17,13 @@ use pgBackRest::Common::Log;
use pgBackRest::Config::Config;
use pgBackRest::Db;
use pgBackRest::File;
use pgBackRest::FileCommon;
use pgBackRest::Manifest;
use pgBackRestTest::Backup::Common::HostBackupTest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::FileTest;
use pgBackRestTest::Common::HostGroupTest;
use pgBackRestTest::CommonTest;
####################################################################################################################################
@@ -52,12 +53,14 @@ sub new
# Assign function parameters, defaults, and log debug info
(
my $strOperation,
$self->{oHostBackup},
$self->{oFile},
$self->{oLogTest}
) =
logDebugParam
(
OP_EXPIRE_COMMON_TEST_NEW, \@_,
{name => 'oHostBackup', trace => true},
{name => 'oFile', trace => true},
{name => 'oLogTest', required => false, trace => true}
);
@@ -104,12 +107,8 @@ sub stanzaCreate
$$oStanza{iControlVersion} = $strDbVersionTemp . '1';
# Create the stanza backup path
my $strBackupClusterPath = BackRestTestCommon_RepoPathGet() . '/backup';
BackRestTestCommon_PathCreate($strBackupClusterPath, undef, true);
$strBackupClusterPath .= "/${strStanza}";
BackRestTestCommon_PathCreate($strBackupClusterPath, undef, true);
BackRestTestCommon_PathCreate("${strBackupClusterPath}/" . PATH_BACKUP_HISTORY, undef, true);
my $strBackupClusterPath = $self->{oHostBackup}->repoPath() . "/backup/${strStanza}";
filePathCreate("${strBackupClusterPath}/" . PATH_BACKUP_HISTORY, undef, undef, true);
$$oStanza{strBackupClusterPath} = $strBackupClusterPath;
@@ -120,11 +119,8 @@ sub stanzaCreate
$oBackupInfo->save();
# Create the stanza archive path
my $strArchiveClusterPath = BackRestTestCommon_RepoPathGet() . '/archive';
BackRestTestCommon_PathCreate($strArchiveClusterPath, undef, true);
$strArchiveClusterPath .= "/${strStanza}";
BackRestTestCommon_PathCreate($strArchiveClusterPath, undef, true);
my $strArchiveClusterPath = $self->{oHostBackup}->repoPath() . "/archive/${strStanza}";
filePathCreate($strArchiveClusterPath, undef, undef, true);
# Create the archive info object
$$oStanza{oArchiveInfo} = new pgBackRest::ArchiveInfo($strArchiveClusterPath);
@@ -132,7 +128,7 @@ sub stanzaCreate
# Create the stanza archive version path
$strArchiveClusterPath .= '/' . $$oStanza{strDbVersion} . '-' . $$oStanza{iDbId};
BackRestTestCommon_PathCreate($strArchiveClusterPath, undef, true);
filePathCreate($strArchiveClusterPath, undef, undef, true);
$$oStanza{strArchiveClusterPath} = $strArchiveClusterPath;
@@ -185,7 +181,7 @@ sub backupCreate
$lTimestamp);
my $strBackupClusterSetPath .= "$$oStanza{strBackupClusterPath}/${strBackupLabel}";
BackRestTestCommon_PathCreate($strBackupClusterSetPath);
filePathCreate($strBackupClusterSetPath);
&log(INFO, "create backup ${strBackupLabel}");
@@ -324,14 +320,13 @@ sub archiveCreate
push(my @stryArchive, $strArchive);
do
{
my $strPath = "$$oStanza{strArchiveClusterPath}/" . substr($strArchive, 0, 16);
BackRestTestCommon_PathCreate($strPath, undef, true);
filePathCreate($strPath);
my $strFile = "${strPath}/${strArchive}-0000000000000000000000000000000000000000" . ($iArchiveIdx % 2 == 0 ? '.gz' : '');
BackRestTestCommon_FileCreate($strFile, 'ARCHIVE');
testFileCreate($strFile, 'ARCHIVE');
$iArchiveIdx++;
@@ -376,13 +371,16 @@ sub supplementalLog
if (defined($self->{oLogTest}))
{
$self->{oLogTest}->supplementalAdd(BackRestTestCommon_RepoPathGet() .
"/backup/${strStanza}/backup.info", undef, $$oStanza{strBackupDescription});
$self->{oLogTest}->supplementalAdd($self->{oHostBackup}->repoPath() .
"/backup/${strStanza}/backup.info", $$oStanza{strBackupDescription});
executeTest('ls ' . BackRestTestCommon_RepoPathGet() . "/backup/${strStanza} | grep -v \"backup.*\"",
{oLogTest => $self->{oLogTest}});
executeTest('ls -R ' . BackRestTestCommon_RepoPathGet() . "/archive/${strStanza} | grep -v \"archive.info\"",
{oLogTest => $self->{oLogTest}});
executeTest(
'ls ' . $self->{oHostBackup}->repoPath() . "/backup/${strStanza} | grep -v \"backup.*\"",
{oLogTest => $self->{oLogTest}});
executeTest(
'ls -R ' . $self->{oHostBackup}->repoPath() . "/archive/${strStanza} | grep -v \"archive.info\"",
{oLogTest => $self->{oLogTest}});
}
return logDebugReturn($strOperation);
@@ -423,8 +421,9 @@ sub process
undef($$oStanza{strBackupDescription});
my $strCommand = BackRestTestCommon_CommandMainGet() .
' "--' . OPTION_CONFIG . '=' . BackRestTestCommon_RepoPathGet() . '/pgbackrest.conf"' .
my $oHostGroup = hostGroupGet();
my $strCommand = $oHostGroup->paramGet(HOST_PARAM_BACKREST_EXE) .
' --' . OPTION_CONFIG . '="' . $self->{oHostBackup}->backrestConfig() . '"' .
' --' . OPTION_STANZA . '=' . $strStanza .
' --' . OPTION_LOG_LEVEL_CONSOLE . '=' . lc(DETAIL);
@@ -446,7 +445,7 @@ sub process
$strCommand .= ' expire';
executeTest($strCommand, {strComment => $strDescription, oLogTest => $self->{oLogTest}});
$self->{oHostBackup}->executeSimple($strCommand, {strComment => $strDescription, oLogTest => $self->{oLogTest}});
$self->supplementalLog($strStanza);
@@ -0,0 +1,861 @@
####################################################################################################################################
# HostBackupTest.pm - Backup host
####################################################################################################################################
package pgBackRestTest::Backup::Common::HostBackupTest;
use parent 'pgBackRestTest::Backup::Common::HostBaseTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Config::Config;
use pgBackRest::File;
use pgBackRest::FileCommon;
use pgBackRest::Manifest;
use pgBackRest::Version;
use pgBackRestTest::Backup::Common::HostBaseTest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::HostGroupTest;
####################################################################################################################################
# Host constants
####################################################################################################################################
use constant HOST_BACKUP => 'backup';
push @EXPORT, qw(HOST_BACKUP);
use constant HOST_BACKUP_USER => 'backup-user';
push @EXPORT, qw(HOST_BACKUP_USER);
####################################################################################################################################
# Host parameters
####################################################################################################################################
use constant HOST_PARAM_BACKREST_CONFIG => 'backrest-config';
push @EXPORT, qw(HOST_PARAM_BACKREST_CONFIG);
use constant HOST_PARAM_BACKREST_EXE => 'backrest-exe';
push @EXPORT, qw(HOST_PARAM_BACKREST_EXE);
use constant HOST_PARAM_LOCK_PATH => 'lock-path';
push @EXPORT, qw(HOST_PARAM_LOCK_PATH);
use constant HOST_PARAM_LOG_PATH => 'log-path';
push @EXPORT, qw(HOST_PARAM_LOG_PATH);
use constant HOST_PARAM_REPO_PATH => 'repo-path';
push @EXPORT, qw(HOST_PARAM_REPO_PATH);
use constant HOST_PARAM_STANZA => 'stanza';
push @EXPORT, qw(HOST_PARAM_STANZA);
use constant HOST_PARAM_THREAD_MAX => 'thread-max';
push @EXPORT, qw(HOST_PARAM_THREAD_MAX);
####################################################################################################################################
# Host paths
####################################################################################################################################
use constant HOST_PATH_LOCK => 'lock';
push @EXPORT, qw(HOST_PATH_LOCK);
use constant HOST_PATH_LOG => 'log';
push @EXPORT, qw(HOST_PATH_LOG);
# !!! This name should be changed to "repo" at the end of this branch
use constant HOST_PATH_REPO => 'backrest';
push @EXPORT, qw(HOST_PATH_REPO);
####################################################################################################################################
# Backup Defaults
####################################################################################################################################
use constant HOST_STANZA => 'db';
push @EXPORT, qw(HOST_STANZA);
use constant HOST_PROTOCOL_TIMEOUT => 10;
push @EXPORT, qw(HOST_PROTOCOL_TIMEOUT);
####################################################################################################################################
# new
####################################################################################################################################
sub new
{
my $class = shift; # Class name
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->new', \@_,
{name => 'oParam', required => false, trace => true},
);
# If params are not passed
my $oHostGroup = hostGroupGet();
my ($strName, $strImage, $strUser, $strVm);
if (!defined($$oParam{strName}) || $$oParam{strName} eq HOST_BACKUP)
{
$strName = HOST_BACKUP;
$strImage = 'backrest/' . $oHostGroup->paramGet(HOST_PARAM_VM) . '-backup-test-pre';
$strUser = $oHostGroup->paramGet(HOST_BACKUP_USER);
$strVm = $oHostGroup->paramGet(HOST_PARAM_VM);
if (!defined($$oParam{strDbMaster}))
{
confess &log(ERROR, "strDbMaster must be specified for dedicated backup hosts");
}
}
else
{
$strName = $$oParam{strName};
$strImage = $$oParam{strImage};
$strUser = $$oParam{strUser};
$strVm = $$oParam{strVm};
}
# Create the host
my $self = $class->SUPER::new($strName, {strImage => $strImage, strUser => $strUser, strVm => $strVm});
bless $self, $class;
# Set parameters
if (defined($$oParam{oHostBackup}))
{
$self->paramSet(HOST_PARAM_REPO_PATH, $$oParam{oHostBackup}->repoPath());
}
else
{
$self->paramSet(HOST_PARAM_REPO_PATH, $self->testPath() . '/' . HOST_PATH_REPO);
$self->paramSet(HOST_PARAM_LOG_PATH, $self->repoPath() . '/' . HOST_PATH_LOG);
$self->paramSet(HOST_PARAM_LOCK_PATH, $self->repoPath() . '/' . HOST_PATH_LOCK);
filePathCreate($self->repoPath(), '0770');
}
$self->paramSet(HOST_PARAM_BACKREST_CONFIG, $self->testPath() . '/' . BACKREST_CONF);
$self->paramSet(HOST_PARAM_BACKREST_EXE, $oHostGroup->paramGet(HOST_PARAM_BACKREST_EXE));
$self->paramSet(HOST_PARAM_STANZA, HOST_STANZA);
$self->paramSet(HOST_PARAM_THREAD_MAX, $oHostGroup->paramGet(HOST_PARAM_THREAD_MAX));
# Set LogTest object
$self->{oLogTest} = $$oParam{oLogTest};
# Set db master host (this is the host where the backups are run)
$self->{strDbMaster} = $$oParam{strDbMaster};
$self->{bSynthetic} = defined($$oParam{bSynthetic}) && $$oParam{bSynthetic} ? true : false;
# Create the local file object
$self->{oFile} = new pgBackRest::File(
$self->stanza(),
$self->repoPath(),
undef,
new pgBackRest::Protocol::Common
(
OPTION_DEFAULT_BUFFER_SIZE, # Buffer size
OPTION_DEFAULT_COMPRESS_LEVEL, # Compress level
OPTION_DEFAULT_COMPRESS_LEVEL_NETWORK, # Compress network level
HOST_PROTOCOL_TIMEOUT # Protocol timeout
));
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self, trace => true}
);
}
####################################################################################################################################
# backupBegin
####################################################################################################################################
sub backupBegin
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strType,
$strComment,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->backupBegin', \@_,
{name => 'strType', trace => true},
{name => 'strComment', trace => true},
{name => 'oParam', required => false, trace => true},
);
# Set defaults
my $strTest = defined($$oParam{strTest}) ? $$oParam{strTest} : undef;
my $fTestDelay = defined($$oParam{fTestDelay}) ? $$oParam{fTestDelay} : .2;
my $oExpectedManifest = defined($$oParam{oExpectedManifest}) ? $$oParam{oExpectedManifest} : undef;
if (!defined($$oParam{iExpectedExitStatus}) && $self->threadMax() > 1)
{
$$oParam{iExpectedExitStatus} = -1;
}
$strComment =
"${strType} backup" . (defined($strComment) ? " - ${strComment}" : '') .
' (' . $self->nameGet() . ' host)';
&log(INFO, " $strComment");
# Execute the backup command
my $oExecuteBackup = $self->execute(
$self->backrestExe() .
' --config=' . $self->backrestConfig() .
(defined($oExpectedManifest) ? " --no-online" : '') .
(defined($$oParam{strOptionalParam}) ? " $$oParam{strOptionalParam}" : '') .
($strType ne 'incr' ? " --type=${strType}" : '') .
' --stanza=' . $self->stanza() . ' backup' .
(defined($strTest) ? " --test --test-delay=${fTestDelay} --test-point=" . lc($strTest) . '=y' : ''),
{strComment => $strComment, iExpectedExitStatus => $$oParam{iExpectedExitStatus}, oLogTest => $self->{oLogTest}});
$oExecuteBackup->begin();
# Return at the test point if one was defined
if (defined($strTest))
{
$oExecuteBackup->end($strTest);
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'oExecuteBackup', value => $oExecuteBackup, trace => true},
);
}
####################################################################################################################################
# backupEnd
####################################################################################################################################
sub backupEnd
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strType,
$oExecuteBackup,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->backupEnd', \@_,
{name => 'strType', trace => true},
{name => 'oExecuteBackup', trace => true},
{name => 'oParam', required => false, trace => true},
);
# Set defaults
my $oExpectedManifest = defined($$oParam{oExpectedManifest}) ? $$oParam{oExpectedManifest} : undef;
my $iExitStatus = $oExecuteBackup->end();
if ($oExecuteBackup->{iExpectedExitStatus} != 0 && $oExecuteBackup->{iExpectedExitStatus} != -1)
{
return;
}
my $strBackup = $self->backupLast();
# Only do compare for synthetic backups
if (defined($oExpectedManifest))
{
# Set backup type in the expected manifest
${$oExpectedManifest}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TYPE} = $strType;
$self->backupCompare($strBackup, $oExpectedManifest);
}
# Add files to expect log
if (defined($self->{oLogTest}) && (!defined($$oParam{bSupplemental}) || $$oParam{bSupplemental}))
{
if ($self->nameTest(HOST_BACKUP))
{
my $oHostGroup = hostGroupGet();
my $oHostDbMaster = $oHostGroup->hostGet($self->{strDbMaster}, true);
if (defined($oHostDbMaster))
{
$self->{oLogTest}->supplementalAdd($oHostDbMaster->testPath() . '/' . BACKREST_CONF);
}
}
$self->{oLogTest}->supplementalAdd($self->testPath() . '/' . BACKREST_CONF);
$self->{oLogTest}->supplementalAdd($self->{oFile}->pathGet(PATH_BACKUP_CLUSTER, "${strBackup}/" . FILE_MANIFEST));
$self->{oLogTest}->supplementalAdd($self->repoPath() . '/backup/' . $self->stanza() . '/backup.info');
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strBackup', value => $strBackup, trace => true},
);
}
####################################################################################################################################
# backup
####################################################################################################################################
sub backup
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strType,
$strComment,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->backup', \@_,
{name => 'strType'},
{name => 'strComment'},
{name => 'oParam', required => false},
);
my $oExecuteBackup = $self->backupBegin($strType, $strComment, $oParam);
my $strBackup = $self->backupEnd($strType, $oExecuteBackup, $oParam);
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strBackup', value => $strBackup},
);
}
####################################################################################################################################
# backupCompare
####################################################################################################################################
sub backupCompare
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strBackup,
$oExpectedManifest,
) =
logDebugParam
(
__PACKAGE__ . '->backupCompare', \@_,
{name => 'strBackup', trace => true},
{name => 'oExpectedManifest', trace => true},
);
${$oExpectedManifest}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_LABEL} = $strBackup;
my $oActualManifest = new pgBackRest::Common::Ini(
$self->{oFile}->pathGet(PATH_BACKUP_CLUSTER, "${strBackup}/" . FILE_MANIFEST));
${$oExpectedManifest}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_START} =
$oActualManifest->get(MANIFEST_SECTION_BACKUP, &MANIFEST_KEY_TIMESTAMP_START);
${$oExpectedManifest}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_STOP} =
$oActualManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_STOP);
${$oExpectedManifest}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_COPY_START} =
$oActualManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_COPY_START);
${$oExpectedManifest}{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} =
$oActualManifest->get(INI_SECTION_BACKREST, INI_KEY_CHECKSUM);
${$oExpectedManifest}{&INI_SECTION_BACKREST}{&INI_KEY_FORMAT} = BACKREST_FORMAT + 0;
foreach my $strPathKey ($oActualManifest->keys(MANIFEST_SECTION_TARGET_PATH))
{
my $strFileSection = MANIFEST_SECTION_TARGET_FILE;
foreach my $strFileKey ($oActualManifest->keys($strFileSection))
{
if ($oActualManifest->test($strFileSection, $strFileKey, MANIFEST_SUBKEY_REPO_SIZE))
{
${$oExpectedManifest}{$strFileSection}{$strFileKey}{&MANIFEST_SUBKEY_REPO_SIZE} =
$oActualManifest->get($strFileSection, $strFileKey, MANIFEST_SUBKEY_REPO_SIZE);
}
}
}
# Set defaults for subkeys that tend to repeat
foreach my $strSection (&MANIFEST_SECTION_TARGET_FILE, &MANIFEST_SECTION_TARGET_PATH, &MANIFEST_SECTION_TARGET_LINK)
{
foreach my $strSubKey (&MANIFEST_SUBKEY_USER, &MANIFEST_SUBKEY_GROUP, &MANIFEST_SUBKEY_MODE)
{
my %oDefault;
my $iSectionTotal = 0;
foreach my $strFile (keys(%{${$oExpectedManifest}{$strSection}}))
{
if (!defined(${$oExpectedManifest}{$strSection}{$strFile}{$strSubKey}) &&
defined(${$oExpectedManifest}{"${strSection}:default"}{$strSubKey}))
{
${$oExpectedManifest}{$strSection}{$strFile}{$strSubKey} =
${$oExpectedManifest}{"${strSection}:default"}{$strSubKey};
}
my $strValue = ${$oExpectedManifest}{$strSection}{$strFile}{$strSubKey};
if (defined($strValue))
{
if (defined($oDefault{$strValue}))
{
$oDefault{$strValue}++;
}
else
{
$oDefault{$strValue} = 1;
}
}
$iSectionTotal++;
}
my $strMaxValue;
my $iMaxValueTotal = 0;
foreach my $strValue (keys(%oDefault))
{
if ($oDefault{$strValue} > $iMaxValueTotal)
{
$iMaxValueTotal = $oDefault{$strValue};
$strMaxValue = $strValue;
}
}
if (defined($strMaxValue) > 0 && $iMaxValueTotal > $iSectionTotal * MANIFEST_DEFAULT_MATCH_FACTOR)
{
${$oExpectedManifest}{"${strSection}:default"}{$strSubKey} = $strMaxValue;
foreach my $strFile (keys(%{${$oExpectedManifest}{$strSection}}))
{
if (defined(${$oExpectedManifest}{$strSection}{$strFile}{$strSubKey}) &&
${$oExpectedManifest}{$strSection}{$strFile}{$strSubKey} eq $strMaxValue)
{
delete(${$oExpectedManifest}{$strSection}{$strFile}{$strSubKey});
}
}
}
}
}
my $strTestPath = $self->testPath();
iniSave("${strTestPath}/actual.manifest", $oActualManifest->{oContent});
iniSave("${strTestPath}/expected.manifest", $oExpectedManifest);
executeTest("diff ${strTestPath}/expected.manifest ${strTestPath}/actual.manifest");
fileRemove("${strTestPath}/expected.manifest");
fileRemove("${strTestPath}/actual.manifest");
# Return from function and log return values if any
return logDebugReturn($strOperation);
}
####################################################################################################################################
# backupLast
####################################################################################################################################
sub backupLast
{
my $self = shift;
my @stryBackup = $self->{oFile}->list(PATH_BACKUP_CLUSTER, undef, undef, 'reverse');
if (!defined($stryBackup[3]))
{
confess 'no backup was found: ' . join(@stryBackup, ', ');
}
return $stryBackup[3];
}
####################################################################################################################################
# check
####################################################################################################################################
sub check
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strComment,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->check', \@_,
{name => 'strComment'},
{name => 'oParam', required => false},
);
$strComment =
'check ' . $self->stanza() . ' - ' . $strComment .
' (' . $self->nameGet() . ' host)';
&log(INFO, " $strComment");
$self->executeSimple(
$self->backrestExe() .
' --config=' . $self->backrestConfig() .
' --log-level-console=detail' .
(defined($$oParam{iTimeout}) ? " --archive-timeout=$$oParam{iTimeout}" : '') .
' --stanza=' . $self->stanza() . ' check',
{strComment => $strComment, iExpectedExitStatus => $$oParam{iExpectedExitStatus}, oLogTest => $self->{oLogTest}});
# Return from function and log return values if any
return logDebugReturn($strOperation);
}
####################################################################################################################################
# expire
####################################################################################################################################
sub expire
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->check', \@_,
{name => 'oParam', required => false},
);
my $strComment =
'expire' .
(defined($$oParam{iRetentionFull}) ? " full=$$oParam{iRetentionFull}" : '') .
(defined($$oParam{iRetentionDiff}) ? " diff=$$oParam{iRetentionDiff}" : '') .
' (' . $self->nameGet() . ' host)';
&log(INFO, " ${strComment}");
# Determine whether or not to expect an error
my $oHostGroup = hostGroupGet();
$self->executeSimple(
$self->backrestExe() .
' --config=' . $self->backrestConfig() .
' --log-level-console=detail' .
(defined($$oParam{iRetentionFull}) ? " --retention-full=$$oParam{iRetentionFull}" : '') .
(defined($$oParam{iRetentionDiff}) ? " --retention-diff=$$oParam{iRetentionDiff}" : '') .
' --stanza=' . $self->stanza() . ' expire',
{strComment => $strComment, iExpectedExitStatus => $$oParam{iExpectedExitStatus}, oLogTest => $self->{oLogTest}});
}
####################################################################################################################################
# info
####################################################################################################################################
sub info
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strComment,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->info', \@_,
{name => 'strComment'},
{name => 'oParam', required => false},
);
$strComment =
'info' . (defined($$oParam{strStanza}) ? " $$oParam{strStanza} stanza" : ' all stanzas') . ' - ' . $strComment .
' (' . $self->nameGet() . ' host)';
&log(INFO, " $strComment");
$self->executeSimple(
$self->backrestExe() .
' --config=' . $self->backrestConfig() .
' --log-level-console=warn' .
(defined($$oParam{strStanza}) ? " --stanza=$$oParam{strStanza}" : '') .
(defined($$oParam{strOutput}) ? " --output=$$oParam{strOutput}" : '') . ' info',
{strComment => $strComment, oLogTest => $self->{oLogTest}});
# Return from function and log return values if any
return logDebugReturn($strOperation);
}
####################################################################################################################################
# start
####################################################################################################################################
sub start
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->start', \@_,
{name => 'oParam', required => false},
);
my $strComment =
'start' . (defined($$oParam{strStanza}) ? " $$oParam{strStanza} stanza" : ' all stanzas') .
' (' . $self->nameGet() . ' host)';
&log(INFO, " $strComment");
$self->executeSimple(
$self->backrestExe() .
' --config=' . $self->backrestConfig() .
(defined($$oParam{strStanza}) ? " --stanza=$$oParam{strStanza}" : '') . ' start',
{strComment => $strComment, oLogTest => $self->{oLogTest}});
}
####################################################################################################################################
# stop
####################################################################################################################################
sub stop
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->stop', \@_,
{name => 'oParam', required => false},
);
my $strComment =
'stop' . (defined($$oParam{strStanza}) ? " $$oParam{strStanza} stanza" : ' all stanzas') .
' (' . $self->nameGet() . ' host)';
&log(INFO, " $strComment");
$self->executeSimple(
$self->backrestExe() .
' --config=' . $self->backrestConfig() .
(defined($$oParam{strStanza}) ? " --stanza=$$oParam{strStanza}" : '') .
(defined($$oParam{bForce}) && $$oParam{bForce} ? ' --force' : '') . ' stop',
{strComment => $strComment, oLogTest => $self->{oLogTest}});
# Return from function and log return values if any
return logDebugReturn($strOperation);
}
####################################################################################################################################
# configCreate
####################################################################################################################################
sub configCreate
{
my $self = shift;
my $oHostRemote = shift;
my $bCompress = shift;
my $bHardlink = shift;
my $iThreadMax = shift;
my $bArchiveAsync = shift;
my $bCompressAsync = shift;
my %oParamHash;
my $strStanza = $self->stanza();
if (defined($oHostRemote))
{
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_COMMAND_REMOTE} = $self->backrestExe();
}
if (defined($oHostRemote) && $oHostRemote->nameTest(HOST_BACKUP))
{
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_BACKUP_HOST} = $oHostRemote->nameGet();
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_BACKUP_USER} = $oHostRemote->userGet();
}
elsif (defined($oHostRemote))
{
$oParamHash{$strStanza}{&OPTION_DB_HOST} = $oHostRemote->nameGet();
$oParamHash{$strStanza}{&OPTION_DB_USER} = $oHostRemote->userGet();
}
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_LOG_LEVEL_CONSOLE} = lc(DEBUG);
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_LOG_LEVEL_FILE} = lc(TRACE);
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_REPO_PATH} = $self->repoPath();
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_LOG_PATH} = $self->logPath();
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_LOCK_PATH} = $self->lockPath();
if ($self->nameTest(HOST_BACKUP))
{
$oParamHash{$strStanza}{&OPTION_DB_PATH} = $oHostRemote->dbBasePath();
if (!$self->synthetic())
{
$oParamHash{$strStanza}{&OPTION_DB_SOCKET_PATH} = $oHostRemote->dbSocketPath();
$oParamHash{$strStanza}{&OPTION_DB_PORT} = $oHostRemote->dbPort();
}
}
else
{
if ($oHostRemote)
{
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_LOG_PATH} = $self->logPath();
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_LOCK_PATH} = $self->lockPath();
}
if ($bArchiveAsync)
{
$oParamHash{&CONFIG_SECTION_GLOBAL . ':' . &CMD_ARCHIVE_PUSH}{&OPTION_ARCHIVE_ASYNC} = 'y';
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_SPOOL_PATH} =
defined($oHostRemote) ? $self->spoolPath() : $self->repoPath();
}
$oParamHash{$strStanza}{&OPTION_DB_PATH} = $self->dbBasePath();
if (!$self->synthetic())
{
$oParamHash{$strStanza}{&OPTION_DB_SOCKET_PATH} = $self->dbSocketPath();
$oParamHash{$strStanza}{&OPTION_DB_PORT} = $self->dbPort();
}
}
if (defined($oHostRemote))
{
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_CONFIG_REMOTE} = $oHostRemote->backrestConfig();
}
if (defined($iThreadMax) && $iThreadMax > 1)
{
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_THREAD_MAX} = $iThreadMax;
}
if ($self->nameTest(HOST_BACKUP) || !defined($oHostRemote))
{
if (defined($bHardlink) && $bHardlink)
{
$oParamHash{&CONFIG_SECTION_GLOBAL . ':' . &CMD_BACKUP}{&OPTION_HARDLINK} = 'y';
}
$oParamHash{&CONFIG_SECTION_GLOBAL . ':' . &CMD_BACKUP}{&OPTION_BACKUP_ARCHIVE_COPY} = 'y';
$oParamHash{&CONFIG_SECTION_GLOBAL . ':' . &CMD_BACKUP}{&OPTION_START_FAST} = 'y';
}
if (defined($bCompress) && !$bCompress)
{
$oParamHash{&CONFIG_SECTION_GLOBAL}{&OPTION_COMPRESS} = 'n';
}
# Write out the configuration file
iniSave($self->backrestConfig(), \%oParamHash, true);
}
####################################################################################################################################
# manifestMunge
#
# Allows for munging of the manifest while making it appear to be valid. This is used to create various error conditions that
# should be caught by the unit tests.
####################################################################################################################################
sub manifestMunge
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strBackup,
$strSection,
$strKey,
$strSubKey,
$strValue,
) =
logDebugParam
(
__PACKAGE__ . '->manifestMunge', \@_,
{name => '$strBackup'},
{name => '$strSection'},
{name => '$strKey'},
{name => '$strSubKey', required => false},
{name => '$strValue', required => false},
);
my $strManifestFile = "${strBackup}/" . FILE_MANIFEST;
# Change mode on the backup path so it can be read/written
if ($self->nameTest(HOST_BACKUP))
{
executeTest('sudo chmod g+w ' . $self->{oFile}->pathGet(PATH_BACKUP_CLUSTER, $strManifestFile));
}
# Read the manifest
my %oManifest;
iniLoad($self->{oFile}->pathGet(PATH_BACKUP_CLUSTER, $strManifestFile), \%oManifest);
# Write in the munged value
if (defined($strSubKey))
{
if (defined($strValue))
{
$oManifest{$strSection}{$strKey}{$strSubKey} = $strValue;
}
else
{
delete($oManifest{$strSection}{$strKey}{$strSubKey});
}
}
else
{
if (defined($strValue))
{
$oManifest{$strSection}{$strKey} = $strValue;
}
else
{
delete($oManifest{$strSection}{$strKey});
}
}
# Remove the old checksum
delete($oManifest{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM});
my $oSHA = Digest::SHA->new('sha1');
my $oJSON = JSON::PP->new()->canonical()->allow_nonref();
$oSHA->add($oJSON->encode(\%oManifest));
# Set the new checksum
$oManifest{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = $oSHA->hexdigest();
# Resave the manifest
iniSave($self->{oFile}->pathGet(PATH_BACKUP_CLUSTER, $strManifestFile), \%oManifest);
}
####################################################################################################################################
# Getters
####################################################################################################################################
sub backrestConfig {return shift->paramGet(HOST_PARAM_BACKREST_CONFIG);}
sub backrestExe {return shift->paramGet(HOST_PARAM_BACKREST_EXE);}
sub lockPath {return shift->paramGet(HOST_PARAM_LOCK_PATH);}
sub logPath {return shift->paramGet(HOST_PARAM_LOG_PATH);}
sub repoPath {return shift->paramGet(HOST_PARAM_REPO_PATH);}
sub stanza {return shift->paramGet(HOST_PARAM_STANZA);}
sub threadMax {return shift->paramGet(HOST_PARAM_THREAD_MAX);}
sub synthetic {return shift->{bSynthetic};}
1;
@@ -0,0 +1,95 @@
####################################################################################################################################
# HostBackupTest.pm - Backup host
####################################################################################################################################
package pgBackRestTest::Backup::Common::HostBaseTest;
use parent 'pgBackRestTest::Common::HostTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Cwd qw(abs_path);
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use pgBackRest::Common::Log;
use pgBackRest::FileCommon;
use pgBackRest::Version;
use pgBackRestTest::Common::HostGroupTest;
####################################################################################################################################
# Host constants
####################################################################################################################################
use constant HOST_BASE => 'base';
push @EXPORT, qw(HOST_BASE);
####################################################################################################################################
# Host parameters
####################################################################################################################################
use constant HOST_PARAM_PROCESS_ID => 'process-id';
push @EXPORT, qw(HOST_PARAM_PROCESS_ID);
use constant HOST_PARAM_TEST_PATH => 'test-path';
push @EXPORT, qw(HOST_PARAM_TEST_PATH);
use constant HOST_PARAM_VM => 'vm';
push @EXPORT, qw(HOST_PARAM_VM);
####################################################################################################################################
# new
####################################################################################################################################
sub new
{
my $class = shift; # Class name
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strName,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->new', \@_,
{name => 'strName', default => HOST_BASE, trace => true},
{name => 'oParam', required => false, trace => true},
);
# Create the test path
my $oHostGroup = hostGroupGet();
my $strTestPath = $oHostGroup->paramGet(HOST_PARAM_TEST_PATH) . ($strName eq HOST_BASE ? '' : "/${strName}");
filePathCreate($strTestPath, '0770');
# Create the host
my $strProjectPath = dirname(dirname(abs_path($0)));
my $strContainer = 'test-' . $oHostGroup->paramGet(HOST_PARAM_PROCESS_ID) . "-$strName";
my $self = $class->SUPER::new(
$strName, $strContainer, $$oParam{strImage}, $$oParam{strUser}, $$oParam{strVm},
["${strProjectPath}:${strProjectPath}", "${strTestPath}:${strTestPath}"]);
bless $self, $class;
# Set parameters
$self->paramSet(HOST_PARAM_TEST_PATH, $strTestPath);
# Set permissions on the test path
$self->executeSimple('chown -R ' . $self->userGet() . ':postgres ' . $self->testPath(), undef, 'root');
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self, trace => true}
);
}
####################################################################################################################################
# Getters
####################################################################################################################################
sub testPath {return shift->paramGet(HOST_PARAM_TEST_PATH);}
1;
@@ -0,0 +1,631 @@
####################################################################################################################################
# HostDbTest.pm - Database host
####################################################################################################################################
package pgBackRestTest::Backup::Common::HostDbCommonTest;
use parent 'pgBackRestTest::Backup::Common::HostBackupTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use DBI;
use Exporter qw(import);
our @EXPORT = qw();
use Fcntl ':mode';
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Common::Wait;
use pgBackRest::Config::Config;
use pgBackRest::Db;
use pgBackRest::File;
use pgBackRest::FileCommon;
use pgBackRest::Manifest;
use pgBackRest::Version;
use pgBackRestTest::Backup::Common::HostBackupTest;
use pgBackRestTest::Backup::Common::HostBaseTest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::HostGroupTest;
####################################################################################################################################
# Host constants
####################################################################################################################################
use constant HOST_DB_MASTER => 'db-master';
push @EXPORT, qw(HOST_DB_MASTER);
use constant HOST_DB_MASTER_USER => 'db-master-user';
push @EXPORT, qw(HOST_DB_MASTER_USER);
####################################################################################################################################
# Host parameters
####################################################################################################################################
use constant HOST_PARAM_DB_BASE_PATH => 'db-base-path';
push @EXPORT, qw(HOST_PARAM_DB_BASE_PATH);
use constant HOST_PARAM_DB_PATH => 'db-path';
push @EXPORT, qw(HOST_PARAM_DB_PATH);
use constant HOST_PARAM_SPOOL_PATH => 'spool-path';
push @EXPORT, qw(HOST_PARAM_SPOOL_PATH);
use constant HOST_PARAM_TABLESPACE_PATH => 'tablespace-path';
push @EXPORT, qw(HOST_PARAM_TABLESPACE_PATH);
####################################################################################################################################
# Host paths
####################################################################################################################################
# !!! This name should be changed to "spool" at the end of this branch
use constant HOST_PATH_SPOOL => 'local';
push @EXPORT, qw(HOST_PATH_SPOOL);
use constant HOST_PATH_DB => 'db';
push @EXPORT, qw(HOST_PATH_DB);
# !!! This name should be changed to "base" at the end of this branch
use constant HOST_PATH_DB_BASE => 'common';
push @EXPORT, qw(HOST_PATH_DB_BASE);
####################################################################################################################################
# new
####################################################################################################################################
sub new
{
my $class = shift; # Class name
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->new', \@_,
{name => 'oParam', required => false, trace => true},
);
my $self = $class->SUPER::new(
{
strName => $$oParam{strName},
strImage => $$oParam{strImage},
strUser => $$oParam{strUser},
strVm => $$oParam{strVm},
oLogTest => $$oParam{oLogTest},
bSynthetic => $$oParam{bSynthetic},
oHostBackup => $$oParam{oHostBackup},
});
bless $self, $class;
# Set parameters
$self->paramSet(HOST_PARAM_DB_PATH, $self->testPath() . '/' . HOST_PATH_DB);
$self->paramSet(HOST_PARAM_DB_BASE_PATH, $self->dbPath() . '/' . HOST_PATH_DB_BASE);
$self->paramSet(HOST_PARAM_TABLESPACE_PATH, $self->dbPath() . '/tablespace');
filePathCreate($self->dbBasePath(), undef, undef, true);
if (defined($$oParam{oHostBackup}))
{
$self->paramSet(HOST_PARAM_REPO_PATH, $$oParam{oHostBackup}->repoPath());
$self->paramSet(HOST_PARAM_SPOOL_PATH, $self->testPath() . '/' . HOST_PATH_SPOOL);
$self->paramSet(HOST_PARAM_LOG_PATH, $self->spoolPath() . '/' . HOST_PATH_LOG);
$self->paramSet(HOST_PARAM_LOCK_PATH, $self->spoolPath() . '/' . HOST_PATH_LOCK);
filePathCreate($self->spoolPath());
}
else
{
$self->paramSet(HOST_PARAM_SPOOL_PATH, $self->repoPath());
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self, trace => true}
);
}
####################################################################################################################################
# archivePush
####################################################################################################################################
sub archivePush
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strXlogPath,
$strArchiveTestFile,
$iArchiveNo,
$iExpectedError,
) =
logDebugParam
(
__PACKAGE__ . '->archivePush', \@_,
{name => 'strXlogPath'},
{name => 'strArchiveTestFile'},
{name => 'iArchiveNo'},
{name => 'iExpectedError', required => false},
);
my $strSourceFile = "${strXlogPath}/" . uc(sprintf('0000000100000001%08x', $iArchiveNo));
$self->{oFile}->copy(
PATH_DB_ABSOLUTE, $strArchiveTestFile, # Source file
PATH_DB_ABSOLUTE, $strSourceFile, # Destination file
false, # Source is not compressed
false, # Destination is not compressed
undef, undef, undef, # Unused params
true); # Create path if it does not exist
$self->executeSimple(
$self->backrestExe() .
' --config=' . $self->backrestConfig() .
' --archive-max-mb=24 --no-fork --stanza=' . $self->stanza() .
(defined($iExpectedError) && $iExpectedError == ERROR_HOST_CONNECT ? ' --backup-host=bogus' : '') .
" archive-push ${strSourceFile}",
{iExpectedExitStatus => $iExpectedError, oLogTest => $self->{oLogTest}});
# Return from function and log return values if any
return logDebugReturn($strOperation);
}
####################################################################################################################################
# configRecovery
####################################################################################################################################
sub configRecovery
{
my $self = shift;
my $oHostBackup = shift;
my $oRecoveryHashRef = shift;
# Get stanza
my $strStanza = $self->stanza();
# Load db config file
my %oConfig;
iniLoad($self->backrestConfig(), \%oConfig, true);
# Load backup config file
my %oRemoteConfig;
if ($oHostBackup->nameTest(HOST_BACKUP))
{
iniLoad($oHostBackup->backrestConfig(), \%oRemoteConfig, true);
}
# Rewrite recovery options
my @stryRecoveryOption;
foreach my $strOption (sort(keys(%$oRecoveryHashRef)))
{
push (@stryRecoveryOption, "${strOption}=${$oRecoveryHashRef}{$strOption}");
}
if (@stryRecoveryOption)
{
$oConfig{$strStanza}{&OPTION_RESTORE_RECOVERY_OPTION} = \@stryRecoveryOption;
}
# Save db config file
iniSave($self->backrestConfig(), \%oConfig, true);
# Save backup config file
if ($oHostBackup->nameTest(HOST_BACKUP))
{
iniSave($oHostBackup->backrestConfig(), \%oRemoteConfig, true);
}
}
####################################################################################################################################
# configRemap
####################################################################################################################################
sub configRemap
{
my $self = shift;
my $oHostBackup = shift;
my $oRemapHashRef = shift;
my $oManifestRef = shift;
# Get stanza name
my $strStanza = $self->stanza();
# Load db config file
my %oConfig;
iniLoad($self->backrestConfig(), \%oConfig, true);
# Load backup config file
my %oRemoteConfig;
if ($oHostBackup->nameTest(HOST_BACKUP))
{
iniLoad($oHostBackup->backrestConfig(), \%oRemoteConfig, true);
}
# Rewrite recovery section
delete($oConfig{"${strStanza}:restore"}{&OPTION_TABLESPACE_MAP});
my @stryTablespaceMap;
foreach my $strRemap (sort(keys(%$oRemapHashRef)))
{
my $strRemapPath = ${$oRemapHashRef}{$strRemap};
if ($strRemap eq MANIFEST_TARGET_PGDATA)
{
$oConfig{$strStanza}{'db-path'} = $strRemapPath;
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} = $strRemapPath;
if ($oHostBackup->nameTest(HOST_BACKUP))
{
$oRemoteConfig{$strStanza}{'db-path'} = $strRemapPath;
}
}
else
{
my $strTablespaceOid = (split('\/', $strRemap))[1];
push (@stryTablespaceMap, "${strTablespaceOid}=${strRemapPath}");
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strRemap}{&MANIFEST_SUBKEY_PATH} = $strRemapPath;
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{MANIFEST_TARGET_PGDATA . "/${strRemap}"}{destination} = $strRemapPath;
}
}
if (@stryTablespaceMap)
{
$oConfig{"${strStanza}:restore"}{&OPTION_TABLESPACE_MAP} = \@stryTablespaceMap;
}
# Save db config file
iniSave($self->backrestConfig(), \%oConfig, true);
# Save backup config file
if ($oHostBackup->nameTest(HOST_BACKUP))
{
iniSave($oHostBackup->backrestConfig(), \%oRemoteConfig, true);
}
}
####################################################################################################################################
# restore
####################################################################################################################################
sub restore
{
my $self = shift;
my $strBackup = shift;
my $oExpectedManifestRef = shift;
my $oRemapHashRef = shift;
my $bDelta = shift;
my $bForce = shift;
my $strType = shift;
my $strTarget = shift;
my $bTargetExclusive = shift;
my $strTargetAction = shift;
my $strTargetTimeline = shift;
my $oRecoveryHashRef = shift;
my $strComment = shift;
my $iExpectedExitStatus = shift;
my $strOptionalParam = shift;
my $bTablespace = shift;
# Set defaults
$bDelta = defined($bDelta) ? $bDelta : false;
$bForce = defined($bForce) ? $bForce : false;
$strComment = 'restore' .
($bDelta ? ' delta' : '') .
($bForce ? ', force' : '') .
($strBackup ne OPTION_DEFAULT_RESTORE_SET ? ", backup '${strBackup}'" : '') .
($strType ? ", type '${strType}'" : '') .
($strTarget ? ", target '${strTarget}'" : '') .
($strTargetTimeline ? ", timeline '${strTargetTimeline}'" : '') .
(defined($bTargetExclusive) && $bTargetExclusive ? ', exclusive' : '') .
(defined($strTargetAction) && $strTargetAction ne OPTION_DEFAULT_RESTORE_TARGET_ACTION
? ', ' . OPTION_TARGET_ACTION . "=${strTargetAction}" : '') .
(defined($oRemapHashRef) ? ', remap' : '') .
(defined($iExpectedExitStatus) ? ", expect exit ${iExpectedExitStatus}" : '') .
(defined($strComment) ? " - ${strComment}" : '') .
' (' . $self->nameGet() . ' host)';
&log(INFO, " ${strComment}");
# Get the backup host
my $oHostGroup = hostGroupGet();
my $oHostBackup = defined($oHostGroup->hostGet(HOST_BACKUP, true)) ? $oHostGroup->hostGet(HOST_BACKUP) : $self;
if (!defined($oExpectedManifestRef))
{
# Change mode on the backup path so it can be read
my $oExpectedManifest = new pgBackRest::Manifest(
$self->{oFile}->pathGet(
PATH_BACKUP_CLUSTER,
($strBackup eq 'latest' ? $oHostBackup->backupLast() : $strBackup) . '/' . FILE_MANIFEST),
true);
$oExpectedManifestRef = $oExpectedManifest->{oContent};
}
# Get the backup host
if (defined($oRemapHashRef))
{
$self->configRemap($oHostBackup, $oRemapHashRef, $oExpectedManifestRef);
}
if (defined($oRecoveryHashRef))
{
$self->configRecovery($oHostBackup, $oRecoveryHashRef);
}
# Create the restorecommand
$self->executeSimple(
$self->backrestExe() .
' --config=' . $self->backrestConfig() .
(defined($bDelta) && $bDelta ? ' --delta' : '') .
(defined($bForce) && $bForce ? ' --force' : '') .
($strBackup ne OPTION_DEFAULT_RESTORE_SET ? " --set=${strBackup}" : '') .
(defined($strOptionalParam) ? " ${strOptionalParam} " : '') .
(defined($strType) && $strType ne RECOVERY_TYPE_DEFAULT ? " --type=${strType}" : '') .
(defined($strTarget) ? " --target=\"${strTarget}\"" : '') .
(defined($strTargetTimeline) ? " --target-timeline=\"${strTargetTimeline}\"" : '') .
(defined($bTargetExclusive) && $bTargetExclusive ? ' --target-exclusive' : '') .
($self->synthetic() ? '' : ' --link-all') .
(defined($strTargetAction) && $strTargetAction ne OPTION_DEFAULT_RESTORE_TARGET_ACTION
? ' --' . OPTION_TARGET_ACTION . "=${strTargetAction}" : '') .
' --stanza=' . $self->stanza() . ' restore',
{strComment => $strComment, iExpectedExitStatus => $iExpectedExitStatus, oLogTest => $self->{oLogTest}});
if (!defined($iExpectedExitStatus))
{
$self->restoreCompare($strBackup, $oExpectedManifestRef, $bTablespace);
if (defined($self->{oLogTest}))
{
$self->{oLogTest}->supplementalAdd(
$$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} .
"/recovery.conf");
}
}
}
####################################################################################################################################
# restoreCompare
####################################################################################################################################
sub restoreCompare
{
my $self = shift;
my $strBackup = shift;
my $oExpectedManifestRef = shift;
my $bTablespace = shift;
my $strTestPath = $self->testPath();
# Load module dynamically
require pgBackRestTest::CommonTest;
pgBackRestTest::CommonTest->import();
# Get the backup host
my $oHostGroup = hostGroupGet();
my $oHostBackup = defined($oHostGroup->hostGet(HOST_BACKUP, true)) ? $oHostGroup->hostGet(HOST_BACKUP) : $self;
# Load the last manifest if it exists
my $oLastManifest = undef;
if (defined(${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_PRIOR}))
{
my $oExpectedManifest =
new pgBackRest::Manifest(
$self->{oFile}->pathGet(
PATH_BACKUP_CLUSTER,
($strBackup eq 'latest' ? $oHostBackup->backupLast() : $strBackup) .
'/'. FILE_MANIFEST), true);
$oLastManifest =
new pgBackRest::Manifest(
$self->{oFile}->pathGet(
PATH_BACKUP_CLUSTER,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_PRIOR} .
'/' . FILE_MANIFEST), true);
}
# Generate the tablespace map for real backups
my $oTablespaceMap = undef;
if (!$self->synthetic())
{
# Tablespace_map file is not restored in versions >= 9.5 because it interferes with internal remapping features.
if (${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_95)
{
delete(${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{MANIFEST_TARGET_PGDATA . '/tablespace_map'});
}
foreach my $strTarget (keys(%{${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}}))
{
if (defined(${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}))
{
my $iTablespaceId =
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID};
$$oTablespaceMap{oid}{$iTablespaceId}{name} =
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_NAME};
}
}
}
# Generate the actual manifest
my $strDbClusterPath =
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH};
if (defined($bTablespace) && !$bTablespace)
{
foreach my $strTarget (keys(%{${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}}))
{
if ($$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TYPE} eq
MANIFEST_VALUE_LINK &&
defined($$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}))
{
my $strRemapPath;
my $iTablespaceName =
$$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_NAME};
$strRemapPath = "../../tablespace/${iTablespaceName}";
$$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH} = $strRemapPath;
$$oExpectedManifestRef{&MANIFEST_SECTION_TARGET_LINK}{MANIFEST_TARGET_PGDATA . "/${strTarget}"}
{&MANIFEST_SUBKEY_DESTINATION} = $strRemapPath;
}
}
}
my $oActualManifest = new pgBackRest::Manifest("${strTestPath}/" . FILE_MANIFEST, false);
$oActualManifest->set(
MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef,
$$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION});
$oActualManifest->numericSet(
MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef,
$$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG});
my $oTablespaceMapRef = undef;
$oActualManifest->build($self->{oFile}, $strDbClusterPath, $oLastManifest, false, $oTablespaceMap);
my $strSectionPath = $oActualManifest->get(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_PATH);
foreach my $strName ($oActualManifest->keys(MANIFEST_SECTION_TARGET_FILE))
{
if (!$self->synthetic())
{
$oActualManifest->set(
MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE,
${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strName}{size});
}
if (defined(${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_REPO_SIZE}))
{
$oActualManifest->numericSet(
MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REPO_SIZE,
${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_REPO_SIZE});
}
if ($oActualManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) != 0)
{
my $oStat = fileStat($oActualManifest->dbPathGet($strSectionPath, $strName));
if ($oStat->blocks > 0 || S_ISLNK($oStat->mode))
{
$oActualManifest->set(
MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM,
$self->{oFile}->hash(PATH_DB_ABSOLUTE, $oActualManifest->dbPathGet($strSectionPath, $strName)));
}
else
{
$oActualManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM);
delete(${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM});
}
}
}
# If the link section is empty then delete it and the default section
if (keys(%{${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_LINK}}) == 0)
{
delete($$oExpectedManifestRef{&MANIFEST_SECTION_TARGET_LINK});
delete($$oExpectedManifestRef{&MANIFEST_SECTION_TARGET_LINK . ':default'});
}
# Set actual to expected for settings that always change from backup to backup
$oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_CHECK, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ARCHIVE_CHECK});
$oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_COPY, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ARCHIVE_COPY});
$oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_COMPRESS, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_COMPRESS});
$oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_HARDLINK, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_HARDLINK});
$oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ONLINE});
$oActualManifest->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION});
$oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CONTROL, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CONTROL});
$oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG});
$oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_SYSTEM_ID, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_SYSTEM_ID});
$oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_ID, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_ID});
$oActualManifest->set(INI_SECTION_BACKREST, INI_KEY_VERSION, undef,
${$oExpectedManifestRef}{&INI_SECTION_BACKREST}{&INI_KEY_VERSION});
$oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_COPY_START, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_COPY_START});
$oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_START, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_START});
$oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_STOP, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_STOP});
$oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_LABEL});
$oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TYPE, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TYPE});
$oActualManifest->set(INI_SECTION_BACKREST, INI_KEY_CHECKSUM, undef,
${$oExpectedManifestRef}{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM});
if (!$self->synthetic())
{
$oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LSN_START, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_LSN_START});
$oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LSN_STOP, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_LSN_STOP});
if (defined(${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_START}))
{
$oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_START, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_START});
}
if (${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_STOP})
{
$oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_STOP, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_STOP});
}
}
# Delete the list of DBs
delete($$oExpectedManifestRef{&MANIFEST_SECTION_DB});
iniSave("${strTestPath}/actual.manifest", $oActualManifest->{oContent});
iniSave("${strTestPath}/expected.manifest", $oExpectedManifestRef);
executeTest("diff ${strTestPath}/expected.manifest ${strTestPath}/actual.manifest");
fileRemove("${strTestPath}/expected.manifest");
fileRemove("${strTestPath}/actual.manifest");
}
####################################################################################################################################
# Getters
####################################################################################################################################
sub dbPath {return shift->paramGet(HOST_PARAM_DB_PATH);}
sub dbBasePath
{
my $self = shift;
my $iIndex = shift;
return $self->paramGet(HOST_PARAM_DB_BASE_PATH) . (defined($iIndex) ? "-${iIndex}" : '');
}
sub spoolPath {return shift->paramGet(HOST_PARAM_SPOOL_PATH);}
sub tablespacePath
{
my $self = shift;
my $iTablespace = shift;
my $iIndex = shift;
return
$self->paramGet(HOST_PARAM_TABLESPACE_PATH) .
(defined($iTablespace) ? "/ts${iTablespace}" .
(defined($iIndex) ? "-${iIndex}" : '') : '');
}
1;
@@ -0,0 +1,705 @@
####################################################################################################################################
# HostDbTest.pm - Database host
####################################################################################################################################
package pgBackRestTest::Backup::Common::HostDbSyntheticTest;
use parent 'pgBackRestTest::Backup::Common::HostDbCommonTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use DBI;
use Exporter qw(import);
our @EXPORT = qw();
use Fcntl ':mode';
use File::Basename qw(basename dirname);
use File::stat;
use pgBackRest::Common::Exception;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Common::Wait;
use pgBackRest::Db;
use pgBackRest::FileCommon;
use pgBackRest::Manifest;
use pgBackRest::Version;
use pgBackRestTest::Backup::Common::HostBackupTest;
use pgBackRestTest::Backup::Common::HostBaseTest;
use pgBackRestTest::Backup::Common::HostDbCommonTest;
use pgBackRestTest::Common::FileTest;
use pgBackRestTest::Common::HostGroupTest;
use pgBackRestTest::CommonTest;
####################################################################################################################################
# new
####################################################################################################################################
sub new
{
my $class = shift; # Class name
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->new', \@_,
{name => 'oParam', required => false, trace => true},
);
# Get host group
my $oHostGroup = hostGroupGet();
my $self = $class->SUPER::new(
{
strName => HOST_DB_MASTER,
strImage => 'backrest/' . $oHostGroup->paramGet(HOST_PARAM_VM) . "-db-test-pre",
strUser => $oHostGroup->paramGet(HOST_DB_MASTER_USER),
strVm => $oHostGroup->paramGet(HOST_PARAM_VM),
oHostBackup => $$oParam{oHostBackup},
oLogTest => $$oParam{oLogTest},
bSynthetic => true,
});
bless $self, $class;
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self, trace => true}
);
}
####################################################################################################################################
# dbFileCreate
#
# Create a file specifying content, mode, and time.
####################################################################################################################################
sub dbFileCreate
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strFile = shift;
my $strContent = shift;
my $lTime = shift;
my $strMode = shift;
# Check that strTarget is a valid
my $strPath = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH};
if (!defined($strPath))
{
confess &log(ERROR, "${strTarget} not a valid target: \n" . Dumper(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}));
}
# Get tablespace path if this is a tablespace
my $strPgPath;
if ($$oManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_90 &&
index($strTarget, DB_PATH_PGTBLSPC . '/') == 0)
{
my $iCatalog = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG};
$strPgPath = 'PG_' . ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} . "_${iCatalog}";
}
# Create actual file location
my $strPathFile = $strPath .
(defined($strPgPath) ? "/${strPgPath}" : '') . "/${strFile}";
if (index($strPathFile, '/') != 0)
{
$strPathFile = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} . '/' .
(defined(dirname($strPathFile)) ? dirname($strPathFile) : '') . "/${strPathFile}";
}
# Create the file
testFileCreate($strPathFile, $strContent, $lTime, $strMode);
# Return path to created file
return $strPathFile;
}
####################################################################################################################################
# dbFileRemove
####################################################################################################################################
sub dbFileRemove
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strFile = shift;
my $bIgnoreMissing = shift;
# Get actual path location
my $strDbFile = $self->manifestDbPathGet($oManifestRef, $strTarget, $strFile);
# Remove the file
if (!(defined($bIgnoreMissing) && $bIgnoreMissing && !(-e $strDbFile)))
{
testFileRemove($strDbFile);
}
return $strDbFile;
}
####################################################################################################################################
# dbLinkCreate
#
# Create a file specifying content, mode, and time.
####################################################################################################################################
sub dbLinkCreate
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strFile = shift;
my $strDestination = shift;
# Create actual file location
my $strDbFile = $self->manifestDbPathGet($oManifestRef, $strTarget, $strFile);
# Create the file
testLinkCreate($strDbFile, $strDestination);
# Return path to created file
return $strDbFile;
}
####################################################################################################################################
# manifestDbPathGet
#
# Get the db path based on the target and file passed.
####################################################################################################################################
sub manifestDbPathGet
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strFile = shift;
# Determine the manifest key
my $strDbPath = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH};
# If target is a tablespace and pg version >= 9.0
if (defined(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}) &&
$$oManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_90)
{
my $iCatalog = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG};
$strDbPath .= '/PG_' . ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} . "_${iCatalog}";
}
$strDbPath .= defined($strFile) ? "/${strFile}" : '';
return $strDbPath;
}
####################################################################################################################################
# manifestFileCreate
#
# Create a file specifying content, mode, and time and add it to the manifest.
####################################################################################################################################
sub manifestFileCreate
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strFile = shift;
my $strContent = shift;
my $strChecksum = shift;
my $lTime = shift;
my $strMode = shift;
# Determine the manifest key
my $strManifestKey = $self->manifestKeyGet($oManifestRef, $strTarget, $strFile);
# Create the file
my $strPathFile = $self->dbFileCreate($oManifestRef, $strTarget, $strFile, $strContent, $lTime, $strMode);
# Stat the file
my $oStat = fileStat($strPathFile);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_MODE} = sprintf('%04o', S_IMODE($oStat->mode));
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_TIMESTAMP} = $oStat->mtime;
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_SIZE} = $oStat->size;
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_REFERENCE});
if (defined($strChecksum))
{
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{checksum} = $strChecksum;
}
}
####################################################################################################################################
# manifestFileRemove
#
# Remove a file from disk and (optionally) the manifest.
####################################################################################################################################
sub manifestFileRemove
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strFile = shift;
# Determine the manifest key
my $strManifestKey = $self->manifestKeyGet($oManifestRef, $strTarget, $strFile);
# Remove the file
$self->dbFileRemove($oManifestRef, $strTarget, $strFile, true);
# Remove from manifest
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey});
}
####################################################################################################################################
# manifestKeyGet
#
# Get the manifest key based on the target and file/path/link passed.
####################################################################################################################################
sub manifestKeyGet
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strFile = shift;
# Determine the manifest key
my $strManifestKey = $strTarget;
# If target is a tablespace and pg version >= 9.0
if (defined(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}) &&
$$oManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_90)
{
my $iCatalog = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG};
$strManifestKey .= '/PG_' . ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} . "_${iCatalog}";
}
$strManifestKey .= (defined($strFile) ? "/$strFile" : '');
return $strManifestKey;
}
####################################################################################################################################
# manifestLinkCreate
#
# Create a link and add it to the manifest.
####################################################################################################################################
sub manifestLinkCreate
{
my $self = shift;
my $oManifestRef = shift;
my $strPath = shift;
my $strFile = shift;
my $strDestination = shift;
# Determine the manifest key
my $strManifestKey = $self->manifestKeyGet($oManifestRef, $strPath, $strFile);
# Load target
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_PATH} = $strDestination;
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_TYPE} = MANIFEST_VALUE_LINK;
# Create the link
my $strDbFile = $self->dbLinkCreate($oManifestRef, $strPath, $strFile, $strDestination);
# Stat the link
my $oStat = fileStat($strDbFile);
# Check for errors in stat
if (!defined($oStat))
{
confess 'unable to stat ${strDbFile}';
}
# Load file into manifest
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strManifestKey}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strManifestKey}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strManifestKey}{&MANIFEST_SUBKEY_DESTINATION} = $strDestination;
# Stat what the link is pointing to
my $strDestinationFile = $strDestination;
if (index($strDestinationFile, '/') != 0)
{
$strDestinationFile = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} . '/' .
(defined(dirname($strPath)) ? dirname($strPath) : '') . "/${strDestination}";
}
$oStat = fileStat($strDestinationFile);
my $strSection = MANIFEST_SECTION_TARGET_PATH;
if (S_ISREG($oStat->mode))
{
$strSection = MANIFEST_SECTION_TARGET_FILE;
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_SIZE} = $oStat->size;
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_TIMESTAMP} = $oStat->mtime;
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_CHECKSUM} = fileHash($strDestinationFile);
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_FILE} =
basename(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_PATH});
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_PATH} =
dirname(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_PATH});
}
# Allow a link to a link to be created to test that backrest errors out correctly
elsif (S_ISLNK($oStat->mode))
{
$strSection = MANIFEST_SECTION_TARGET_LINK;
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_DESTINATION} = $strDestination;
}
elsif (!S_ISDIR($oStat->mode))
{
confess &log(ASSERT, "unrecognized file type for file $strDestinationFile");
}
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_MODE} = sprintf('%04o', S_IMODE($oStat->mode));
}
####################################################################################################################################
# manifestLinkMap
#
# Remap links to new directories/files
####################################################################################################################################
sub manifestLinkMap
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strDestination = shift;
if ($$oManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TYPE} ne MANIFEST_VALUE_LINK)
{
confess "cannot map target ${strTarget} because it is not a link";
}
if (defined($$oManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}))
{
confess "tablespace ${strTarget} cannot be remapped with this function";
}
if (defined($strDestination))
{
confess "GENERAL LINK REMAP NOT IMPLEMENTED";
}
else
{
delete($$oManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget});
delete($$oManifestRef{&MANIFEST_SECTION_TARGET_LINK}{$strTarget});
}
}
####################################################################################################################################
# manifestLinkRemove
#
# Create a link and add it to the manifest.
####################################################################################################################################
sub manifestLinkRemove
{
my $self = shift;
my $oManifestRef = shift;
my $strPath = shift;
my $strFile = shift;
# Delete the link
my $strDbFile = $self->dbFileRemove($oManifestRef, $strPath, $strFile);
# Determine the manifest key
my $strManifestKey = $self->manifestKeyGet($oManifestRef, $strPath, $strFile);
# Delete from manifest
delete(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey});
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strManifestKey});
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey});
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strManifestKey});
}
####################################################################################################################################
# manifestPathCreate
#
# Create a path specifying mode and add it to the manifest.
####################################################################################################################################
sub manifestPathCreate
{
my $self = shift;
my $oManifestRef = shift;
my $strPath = shift;
my $strSubPath = shift;
my $strMode = shift;
# Determine the manifest key
my $strManifestKey = $self->manifestKeyGet($oManifestRef, $strPath, $strSubPath);
# Create the db path
my $strDbPath = $self->dbPathCreate($oManifestRef, $strPath, $strSubPath, $strMode);
# Stat the file
my $oStat = lstat($strDbPath);
# Check for errors in stat
if (!defined($oStat))
{
confess 'unable to stat ${strSubPath}';
}
# Load file into manifest
my $strSection = MANIFEST_SECTION_TARGET_PATH;
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_MODE} = sprintf('%04o', S_IMODE($oStat->mode));
}
####################################################################################################################################
# manifestReference
#
# Update all files that do not have a reference with the supplied reference.
####################################################################################################################################
sub manifestReference
{
my $self = shift;
my $oManifestRef = shift;
my $strReference = shift;
my $bClear = shift;
# Set prior backup
if (defined($strReference))
{
${$oManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_PRIOR} = $strReference;
}
else
{
delete(${$oManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_PRIOR});
}
# Find all file sections
foreach my $strSectionFile (sort(keys(%$oManifestRef)))
{
# Skip non-file sections
if ($strSectionFile !~ /\:file$/)
{
next;
}
foreach my $strFile (sort(keys(%{${$oManifestRef}{$strSectionFile}})))
{
if (!defined($strReference))
{
delete(${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE});
}
elsif (defined($bClear) && $bClear)
{
if (defined(${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE}) &&
${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE} ne $strReference)
{
delete(${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE});
}
}
elsif (!defined(${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE}))
{
${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE} = $strReference;
}
}
}
}
####################################################################################################################################
# manifestTablespaceCreate
#
# Create a tablespace specifying mode and add it to the manifest.
####################################################################################################################################
sub manifestTablespaceCreate
{
my $self = shift;
my $oManifestRef = shift;
my $iOid = shift;
my $strMode = shift;
# Load linked path into manifest
my $strLinkPath = $self->tablespacePath($iOid);
my $strTarget = MANIFEST_TARGET_PGTBLSPC . "/${iOid}";
my $oStat = fileStat($strLinkPath);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strTarget}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strTarget}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strTarget}{&MANIFEST_SUBKEY_MODE} =
sprintf('%04o', S_IMODE($oStat->mode));
# Create the tablespace path if it does not exist
my $strTablespacePath = $strLinkPath;
my $strPathTarget = $strTarget;
if ($$oManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_90)
{
my $iCatalog = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG};
my $strTablespaceId = 'PG_' . ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} . "_${iCatalog}";
$strTablespacePath .= "/${strTablespaceId}";
$strPathTarget .= "/${strTablespaceId}";
}
if (!-e $strTablespacePath)
{
filePathCreate($strTablespacePath, $strMode);
}
# Load tablespace path into manifest
$oStat = fileStat($strTablespacePath);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{&MANIFEST_TARGET_PGTBLSPC} =
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{&MANIFEST_TARGET_PGDATA};
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strPathTarget}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strPathTarget}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strPathTarget}{&MANIFEST_SUBKEY_MODE} =
sprintf('%04o', S_IMODE($oStat->mode));
# Create the link in DB_PATH_PGTBLSPC
my $strLink = $self->dbBasePath() . '/' . DB_PATH_PGTBLSPC . "/${iOid}";
symlink($strLinkPath, $strLink)
or confess "unable to link ${strLink} to ${strLinkPath}";
# Load link into the manifest
$oStat = fileStat($strLink);
my $strLinkTarget = MANIFEST_TARGET_PGDATA . "/${strTarget}";
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strLinkTarget}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strLinkTarget}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strLinkTarget}{&MANIFEST_SUBKEY_DESTINATION} = $strLinkPath;
# Load tablespace target into the manifest
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH} = $strLinkPath;
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TYPE} = MANIFEST_VALUE_LINK;
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID} = $iOid;
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_NAME} = "ts${iOid}";
}
####################################################################################################################################
# manifestTablespaceDrop
#
# Drop a tablespace add remove it from the manifest.
####################################################################################################################################
sub manifestTablespaceDrop
{
my $self = shift;
my $oManifestRef = shift;
my $iOid = shift;
my $iIndex = shift;
# Remove tablespace path/file/link from manifest
my $strTarget = DB_PATH_PGTBLSPC . "/${iOid}";
# Remove manifest path, link, target
delete(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget});
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{&MANIFEST_TARGET_PGDATA . "/${strTarget}"});
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strTarget});
# Remove nested manifest files and paths
foreach my $strSection (&MANIFEST_SECTION_TARGET_PATH, &MANIFEST_SECTION_TARGET_FILE)
{
foreach my $strFile (keys(%{${$oManifestRef}{$strSection}}))
{
if (index($strFile, "${strTarget}/") == 0)
{
delete($$oManifestRef{$strSection}{$strFile});
}
}
}
# Drop the link in DB_PATH_PGTBLSPC
testFileRemove($self->dbBasePath($iIndex) . "/${strTarget}");
}
####################################################################################################################################
# dbPathCreate
#
# Create a path specifying mode.
####################################################################################################################################
sub dbPathCreate
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strSubPath = shift;
my $strMode = shift;
# Create final file location
my $strFinalPath = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH};
# Get tablespace path if this is a tablespace
if ($$oManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_90 &&
index($strTarget, DB_PATH_PGTBLSPC . '/') == 0)
{
my $iCatalog = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG};
$strFinalPath .= '/PG_' . ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} . "_${iCatalog}";
}
$strFinalPath .= (defined($strSubPath) ? "/${strSubPath}" : '');
# Create the path
if (!(-e $strFinalPath))
{
filePathCreate($strFinalPath, $strMode);
}
return $strFinalPath;
}
####################################################################################################################################
# dbPathMode
#
# Change the mode of a path.
####################################################################################################################################
sub dbPathMode
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strPath = shift;
my $strMode = shift;
# Get the db path
my $strDbPath = $self->manifestDbPathGet($oManifestRef, $strTarget, $strPath);
testPathMode($strDbPath, $strMode);
return $strDbPath;
}
####################################################################################################################################
# dbPathRemove
#
# Remove a path.
####################################################################################################################################
sub dbPathRemove
{
my $self = shift;
my $oManifestRef = shift;
my $strTarget = shift;
my $strPath = shift;
# Get the db path
my $strDbPath = $self->manifestDbPathGet($oManifestRef, $strTarget, $strPath);
# Create the path
testPathRemove($strDbPath);
return $strDbPath;
}
1;
@@ -0,0 +1,495 @@
####################################################################################################################################
# HostDbTest.pm - Database host
####################################################################################################################################
package pgBackRestTest::Backup::Common::HostDbTest;
use parent 'pgBackRestTest::Backup::Common::HostDbCommonTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use DBI;
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Common::Exception;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Common::Wait;
use pgBackRest::Db;
use pgBackRest::FileCommon;
use pgBackRest::Manifest;
use pgBackRest::Version;
use pgBackRestTest::Backup::Common::HostBackupTest;
use pgBackRestTest::Backup::Common::HostBaseTest;
use pgBackRestTest::Backup::Common::HostDbCommonTest;
use pgBackRestTest::Common::HostGroupTest;
####################################################################################################################################
# Host parameters
####################################################################################################################################
use constant HOST_PARAM_DB_BIN_PATH => 'db-bin-path';
push @EXPORT, qw(HOST_PARAM_DB_BIN_PATH);
use constant HOST_PARAM_DB_LOG_FILE => 'db-log-file';
push @EXPORT, qw(HOST_PARAM_LOG_DB_FILE);
use constant HOST_PARAM_DB_LOG_PATH => 'db-log-path';
push @EXPORT, qw(HOST_PARAM_LOG_DB_PATH);
use constant HOST_PARAM_DB_PORT => 'db-port';
push @EXPORT, qw(HOST_PARAM_DB_PORT);
use constant HOST_PARAM_DB_SOCKET_PATH => 'db-socket-path';
push @EXPORT, qw(HOST_PARAM_DB_SOCKET_PATH);
use constant HOST_PARAM_DB_VERSION => 'db-version';
push @EXPORT, qw(HOST_PARAM_DB_VERSION);
####################################################################################################################################
# Db defaults
####################################################################################################################################
use constant HOST_DB_PORT => 6543;
push @EXPORT, qw(HOST_DB_PORT);
use constant HOST_DB_DEFAULT => 'postgres';
push @EXPORT, qw(HOST_DB_DEFAULT);
use constant HOST_DB_TIMEOUT => 30;
push @EXPORT, qw(HOST_DB_TIMEOUT);
####################################################################################################################################
# new
####################################################################################################################################
sub new
{
my $class = shift; # Class name
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oParam,
) =
logDebugParam
(
__PACKAGE__ . '->new', \@_,
{name => 'oParam', required => false, trace => true},
);
# Get db version
my $oHostGroup = hostGroupGet();
my $strDbVersion = $oHostGroup->paramGet(HOST_PARAM_DB_VERSION);
my $self = $class->SUPER::new(
{
strName => HOST_DB_MASTER,
strImage => 'backrest/' . $oHostGroup->paramGet(HOST_PARAM_VM) . "-db-${strDbVersion}-test-pre",
strUser => $oHostGroup->paramGet(HOST_DB_MASTER_USER),
strVm => $oHostGroup->paramGet(HOST_PARAM_VM),
oHostBackup => $$oParam{oHostBackup},
});
bless $self, $class;
# Set parameters
$self->paramSet(HOST_PARAM_DB_BIN_PATH, $oHostGroup->paramGet(HOST_PARAM_DB_BIN_PATH));
$self->paramSet(HOST_PARAM_DB_VERSION, $strDbVersion);
$self->paramSet(HOST_PARAM_DB_SOCKET_PATH, $self->dbPath());
$self->paramSet(HOST_PARAM_DB_PORT, HOST_DB_PORT);
$self->paramSet(HOST_PARAM_DB_LOG_PATH, $self->testPath());
$self->paramSet(HOST_PARAM_DB_LOG_FILE, $self->dbLogPath() . '/postgresql.log');
# Get Db version
if (defined($strDbVersion))
{
my $strOutLog = $self->executeSimple($self->dbBinPath() . '/postgres --version');
my @stryVersionToken = split(/ /, $strOutLog);
@stryVersionToken = split(/\./, $stryVersionToken[2]);
my $strDbVersionActual = $stryVersionToken[0] . '.' . trim($stryVersionToken[1]);
# Warn if this is a devel/alpha/beta version
my $strVersionRegExp = '(devel|((alpha|beta|rc)[0-9]+))$';
if ($strDbVersionActual =~ /$strVersionRegExp/)
{
my $strDevVersion = $strDbVersionActual;
$strDbVersionActual =~ s/$strVersionRegExp//;
$strDevVersion = substr($strDevVersion, length($strDbVersionActual));
&log(WARN, "Testing against ${strDbVersionActual} ${strDevVersion} version");
}
# Don't run unit tests for unsupported versions
my @stryVersionSupport = versionSupport();
if ($strDbVersionActual < $stryVersionSupport[0])
{
confess &log(ERROR, "only PostgreSQL version $stryVersionSupport[0] and up are supported");
}
if ($strDbVersion ne $strDbVersionActual)
{
confess &log(ERROR, "actual database version ${strDbVersionActual} does not match expected version ${strDbVersion}");
}
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self, trace => true}
);
}
####################################################################################################################################
# sqlConnect
####################################################################################################################################
sub sqlConnect
{
my $self = shift;
my $hParam = shift;
# Set defaults
my $iTimeout = defined($$hParam{iTimeout}) ? $$hParam{iTimeout} : HOST_DB_TIMEOUT;
my $strDb = defined($$hParam{strDb}) ? $$hParam{strDb} : HOST_DB_DEFAULT;
if (!defined($self->{db}{$strDb}{hDb}))
{
# Setup the wait loop
my $oWait = waitInit($iTimeout);
do
{
# Connect to the db (whether it is local or remote)
$self->{db}{$strDb}{hDb} =
DBI->connect(
"dbi:Pg:dbname=${strDb};port=" . $self->dbPort() . ';host=' . $self->dbSocketPath(),
$self->userGet(), undef,
{AutoCommit => 0, RaiseError => 0, PrintError => 0});
return $self->{db}{$strDb}{hDb} if $self->{db}{$strDb}{hDb};
}
while (!defined($self->{db}{$strDb}{hDb}) && waitMore($oWait));
if (!defined($self->{db}{$strDb}{hDb}))
{
confess &log(ERROR, "unable to connect to PostgreSQL after ${iTimeout} second(s):\n" . $DBI::errstr, ERROR_DB_CONNECT);
}
}
return $self->{db}{$strDb}{hDb};
}
####################################################################################################################################
# sqlDisconnect
####################################################################################################################################
sub sqlDisconnect
{
my $self = shift;
my $hParam = shift;
foreach my $strDb (keys(%{$self->{db}}))
{
if (defined($$hParam{$strDb}) && $$hParam{$strDb} ne $strDb)
{
next;
}
if (defined($self->{db}{$strDb}{hDb}))
{
$self->{db}{$strDb}{hDb}->disconnect();
undef($self->{db}{$strDb}{hDb});
}
}
}
####################################################################################################################################
# sqlExecute
####################################################################################################################################
sub sqlExecute
{
my $self = shift;
my $strSql = shift;
my $hParam = shift;
# Set defaults
my $bCheckPoint = defined($$hParam{bCheckPoint}) ? $$hParam{bCheckPoint} : false;
my $bCommit = defined($$hParam{bCommit}) ? $$hParam{bCommit} : true;
# Get the db handle
my $hDb = $self->sqlConnect({strDb => $$hParam{strDb}});
# Set autocommit on/off
$hDb->{AutoCommit} = defined($$hParam{bAutoCommit}) ? ($$hParam{bAutoCommit} ? true : false) : false;
# Log and execute the statement
&log(DETAIL, "SQL: ${strSql}");
my $hStatement = $hDb->prepare($strSql);
$hStatement->execute() or
confess &log(ERROR, "Unable to execute: ${strSql}\n" . $DBI::errstr);
$hStatement->finish();
if ($bCommit && !$hDb->{AutoCommit})
{
$self->sqlCommit();
}
# Perform a checkpoint if requested
if ($bCheckPoint)
{
$self->sqlExecute('checkpoint', {bCommit => false, bCheckPoint => false});
}
# Set autocommit off
$hDb->{AutoCommit} = 0;
}
####################################################################################################################################
# sqlSelect
####################################################################################################################################
sub sqlSelect
{
my $self = shift;
my $strSql = shift;
my $hParam = shift;
# Get the db handle
my $hDb = $self->sqlConnect({strDb => $$hParam{strDb}});
# Log and execute the statement
&log(DEBUG, "SQL: ${strSql}");
my $hStatement = $hDb->prepare($strSql);
$hStatement = $hDb->prepare($strSql);
$hStatement->execute() or
confess &log(ERROR, "Unable to execute: ${strSql}\n" . $DBI::errstr);
my @oyRow = $hStatement->fetchrow_array();
$hStatement->finish();
return @oyRow;
}
####################################################################################################################################
# sqlSelectOne
####################################################################################################################################
sub sqlSelectOne
{
return (shift->sqlSelect(shift))[0];
}
####################################################################################################################################
# sqlSelectOneTest
####################################################################################################################################
sub sqlSelectOneTest
{
my $self = shift;
my $strSql = shift;
my $strExpectedValue = shift;
my $hParam = shift;
# Set defaults
my $iTimeout = defined($$hParam{iTimeout}) ? $$hParam{iTimeout} : HOST_DB_TIMEOUT;
my $lStartTime = time();
my $strActualValue;
do
{
$strActualValue = $self->sqlSelectOne($strSql);
if (defined($strActualValue) && $strActualValue eq $strExpectedValue)
{
return;
}
}
while (defined($iTimeout) && (time() - $lStartTime) <= $iTimeout);
confess &log(
ERROR, "expected value '${strExpectedValue}' from '${strSql}' but actual was '" .
(defined($strActualValue) ? $strActualValue : '[undef]') . "'");
}
####################################################################################################################################
# sqlCommit
####################################################################################################################################
sub sqlCommit
{
my $self = shift;
my $hParam = shift;
my $bCheckPoint = defined($$hParam{bCheckPoint}) ? $$hParam{bCheckPoint} : false;
$self->sqlExecute('commit', {bCommit => false, bCheckPoint => $bCheckPoint});
}
####################################################################################################################################
# sqlXlogRotate
####################################################################################################################################
sub sqlXlogRotate
{
my $self = shift;
$self->sqlExecute('select pg_switch_xlog()', {bCommit => false, bCheckPoint => false});
}
####################################################################################################################################
# clusterCreate
#
# Create the PostgreSQL cluster and start it.
####################################################################################################################################
sub clusterCreate
{
my $self = shift;
my $hParam = shift;
# Set defaults
my $strXlogPath = defined($$hParam{strXlogPath}) ? $$hParam{strXlogPath} : $self->dbPath() . '/pg_xlog';
# Don't link pg_xlog for versions < 9.2 because some recovery scenarios won't work.
$self->executeSimple(
$self->dbBinPath() . '/initdb' . ($self->dbVersion() >= PG_VERSION_92 ? " --xlogdir=${strXlogPath}" : '') .
' --pgdata=' . $self->dbBasePath() . ' --auth=trust');
$self->clusterStart(
{bHotStandby => $$hParam{bHotStandby}, bArchive => $$hParam{bArchive}, bArchiveAlways => $$hParam{bArchiveAlways},
bArchiveInvalid => $$hParam{bArchiveInvalid}});
}
####################################################################################################################################
# clusterStart
#
# Start the PostgreSQL cluster with various test options.
####################################################################################################################################
sub clusterStart
{
my $self = shift;
my $hParam = shift;
# Set defaults
my $bHotStandby = defined($$hParam{bHotStandby}) ? $$hParam{bHotStandby} : false;
my $bArchive = defined($$hParam{bArchive}) ? $$hParam{bArchive} : true;
my $bArchiveAlways = defined($$hParam{bArchiveAlways}) ? $$hParam{bArchiveAlways} : false;
my $bArchiveInvalid = defined($$hParam{bArchiveInvalid}) ? $$hParam{bArchiveInvalid} : false;
# Make sure postgres is not running
if (-e $self->dbBasePath() . '/postmaster.pid')
{
confess 'postmaster.pid exists';
}
# Create the archive command
my $strArchive =
$self->backrestExe() . ' --stanza=' . ($bArchiveInvalid ? 'bogus' : $self->stanza()) .
' --config=' . $self->backrestConfig() . ' archive-push %p';
# Start the cluster
my $strCommand =
$self->dbBinPath() . '/pg_ctl start -o "-c port=' . $self->dbPort() .
($self->dbVersion() < PG_VERSION_95 ? ' -c checkpoint_segments=1' : '');
if ($self->dbVersion() >= PG_VERSION_83)
{
if ($self->dbVersion() >= PG_VERSION_95 && $bArchiveAlways)
{
$strCommand .= " -c archive_mode=always";
}
else
{
$strCommand .= " -c archive_mode=on";
}
}
if ($bArchive)
{
$strCommand .= " -c archive_command='${strArchive}'";
}
else
{
$strCommand .= " -c archive_command=true";
}
if ($self->dbVersion() >= PG_VERSION_90)
{
$strCommand .= " -c wal_level=hot_standby";
if ($bHotStandby)
{
$strCommand .= ' -c hot_standby=on';
}
}
$strCommand .=
" -c log_error_verbosity=verbose" .
" -c unix_socket_director" . ($self->dbVersion() < PG_VERSION_93 ? 'y=\'' : 'ies=\'') . $self->dbPath() . '\'"' .
' -D ' . $self->dbBasePath() . ' -l ' . $self->dbLogFile() . ' -s';
$self->executeSimple($strCommand);
# Connect user session
$self->sqlConnect();
}
####################################################################################################################################
# clusterStop
#
# Stop the PostgreSQL cluster and optionally check for errors in the server log.
####################################################################################################################################
sub clusterStop
{
my $self = shift;
my $hParam = shift;
# Set defaults
my $bImmediate = defined($$hParam{bImmediate}) ? $$hParam{bImmediate} : false;
my $bIgnoreLogError = defined($$hParam{bIgnoreLogError}) ? $$hParam{bIgnoreLogError} : false;
# Disconnect user session
$self->sqlDisconnect();
# If postmaster process is running then stop the cluster
if (-e $self->dbBasePath() . '/' . DB_FILE_POSTMASTERPID)
{
$self->executeSimple(
$self->dbBinPath() . '/pg_ctl stop -D ' . $self->dbBasePath() . ' -w -s -m ' .
($bImmediate ? 'immediate' : 'fast'));
}
# Grep for errors in postgresql.log
if (!$bIgnoreLogError && fileExists($self->dbLogFile()))
{
$self->executeSimple('grep ERROR ' . $self->dbLogFile(), {iExpectedExitStatus => 1});
}
# Remove the log file
fileRemove($self->dbLogFile(), true);
}
####################################################################################################################################
# clusterRestart
#
# Restart the PostgreSQL cluster.
####################################################################################################################################
sub clusterRestart
{
my $self = shift;
my $hParam = shift;
$self->clusterStop($hParam);
$self->clusterStart($hParam);
}
####################################################################################################################################
# Getters
####################################################################################################################################
sub dbBinPath {return shift->paramGet(HOST_PARAM_DB_BIN_PATH);}
sub dbLogFile {return shift->paramGet(HOST_PARAM_DB_LOG_FILE);}
sub dbLogPath {return shift->paramGet(HOST_PARAM_DB_LOG_PATH);}
sub dbPort {return shift->paramGet(HOST_PARAM_DB_PORT);}
sub dbSocketPath {return shift->paramGet(HOST_PARAM_DB_SOCKET_PATH);}
sub dbVersion {return shift->paramGet(HOST_PARAM_DB_VERSION);}
1;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,7 +1,7 @@
####################################################################################################################################
# ContainerTest.pm - Build docker containers for testing and documentation
# ContainerTest.pm - Build containers for testing and documentation
####################################################################################################################################
package pgBackRestTest::Docker::ContainerTest;
package pgBackRestTest::Common::ContainerTest;
####################################################################################################################################
# Perl includes
@@ -200,7 +200,6 @@ sub repoSetup
"RUN chmod 750 /var/lib/pgbackrest";
}
####################################################################################################################################
# Sudo setup
####################################################################################################################################
@@ -509,21 +508,8 @@ sub containerBuild
$strImageParent = "backrest/${strOS}-db-${strDbVersion}";
$strImage = "${strOS}-db-${strDbVersion}-test";
# Create BackRest User
$strScript = backrestUserCreate($strOS);
# Install SSH key
$strScript .=
"\n\n" . sshSetup($strOS, BACKREST_USER, BACKREST_GROUP);
# Install SSH key
$strScript .=
"\n\n" . sshSetup($strOS, TEST_USER, TEST_GROUP);
# Make test user home readable
$strScript .=
"\n\n# Make " . TEST_USER . " home dir readable\n" .
'RUN chmod g+r,g+x /home/' . TEST_USER;
$strScript = sshSetup($strOS, TEST_USER, TEST_GROUP);
# Write the image
containerWrite($strTempPath, $strOS, "${strTitle} Test", $strImageParent, $strImage, $strScript, $bVmForce, true, true);
@@ -0,0 +1,161 @@
####################################################################################################################################
# DefineTest.pm - Defines all tests that can be run
####################################################################################################################################
package pgBackRestTest::Common::DefineTest;
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Common::Log;
################################################################################################################################
# Test definition constants
################################################################################################################################
use constant TESTDEF_MODULE => 'module';
push @EXPORT, qw(TESTDEF_MODULE);
use constant TESTDEF_MODULE_NAME => 'name';
push @EXPORT, qw(TESTDEF_MODULE_NAME);
use constant TESTDEF_TEST => 'test';
push @EXPORT, qw(TESTDEF_TEST);
use constant TESTDEF_TEST_NAME => 'name';
push @EXPORT, qw(TESTDEF_TEST_NAME);
use constant TESTDEF_TEST_TOTAL => 'total';
push @EXPORT, qw(TESTDEF_TEST_TOTAL);
use constant TESTDEF_TEST_CONTAINER => 'container';
push @EXPORT, qw(TESTDEF_TEST_CONTAINER);
use constant TESTDEF_TEST_THREAD => 'thread';
push @EXPORT, qw(TESTDEF_TEST_THREAD);
use constant TESTDEF_TEST_DB => 'db';
push @EXPORT, qw(TESTDEF_TEST_DB);
################################################################################################################################
# Define tests
################################################################################################################################
my $oTestDef =
{
&TESTDEF_MODULE =>
[
# Help tests
{
&TESTDEF_MODULE_NAME => 'help',
&TESTDEF_TEST_CONTAINER => true,
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'help'
}
]
},
# Config tests
{
&TESTDEF_MODULE_NAME => 'config',
&TESTDEF_TEST_CONTAINER => true,
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'option'
},
{
&TESTDEF_TEST_NAME => 'config'
}
]
},
# File tests
{
&TESTDEF_MODULE_NAME => 'file',
&TESTDEF_TEST_CONTAINER => true,
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'path_create'
},
{
&TESTDEF_TEST_NAME => 'move'
},
{
&TESTDEF_TEST_NAME => 'compress'
},
{
&TESTDEF_TEST_NAME => 'wait'
},
{
&TESTDEF_TEST_NAME => 'manifest'
},
{
&TESTDEF_TEST_NAME => 'list'
},
{
&TESTDEF_TEST_NAME => 'remove'
},
{
&TESTDEF_TEST_NAME => 'hash'
},
{
&TESTDEF_TEST_NAME => 'exists'
},
{
&TESTDEF_TEST_NAME => 'copy'
}
]
},
# Backup tests
{
&TESTDEF_MODULE_NAME => 'backup',
&TESTDEF_TEST_CONTAINER => false,
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'archive-push',
&TESTDEF_TEST_TOTAL => 8
},
{
&TESTDEF_TEST_NAME => 'archive-stop',
&TESTDEF_TEST_TOTAL => 6
},
{
&TESTDEF_TEST_NAME => 'archive-get',
&TESTDEF_TEST_TOTAL => 8
},
{
&TESTDEF_TEST_NAME => 'expire',
&TESTDEF_TEST_TOTAL => 1
},
{
&TESTDEF_TEST_NAME => 'synthetic',
&TESTDEF_TEST_TOTAL => 8,
&TESTDEF_TEST_THREAD => true
},
{
&TESTDEF_TEST_NAME => 'full',
&TESTDEF_TEST_TOTAL => 8,
&TESTDEF_TEST_THREAD => true,
&TESTDEF_TEST_DB => true
}
]
}
]
};
####################################################################################################################################
# testDefGet
####################################################################################################################################
sub testDefGet
{
return $oTestDef;
}
push @EXPORT, qw(testDefGet);
1;
+5 -22
View File
@@ -12,13 +12,11 @@ use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use IO::Select;
use IPC::Open3;
use POSIX ':sys_wait_h';
use Symbol 'gensym';
use lib dirname($0) . '/../lib';
use pgBackRest::Common::Log;
use pgBackRest::Common::Wait;
use pgBackRest::Protocol::IO;
@@ -47,13 +45,13 @@ sub new
# Assign function parameters, defaults, and log debug info
(
my $strOperation,
$self->{strCommandOriginal},
$self->{strCommand},
my $oParam
) =
logDebugParam
(
OP_EXECUTE_TEST_NEW, \@_,
{name => 'strCommandOriginal'},
{name => 'strCommand'},
{name => 'oParam', required => false}
);
@@ -64,7 +62,6 @@ sub new
}
# Set defaults
$self->{bRemote} = defined($self->{bRemote}) ? $self->{bRemote} : false;
$self->{bSuppressError} = defined($self->{bSuppressError}) ? $self->{bSuppressError} : false;
$self->{bSuppressStdErr} = defined($self->{bSuppressStdErr}) ? $self->{bSuppressStdErr} : false;
$self->{bShowOutput} = defined($self->{bShowOutput}) ? $self->{bShowOutput} : false;
@@ -72,9 +69,6 @@ sub new
$self->{iExpectedExitStatus} = defined($self->{iExpectedExitStatus}) ? $self->{iExpectedExitStatus} : 0;
$self->{iRetrySeconds} = defined($self->{iRetrySeconds}) ? $self->{iRetrySeconds} : undef;
$self->{strUserBackRest} = 'backrest'; #BackRestTestCommon_UserBackRestGet();
$self->{strHost} = '127.0.0.1'; #BackRestTestCommon_HostGet();
# Return from function and log return values if any
return logDebugReturn
(
@@ -93,16 +87,6 @@ sub begin
# Assign function parameters, defaults, and log debug info
logDebugParam(OP_EXECUTE_TEST_BEGIN);
if ($self->{bRemote})
{
# $self->{strCommand} = "sudo -u $self->{strUserBackRest} $self->{strCommandOriginal}";
$self->{strCommand} = "ssh $self->{strUserBackRest}\@$self->{strHost} '$self->{strCommandOriginal}'";
}
else
{
$self->{strCommand} = $self->{strCommandOriginal};
}
$self->{strErrorLog} = '';
$self->{strOutLog} = '';
@@ -116,7 +100,7 @@ sub begin
$self->{strFullLog} .= '> ' . $self->{oTestLog}->regExpAll($self->{strCommand}) . "\n" . ('-' x '132') . "\n";
}
logDebugMisc("executing command: $self->{strCommand}");
&log(DETAIL, "executing command: $self->{strCommand}");
# Execute the command
$self->{hError} = gensym;
@@ -154,11 +138,10 @@ sub endRetry
);
# Drain the output and error streams and look for test points
# my $iWait = $bWait ? .05 : 0;
while(waitpid($self->{pId}, WNOHANG) == 0)
{
my $bFound = false;
# # Drain the stderr stream
# ??? This is a good idea but can only be done when the IO object has separate buffers for stdin and stderr
# while (my $strLine = $self->{oIO}->lineRead(0, false, false))
@@ -219,7 +202,7 @@ sub endRetry
# Pass the log to the LogTest object
if (defined($self->{oLogTest}))
{
$self->{oLogTest}->logAdd($self->{strCommandOriginal}, $self->{strComment}, $self->{strOutLog});
$self->{oLogTest}->logAdd($self->{strCommand}, $self->{strComment}, $self->{strOutLog});
}
# If an error was expected then return success if that error occurred
+186
View File
@@ -0,0 +1,186 @@
####################################################################################################################################
# CommonTest.pm - Common globals used for testing
####################################################################################################################################
package pgBackRestTest::Common::FileTest;
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Cwd qw(abs_path cwd);
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use File::Copy qw(move);
use File::Path qw(remove_tree);
use IO::Select;
use IPC::Open3;
use POSIX ':sys_wait_h';
use Symbol 'gensym';
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Common::Wait;
use pgBackRest::Config::Config;
use pgBackRest::Db;
use pgBackRest::File;
use pgBackRest::Manifest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::LogTest;
use pgBackRestTest::Common::VmTest;
use pgBackRestTest::Backup::Common::HostBackupTest;
use pgBackRestTest::Backup::Common::HostDbCommonTest;
use pgBackRestTest::Backup::Common::HostDbTest;
####################################################################################################################################
# testLinkCreate
#
# Create a symlink
####################################################################################################################################
sub testLinkCreate
{
my $strLink = shift;
my $strDestination = shift;
# Create the file
symlink($strDestination, $strLink)
or confess "unable to link ${strLink} to ${strDestination}";
}
push(@EXPORT, qw(testLinkCreate));
####################################################################################################################################
# testPathMode
#
# Set mode of an existing path.
####################################################################################################################################
sub testPathMode
{
my $strPath = shift;
my $strMode = shift;
# Set the mode
chmod(oct($strMode), $strPath)
or confess 'unable to set mode ${strMode} for ${strPath}';
}
push(@EXPORT, qw(testPathMode));
####################################################################################################################################
# testPathRemove
#
# Remove a path and all subpaths.
####################################################################################################################################
sub testPathRemove
{
my $strPath = shift;
my $bSuppressError = shift;
executeTest('sudo rm -rf ' . $strPath, {bSuppressError => $bSuppressError});
# remove_tree($strPath, {result => \my $oError});
#
# if (@$oError)
# {
# my $strMessage = "error(s) occurred while removing ${strPath}:";
#
# for my $strFile (@$oError)
# {
# $strMessage .= "\nunable to remove: " . $strFile;
# }
#
# confess $strMessage;
# }
}
push(@EXPORT, qw(testPathRemove));
####################################################################################################################################
# testPathCopy
#
# Copy a path.
####################################################################################################################################
sub testPathCopy
{
my $strSourcePath = shift;
my $strDestinationPath = shift;
my $bSuppressError = shift;
executeTest("cp -RpP ${strSourcePath} ${strDestinationPath}", {bSuppressError => $bSuppressError});
}
####################################################################################################################################
# testPathMove
#
# Copy a path.
####################################################################################################################################
sub testPathMove
{
my $strSourcePath = shift;
my $strDestinationPath = shift;
my $bSuppressError = shift;
testPathCopy($strSourcePath, $strDestinationPath, $bSuppressError);
testPathRemove($strSourcePath, $bSuppressError);
}
push(@EXPORT, qw(testPathMove));
####################################################################################################################################
# testFileCreate
#
# Create a file specifying content, mode, and time.
####################################################################################################################################
sub testFileCreate
{
my $strFile = shift;
my $strContent = shift;
my $lTime = shift;
my $strMode = shift;
# Open the file and save strContent to it
my $hFile = shift;
open($hFile, '>', $strFile)
or confess "unable to open ${strFile} for writing";
syswrite($hFile, $strContent)
or confess "unable to write to ${strFile}: $!";
close($hFile);
# Set the time
if (defined($lTime))
{
utime($lTime, $lTime, $strFile)
or confess 'unable to set time ${lTime} for ${strPath}';
}
# Set the mode
chmod(oct(defined($strMode) ? $strMode : '0600'), $strFile)
or confess 'unable to set mode ${strMode} for ${strFile}';
}
push(@EXPORT, qw(testFileCreate));
####################################################################################################################################
# testFileRemove
#
# Remove a file.
####################################################################################################################################
sub testFileRemove
{
my $strFile = shift;
unlink($strFile)
or confess "unable to remove ${strFile}: $!";
}
push(@EXPORT, qw(testFileRemove));
1;
@@ -0,0 +1,174 @@
####################################################################################################################################
# HostGroupTest.pm - Encapsulate a group of docker containers for testing
####################################################################################################################################
package pgBackRestTest::Common::HostGroupTest;
use parent 'pgBackRestTest::Common::ParamTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Cwd qw(abs_path);
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRestTest::Common::ExecuteTest;
####################################################################################################################################
# Global host group variable
####################################################################################################################################
my $oHostGroup;
####################################################################################################################################
# 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');
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self, trace => true}
);
}
####################################################################################################################################
# hostAdd
####################################################################################################################################
sub hostAdd
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oHost
) =
logDebugParam
(
__PACKAGE__ . '->hostAdd', \@_,
{name => 'oHost'}
);
$self->{host}{$oHost->{strName}} = $oHost;
$oHost->executeSimple("sh -c 'echo \"\" >> /etc/hosts\'", undef, 'root');
$oHost->executeSimple("sh -c 'echo \"# Test Hosts\" >> /etc/hosts'", undef, 'root');
# Iterate hosts to add IP mappings
foreach my $strOtherHostName (sort(keys(%{$self->{host}})))
{
my $oOtherHost = $self->{host}{$strOtherHostName};
if ($strOtherHostName ne $oHost->{strName})
{
# Add this host IP to all hosts
$oOtherHost->executeSimple("sh -c 'echo \"$oHost->{strIP} $oHost->{strName}\" >> /etc/hosts'", undef, 'root');
# Add all other host IPs to this host
$oHost->executeSimple("sh -c 'echo \"$oOtherHost->{strIP} ${strOtherHostName}\" >> /etc/hosts'", undef, 'root');
}
}
# Return from function and log return values if any
return logDebugReturn($strOperation);
}
####################################################################################################################################
# hostGet
####################################################################################################################################
sub hostGet
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strName,
$bIgnoreMissing,
) =
logDebugParam
(
__PACKAGE__ . '->hostGet', \@_,
{name => 'strName', trace => true},
{name => 'bIgnoreMissing', default => false, trace => true},
);
my $oHost = $self->{host}{$strName};
if (!defined($oHost) && !$bIgnoreMissing)
{
confess &log(ERROR, "host ${strName} does not exist");
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'oHost', value => $oHost}
);
}
####################################################################################################################################
# removeAll
####################################################################################################################################
sub removeAll
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my ($strOperation) = logDebugParam(__PACKAGE__ . '->removeAll');
my $iTotal = 0;
foreach my $strHostName (sort(keys(%{$self->{host}})))
{
${$self->{host}}{$strHostName}->remove();
delete($self->{host}{$strHostName});
$iTotal++;
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'iTotal', value => $iTotal}
);
}
####################################################################################################################################
# hostGroupGet
#
# Get the global host group object.
####################################################################################################################################
sub hostGroupGet
{
if (!defined($oHostGroup))
{
$oHostGroup = new pgBackRestTest::Common::HostGroupTest();
}
return $oHostGroup;
}
push @EXPORT, qw(hostGroupGet);
1;
+76 -33
View File
@@ -2,6 +2,7 @@
# HostTest.pm - Encapsulate a docker host for testing
####################################################################################################################################
package pgBackRestTest::Common::HostTest;
use parent 'pgBackRestTest::Common::ParamTest';
####################################################################################################################################
# Perl includes
@@ -13,25 +14,12 @@ use Carp qw(confess);
use Cwd qw(abs_path);
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use lib dirname($0) . '/../lib';
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRestTest::Common::ExecuteTest;
####################################################################################################################################
# Operation constants
####################################################################################################################################
use constant OP_HOST_TEST => 'LogTest';
use constant OP_HOST_TEST_COPY_FROM => OP_HOST_TEST . "->copyFrom";
use constant OP_HOST_TEST_COPY_TO => OP_HOST_TEST . "->copyTo";
use constant OP_HOST_TEST_EXECUTE => OP_HOST_TEST . "->execute";
use constant OP_HOST_TEST_EXECUTE_SIMPLE => OP_HOST_TEST . "->executeSimple";
use constant OP_HOST_TEST_NEW => OP_HOST_TEST . "->new";
####################################################################################################################################
# new
####################################################################################################################################
@@ -47,32 +35,30 @@ sub new
(
my $strOperation,
$self->{strName},
$self->{strContainer},
$self->{strImage},
$self->{strUser},
$self->{strOS},
$self->{strMount}
$self->{stryMount}
) =
logDebugParam
(
OP_HOST_TEST_NEW, \@_,
__PACKAGE__ . '->new', \@_,
{name => 'strName', trace => true},
{name => 'strContainer', trace => true},
{name => 'strImage', trace => true},
{name => 'strUser', trace => true},
{name => 'strOS', trace => true},
{name => 'strMount', trace => true}
{name => 'stryMount', trace => true}
);
executeTest("docker kill $self->{strName}", {bSuppressError => true});
executeTest("docker rm $self->{strName}", {bSuppressError => true});
executeTest("docker rm -f $self->{strContainer}", {bSuppressError => true});
executeTest("rm -rf ~/data/$self->{strName}");
executeTest("mkdir -p ~/data/$self->{strName}/etc");
executeTest("docker run -itd -h $self->{strName} --name=$self->{strContainer}" .
(defined($self->{stryMount}) ? ' -v ' . join(' -v ', @{$self->{stryMount}}) : '') .
" $self->{strImage}");
executeTest("docker run -itd -h $self->{strName} --name=$self->{strName} " .
(defined($self->{strMount}) ? "-v $self->{strMount} " : '') .
"$self->{strImage}");
$self->{strIP} = trim(executeTest("docker inspect --format '\{\{ .NetworkSettings.IPAddress \}\}' $self->{strName}"));
$self->{strIP} = trim(executeTest("docker inspect --format '\{\{ .NetworkSettings.IPAddress \}\}' $self->{strContainer}"));
$self->{bActive} = true;
# Return from function and log return values if any
@@ -83,6 +69,27 @@ sub new
);
}
####################################################################################################################################
# remove
####################################################################################################################################
sub remove
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my ($strOperation) = logDebugParam(__PACKAGE__ . '->remove');
if ($self->{bActive})
{
executeTest("docker rm -f $self->{strContainer}", {bSuppressError => true});
$self->{bActive} = false;
}
# Return from function and log return values if any
return logDebugReturn($strOperation);
}
####################################################################################################################################
# execute
####################################################################################################################################
@@ -100,7 +107,7 @@ sub execute
) =
logDebugParam
(
OP_HOST_TEST_EXECUTE, \@_,
__PACKAGE__ . '->execute', \@_,
{name => 'strCommand'},
{name => 'oParam', required=> false},
{name => 'strUser', required => false}
@@ -113,7 +120,7 @@ sub execute
}
my $oExec = new pgBackRestTest::Common::ExecuteTest(
"docker exec -u ${strUser} $self->{strName} ${strCommand}" , $oParam);
"docker exec -u ${strUser} $self->{strContainer} ${strCommand}" , $oParam);
# Return from function and log return values if any
return logDebugReturn
@@ -140,7 +147,7 @@ sub executeSimple
) =
logDebugParam
(
OP_HOST_TEST_EXECUTE_SIMPLE, \@_,
__PACKAGE__ . '->executeSimple', \@_,
{name => 'strCommand', trace => true},
{name => 'oParam', required=> false, trace => true},
{name => 'strUser', required => false, trace => true}
@@ -150,7 +157,12 @@ sub executeSimple
$oExec->begin();
$oExec->end();
return $oExec->{strOutLog};
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strOutLog', value => $oExec->{strOutLog}, trace => true}
);
}
####################################################################################################################################
@@ -171,14 +183,14 @@ sub copyTo
) =
logDebugParam
(
OP_HOST_TEST_COPY_TO, \@_,
__PACKAGE__ . '->copyTo', \@_,
{name => 'strSource'},
{name => 'strDestination'},
{name => 'strOwner', required => false},
{name => 'strMode', required => false}
);
executeTest("docker cp ${strSource} $self->{strName}:${strDestination}");
executeTest("docker cp ${strSource} $self->{strContainer}:${strDestination}");
if (defined($strOwner))
{
@@ -210,15 +222,46 @@ sub copyFrom
) =
logDebugParam
(
OP_HOST_TEST_COPY_FROM, \@_,
__PACKAGE__ . '->copyFrom', \@_,
{name => 'strSource'},
{name => 'strDestination'}
);
executeTest("docker cp $self->{strName}:${strSource} ${strDestination}");
executeTest("docker cp $self->{strContainer}:${strSource} ${strDestination}");
# Return from function and log return values if any
return logDebugReturn($strOperation);
}
####################################################################################################################################
# nameGet
####################################################################################################################################
sub nameGet
{
my $self = shift;
return $self->{strName};
}
####################################################################################################################################
# nameTest
####################################################################################################################################
sub nameTest
{
my $self = shift;
my $strName = shift;
return $self->{strName} eq $strName;
}
####################################################################################################################################
# userGet
####################################################################################################################################
sub userGet
{
my $self = shift;
return $self->{strUser};
}
1;
+176
View File
@@ -0,0 +1,176 @@
####################################################################################################################################
# ListTest.pm - Creates a list of tests to be run based on input criteria
####################################################################################################################################
package pgBackRestTest::Common::ListTest;
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Common::Log;
use pgBackRestTest::Common::DefineTest;
use pgBackRestTest::Common::VmTest;
################################################################################################################################
# Test constants
################################################################################################################################
use constant TEST_DB => 'db';
push @EXPORT, qw(TEST_DB);
use constant TEST_CONTAINER => 'container';
push @EXPORT, qw(TEST_CONTAINER);
use constant TEST_MODULE => 'module';
push @EXPORT, qw(TEST_MODULE);
use constant TEST_NAME => 'test';
push @EXPORT, qw(TEST_NAME);
use constant TEST_PGSQL_BIN => 'pgsql-bin';
push @EXPORT, qw(TEST_PGSQL_BIN);
use constant TEST_RUN => 'run';
push @EXPORT, qw(TEST_RUN);
use constant TEST_THREAD => 'thread';
push @EXPORT, qw(TEST_THREAD);
use constant TEST_VM => 'os';
push @EXPORT, qw(TEST_VM);
####################################################################################################################################
# testListGet
####################################################################################################################################
sub testListGet
{
my $strVm = shift;
my $strModule = shift;
my $strModuleTest = shift;
my $iModuleTestRun = shift;
my $strDbVersion = shift;
my $iThreadMax = shift;
my $oTestDef = testDefGet();
my $oyVm = vmGet();
my $oyTestRun = [];
if ($strVm ne 'all' && !defined($${oyVm}{$strVm}))
{
confess &log(ERROR, "${strVm} is not a valid VM");
}
my $stryTestOS = [];
if ($strVm eq 'all')
{
$stryTestOS = [VM_CO6, VM_U16, VM_D8, VM_CO7, VM_U14, VM_U12];
}
else
{
$stryTestOS = [$strVm];
}
foreach my $strTestOS (@{$stryTestOS})
{
foreach my $oModule (@{$$oTestDef{&TESTDEF_MODULE}})
{
if ($strModule eq $$oModule{&TESTDEF_MODULE_NAME} || $strModule eq 'all')
{
foreach my $oTest (@{$$oModule{test}})
{
if ($strModuleTest eq $$oTest{&TESTDEF_TEST_NAME} || $strModuleTest eq 'all')
{
my $iDbVersionMin = -1;
my $iDbVersionMax = -1;
# By default test every db version that is supported for each OS
my $strDbVersionKey = 'db';
# Run a reduced set of tests where each PG version is only tested on a single OS
if ($strDbVersion eq 'minimal')
{
$strDbVersionKey = &VM_DB_MINIMAL;
}
if (defined($$oTest{&TESTDEF_TEST_DB}) && $$oTest{&TESTDEF_TEST_DB})
{
$iDbVersionMin = 0;
$iDbVersionMax = @{$$oyVm{$strTestOS}{$strDbVersionKey}} - 1;
}
my $bFirstDbVersion = true;
for (my $iDbVersionIdx = $iDbVersionMax; $iDbVersionIdx >= $iDbVersionMin; $iDbVersionIdx--)
{
if ($iDbVersionIdx == -1 || $strDbVersion eq 'all' || $strDbVersion eq 'minimal' ||
($strDbVersion ne 'all' &&
$strDbVersion eq ${$$oyVm{$strTestOS}{$strDbVersionKey}}[$iDbVersionIdx]))
{
my $iTestRunMin = defined($iModuleTestRun) ?
$iModuleTestRun : (defined($$oTest{&TESTDEF_TEST_TOTAL}) ? 1 : -1);
my $iTestRunMax = defined($iModuleTestRun) ?
$iModuleTestRun : (defined($$oTest{&TESTDEF_TEST_TOTAL}) ?
$$oTest{&TESTDEF_TEST_TOTAL} : -1);
if (defined($$oTest{total}) && $iTestRunMax > $$oTest{total})
{
confess &log(ERROR, "invalid run - must be >= 1 and <= $$oTest{total}")
}
for (my $iTestRunIdx = $iTestRunMin; $iTestRunIdx <= $iTestRunMax; $iTestRunIdx++)
{
my $iyThreadMax = [defined($iThreadMax) ? $iThreadMax : 1];
if (defined($$oTest{&TESTDEF_TEST_THREAD}) && $$oTest{&TESTDEF_TEST_THREAD} &&
!defined($iThreadMax) && $bFirstDbVersion)
{
$iyThreadMax = [1, 4];
}
foreach my $iThreadTestMax (@{$iyThreadMax})
{
my $strDbVersion = $iDbVersionIdx == -1 ? undef :
${$$oyVm{$strTestOS}{$strDbVersionKey}}[$iDbVersionIdx];
my $strPgSqlBin = $$oyVm{$strTestOS}{&VMDEF_PGSQL_BIN};
if (defined($strDbVersion))
{
$strPgSqlBin =~ s/\{\[version\]\}/$strDbVersion/g;
}
else
{
$strPgSqlBin =~ s/\{\[version\]\}/9\.4/g;
}
my $oTestRun =
{
&TEST_VM => $strTestOS,
&TEST_CONTAINER => $$oModule{&TESTDEF_TEST_CONTAINER},
&TEST_PGSQL_BIN => $strPgSqlBin,
&TEST_MODULE => $$oModule{&TESTDEF_MODULE_NAME},
&TEST_NAME => $$oTest{&TESTDEF_TEST_NAME},
&TEST_RUN => $iTestRunIdx == -1 ? undef : $iTestRunIdx,
&TEST_THREAD => $iThreadTestMax,
&TEST_DB => $strDbVersion
};
push(@{$oyTestRun}, $oTestRun);
}
}
$bFirstDbVersion = false;
}
}
}
}
}
}
}
return $oyTestRun;
}
push @EXPORT, qw(testListGet);
1;
+21 -30
View File
@@ -15,7 +15,6 @@ use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use lib dirname($0) . '/../lib';
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Version;
@@ -51,7 +50,6 @@ sub new
$self->{bForce},
$self->{strComment},
$self->{strCommandMain},
$self->{strCommandRemote},
$self->{strPgSqlBin},
$self->{strTestPath},
$self->{strRepoPath}
@@ -65,7 +63,6 @@ sub new
{name => 'bForce', trace => true},
{name => 'strComment', trace => true},
{name => 'strCommandMain', trace => true},
{name => 'strCommandRemote', trace => true},
{name => 'strPgSqlBin', required => false, trace => true},
{name => 'strTestPath', trace => true},
{name => 'strRepoPath', trace => true}
@@ -149,15 +146,8 @@ sub supplementalAdd
{
my $self = shift;
my $strFileName = shift;
my $bRemote = shift;
my $strComment = shift;
if ($bRemote)
{
executeTest("chmod g+x " . $self->{strRepoPath},
{bRemote => true});
}
open(my $hFile, '<', $strFileName)
or confess &log(ERROR, "unable to open ${strFileName} for appending to test log");
@@ -176,13 +166,6 @@ sub supplementalAdd
}
close($hFile);
if ($bRemote)
{
executeTest("chmod g-x " . $self->{strRepoPath},
{bRemote => true});
}
}
####################################################################################################################################
@@ -285,23 +268,26 @@ sub regExpReplace
$strReplacement = $strReplace;
}
if (defined(${$self->{oReplaceHash}}{$strType}{$strReplacement}))
if (defined($strType))
{
$iIndex = ${$self->{oReplaceHash}}{$strType}{$strReplacement}{index};
}
else
{
if (!defined(${$self->{oReplaceHash}}{$strType}{index}))
if (defined(${$self->{oReplaceHash}}{$strType}{$strReplacement}))
{
${$self->{oReplaceHash}}{$strType}{index} = 1;
$iIndex = ${$self->{oReplaceHash}}{$strType}{$strReplacement}{index};
}
else
{
if (!defined(${$self->{oReplaceHash}}{$strType}{index}))
{
${$self->{oReplaceHash}}{$strType}{index} = 1;
}
$iIndex = ${$self->{oReplaceHash}}{$strType}{index}++;
${$self->{oReplaceHash}}{$strType}{$strReplacement}{index} = $iIndex;
$iIndex = ${$self->{oReplaceHash}}{$strType}{index}++;
${$self->{oReplaceHash}}{$strType}{$strReplacement}{index} = $iIndex;
}
}
}
$strTypeReplacement = "[${strType}" . (defined($iIndex) ? "-${iIndex}" : '') . ']';
$strTypeReplacement = defined($strType) ? "[${strType}" . (defined($iIndex) ? "-${iIndex}" : '') . ']' : '';
if (defined($strToken))
{
@@ -331,9 +317,11 @@ sub regExpReplaceAll
my $strBinPath = dirname(dirname(abs_path($0))) . '/bin';
$strLine =~ s/$self->{strCommandMain}/[BACKREST_BIN]/g;
$strLine =~ s/$self->{strCommandRemote}/[BACKREST_BIN]/g;
$strLine =~ s/$self->{strTestPath}/[TEST_PATH]/g;
$strLine =~ s/$self->{strCommandMain}/[BACKREST-BIN]/g;
# !!! Replace with a loop through all hosts
$strLine =~ s/$self->{strTestPath}\/db\-master/[TEST_PATH]/g;
$strLine =~ s/$self->{strTestPath}\/backup/[TEST_PATH]/g;
if (defined($self->{strPgSqlBin}))
{
@@ -343,6 +331,9 @@ sub regExpReplaceAll
$strLine = $self->regExpReplace($strLine, 'BACKREST_NAME_VERSION', '^' . BACKREST_NAME . ' ' . BACKREST_VERSION,
undef, false);
$strLine = $self->regExpReplace($strLine, undef, '^docker exec -u [a-z]* test-[0-9]+\-', 'test-[0-9]+\-', false);
$strLine = $self->regExpReplace($strLine, 'CONTAINER-EXEC', '^docker exec -u [a-z]*', '^docker exec -u [a-z]*', false);
$strLine = $self->regExpReplace($strLine, 'PROCESS-ID', 'process [0-9]+', '[0-9]+$', false);
$strLine = $self->regExpReplace($strLine, 'MODIFICATION-TIME', 'lModificationTime = [0-9]+', '[0-9]+$');
$strLine = $self->regExpReplace($strLine, 'MODIFICATION-TIME', 'and modification time [0-9]+', '[0-9]+$');
+119
View File
@@ -0,0 +1,119 @@
####################################################################################################################################
# ParamTest.pm - Allows parameters to be added to any object
####################################################################################################################################
package pgBackRestTest::Common::ParamTest;
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use pgBackRest::Common::Log;
####################################################################################################################################
# paramSet
####################################################################################################################################
sub paramSet
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strKey,
$strValue,
) =
logDebugParam
(
__PACKAGE__ . '->paramSet', \@_,
{name => 'strKey', trace => true},
{name => 'strValue', trace => true},
);
$self->{param}{$strKey} = $strValue;
# Return from function and log return values if any
return logDebugReturn($strOperation);
}
####################################################################################################################################
# paramGet
####################################################################################################################################
sub paramGet
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strKey,
$bRequired,
$strDefault,
) =
logDebugParam
(
__PACKAGE__ . '->paramGet', \@_,
{name => 'strKey', trace => true},
{name => 'bRequired', default => true, trace => true},
{name => 'strDefault', required => false, trace => true},
);
my $strValue = $self->{param}{$strKey};
if (!defined($strValue))
{
if ($bRequired)
{
confess &log(ERROR, "param '${strKey}' is required");
}
$strValue = $strDefault;
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strValue', value => $strValue, trace => true}
);
}
####################################################################################################################################
# paramTest
####################################################################################################################################
sub paramTest
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strKey,
$strTestValue,
) =
logDebugParam
(
__PACKAGE__ . '->paramTest', \@_,
{name => 'strKey', trace => true},
{name => 'strTestValue', required => false, trace => true},
);
my $strValue = $self->paramGet($strKey, false);
my $bResult =
!defined($strTestValue) && defined($strValue) || defined($strTestValue) && $strTestValue eq $strValue ? true : false;
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'bResult', value => $bResult, trace => true}
);
}
1;
+2 -5
View File
@@ -10,14 +10,11 @@ use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use File::Basename qw(dirname);
use lib dirname($0) . '/../lib';
use pgBackRest::Db;
use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Db;
####################################################################################################################################
# VM hash keywords
####################################################################################################################################
+30 -800
View File
@@ -10,156 +10,36 @@ use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Cwd qw(abs_path cwd);
use Cwd qw(abs_path);
use Exporter qw(import);
use File::Basename;
use File::Copy qw(move);
use File::Path qw(remove_tree);
use IO::Select;
use IPC::Open3;
use POSIX ':sys_wait_h';
use Symbol 'gensym';
our @EXPORT = qw();
use File::Basename qw(dirname);
use lib dirname($0) . '/../lib';
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Common::Wait;
use pgBackRest::Config::Config;
use pgBackRest::Db;
use pgBackRest::File;
use pgBackRest::Manifest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::LogTest;
our @EXPORT = qw(BackRestTestCommon_Create BackRestTestCommon_Drop BackRestTestCommon_Setup
BackRestTestCommon_PathCreate BackRestTestCommon_PathMode BackRestTestCommon_PathRemove
BackRestTestCommon_FileCreate BackRestTestCommon_FileRemove BackRestTestCommon_PathCopy BackRestTestCommon_PathMove
BackRestTestCommon_ConfigCreate BackRestTestCommon_ConfigRemap BackRestTestCommon_ConfigRecovery
BackRestTestCommon_Run BackRestTestCommon_Cleanup BackRestTestCommon_PgSqlBinPathGet
BackRestTestCommon_StanzaGet BackRestTestCommon_CommandMainGet BackRestTestCommon_CommandRemoteGet
BackRestTestCommon_HostGet BackRestTestCommon_UserGet BackRestTestCommon_GroupGet
BackRestTestCommon_UserBackRestGet BackRestTestCommon_TestPathGet BackRestTestCommon_DataPathGet
BackRestTestCommon_RepoPathGet BackRestTestCommon_LocalPathGet BackRestTestCommon_DbPathGet
BackRestTestCommon_DbCommonPathGet BackRestTestCommon_ClusterStop BackRestTestCommon_DbTablespacePathGet
BackRestTestCommon_DbPortGet BackRestTestCommon_iniLoad BackRestTestCommon_iniSave BackRestTestCommon_DbVersion
BackRestTestCommon_CommandPsqlGet BackRestTestCommon_DropRepo BackRestTestCommon_CreateRepo
BackRestTestCommon_manifestLoad BackRestTestCommon_manifestSave BackRestTestCommon_CommandMainAbsGet
BackRestTestCommon_CommandRemoteFullGet BackRestTestCommon_BasePathGet BackRestTestCommon_LinkCreate);
####################################################################################################################################
# Module variables
####################################################################################################################################
my $strPgSqlBin;
my $strCommonStanza;
my $strCommonCommandMain;
my $bCommandMainSet = false;
my $strCommonCommandRemote;
my $strCommonCommandRemoteFull;
my $strCommonCommandPsql;
my $strCommonHost;
my $strCommonUser;
my $strCommonGroup;
my $strCommonUserBackRest;
my $strCommonBasePath;
my $strCommonTestPath;
my $strCommonDataPath;
my $strCommonRepoPath;
my $strCommonLocalPath;
my $strCommonDbPath;
my $strCommonDbCommonPath;
my $strCommonDbTablespacePath;
my $iCommonDbPort;
my $strCommonDbVersion;
my $iModuleTestRunOnly;
my $bDryRun;
my $bNoCleanup;
my $bLogForce;
use constant PROTOCOL_TIMEOUT_TEST => 30;
push @EXPORT, qw(PROTOCOL_TIMEOUT_TEST);
####################################################################################################################################
# BackRestTestCommon_ClusterStop
# testRun
####################################################################################################################################
sub BackRestTestCommon_ClusterStop
{
my $strPath = shift;
my $bImmediate = shift;
# Set default
$strPath = defined($strPath) ? $strPath : BackRestTestCommon_DbCommonPathGet();
$bImmediate = defined($bImmediate) ? $bImmediate : false;
# If postmaster process is running then stop the cluster
if (-e $strPath . '/postmaster.pid')
{
executeTest(BackRestTestCommon_PgSqlBinPathGet() . "/pg_ctl stop -D ${strPath} -w -s -m " .
($bImmediate ? 'immediate' : 'fast'));
}
}
####################################################################################################################################
# BackRestTestCommon_DropRepo
####################################################################################################################################
sub BackRestTestCommon_DropRepo
{
# Remove the backrest private directory
while (-e BackRestTestCommon_RepoPathGet())
{
BackRestTestCommon_PathRemove(BackRestTestCommon_RepoPathGet(), true, true);
BackRestTestCommon_PathRemove(BackRestTestCommon_RepoPathGet(), false, true);
waitHiRes(.1);
}
}
####################################################################################################################################
# BackRestTestCommon_CreateRepo
####################################################################################################################################
sub BackRestTestCommon_CreateRepo
{
my $bRemote = shift;
BackRestTestCommon_DropRepo();
# Create the backup directory
if ($bRemote)
{
executeTest('mkdir -m 700 ' . BackRestTestCommon_RepoPathGet(),
{bRemote => true});
}
else
{
BackRestTestCommon_PathCreate(BackRestTestCommon_RepoPathGet());
}
}
####################################################################################################################################
# BackRestTestCommon_Drop
####################################################################################################################################
sub BackRestTestCommon_Drop
{
# Drop the cluster if it exists
BackRestTestCommon_ClusterStop(BackRestTestCommon_DbCommonPathGet(), true);
# Remove the backrest private directory
BackRestTestCommon_DropRepo();
# Remove contents of the test directory
executeTest('rm -rf ' . BackRestTestCommon_TestPathGet() . '/*');
}
####################################################################################################################################
# BackRestTestCommon_Create
####################################################################################################################################
sub BackRestTestCommon_Create
{
# Test directory is now created in parent VM so nothing to do here. Leaving as a place holder for a while in case any other
# test init needs to be done when refactoring.
}
####################################################################################################################################
# BackRestTestCommon_Run
####################################################################################################################################
sub BackRestTestCommon_Run
sub testRun
{
my $iRun = shift;
my $strLog = shift;
@@ -170,7 +50,7 @@ sub BackRestTestCommon_Run
# Save the previous test log
if (defined($$oLogTestRef))
{
$$oLogTestRef->logWrite(BackRestTestCommon_BasePathGet(), BackRestTestCommon_TestPathGet());
$$oLogTestRef->logWrite($strCommonBasePath, $strCommonTestPath);
$$oLogTestRef = undef;
}
@@ -191,28 +71,27 @@ sub BackRestTestCommon_Run
# If the module is defined then create a LogTest object
if (defined($strModuleParam))
{
$$oLogTestRef = new pgBackRestTest::Common::LogTest($strModuleParam, $strModuleTestParam, $iRun, $bLogForce, $strLog,
BackRestTestCommon_CommandMainGet(),
BackRestTestCommon_CommandMainAbsGet(),
BackRestTestCommon_PgSqlBinPathGet(),
BackRestTestCommon_TestPathGet(),
BackRestTestCommon_RepoPathGet());
$$oLogTestRef = new pgBackRestTest::Common::LogTest(
$strModuleParam, $strModuleTestParam, $iRun, $bLogForce, $strLog, $strCommonCommandMain, $strPgSqlBin,
$strCommonTestPath, $strCommonRepoPath);
}
return true;
}
push(@EXPORT, qw(testRun));
####################################################################################################################################
# BackRestTestCommon_Cleanup
# testCleanup
####################################################################################################################################
sub BackRestTestCommon_Cleanup
sub testCleanup
{
my $oLogTestRef = shift;
# Save the previous test log
if (defined($$oLogTestRef))
{
$$oLogTestRef->logWrite(BackRestTestCommon_BasePathGet(), BackRestTestCommon_TestPathGet());
$$oLogTestRef->logWrite($strCommonBasePath, $strCommonTestPath);
$$oLogTestRef = undef;
}
@@ -220,176 +99,13 @@ sub BackRestTestCommon_Cleanup
return !$bNoCleanup && !$bDryRun;
}
push(@EXPORT, qw(testCleanup));
####################################################################################################################################
# BackRestTestCommon_LinkCreate
#
# Create a symlink
# testSetup
####################################################################################################################################
sub BackRestTestCommon_LinkCreate
sub testSetup
{
my $strLink = shift;
my $strDestination = shift;
# Create the file
symlink($strDestination, $strLink)
or confess "unable to link ${strLink} to ${strDestination}";
}
####################################################################################################################################
# BackRestTestCommon_PathCreate
#
# Create a path and set mode.
####################################################################################################################################
sub BackRestTestCommon_PathCreate
{
my $strPath = shift;
my $strMode = shift;
my $bIgnoreExists = shift;
# Create the path
if (!mkdir($strPath))
{
if (!(defined($bIgnoreExists) && $bIgnoreExists && -e $strPath))
{
confess "unable to create ${strPath} path";
}
}
# Set the mode
chmod(oct(defined($strMode) ? $strMode : '0700'), $strPath)
or confess 'unable to set mode ${strMode} for ${strPath}';
}
####################################################################################################################################
# BackRestTestCommon_PathMode
#
# Set mode of an existing path.
####################################################################################################################################
sub BackRestTestCommon_PathMode
{
my $strPath = shift;
my $strMode = shift;
# Set the mode
chmod(oct($strMode), $strPath)
or confess 'unable to set mode ${strMode} for ${strPath}';
}
####################################################################################################################################
# BackRestTestCommon_PathRemove
#
# Remove a path and all subpaths.
####################################################################################################################################
sub BackRestTestCommon_PathRemove
{
my $strPath = shift;
my $bRemote = shift;
my $bSuppressError = shift;
executeTest('rm -rf ' . $strPath,
{bRemote => $bRemote, bSuppressError => $bSuppressError});
# remove_tree($strPath, {result => \my $oError});
#
# if (@$oError)
# {
# my $strMessage = "error(s) occurred while removing ${strPath}:";
#
# for my $strFile (@$oError)
# {
# $strMessage .= "\nunable to remove: " . $strFile;
# }
#
# confess $strMessage;
# }
}
####################################################################################################################################
# BackRestTestCommon_PathCopy
#
# Copy a path.
####################################################################################################################################
sub BackRestTestCommon_PathCopy
{
my $strSourcePath = shift;
my $strDestinationPath = shift;
my $bRemote = shift;
my $bSuppressError = shift;
executeTest("cp -RpP ${strSourcePath} ${strDestinationPath}",
{bRemote => $bRemote, bSuppressError => $bSuppressError});
}
####################################################################################################################################
# BackRestTestCommon_PathMove
#
# Copy a path.
####################################################################################################################################
sub BackRestTestCommon_PathMove
{
my $strSourcePath = shift;
my $strDestinationPath = shift;
my $bRemote = shift;
my $bSuppressError = shift;
BackRestTestCommon_PathCopy($strSourcePath, $strDestinationPath, $bRemote, $bSuppressError);
BackRestTestCommon_PathRemove($strSourcePath, $bRemote, $bSuppressError);
}
####################################################################################################################################
# BackRestTestCommon_FileCreate
#
# Create a file specifying content, mode, and time.
####################################################################################################################################
sub BackRestTestCommon_FileCreate
{
my $strFile = shift;
my $strContent = shift;
my $lTime = shift;
my $strMode = shift;
# Open the file and save strContent to it
my $hFile = shift;
open($hFile, '>', $strFile)
or confess "unable to open ${strFile} for writing";
syswrite($hFile, $strContent)
or confess "unable to write to ${strFile}: $!";
close($hFile);
# Set the time
if (defined($lTime))
{
utime($lTime, $lTime, $strFile)
or confess 'unable to set time ${lTime} for ${strPath}';
}
# Set the mode
chmod(oct(defined($strMode) ? $strMode : '0600'), $strFile)
or confess 'unable to set mode ${strMode} for ${strFile}';
}
####################################################################################################################################
# BackRestTestCommon_FileRemove
#
# Remove a file.
####################################################################################################################################
sub BackRestTestCommon_FileRemove
{
my $strFile = shift;
unlink($strFile)
or confess "unable to remove ${strFile}: $!";
}
####################################################################################################################################
# BackRestTestCommon_Setup
####################################################################################################################################
sub BackRestTestCommon_Setup
{
my $strExe = shift;
my $strTestPathParam = shift;
my $strPgSqlBinParam = shift;
my $iModuleTestRunOnlyParam = shift;
@@ -401,12 +117,6 @@ sub BackRestTestCommon_Setup
$strPgSqlBin = $strPgSqlBinParam;
$strCommonStanza = 'db';
$strCommonHost = '127.0.0.1';
$strCommonUser = getpwuid($<);
$strCommonGroup = getgrgid($();
$strCommonUserBackRest = 'backrest';
if (defined($strTestPathParam))
{
$strCommonTestPath = $strTestPathParam;
@@ -418,154 +128,30 @@ sub BackRestTestCommon_Setup
$strCommonDataPath = "${strCommonBasePath}/test/data";
$strCommonRepoPath = "${strCommonTestPath}/backrest";
$strCommonLocalPath = "${strCommonTestPath}/local";
$strCommonDbPath = "${strCommonTestPath}/db";
$strCommonDbCommonPath = "${strCommonTestPath}/db/common";
$strCommonDbTablespacePath = "${strCommonTestPath}/db/tablespace";
$strCommonDbPath = "${strCommonTestPath}/db-master/db";
$strCommonDbCommonPath = "${strCommonDbPath}/common";
$strCommonCommandMain = defined($strExe) ? $strExe : $strCommonBasePath . "/bin/../bin/pgbackrest";
$bCommandMainSet = defined($strExe) ? true : false;
$strCommonCommandRemote = defined($strExe) ? $strExe : "${strCommonBasePath}/bin/pgbackrest";
$strCommonCommandRemoteFull = "${strCommonCommandRemote} --stanza=${strCommonStanza}" .
" --repo-path=${strCommonRepoPath} --no-config --command=test remote";
$strCommonCommandMain = $strCommonBasePath . '/bin/pgbackrest';
$iCommonDbPort = 6543;
$iModuleTestRunOnly = $iModuleTestRunOnlyParam;
$bDryRun = $bDryRunParam;
$bNoCleanup = $bNoCleanupParam;
$bLogForce = $bLogForceParam;
# Get the Postgres version
if (defined($strPgSqlBinParam))
{
my $strVersionRegExp = '(devel|((alpha|beta|rc)[0-9]+))$';
my $strOutLog = executeTest($strPgSqlBin . '/postgres --version');
my @stryVersionToken = split(/ /, $strOutLog);
@stryVersionToken = split(/\./, $stryVersionToken[2]);
$strCommonDbVersion = $stryVersionToken[0] . '.' . trim($stryVersionToken[1]);
# Warn if this is a devel/alpha/beta version
if ($strCommonDbVersion =~ /$strVersionRegExp/)
{
my $strDevVersion = $strCommonDbVersion;
$strCommonDbVersion =~ s/$strVersionRegExp//;
$strDevVersion = substr($strDevVersion, length($strCommonDbVersion));
&log(WARN, "Testing against ${strCommonDbVersion} ${strDevVersion} version");
}
# Don't run unit tests for unsupported versions
my @stryVersionSupport = versionSupport();
if ($strCommonDbVersion < $stryVersionSupport[0])
{
confess "currently only version $stryVersionSupport[0] and up are supported";
}
$strCommonCommandPsql = "${strPgSqlBin}/psql -X %option% -h ${strCommonDbPath}";
}
return true;
}
####################################################################################################################################
# BackRestTestCommon_manifestLoad
####################################################################################################################################
sub BackRestTestCommon_manifestLoad
{
my $strFileName = shift;
my $bRemote = shift;
# Defaults
$bRemote = defined($bRemote) ? $bRemote : false;
if ($bRemote)
{
executeTest("chmod g+x " . BackRestTestCommon_RepoPathGet(),
{bRemote => true});
}
my $oManifest = new pgBackRest::Manifest($strFileName);
if ($bRemote)
{
executeTest("chmod g-x " . BackRestTestCommon_RepoPathGet(),
{bRemote => true});
}
return $oManifest;
}
push(@EXPORT, qw(testSetup));
####################################################################################################################################
# BackRestTestCommon_manifestSave
# testIniSave
####################################################################################################################################
sub BackRestTestCommon_manifestSave
{
my $strFileName = shift;
my $oManifest = shift;
my $bRemote = shift;
# Defaults
$bRemote = defined($bRemote) ? $bRemote : false;
if ($bRemote)
{
executeTest('chmod g+x ' . BackRestTestCommon_RepoPathGet() . ' && chmod g+w ' . dirname($strFileName), {bRemote => true});
}
$oManifest->save();
if ($bRemote)
{
executeTest('chmod g-w ' . dirname($strFileName) . ' && chmod g-x ' . BackRestTestCommon_RepoPathGet(), {bRemote => true});
}
}
####################################################################################################################################
# BackRestTestCommon_iniLoad
####################################################################################################################################
sub BackRestTestCommon_iniLoad
sub testIniSave
{
my $strFileName = shift;
my $oIniRef = shift;
my $bRemote = shift;
# Defaults
$bRemote = defined($bRemote) ? $bRemote : false;
if ($bRemote)
{
executeTest("chmod g+x " . BackRestTestCommon_RepoPathGet(), {bRemote => true});
}
iniLoad($strFileName, $oIniRef);
if ($bRemote)
{
executeTest("chmod g-x " . BackRestTestCommon_RepoPathGet(), {bRemote => true});
}
}
####################################################################################################################################
# BackRestTestCommon_iniSave
####################################################################################################################################
sub BackRestTestCommon_iniSave
{
my $strFileName = shift;
my $oIniRef = shift;
my $bRemote = shift;
my $bChecksum = shift;
# Defaults
$bRemote = defined($bRemote) ? $bRemote : false;
if ($bRemote)
{
executeTest('chmod g+x ' . BackRestTestCommon_RepoPathGet() . ' && chmod g+w ' . $strFileName, {bRemote => true});
}
# Calculate a new checksum if requested
if (defined($bChecksum) && $bChecksum)
{
@@ -579,374 +165,18 @@ sub BackRestTestCommon_iniSave
}
iniSave($strFileName, $oIniRef);
if ($bRemote)
{
executeTest("chmod g-w " . $strFileName . ' && chmod g-x ' . BackRestTestCommon_RepoPathGet(), {bRemote => true});
}
}
####################################################################################################################################
# BackRestTestCommon_ConfigRemap
####################################################################################################################################
sub BackRestTestCommon_ConfigRemap
{
my $oRemapHashRef = shift;
my $oManifestRef = shift;
my $bRemote = shift;
# Create config filename
my $strConfigFile = BackRestTestCommon_DbPathGet() . '/pgbackrest.conf';
my $strStanza = BackRestTestCommon_StanzaGet();
# Load Config file
my %oConfig;
iniLoad($strConfigFile, \%oConfig, true);
# Load remote config file
my %oRemoteConfig;
my $strRemoteConfigFile = BackRestTestCommon_TestPathGet() . '/pgbackrest.conf.remote';
if ($bRemote)
{
executeTest("mv " . BackRestTestCommon_RepoPathGet() . "/pgbackrest.conf ${strRemoteConfigFile}",
{bRemote => true});
iniLoad($strRemoteConfigFile, \%oRemoteConfig, true);
}
# Rewrite recovery section
delete($oConfig{"${strStanza}:restore"}{&OPTION_TABLESPACE_MAP});
my @stryTablespaceMap;
foreach my $strRemap (sort(keys(%$oRemapHashRef)))
{
my $strRemapPath = ${$oRemapHashRef}{$strRemap};
if ($strRemap eq MANIFEST_TARGET_PGDATA)
{
$oConfig{$strStanza}{'db-path'} = $strRemapPath;
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} = $strRemapPath;
if ($bRemote)
{
$oRemoteConfig{$strStanza}{'db-path'} = $strRemapPath;
}
}
else
{
my $strTablespaceOid = (split('\/', $strRemap))[1];
push (@stryTablespaceMap, "${strTablespaceOid}=${strRemapPath}");
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strRemap}{&MANIFEST_SUBKEY_PATH} = $strRemapPath;
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{MANIFEST_TARGET_PGDATA . "/${strRemap}"}{destination} = $strRemapPath;
}
}
if (@stryTablespaceMap)
{
$oConfig{"${strStanza}:restore"}{&OPTION_TABLESPACE_MAP} = \@stryTablespaceMap;
}
# Resave the config file
iniSave($strConfigFile, \%oConfig, true);
# Load remote config file
if ($bRemote)
{
iniSave($strRemoteConfigFile, \%oRemoteConfig, true);
executeTest("mv ${strRemoteConfigFile} " . BackRestTestCommon_RepoPathGet() . '/pgbackrest.conf',
{bRemote => true});
}
}
####################################################################################################################################
# BackRestTestCommon_ConfigRecovery
####################################################################################################################################
sub BackRestTestCommon_ConfigRecovery
{
my $oRecoveryHashRef = shift;
my $bRemote = shift;
# Create config filename
my $strConfigFile = BackRestTestCommon_DbPathGet() . '/pgbackrest.conf';
my $strStanza = BackRestTestCommon_StanzaGet();
# Load Config file
my %oConfig;
iniLoad($strConfigFile, \%oConfig, true);
# Load remote config file
my %oRemoteConfig;
my $strRemoteConfigFile = BackRestTestCommon_TestPathGet() . '/pgbackrest.conf.remote';
if ($bRemote)
{
executeTest("mv " . BackRestTestCommon_RepoPathGet() . "/pgbackrest.conf ${strRemoteConfigFile}",
{bRemote => true});
iniLoad($strRemoteConfigFile, \%oRemoteConfig, true);
}
# Rewrite recovery options
my @stryRecoveryOption;
foreach my $strOption (sort(keys(%$oRecoveryHashRef)))
{
push (@stryRecoveryOption, "${strOption}=${$oRecoveryHashRef}{$strOption}");
}
if (@stryRecoveryOption)
{
$oConfig{$strStanza}{&OPTION_RESTORE_RECOVERY_OPTION} = \@stryRecoveryOption;
}
# Resave the config file
iniSave($strConfigFile, \%oConfig, true);
# Load remote config file
if ($bRemote)
{
iniSave($strRemoteConfigFile, \%oRemoteConfig, true);
executeTest("mv ${strRemoteConfigFile} " . BackRestTestCommon_RepoPathGet() . '/pgbackrest.conf',
{bRemote => true});
}
}
####################################################################################################################################
# BackRestTestCommon_ConfigCreate
####################################################################################################################################
sub BackRestTestCommon_ConfigCreate
{
my $strLocal = shift;
my $strRemote = shift;
my $bCompress = shift;
my $bChecksum = shift;
my $bHardlink = shift;
my $iThreadMax = shift;
my $bArchiveAsync = shift;
my $bCompressAsync = shift;
my %oParamHash;
if (defined($strRemote))
{
$oParamHash{'global'}{'cmd-remote'} = $strCommonCommandRemote;
}
if (defined($strRemote) && $strRemote eq BACKUP)
{
$oParamHash{'global'}{'backup-host'} = $strCommonHost;
$oParamHash{'global'}{'backup-user'} = $strCommonUserBackRest;
}
elsif (defined($strRemote) && $strRemote eq DB)
{
$oParamHash{$strCommonStanza}{'db-host'} = $strCommonHost;
$oParamHash{$strCommonStanza}{'db-user'} = $strCommonUser;
}
$oParamHash{'global'}{'log-level-console'} = 'debug';
$oParamHash{'global'}{'log-level-file'} = 'trace';
$oParamHash{'global'}{'repo-path'} = $strCommonRepoPath;
$oParamHash{'global'}{'log-path'} = "${strCommonRepoPath}/log";
$oParamHash{'global'}{'lock-path'} = "${strCommonRepoPath}/lock";
if ($strLocal eq BACKUP)
{
$oParamHash{'global'}{'config-remote'} = "${strCommonDbPath}/pgbackrest.conf";
}
elsif ($strLocal eq DB)
{
$oParamHash{'global'}{'config-remote'} = "${strCommonRepoPath}/pgbackrest.conf";
if (defined($strRemote))
{
$oParamHash{'global'}{'log-path'} = "${strCommonLocalPath}/log";
$oParamHash{'global'}{'lock-path'} = "${strCommonLocalPath}/lock";
}
if ($bArchiveAsync)
{
$oParamHash{'global:archive-push'}{'archive-async'} = 'y';
if (defined($strRemote))
{
$oParamHash{'global'}{'spool-path'} = $strCommonLocalPath;
}
else
{
$oParamHash{'global'}{'spool-path'} = $oParamHash{'global'}{'repo-path'};
}
}
}
else
{
confess "invalid local type ${strLocal}";
}
if (defined($iThreadMax) && $iThreadMax > 1)
{
$oParamHash{'global'}{'thread-max'} = $iThreadMax;
}
if (($strLocal eq BACKUP) || ($strLocal eq DB && !defined($strRemote)))
{
if (defined($bHardlink) && $bHardlink)
{
$oParamHash{'global:backup'}{'hardlink'} = 'y';
}
$oParamHash{'global:backup'}{'archive-copy'} = 'y';
$oParamHash{'global:backup'}{'start-fast'} = 'y';
}
if (defined($bCompress) && !$bCompress)
{
$oParamHash{'global'}{'compress'} = 'n';
}
# Stanza settings
$oParamHash{$strCommonStanza}{'db-path'} = $strCommonDbCommonPath;
$oParamHash{$strCommonStanza}{'db-port'} = $iCommonDbPort;
$oParamHash{$strCommonStanza}{'db-socket-path'} = BackRestTestCommon_DbPathGet();
# Write out the configuration file
my $strFile = BackRestTestCommon_TestPathGet() . '/pgbackrest.conf';
iniSave($strFile, \%oParamHash, true);
# Move the configuration file based on local
if ($strLocal eq 'db')
{
rename($strFile, BackRestTestCommon_DbPathGet() . '/pgbackrest.conf')
or die "unable to move ${strFile} to " . BackRestTestCommon_DbPathGet() . '/pgbackrest.conf path';
}
elsif ($strLocal eq 'backup' && !defined($strRemote))
{
rename($strFile, BackRestTestCommon_RepoPathGet() . '/pgbackrest.conf')
or die "unable to move ${strFile} to " . BackRestTestCommon_RepoPathGet() . '/pgbackrest.conf path';
}
else
{
executeTest("mv ${strFile} " . BackRestTestCommon_RepoPathGet() . '/pgbackrest.conf',
{bRemote => true});
}
}
push(@EXPORT, qw(testIniSave));
####################################################################################################################################
# Get Methods
####################################################################################################################################
sub BackRestTestCommon_PgSqlBinPathGet
{
return $strPgSqlBin;
}
sub BackRestTestCommon_StanzaGet
{
return $strCommonStanza;
}
sub BackRestTestCommon_CommandPsqlGet
{
return $strCommonCommandPsql;
}
sub BackRestTestCommon_CommandMainGet
{
return $strCommonCommandMain;
}
sub BackRestTestCommon_CommandMainAbsGet
{
if ($bCommandMainSet)
{
return BackRestTestCommon_CommandMainGet()
}
return abs_path(BackRestTestCommon_CommandMainGet());
}
sub BackRestTestCommon_CommandRemoteGet
{
return $strCommonCommandRemote;
}
sub BackRestTestCommon_CommandRemoteFullGet
{
return $strCommonCommandRemoteFull;
}
sub BackRestTestCommon_HostGet
{
return $strCommonHost;
}
sub BackRestTestCommon_UserGet
{
return $strCommonUser;
}
sub BackRestTestCommon_GroupGet
{
return $strCommonGroup;
}
sub BackRestTestCommon_UserBackRestGet
{
return $strCommonUserBackRest;
}
sub BackRestTestCommon_BasePathGet
{
return $strCommonBasePath;
}
sub BackRestTestCommon_TestPathGet
{
return $strCommonTestPath;
}
sub BackRestTestCommon_DataPathGet
sub testDataPath
{
return $strCommonDataPath;
}
sub BackRestTestCommon_RepoPathGet
{
return $strCommonRepoPath;
}
sub BackRestTestCommon_LocalPathGet
{
return $strCommonLocalPath;
}
sub BackRestTestCommon_DbPathGet
{
return $strCommonDbPath;
}
sub BackRestTestCommon_DbCommonPathGet
{
my $iIndex = shift;
return $strCommonDbCommonPath . (defined($iIndex) ? "-${iIndex}" : '');
}
sub BackRestTestCommon_DbTablespacePathGet
{
my $iTablespace = shift;
my $iIndex = shift;
return $strCommonDbTablespacePath . (defined($iTablespace) ? "/ts${iTablespace}" . (defined($iIndex) ? "-${iIndex}" : '') : '');
}
sub BackRestTestCommon_DbPortGet
{
return $iCommonDbPort;
}
sub BackRestTestCommon_DbVersion
{
return $strCommonDbVersion;
}
push(@EXPORT, qw(testDataPath));
1;
-128
View File
@@ -1,128 +0,0 @@
####################################################################################################################################
# CompareTest.pm - Performance comparison tests between rsync and backrest
####################################################################################################################################
package pgBackRestTest::CompareTest;
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
use File::Basename qw(dirname);
use File::stat;
use Time::HiRes qw(gettimeofday);
use lib dirname($0) . '/../lib';
use pgBackRest::Common::Log;
use pgBackRest::Manifest;
use pgBackRestTest::BackupTest;
use pgBackRestTest::CommonTest;
####################################################################################################################################
# Exports
####################################################################################################################################
our @EXPORT = qw(BackRestTestCompare_Test);
####################################################################################################################################
# BackRestTestCompare_BuildDb
####################################################################################################################################
sub BackRestTestCompare_BuildDb
{
my $iTableTotal = shift;
my $iTableSize = shift;
&log(INFO, "build database: " . fileSizeFormat($iTableTotal * $iTableSize * 1024 * 1024));
for (my $iTableIdx = 0; $iTableIdx < $iTableTotal; $iTableIdx++)
{
my $strSourceFile = BackRestTestCommon_DataPathGet() . "/test.table.bin";
my $strTableFile = BackRestTestCommon_DbCommonPathGet() . "/test-${iTableIdx}";
for (my $iTableSizeIdx = 0; $iTableSizeIdx < $iTableSize; $iTableSizeIdx++)
{
executeTest("cat ${strSourceFile} >> ${strTableFile}");
}
}
}
####################################################################################################################################
# BackRestTestCompare_Test
####################################################################################################################################
sub BackRestTestCompare_Test
{
my $strTest = shift;
#-------------------------------------------------------------------------------------------------------------------------------
# Test rsync
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'rsync')
{
my $iRun = 0;
my $bRemote = false;
&log(INFO, "Test rsync\n");
# Increment the run, log, and decide whether this unit test should be run
if (!BackRestTestCommon_Run(++$iRun,
"rmt ${bRemote}")) {next}
# Create the cluster and paths
BackRestTestBackup_Create($bRemote, false);
BackRestTestCommon_PathCreate(BackRestTestCommon_DbCommonPathGet() . '/' . DB_PATH_PGTBLSPC);
BackRestTestCompare_BuildDb(48, 10);
executeTest('sync');
for (my $bRemote = true; $bRemote <= true; $bRemote++)
{
for (my $bRsync = true; $bRsync >= false; $bRsync--)
{
my $strCommand;
BackRestTestCommon_CreateRepo($bRemote);
&log(INFO, ($bRsync ? 'rsync' : 'backrest') . " test");
if ($bRsync)
{
$strCommand = 'rsync --compress-level=6 -zvlhprtogHS --delete ' .
($bRemote ? BackRestTestCommon_UserGet . '@' . BackRestTestCommon_HostGet . ':' : '') .
BackRestTestCommon_DbCommonPathGet() . '/ ' . BackRestTestCommon_RepoPathGet() . ';' .
'gzip -r "' . BackRestTestCommon_RepoPathGet() . '"';
}
else
{
$strCommand = BackRestTestCommon_CommandMainGet() .
' --stanza=main' .
($bRemote ? ' "--db-host=' . BackRestTestCommon_HostGet . '"' .
' "--db-user=' . BackRestTestCommon_UserGet . '"' : '') .
# ' --log-level-file=debug' .
' --no-start-stop' .
# ' --no-compress' .
' --thread-max=4' .
' "--db-path=' . BackRestTestCommon_DbCommonPathGet() . '"' .
' "--repo-path=' . BackRestTestCommon_RepoPathGet() . '"' .
' --type=full backup';
}
my $fTimeBegin = gettimeofday();
executeTest($strCommand, $bRemote);
executeTest('sync');
my $fTimeEnd = gettimeofday();
&log(INFO, " time = " . (int(($fTimeEnd - $fTimeBegin) * 100) / 100));
}
}
if (BackRestTestCommon_Cleanup())
{
&log(INFO, 'cleanup');
BackRestTestBackup_Drop();
}
}
}
1;
@@ -1,7 +1,7 @@
####################################################################################################################################
# ConfigTest.pm - Unit Tests for pgBackRest::Param and pgBackRest::Config::Config
####################################################################################################################################
package pgBackRestTest::ConfigTest;
package pgBackRestTest::Config::ConfigTest;
####################################################################################################################################
# Perl includes
@@ -12,15 +12,15 @@ use Carp qw(confess);
use Cwd qw(abs_path);
use Exporter qw(import);
use File::Basename qw(dirname);
use Scalar::Util qw(blessed);
use lib dirname($0) . '/../lib';
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Config::Config;
use pgBackRestTest::Backup::Common::HostBaseTest;
use pgBackRestTest::Common::HostGroupTest;
use pgBackRestTest::CommonTest;
sub optionSetTest
@@ -229,24 +229,25 @@ sub optionTestExpect
}
####################################################################################################################################
# BackRestTestConfig_Test
# configTestRun
####################################################################################################################################
our @EXPORT = qw(BackRestTestConfig_Test);
sub BackRestTestConfig_Test
sub configTestRun
{
my $strTest = shift;
my $iThreadMax = shift;
my $bVmOut = shift;
# Setup test variables
my $oHostGroup = hostGroupGet();
my $iRun;
my $bCreate;
my $strStanza = 'main';
my $oOption = {};
my $oConfig = {};
my @oyArray;
my $strConfigFile = BackRestTestCommon_TestPathGet() . '/pgbackrest.conf';
my $strTestPath = $oHostGroup->paramGet(HOST_PARAM_TEST_PATH);
my $strConfigFile = "${strTestPath}/pgbackrest.conf";
use constant BOGUS => 'bogus';
@@ -256,8 +257,6 @@ sub BackRestTestConfig_Test
&log(INFO, 'CONFIG MODULE ******************************************************************');
}
BackRestTestCommon_Drop();
#-------------------------------------------------------------------------------------------------------------------------------
# Test command-line options
#-------------------------------------------------------------------------------------------------------------------------------
@@ -272,21 +271,21 @@ sub BackRestTestConfig_Test
&log(INFO, "Test ${strThisTest}\n");
}
if (BackRestTestCommon_Run(++$iRun, 'backup with no stanza'))
if (testRun(++$iRun, 'backup with no stanza'))
{
optionSetTest($oOption, OPTION_DB_PATH, '/db');
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_REQUIRED, OPTION_STANZA);
}
if (BackRestTestCommon_Run(++$iRun, 'backup with boolean stanza'))
if (testRun(++$iRun, 'backup with boolean stanza'))
{
optionBoolSetTest($oOption, OPTION_STANZA);
configLoadExpect($oOption, CMD_BACKUP, ERROR_COMMAND_REQUIRED);
}
if (BackRestTestCommon_Run(++$iRun, 'backup type defaults to ' . BACKUP_TYPE_INCR))
if (testRun(++$iRun, 'backup type defaults to ' . BACKUP_TYPE_INCR))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -295,7 +294,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_TYPE, BACKUP_TYPE_INCR);
}
if (BackRestTestCommon_Run(++$iRun, 'backup type set to ' . BACKUP_TYPE_FULL))
if (testRun(++$iRun, 'backup type set to ' . BACKUP_TYPE_FULL))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -305,7 +304,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_TYPE, BACKUP_TYPE_FULL);
}
if (BackRestTestCommon_Run(++$iRun, 'backup type invalid'))
if (testRun(++$iRun, 'backup type invalid'))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -314,7 +313,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_INVALID_VALUE, BOGUS, OPTION_TYPE);
}
if (BackRestTestCommon_Run(++$iRun, 'backup invalid force'))
if (testRun(++$iRun, 'backup invalid force'))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -323,7 +322,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_INVALID, OPTION_FORCE, 'no-' . OPTION_ONLINE);
}
if (BackRestTestCommon_Run(++$iRun, 'backup valid force'))
if (testRun(++$iRun, 'backup valid force'))
{
# $oOption = {};
optionSetTest($oOption, OPTION_STANZA, $strStanza);
@@ -336,7 +335,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_FORCE, true);
}
if (BackRestTestCommon_Run(++$iRun, 'backup invalid value for ' . OPTION_TEST_DELAY))
if (testRun(++$iRun, 'backup invalid value for ' . OPTION_TEST_DELAY))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -346,7 +345,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_INVALID_VALUE, BOGUS, OPTION_TEST_DELAY);
}
if (BackRestTestCommon_Run(++$iRun, 'backup invalid ' . OPTION_TEST_DELAY))
if (testRun(++$iRun, 'backup invalid ' . OPTION_TEST_DELAY))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -355,7 +354,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_INVALID, OPTION_TEST_DELAY, OPTION_TEST);
}
if (BackRestTestCommon_Run(++$iRun, 'backup check ' . OPTION_TEST_DELAY . ' undef'))
if (testRun(++$iRun, 'backup check ' . OPTION_TEST_DELAY . ' undef'))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -364,7 +363,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_TEST_DELAY);
}
if (BackRestTestCommon_Run(++$iRun, 'restore invalid ' . OPTION_TARGET))
if (testRun(++$iRun, 'restore invalid ' . OPTION_TARGET))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -375,7 +374,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_RESTORE, ERROR_OPTION_INVALID, OPTION_TARGET, OPTION_TYPE, \@oyArray);
}
if (BackRestTestCommon_Run(++$iRun, 'restore ' . OPTION_TARGET))
if (testRun(++$iRun, 'restore ' . OPTION_TARGET))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -388,7 +387,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_TARGET_TIMELINE);
}
if (BackRestTestCommon_Run(++$iRun, 'invalid string ' . OPTION_THREAD_MAX))
if (testRun(++$iRun, 'invalid string ' . OPTION_THREAD_MAX))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -397,7 +396,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_INVALID_VALUE, BOGUS, OPTION_THREAD_MAX);
}
if (BackRestTestCommon_Run(++$iRun, 'invalid float ' . OPTION_THREAD_MAX))
if (testRun(++$iRun, 'invalid float ' . OPTION_THREAD_MAX))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -406,7 +405,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_INVALID_VALUE, '0.0', OPTION_THREAD_MAX);
}
if (BackRestTestCommon_Run(++$iRun, 'valid ' . OPTION_THREAD_MAX))
if (testRun(++$iRun, 'valid ' . OPTION_THREAD_MAX))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -415,7 +414,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP);
}
if (BackRestTestCommon_Run(++$iRun, 'valid float ' . OPTION_TEST_DELAY))
if (testRun(++$iRun, 'valid float ' . OPTION_TEST_DELAY))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -425,7 +424,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP);
}
if (BackRestTestCommon_Run(++$iRun, 'valid int ' . OPTION_TEST_DELAY))
if (testRun(++$iRun, 'valid int ' . OPTION_TEST_DELAY))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -435,7 +434,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP);
}
if (BackRestTestCommon_Run(++$iRun, 'restore valid ' . OPTION_TARGET_TIMELINE))
if (testRun(++$iRun, 'restore valid ' . OPTION_TARGET_TIMELINE))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -444,7 +443,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_RESTORE);
}
if (BackRestTestCommon_Run(++$iRun, 'invalid ' . OPTION_BUFFER_SIZE))
if (testRun(++$iRun, 'invalid ' . OPTION_BUFFER_SIZE))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_BUFFER_SIZE, '512');
@@ -452,7 +451,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_RESTORE, ERROR_OPTION_INVALID_RANGE, '512', OPTION_BUFFER_SIZE);
}
if (BackRestTestCommon_Run(++$iRun, CMD_BACKUP . ' invalid option ' . OPTION_RETENTION_ARCHIVE_TYPE))
if (testRun(++$iRun, CMD_BACKUP . ' invalid option ' . OPTION_RETENTION_ARCHIVE_TYPE))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -461,7 +460,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_INVALID, OPTION_RETENTION_ARCHIVE_TYPE, OPTION_RETENTION_ARCHIVE);
}
if (BackRestTestCommon_Run(++$iRun, CMD_BACKUP . ' invalid value ' . OPTION_RETENTION_ARCHIVE_TYPE))
if (testRun(++$iRun, CMD_BACKUP . ' invalid value ' . OPTION_RETENTION_ARCHIVE_TYPE))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -471,7 +470,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_INVALID_VALUE, BOGUS, OPTION_RETENTION_ARCHIVE_TYPE);
}
if (BackRestTestCommon_Run(++$iRun, CMD_BACKUP . ' invalid value ' . OPTION_PROTOCOL_TIMEOUT))
if (testRun(++$iRun, CMD_BACKUP . ' invalid value ' . OPTION_PROTOCOL_TIMEOUT))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -483,7 +482,7 @@ sub BackRestTestConfig_Test
"'protocol-timeout' option should be greater than 'db-timeout' option");
}
if (BackRestTestCommon_Run(++$iRun, CMD_BACKUP . ' valid value ' . OPTION_RETENTION_ARCHIVE_TYPE))
if (testRun(++$iRun, CMD_BACKUP . ' valid value ' . OPTION_RETENTION_ARCHIVE_TYPE))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -495,7 +494,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_RETENTION_ARCHIVE_TYPE, BACKUP_TYPE_FULL);
}
if (BackRestTestCommon_Run(++$iRun, CMD_RESTORE . ' invalid value ' . OPTION_RESTORE_RECOVERY_OPTION))
if (testRun(++$iRun, CMD_RESTORE . ' invalid value ' . OPTION_RESTORE_RECOVERY_OPTION))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -504,7 +503,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_RESTORE, ERROR_OPTION_INVALID_PAIR, '=', OPTION_RESTORE_RECOVERY_OPTION);
}
if (BackRestTestCommon_Run(++$iRun, CMD_RESTORE . ' invalid value ' . OPTION_RESTORE_RECOVERY_OPTION))
if (testRun(++$iRun, CMD_RESTORE . ' invalid value ' . OPTION_RESTORE_RECOVERY_OPTION))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -513,7 +512,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_RESTORE, ERROR_OPTION_INVALID_PAIR, '=' . BOGUS, OPTION_RESTORE_RECOVERY_OPTION);
}
if (BackRestTestCommon_Run(++$iRun, CMD_RESTORE . ' invalid value ' . OPTION_RESTORE_RECOVERY_OPTION))
if (testRun(++$iRun, CMD_RESTORE . ' invalid value ' . OPTION_RESTORE_RECOVERY_OPTION))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -522,7 +521,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_RESTORE, ERROR_OPTION_INVALID_PAIR, BOGUS . '=', OPTION_RESTORE_RECOVERY_OPTION);
}
if (BackRestTestCommon_Run(++$iRun, CMD_RESTORE . ' valid value ' . OPTION_RESTORE_RECOVERY_OPTION))
if (testRun(++$iRun, CMD_RESTORE . ' valid value ' . OPTION_RESTORE_RECOVERY_OPTION))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -532,7 +531,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_RESTORE_RECOVERY_OPTION, 'db.domain.net', 'primary-conn-info');
}
if (BackRestTestCommon_Run(++$iRun, CMD_RESTORE . ' values passed to ' . CMD_ARCHIVE_GET))
if (testRun(++$iRun, CMD_RESTORE . ' values passed to ' . CMD_ARCHIVE_GET))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db path/main');
@@ -551,7 +550,7 @@ sub BackRestTestConfig_Test
}
}
if (BackRestTestCommon_Run(++$iRun, CMD_BACKUP . ' default value ' . OPTION_COMMAND_REMOTE))
if (testRun(++$iRun, CMD_BACKUP . ' default value ' . OPTION_COMMAND_REMOTE))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -560,7 +559,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_COMMAND_REMOTE, abs_path($0));
}
if (BackRestTestCommon_Run(++$iRun, CMD_BACKUP . ' missing option ' . OPTION_DB_PATH))
if (testRun(++$iRun, CMD_BACKUP . ' missing option ' . OPTION_DB_PATH))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
@@ -582,9 +581,7 @@ sub BackRestTestConfig_Test
&log(INFO, "Test ${strThisTest}\n");
}
BackRestTestCommon_Create();
if (BackRestTestCommon_Run(++$iRun, 'set and negate option ' . OPTION_CONFIG))
if (testRun(++$iRun, 'set and negate option ' . OPTION_CONFIG))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -594,7 +591,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_NEGATE, OPTION_CONFIG);
}
if (BackRestTestCommon_Run(++$iRun, 'option ' . OPTION_CONFIG))
if (testRun(++$iRun, 'option ' . OPTION_CONFIG))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -604,7 +601,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_CONFIG);
}
if (BackRestTestCommon_Run(++$iRun, 'default option ' . OPTION_CONFIG))
if (testRun(++$iRun, 'default option ' . OPTION_CONFIG))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
@@ -613,16 +610,16 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_CONFIG, OPTION_DEFAULT_CONFIG);
}
if (BackRestTestCommon_Run(++$iRun, 'config file is a path'))
if (testRun(++$iRun, 'config file is a path'))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_DB_PATH, '/db');
optionSetTest($oOption, OPTION_CONFIG, BackRestTestCommon_TestPathGet());
optionSetTest($oOption, OPTION_CONFIG, $strTestPath);
configLoadExpect($oOption, CMD_BACKUP, ERROR_FILE_INVALID, BackRestTestCommon_TestPathGet());
configLoadExpect($oOption, CMD_BACKUP, ERROR_FILE_INVALID, $strTestPath);
}
if (BackRestTestCommon_Run(++$iRun, 'load from config stanza command section - option ' . OPTION_THREAD_MAX))
if (testRun(++$iRun, 'load from config stanza command section - option ' . OPTION_THREAD_MAX))
{
$oConfig = {};
$$oConfig{"${strStanza}:" . &CMD_BACKUP}{&OPTION_THREAD_MAX} = 2;
@@ -636,7 +633,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_THREAD_MAX, 2);
}
if (BackRestTestCommon_Run(++$iRun, 'load from config stanza section - option ' . OPTION_THREAD_MAX))
if (testRun(++$iRun, 'load from config stanza section - option ' . OPTION_THREAD_MAX))
{
$oConfig = {};
$$oConfig{$strStanza}{&OPTION_THREAD_MAX} = 3;
@@ -651,7 +648,7 @@ sub BackRestTestConfig_Test
}
if (BackRestTestCommon_Run(++$iRun, 'load from config global command section - option ' . OPTION_THREAD_MAX))
if (testRun(++$iRun, 'load from config global command section - option ' . OPTION_THREAD_MAX))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL . ':' . &CMD_BACKUP}{&OPTION_THREAD_MAX} = 2;
@@ -665,7 +662,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_THREAD_MAX, 2);
}
if (BackRestTestCommon_Run(++$iRun, 'load from config global section - option ' . OPTION_THREAD_MAX))
if (testRun(++$iRun, 'load from config global section - option ' . OPTION_THREAD_MAX))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL}{&OPTION_THREAD_MAX} = 5;
@@ -679,7 +676,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_THREAD_MAX, 5);
}
if (BackRestTestCommon_Run(++$iRun, 'default - option ' . OPTION_THREAD_MAX))
if (testRun(++$iRun, 'default - option ' . OPTION_THREAD_MAX))
{
$oConfig = {};
iniSave($strConfigFile, $oConfig, true);
@@ -692,7 +689,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_THREAD_MAX, 1);
}
if (BackRestTestCommon_Run(++$iRun, 'command-line override - option ' . OPTION_THREAD_MAX))
if (testRun(++$iRun, 'command-line override - option ' . OPTION_THREAD_MAX))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL}{&OPTION_THREAD_MAX} = 9;
@@ -707,7 +704,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_THREAD_MAX, 7);
}
if (BackRestTestCommon_Run(++$iRun, 'invalid boolean - option ' . OPTION_HARDLINK))
if (testRun(++$iRun, 'invalid boolean - option ' . OPTION_HARDLINK))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL . ':' . &CMD_BACKUP}{&OPTION_HARDLINK} = 'Y';
@@ -720,7 +717,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_INVALID_VALUE, 'Y', OPTION_HARDLINK);
}
if (BackRestTestCommon_Run(++$iRun, 'invalid value - option ' . OPTION_LOG_LEVEL_CONSOLE))
if (testRun(++$iRun, 'invalid value - option ' . OPTION_LOG_LEVEL_CONSOLE))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL}{&OPTION_LOG_LEVEL_CONSOLE} = BOGUS;
@@ -733,7 +730,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_BACKUP, ERROR_OPTION_INVALID_VALUE, BOGUS, OPTION_LOG_LEVEL_CONSOLE);
}
if (BackRestTestCommon_Run(++$iRun, 'valid value - option ' . OPTION_LOG_LEVEL_CONSOLE))
if (testRun(++$iRun, 'valid value - option ' . OPTION_LOG_LEVEL_CONSOLE))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL}{&OPTION_LOG_LEVEL_CONSOLE} = lc(INFO);
@@ -746,7 +743,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_RESTORE);
}
if (BackRestTestCommon_Run(++$iRun, 'archive-push - option ' . OPTION_LOG_LEVEL_CONSOLE))
if (testRun(++$iRun, 'archive-push - option ' . OPTION_LOG_LEVEL_CONSOLE))
{
optionSetTest($oOption, OPTION_STANZA, $strStanza);
optionSetTest($oOption, OPTION_CONFIG, $strConfigFile);
@@ -754,7 +751,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_ARCHIVE_PUSH);
}
if (BackRestTestCommon_Run(++$iRun, CMD_EXPIRE . ' ' . OPTION_RETENTION_FULL))
if (testRun(++$iRun, CMD_EXPIRE . ' ' . OPTION_RETENTION_FULL))
{
$oConfig = {};
$$oConfig{"${strStanza}:" . &CMD_EXPIRE}{&OPTION_RETENTION_FULL} = 2;
@@ -767,7 +764,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_RETENTION_FULL, 2);
}
if (BackRestTestCommon_Run(++$iRun, CMD_BACKUP . ' option ' . OPTION_COMPRESS))
if (testRun(++$iRun, CMD_BACKUP . ' option ' . OPTION_COMPRESS))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL . ':' . &CMD_BACKUP}{&OPTION_COMPRESS} = 'n';
@@ -781,7 +778,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_COMPRESS, false);
}
if (BackRestTestCommon_Run(++$iRun, CMD_RESTORE . ' global option ' . OPTION_RESTORE_RECOVERY_OPTION . ' error'))
if (testRun(++$iRun, CMD_RESTORE . ' global option ' . OPTION_RESTORE_RECOVERY_OPTION . ' error'))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL . ':' . &CMD_RESTORE}{&OPTION_RESTORE_RECOVERY_OPTION} = 'bogus=';
@@ -794,7 +791,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_RESTORE, ERROR_OPTION_INVALID_VALUE, 'bogus=', OPTION_RESTORE_RECOVERY_OPTION);
}
if (BackRestTestCommon_Run(++$iRun, CMD_RESTORE . ' global option ' . OPTION_RESTORE_RECOVERY_OPTION . ' error'))
if (testRun(++$iRun, CMD_RESTORE . ' global option ' . OPTION_RESTORE_RECOVERY_OPTION . ' error'))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL . ':' . &CMD_RESTORE}{&OPTION_RESTORE_RECOVERY_OPTION} = '=bogus';
@@ -807,7 +804,7 @@ sub BackRestTestConfig_Test
configLoadExpect($oOption, CMD_RESTORE, ERROR_OPTION_INVALID_VALUE, '=bogus', OPTION_RESTORE_RECOVERY_OPTION);
}
if (BackRestTestCommon_Run(++$iRun, CMD_RESTORE . ' global option ' . OPTION_RESTORE_RECOVERY_OPTION))
if (testRun(++$iRun, CMD_RESTORE . ' global option ' . OPTION_RESTORE_RECOVERY_OPTION))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL . ':' . &CMD_RESTORE}{&OPTION_RESTORE_RECOVERY_OPTION} =
@@ -822,7 +819,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_RESTORE_RECOVERY_OPTION, '/path/to/pgbackrest', 'archive-command');
}
if (BackRestTestCommon_Run(++$iRun, CMD_RESTORE . ' stanza option ' . OPTION_RESTORE_RECOVERY_OPTION))
if (testRun(++$iRun, CMD_RESTORE . ' stanza option ' . OPTION_RESTORE_RECOVERY_OPTION))
{
$oConfig = {};
$$oConfig{$strStanza}{&OPTION_RESTORE_RECOVERY_OPTION} = ['standby-mode=on', 'a=b'];
@@ -837,7 +834,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_RESTORE_RECOVERY_OPTION, 'on', 'standby-mode');
}
if (BackRestTestCommon_Run(++$iRun, CMD_BACKUP . ' option ' . OPTION_DB_PATH))
if (testRun(++$iRun, CMD_BACKUP . ' option ' . OPTION_DB_PATH))
{
$oConfig = {};
$$oConfig{$strStanza}{&OPTION_DB_PATH} = '/path/to/db';
@@ -850,7 +847,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_DB_PATH, '/path/to/db');
}
if (BackRestTestCommon_Run(++$iRun, CMD_BACKUP . ' option ' . OPTION_BACKUP_ARCHIVE_CHECK))
if (testRun(++$iRun, CMD_BACKUP . ' option ' . OPTION_BACKUP_ARCHIVE_CHECK))
{
$oConfig = {};
$$oConfig{$strStanza}{&OPTION_DB_PATH} = '/path/to/db';
@@ -865,7 +862,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_BACKUP_ARCHIVE_CHECK, false);
}
if (BackRestTestCommon_Run(++$iRun, CMD_ARCHIVE_PUSH . ' option ' . OPTION_DB_PATH))
if (testRun(++$iRun, CMD_ARCHIVE_PUSH . ' option ' . OPTION_DB_PATH))
{
$oConfig = {};
$$oConfig{$strStanza}{&OPTION_DB_PATH} = '/path/to/db';
@@ -878,7 +875,7 @@ sub BackRestTestConfig_Test
optionTestExpect(OPTION_DB_PATH, '/path/to/db');
}
if (BackRestTestCommon_Run(++$iRun, CMD_BACKUP . ' option ' . OPTION_REPO_PATH))
if (testRun(++$iRun, CMD_BACKUP . ' option ' . OPTION_REPO_PATH))
{
$oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL}{&OPTION_REPO_PATH} = '/repo';
@@ -893,12 +890,10 @@ sub BackRestTestConfig_Test
}
# Cleanup
if (BackRestTestCommon_Cleanup())
{
&log(INFO, 'cleanup');
BackRestTestCommon_Drop(true);
}
testCleanup();
}
}
our @EXPORT = qw(configTestRun);
1;
@@ -1,7 +1,7 @@
####################################################################################################################################
# FileTest.pm - Unit Tests for pgBackRest::File
####################################################################################################################################
package pgBackRestTest::FileTest;
package pgBackRestTest::File::FileTest;
####################################################################################################################################
# Perl includes
@@ -13,20 +13,21 @@ use Carp qw(confess);
use Cwd qw(abs_path cwd);
use Exporter qw(import);
use Fcntl qw(:mode);
use File::Basename;
use File::stat;
use POSIX qw(ceil);
use Scalar::Util qw(blessed);
use Time::HiRes qw(gettimeofday usleep);
use lib dirname($0) . '/../lib';
use pgBackRest::Common::Log;
use pgBackRest::Config::Config;
use pgBackRest::File;
use pgBackRest::Protocol::Common;
use pgBackRest::Protocol::RemoteMaster;
use pgBackRestTest::Backup::Common::HostBackupTest;
use pgBackRestTest::Backup::Common::HostBaseTest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::HostGroupTest;
use pgBackRestTest::CommonTest;
my $strTestPath;
@@ -34,9 +35,9 @@ my $strHost;
my $strUserBackRest;
####################################################################################################################################
# BackRestTestFile_Setup
# fileTestSetup
####################################################################################################################################
sub BackRestTestFile_Setup
sub fileTestSetup
{
my $bPrivate = shift;
my $bDropOnly = shift;
@@ -65,11 +66,9 @@ sub BackRestTestFile_Setup
}
####################################################################################################################################
# BackRestTestFile_Test
# fileTestRun
####################################################################################################################################
our @EXPORT = qw(BackRestTestFile_Test);
sub BackRestTestFile_Test
sub fileTestRun
{
my $strTest = shift;
my $iThreadMax = shift;
@@ -82,13 +81,13 @@ sub BackRestTestFile_Test
}
# Setup test variables
my $iRun;
$strTestPath = BackRestTestCommon_TestPathGet();
my $strStanza = BackRestTestCommon_StanzaGet();
my $strUser = BackRestTestCommon_UserGet();
my $strGroup = BackRestTestCommon_GroupGet();
$strHost = BackRestTestCommon_HostGet();
$strUserBackRest = BackRestTestCommon_UserBackRestGet();
my $oHostGroup = hostGroupGet();
$strTestPath = $oHostGroup->paramGet(HOST_PARAM_TEST_PATH);
my $strStanza = 'db';
my $strUser = getpwuid($<);
my $strGroup = getgrgid($();
$strHost = '127.0.0.1';
$strUserBackRest = 'backrest';
# Print test banner
if (!$bVmOut)
@@ -99,33 +98,33 @@ sub BackRestTestFile_Test
#-------------------------------------------------------------------------------------------------------------------------------
# Create remotes
#-------------------------------------------------------------------------------------------------------------------------------
mkdir($strTestPath . '/backrest', oct('0770')) or confess 'Unable to create backrest directory';
my $strRepoPath = "${strTestPath}/repo";
my $oRemote = new pgBackRest::Protocol::RemoteMaster
(
BackRestTestCommon_CommandRemoteFullGet(), # Remote command
OPTION_DEFAULT_BUFFER_SIZE, # Buffer size
OPTION_DEFAULT_COMPRESS_LEVEL, # Compress level
OPTION_DEFAULT_COMPRESS_LEVEL_NETWORK, # Compress network level
$strHost, # Host
$strUserBackRest, # User
PROTOCOL_TIMEOUT_TEST # Protocol timeout
);
mkdir($strRepoPath, oct('0770'))
or confess "Unable to create repo directory: ${strRepoPath}";
my $oLocal = new pgBackRest::Protocol::Common
(
OPTION_DEFAULT_BUFFER_SIZE, # Buffer size
OPTION_DEFAULT_COMPRESS_LEVEL, # Compress level
OPTION_DEFAULT_COMPRESS_LEVEL_NETWORK, # Compress network level
PROTOCOL_TIMEOUT_TEST # Protocol timeout
);
my $oRemote = new pgBackRest::Protocol::RemoteMaster(
$oHostGroup->paramGet(HOST_PARAM_BACKREST_EXE) . ' --stanza=' . HOST_STANZA .
" --repo-path=${strRepoPath} --no-config --command=test remote",
OPTION_DEFAULT_BUFFER_SIZE,
OPTION_DEFAULT_COMPRESS_LEVEL,
OPTION_DEFAULT_COMPRESS_LEVEL_NETWORK,
$strHost,
$strUserBackRest,
HOST_PROTOCOL_TIMEOUT);
my $oLocal = new pgBackRest::Protocol::Common(
OPTION_DEFAULT_BUFFER_SIZE,
OPTION_DEFAULT_COMPRESS_LEVEL,
OPTION_DEFAULT_COMPRESS_LEVEL_NETWORK,
HOST_PROTOCOL_TIMEOUT);
#-------------------------------------------------------------------------------------------------------------------------------
# Test path_create()
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'path_create')
{
$iRun = 0;
my $iRun = 0;
if (!$bVmOut)
{
@@ -153,11 +152,11 @@ sub BackRestTestFile_Test
my $strPathType = PATH_BACKUP_CLUSTER;
# Increment the run, log, and decide whether this unit test should be run
if (!BackRestTestCommon_Run(++$iRun,
if (!testRun(++$iRun,
"rmt ${bRemote}, err ${bError}, mode ${bMode}")) {next}
# Setup test directory
BackRestTestFile_Setup($bError);
fileTestSetup($bError);
mkdir("${strTestPath}/backup") or confess 'Unable to create test/backup directory';
mkdir("${strTestPath}/backup/db") or confess 'Unable to create test/backup/db directory';
@@ -237,7 +236,7 @@ sub BackRestTestFile_Test
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'move')
{
$iRun = 0;
my $iRun = 0;
if (!$bVmOut)
{
@@ -271,13 +270,13 @@ sub BackRestTestFile_Test
for (my $bCreate = 0; $bCreate <= $bDestinationExists; $bCreate++)
{
# Increment the run, log, and decide whether this unit test should be run
if (!BackRestTestCommon_Run(++$iRun,
if (!testRun(++$iRun,
"src_exists ${bSourceExists}, src_error ${bSourceError}, " .
", dst_exists ${bDestinationExists}, dst_error ${bDestinationError}, " .
"dst_create ${bCreate}")) {next}
# Setup test directory
BackRestTestFile_Setup($bSourceError || $bDestinationError);
fileTestSetup($bSourceError || $bDestinationError);
my $strSourceFile = "${strTestPath}/test.txt";
my $strDestinationFile = "${strTestPath}/test-dest.txt";
@@ -338,7 +337,7 @@ sub BackRestTestFile_Test
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'compress')
{
$iRun = 0;
my $iRun = 0;
if (!$bVmOut)
{
@@ -361,11 +360,11 @@ sub BackRestTestFile_Test
{
for (my $bError = 0; $bError <= 1; $bError++)
{
if (!BackRestTestCommon_Run(++$iRun,
if (!testRun(++$iRun,
"rmt ${bRemote}, exists ${bExists}, err ${bError}")) {next}
# Setup test directory
BackRestTestFile_Setup($bError);
fileTestSetup($bError);
my $strFile = "${strTestPath}/test.txt";
my $strSourceHash;
@@ -432,7 +431,7 @@ sub BackRestTestFile_Test
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'wait')
{
$iRun = 0;
my $iRun = 0;
if (!$bVmOut)
{
@@ -452,7 +451,7 @@ sub BackRestTestFile_Test
my $lTimeBegin = gettimeofday();
if (!BackRestTestCommon_Run(++$iRun,
if (!testRun(++$iRun,
"rmt ${bRemote}, begin ${lTimeBegin}")) {next}
# If there is not enough time to complete the test then sleep
@@ -491,7 +490,7 @@ sub BackRestTestFile_Test
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'manifest')
{
$iRun = 0;
my $iRun = 0;
if (!$bVmOut)
{
@@ -525,11 +524,11 @@ sub BackRestTestFile_Test
{
for (my $bExists = 0; $bExists <= 1; $bExists++)
{
if (!BackRestTestCommon_Run(++$iRun,
if (!testRun(++$iRun,
"rmt ${bRemote}, exists ${bExists}, err ${bError}")) {next}
# Setup test directory
BackRestTestFile_Setup($bError);
fileTestSetup($bError);
# Setup test data
system("mkdir -m 750 ${strTestPath}/sub1") == 0 or confess 'Unable to create test directory';
@@ -647,7 +646,7 @@ sub BackRestTestFile_Test
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'list')
{
$iRun = 0;
my $iRun = 0;
if (!$bVmOut)
{
@@ -694,13 +693,13 @@ sub BackRestTestFile_Test
# Loop through error
for (my $bError = false; $bError <= true; $bError++)
{
if (!BackRestTestCommon_Run(++$iRun,
if (!testRun(++$iRun,
"rmt ${bRemote}, err ${bError}, exists ${bExists}, ignmis ${bIgnoreMissing}, " .
'expression ' . (defined($strExpression) ? $strExpression : '[undef]') . ', ' .
'sort ' . (defined($strSort) ? $strSort : '[undef]'))) {next}
# Setup test directory
BackRestTestFile_Setup($bError);
fileTestSetup($bError);
my $strPath = $strTestPath;
@@ -776,7 +775,7 @@ sub BackRestTestFile_Test
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'remove')
{
$iRun = 0;
my $iRun = 0;
if (!$bVmOut)
{
@@ -805,12 +804,12 @@ sub BackRestTestFile_Test
# Loop through ignore missing
for (my $bIgnoreMissing = 0; $bIgnoreMissing <= 1; $bIgnoreMissing++)
{
if (!BackRestTestCommon_Run(++$iRun,
if (!testRun(++$iRun,
"rmt ${bRemote}, err = ${bError}, exists ${bExists}, tmp ${bTemp}, " .
"ignore missing ${bIgnoreMissing}")) {next}
# Setup test directory
BackRestTestFile_Setup($bError);
fileTestSetup($bError);
my $strFile = "${strTestPath}/test.txt";
@@ -881,7 +880,7 @@ sub BackRestTestFile_Test
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'hash')
{
$iRun = 0;
my $iRun = 0;
if (!$bVmOut)
{
@@ -907,11 +906,11 @@ sub BackRestTestFile_Test
# Loop through exists
for (my $bCompressed = false; $bCompressed <= true; $bCompressed++)
{
if (!BackRestTestCommon_Run(++$iRun,
if (!testRun(++$iRun,
"rmt ${bRemote}, err ${bError}, exists ${bExists}, cmp ${bCompressed}")) {next}
# Setup test directory
BackRestTestFile_Setup($bError);
fileTestSetup($bError);
my $strFile = "${strTestPath}/test.txt";
@@ -974,7 +973,7 @@ sub BackRestTestFile_Test
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'exists')
{
$iRun = 0;
my $iRun = 0;
if (!$bVmOut)
{
@@ -997,11 +996,11 @@ sub BackRestTestFile_Test
# Loop through exists
for (my $bError = 0; $bError <= $bExists; $bError++)
{
if (!BackRestTestCommon_Run(++$iRun,
if (!testRun(++$iRun,
"rmt ${bRemote}, err ${bError}, exists ${bExists}")) {next}
# Setup test directory
BackRestTestFile_Setup($bError);
fileTestSetup($bError);
my $strFile = "${strTestPath}/test.txt";
@@ -1063,7 +1062,7 @@ sub BackRestTestFile_Test
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'copy')
{
$iRun = 0;
my $iRun = 0;
# Loop through small/large
for (my $iLarge = 0; $iLarge <= 3; $iLarge++)
@@ -1119,7 +1118,7 @@ sub BackRestTestFile_Test
my $strDestinationPathType = $bDestinationPathType ? PATH_DB_ABSOLUTE : PATH_BACKUP_ABSOLUTE;
my $strDestinationPath = $bDestinationPathType ? 'db' : 'backup';
if (!BackRestTestCommon_Run(++$iRun,
if (!testRun(++$iRun,
"lrg ${iLarge}, rmt " .
(defined($strRemote) && ($strRemote eq $strSourcePath ||
$strRemote eq $strDestinationPath) ? 1 : 0) .
@@ -1132,7 +1131,7 @@ sub BackRestTestFile_Test
"dstcmp $bDestinationCompress")) {next}
# Setup test directory
BackRestTestFile_Setup(false);
fileTestSetup(false);
system("mkdir ${strTestPath}/backup") == 0 or confess 'Unable to create test/backup directory';
system("mkdir ${strTestPath}/db") == 0 or confess 'Unable to create test/db directory';
@@ -1155,13 +1154,13 @@ sub BackRestTestFile_Test
if ($iLarge < 3)
{
executeTest('cp ' . BackRestTestCommon_DataPathGet() . "/test.archive${iLarge}.bin ${strSourceFile}");
executeTest('cp ' . testDataPath() . "/test.archive${iLarge}.bin ${strSourceFile}");
}
else
{
for (my $iTableSizeIdx = 0; $iTableSizeIdx < 100; $iTableSizeIdx++)
{
executeTest('cat ' . BackRestTestCommon_DataPathGet() . "/test.table.bin >> ${strSourceFile}");
executeTest('cat ' . testDataPath() . "/test.table.bin >> ${strSourceFile}");
}
}
}
@@ -1317,10 +1316,9 @@ sub BackRestTestFile_Test
}
}
if (BackRestTestCommon_Cleanup())
{
BackRestTestFile_Setup(undef, true);
}
testCleanup();
}
our @EXPORT = qw(fileTestRun);
1;
@@ -1,7 +1,7 @@
####################################################################################################################################
# HelpTest.pm - Unit Tests for help
####################################################################################################################################
package pgBackRestTest::HelpTest;
package pgBackRestTest::Help::HelpTest;
####################################################################################################################################
# Perl includes
@@ -11,31 +11,31 @@ use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
use File::Basename qw(dirname);
our @EXPORT = qw();
use lib dirname($0) . '/../lib';
use pgBackRest::Common::Log;
use pgBackRest::Config::Config;
use pgBackRestTest::Backup::Common::HostBackupTest;
use pgBackRestTest::Common::HostGroupTest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::CommonTest;
####################################################################################################################################
# BackRestTestHelp_ExecuteHelp
# helpExecute
####################################################################################################################################
sub BackRestTestHelp_ExecuteHelp
sub helpExecute
{
my $strCommand = shift;
executeTest(BackRestTestCommon_CommandMainAbsGet() . ' --no-config ' . $strCommand);
my $oHostGroup = hostGroupGet();
executeTest($oHostGroup->paramGet(HOST_PARAM_BACKREST_EXE) . ' --no-config ' . $strCommand);
}
####################################################################################################################################
# BackRestTestHelp_Test
# helpTestRun
####################################################################################################################################
our @EXPORT = qw(BackRestTestHelp_Test);
sub BackRestTestHelp_Test
sub helpTestRun
{
my $strTest = shift;
my $iThreadMax = shift;
@@ -65,26 +65,21 @@ sub BackRestTestHelp_Test
&log(INFO, "Test help\n");
}
BackRestTestCommon_Drop(true);
BackRestTestCommon_Create();
# Increment the run, log, and decide whether this unit test should be run
if (BackRestTestCommon_Run(++$iRun, 'base', $strModule, $strThisTest, undef, false))
if (testRun(++$iRun, 'base', $strModule, $strThisTest, undef, false))
{
BackRestTestHelp_ExecuteHelp('version');
BackRestTestHelp_ExecuteHelp('help');
BackRestTestHelp_ExecuteHelp('help version');
BackRestTestHelp_ExecuteHelp('help --output=json --stanza=main info');
BackRestTestHelp_ExecuteHelp('help --output=json --stanza=main info output');
helpExecute('version');
helpExecute('help');
helpExecute('help version');
helpExecute('help --output=json --stanza=main info');
helpExecute('help --output=json --stanza=main info output');
}
# Cleanup
if (BackRestTestCommon_Cleanup())
{
&log(INFO, 'cleanup');
BackRestTestCommon_Drop(true);
}
testCleanup();
}
}
push @EXPORT, qw(helpTestRun);
1;
-124
View File
@@ -1,124 +0,0 @@
####################################################################################################################################
# IniTest.pm - Unit Tests for ini load and save
####################################################################################################################################
package pgBackRestTest::IniTest;
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
use File::Basename qw(dirname);
use lib dirname($0) . '/../lib';
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Config::Config;
use pgBackRest::File;
use pgBackRestTest::CommonTest;
####################################################################################################################################
# BackRestTestIni_Test
####################################################################################################################################
our @EXPORT = qw(BackRestTestIni_Test);
sub BackRestTestIni_Test
{
my $strTest = shift;
# Setup test variables
my $iRun;
my $bCreate;
my $strTestPath = BackRestTestCommon_TestPathGet();
# Print test banner
&log(INFO, 'INI MODULE ******************************************************************');
#-------------------------------------------------------------------------------------------------------------------------------
# Create remote
#-------------------------------------------------------------------------------------------------------------------------------
my $oLocal = new pgBackRest::Protocol::Common
(
OPTION_DEFAULT_BUFFER_SIZE, # Buffer size
OPTION_DEFAULT_COMPRESS_LEVEL, # Compress level
OPTION_DEFAULT_COMPRESS_LEVEL_NETWORK # Compress network level
);
#-------------------------------------------------------------------------------------------------------------------------------
# Test config
#-------------------------------------------------------------------------------------------------------------------------------
if ($strTest eq 'all' || $strTest eq 'config')
{
$iRun = 0;
$bCreate = true;
my $oFile = new pgBackRest::File
(
undef,
undef,
undef,
$oLocal
);
&log(INFO, "Test config\n");
# Increment the run, log, and decide whether this unit test should be run
if (BackRestTestCommon_Run(++$iRun, 'base'))
{
# Create the test directory
if ($bCreate)
{
BackRestTestCommon_Drop();
BackRestTestCommon_Create();
$bCreate = false;
}
# Generate a test config
my %oConfig;
$oConfig{test1}{key1} = 'value';
$oConfig{test1}{key2} = 'value';
$oConfig{test2}{key1} = 'value';
$oConfig{test3}{key1} = 'value';
$oConfig{test3}{key2}{sub1} = 'value';
$oConfig{test3}{key2}{sub2} = 'value';
# Save the test config
my $strFile = "${strTestPath}/config.cfg";
iniSave($strFile, \%oConfig);
my $strConfigHash = $oFile->hash(PATH_ABSOLUTE, $strFile);
# Reload the test config
my %oConfigTest;
iniLoad($strFile, \%oConfigTest);
# Resave the test config and compare hashes
my $strFileTest = "${strTestPath}/config-test.cfg";
iniSave($strFileTest, \%oConfigTest);
my $strConfigTestHash = $oFile->hash(PATH_ABSOLUTE, $strFileTest);
if ($strConfigHash ne $strConfigTestHash)
{
confess "config hash ${strConfigHash} != ${strConfigTestHash}";
}
if (BackRestTestCommon_Cleanup())
{
&log(INFO, 'cleanup');
BackRestTestCommon_Drop();
}
}
}
}
1;