You've already forked pgbackrest
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:
@@ -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;
|
||||
Executable
+2038
File diff suppressed because it is too large
Load Diff
+28
-29
@@ -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
+3
-17
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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]+$');
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
####################################################################################################################################
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
+68
-73
@@ -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;
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user