1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-01-18 04:58:51 +02:00

Created unit tests for files deleted by the db during backup.

This commit is contained in:
David Steele 2014-08-10 15:02:14 -04:00
parent 09e2351ae8
commit 0298e8dd16
7 changed files with 200 additions and 64 deletions

View File

@ -18,8 +18,6 @@ Put something here, there are people to recognize!
* Store actual backup begin and end times in backup.manifest
* Fix backup.manifest to not be a binary dump.
* Move backups to be removed to temp before deleting.
* Async archive-get.
@ -40,9 +38,10 @@ Put something here, there are people to recognize!
* File->wait() function. Waits for a file or directory to exist with configurable retry and timeout.
* Missing files during backup generate an ERROR in the log - the backup works but this message should probably be suppressed.
## required perl modules
* IPC::Run
* Net::OpenSSH
* Digest::SHA
* IO::Compress::Gzip
@ -50,7 +49,7 @@ Put something here, there are people to recognize!
* JSON
* Moose (Not using many features here, just use standard Perl object syntax?)
* IPC::System::Simple (only used in DB object - should convert to IPC::Run)
* IPC::System::Simple (only used in DB object - should convert this to DBD::Pg)
## release notes

View File

@ -644,12 +644,11 @@ if ($strOperation eq OP_EXPIRE)
}
remote_exit(0);
####################################################################################################################################
# START EVAL BLOCK TO CATCH ERRORS AND STOP THREADS
####################################################################################################################################
};
####################################################################################################################################
# CHECK FOR ERRORS AND STOP THREADS
####################################################################################################################################
if ($@)
{
remote_exit();

View File

@ -1231,10 +1231,6 @@ sub backup_file_thread
# If file is missing assume the database removed it (else corruption and nothing we can do!)
&log(INFO, "thread ${iThreadIdx} skipped file removed by database: " . $oFileCopyMap{$strFile}{db_file});
# Remove the destination file and the temp file just in case they had already been written
$oFileThread->file_remove(PATH_BACKUP_TMP, $oFileCopyMap{$strFile}{backup_file}, true);
$oFileThread->file_remove(PATH_BACKUP_TMP, $oFileCopyMap{$strFile}{backup_file});
# Write a message into the master queue to have the file removed from the manifest
$oMasterQueue[$iThreadIdx]->enqueue("remove|$oFileCopyMap{$strFile}{file_section}|$oFileCopyMap{$strFile}{file}");

View File

@ -1320,7 +1320,6 @@ sub copy
eval
{
$strOutput = $self->{oRemote}->output_read($strOperation eq OP_FILE_COPY, $strDebug);
};
# If there is an error then evaluate

View File

@ -20,7 +20,7 @@ use Exporter qw(import);
our @EXPORT = qw(version_get
data_hash_build trim common_prefix wait_for_file date_string_get file_size_format execute
log log_file_set log_level_set test_set
log log_file_set log_level_set test_set test_check
lock_file_create lock_file_remove
config_save config_load
TRACE DEBUG ERROR ASSERT WARN INFO OFF true false
@ -389,6 +389,17 @@ sub log_level_set
}
}
####################################################################################################################################
# TEST_CHECK - Check for a test message
####################################################################################################################################
sub test_check
{
my $strLog = shift;
my $strTest = shift;
return index($strLog, TEST_ENCLOSE . '-' . $strTest . '-' . TEST_ENCLOSE) != -1;
}
####################################################################################################################################
# LOG - log messages
####################################################################################################################################
@ -401,23 +412,25 @@ sub log
my $strMessageFormat = $strMessage;
my $iLogLevelRank = $oLogLevelRank{"${strLevel}"}{rank};
# If test message
if ($strLevel eq TEST)
{
$iLogLevelRank = $oLogLevelRank{TRACE}{rank} + 1;
$strMessageFormat = TEST_ENCLOSE . '-' . $strMessageFormat . '-' . TEST_ENCLOSE;
}
# Else level rank must be valid
elsif (!defined($iLogLevelRank))
{
confess &log(ASSERT, "log level ${strLevel} does not exist");
}
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
# If message was undefined then set default message
if (!defined($strMessageFormat))
{
$strMessageFormat = "(undefined)";
}
# Indent subsequent lines of the message if it has more than one line - makes the log more readable
if ($strLevel eq TRACE || $strLevel eq TEST)
{
$strMessageFormat =~ s/\n/\n /g;
@ -433,24 +446,29 @@ sub log
$strMessageFormat =~ s/\n/\n /g;
}
# Format the message text
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$strMessageFormat = sprintf("%4d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec) .
sprintf(" T%02d", threads->tid()) .
(" " x (7 - length($strLevel))) . "${strLevel}: ${strMessageFormat}" .
(defined($iCode) ? " (code ${iCode})" : "") . "\n";
# if ($strLevel eq TEST)
# {
# confess "log level rank $iLogLevelRank";
# }
# Output to console depending on log level and test flag
if ($iLogLevelRank <= $oLogLevelRank{"${strLogLevelConsole}"}{rank} ||
$bTest && $strLevel eq TEST)
{
print $strMessageFormat;
if ($bTest && $strLevel eq TEST)
{
*STDOUT->flush();
sleep($iTestDelay);
}
}
if ($iLogLevelRank <= $oLogLevelRank{"${strLogLevelFile}"}{rank} ||
$bTest && $strLevel eq TEST)
# Output to file depending on log level and test flag
if ($iLogLevelRank <= $oLogLevelRank{"${strLogLevelFile}"}{rank})
{
if (defined($hLogFile))
{
@ -458,16 +476,13 @@ sub log
}
}
# Throw a typed exception if code is defined
if (defined($iCode))
{
return BackRest::Exception->new(iCode => $iCode, strMessage => $strMessage);
}
if ($bTest && $strLevel eq TEST)
{
sleep($iTestDelay);
}
# Return the message test so it can be used in a confess
return $strMessage;
}

View File

@ -14,6 +14,7 @@ use Carp;
use File::Basename;
use File::Copy "cp";
use DBI;
use lib dirname($0) . "/../lib";
use BackRest::Utility;
@ -28,6 +29,56 @@ our @EXPORT = qw(BackRestTestBackup_Test);
my $strTestPath;
my $strHost;
my $strUserBackRest;
my $hDb;
####################################################################################################################################
# BackRestTestBackup_PgConnect
####################################################################################################################################
sub BackRestTestBackup_PgConnect
{
# Disconnect user session
BackRestTestBackup_PgDisconnect();
# Connect to the db (whether it is local or remote)
$hDb = DBI->connect('dbi:Pg:dbname=postgres;port=' . BackRestTestCommon_DbPortGet .
';host=' . BackRestTestCommon_DbPathGet(),
BackRestTestCommon_UserGet(),
undef,
{AutoCommit => 1, RaiseError => 1});
}
####################################################################################################################################
# BackRestTestBackup_Disconnect
####################################################################################################################################
sub BackRestTestBackup_PgDisconnect
{
# Connect to the db (whether it is local or remote)
if (defined($hDb))
{
$hDb->disconnect;
undef($hDb);
}
}
####################################################################################################################################
# BackRestTestBackup_PgExecute
####################################################################################################################################
sub BackRestTestBackup_PgExecute
{
my $strSql = shift;
my $bSwitchXlog = shift;
&log(DEBUG, "SQL: ${strSql}");
my $hStatement = $hDb->prepare($strSql);
$hStatement->execute() or
confess &log(ERROR, "Unable to execute: ${strSql}");
$hStatement->finish();
if (defined($bSwitchXlog) && $bSwitchXlog)
{
BackRestTestBackup_PgExecute('select pg_switch_xlog()');
}
}
####################################################################################################################################
# BackRestTestBackup_ClusterStop
@ -36,7 +87,10 @@ sub BackRestTestBackup_ClusterStop
{
my $strPath = shift;
# If the db directory already exists, stop the cluster and remove the directory
# Disconnect user session
BackRestTestBackup_PgDisconnect();
# If postmaster process is running them stop the cluster
if (-e $strPath . "/postmaster.pid")
{
BackRestTestCommon_Execute("pg_ctl stop -D $strPath -w -s -m fast");
@ -50,11 +104,17 @@ sub BackRestTestBackup_ClusterRestart
{
my $strPath = BackRestTestCommon_DbCommonPathGet();
# If the db directory already exists, stop the cluster and remove the directory
# Disconnect user session
BackRestTestBackup_PgDisconnect();
# If postmaster process is running them stop the cluster
if (-e $strPath . "/postmaster.pid")
{
BackRestTestCommon_Execute("pg_ctl restart -D $strPath -w -s");
}
# Connect user session
BackRestTestBackup_PgConnect();
}
####################################################################################################################################
@ -70,9 +130,12 @@ sub BackRestTestBackup_ClusterCreate
BackRestTestCommon_Execute("initdb -D $strPath -A trust");
BackRestTestCommon_Execute("pg_ctl start -o \"-c port=$iPort -c checkpoint_segments=1 " .
"-c wal_level=archive -c archive_mode=on -c archive_command='$strArchive'\" " .
# "-c unix_socket_directories='" . BackRestTestCommon_DbCommonPathGet() . "'\" " .
"-c wal_level=archive -c archive_mode=on -c archive_command='$strArchive' " .
"-c unix_socket_directories='" . BackRestTestCommon_DbPathGet() . "'\" " .
"-D $strPath -l $strPath/postgresql.log -w -s");
# Connect user session
BackRestTestBackup_PgConnect();
}
####################################################################################################################################
@ -156,15 +219,17 @@ sub BackRestTestBackup_Test
$strTest = 'all';
}
# Setup global variables
$strTestPath = BackRestTestCommon_TestPathGet();
$strHost = BackRestTestCommon_HostGet();
$strUserBackRest = BackRestTestCommon_UserBackRestGet();
# Setup test variables
my $iRun;
my $bCreate;
$strTestPath = BackRestTestCommon_TestPathGet();
my $strStanza = BackRestTestCommon_StanzaGet();
my $strUserBackRest = BackRestTestCommon_UserBackRestGet();
my $strGroup = BackRestTestCommon_GroupGet();
$strHost = BackRestTestCommon_HostGet();
$strUserBackRest = BackRestTestCommon_UserBackRestGet();
my $strArchiveChecksum = '1c7e00fd09b9dd11fc2966590b3e3274645dd031';
my $iArchiveMax = 3;
my $strXlogPath = BackRestTestCommon_DbCommonPathGet() . '/pg_xlog';
@ -494,20 +559,35 @@ sub BackRestTestBackup_Test
undef); # compress-async
}
# Create the backup command
my $strCommand = BackRestTestCommon_CommandMainGet() . ' --config=' .
($bRemote ? BackRestTestCommon_BackupPathGet() : BackRestTestCommon_DbPathGet()) .
"/pg_backrest.conf --test --type=incr --stanza=${strStanza} backup";
# Run the full/incremental tests
for (my $iFull = 1; $iFull <= 1; $iFull++)
{
&log(INFO, " full " . sprintf("%02d", $iFull));
my $strCommand = BackRestTestCommon_CommandMainGet() . ' --config=' .
($bRemote ? BackRestTestCommon_BackupPathGet() : BackRestTestCommon_DbPathGet()) .
"/pg_backrest.conf --test --type=incr --stanza=${strStanza} backup";
BackRestTestCommon_Execute($strCommand, $bRemote);
# exit 0;
for (my $iIncr = 1; $iIncr <= 1; $iIncr++)
for (my $iIncr = 0; $iIncr <= 1; $iIncr++)
{
&log(INFO, " incr " . sprintf("%02d", $iIncr));
&log(INFO, " " . ($iIncr == 0 ? "full " : " incr ") . sprintf("%02d", $iFull));
BackRestTestBackup_PgExecute('create table test (id int)');
BackRestTestCommon_ExecuteBegin($strCommand, $bRemote);
if (BackRestTestCommon_ExecuteEnd(TEST_MANIFEST_BUILD))
{
BackRestTestBackup_PgExecute('drop table test', true);
BackRestTestCommon_ExecuteEnd();
}
else
{
confess &log(ERROR, 'test point ' . TEST_MANIFEST_BUILD . ' was not found');
}
BackRestTestCommon_Execute($strCommand, $bRemote);
}

View File

@ -23,7 +23,8 @@ use BackRest::Utility;
use BackRest::File;
use Exporter qw(import);
our @EXPORT = qw(BackRestTestCommon_Setup BackRestTestCommon_Execute BackRestTestCommon_ExecuteBackRest
our @EXPORT = qw(BackRestTestCommon_Setup BackRestTestCommon_ExecuteBegin BackRestTestCommon_ExecuteEnd
BackRestTestCommon_Execute BackRestTestCommon_ExecuteBackRest
BackRestTestCommon_ConfigCreate BackRestTestCommon_Run BackRestTestCommon_Cleanup
BackRestTestCommon_StanzaGet BackRestTestCommon_CommandMainGet BackRestTestCommon_CommandRemoteGet
BackRestTestCommon_HostGet BackRestTestCommon_UserGet BackRestTestCommon_GroupGet
@ -50,6 +51,14 @@ my $iModuleTestRun;
my $bDryRun;
my $bNoCleanup;
# Execution globals
my $strErrorLog;
my $hError;
my $strOutLog;
my $hOut;
my $pId;
my $strCommand;
####################################################################################################################################
# BackRestTestBackup_Run
####################################################################################################################################
@ -82,32 +91,44 @@ sub BackRestTestCommon_Cleanup
}
####################################################################################################################################
# BackRestTestBackup_Execute
# BackRestTestBackup_ExecuteBegin
####################################################################################################################################
sub BackRestTestCommon_Execute
sub BackRestTestCommon_ExecuteBegin
{
my $strCommand = shift;
my $strCommandParam = shift;
my $bRemote = shift;
my $bSuppressError = shift;
# Set defaults
$bRemote = defined($bRemote) ? $bRemote : false;
$bSuppressError = defined($bSuppressError) ? $bSuppressError : false;
if ($bRemote)
{
$strCommand = "ssh ${strCommonUserBackRest}\@${strCommonHost} '${strCommand}'";
$strCommand = "ssh ${strCommonUserBackRest}\@${strCommonHost} '${strCommandParam}'";
}
else
{
$strCommand = $strCommandParam;
}
# Create error and out file handles and buffers
my $strErrorLog = '';
my $hError;
my $strOutLog = '';
my $hOut;
$strErrorLog = '';
$hError = undef;
$strOutLog = '';
$hOut = undef;
# Execute the command
my $pId = open3(undef, $hOut, $hError, $strCommand);
$pId = open3(undef, $hOut, $hError, $strCommand);
}
####################################################################################################################################
# BackRestTestBackup_ExecuteEnd
####################################################################################################################################
sub BackRestTestCommon_ExecuteEnd
{
my $strTest = shift;
my $bSuppressError = shift;
# Set defaults
$bSuppressError = defined($bSuppressError) ? $bSuppressError : false;
# Create select objects
my $oErrorSelect = IO::Select->new();
@ -133,6 +154,12 @@ sub BackRestTestCommon_Execute
while (my $strLine = readline($hOut))
{
$strOutLog .= $strLine;
if (defined($strTest) && test_check($strLine, $strTest))
{
&log(DEBUG, "Found test ${strTest}");
return true;
}
}
}
}
@ -146,6 +173,24 @@ sub BackRestTestCommon_Execute
($strOutLog ne '' ? "STDOUT:\n${strOutLog}" : '') .
($strErrorLog ne '' ? "STDERR:\n${strErrorLog}" : ''));
}
$hError = undef;
$hOut = undef;
return false;
}
####################################################################################################################################
# BackRestTestBackup_Execute
####################################################################################################################################
sub BackRestTestCommon_Execute
{
my $strCommand = shift;
my $bRemote = shift;
my $bSuppressError = shift;
BackRestTestCommon_ExecuteBegin($strCommand, $bRemote);
BackRestTestCommon_ExecuteEnd(undef, $bSuppressError);
}
####################################################################################################################################
@ -160,20 +205,23 @@ sub BackRestTestCommon_Setup
my $strBasePath = dirname(dirname(abs_path($0)));
$strCommonStanza = "db";
$strCommonCommandMain = "${strBasePath}/bin/pg_backrest.pl";
$strCommonCommandRemote = "${strBasePath}/bin/pg_backrest_remote.pl";
$strCommonCommandPsql = '/Library/PostgreSQL/9.3/bin/psql -X %option%';
# $strCommonCommandPsql = 'psql -X %option%';
$strCommonHost = '127.0.0.1';
$strCommonUser = getpwuid($<);
$strCommonGroup = getgrgid($();
$strCommonUserBackRest = 'backrest';
$strCommonTestPath = "${strBasePath}/test/test";
$strCommonDataPath = "${strBasePath}/test/data";
$strCommonBackupPath = "${strCommonTestPath}/backrest";
$strCommonArchivePath = "${strCommonTestPath}/archive";
$strCommonDbPath = "${strCommonTestPath}/db";
$strCommonDbCommonPath = "${strCommonTestPath}/db/common";
$strCommonCommandMain = "${strBasePath}/bin/pg_backrest.pl";
$strCommonCommandRemote = "${strBasePath}/bin/pg_backrest_remote.pl";
$strCommonCommandPsql = "/Library/PostgreSQL/9.3/bin/psql -X %option% -h ${strCommonDbPath}";
# $strCommonCommandPsql = 'psql -X %option%';
$iCommonDbPort = 6543;
$iModuleTestRun = $iModuleTestRunParam;
$bDryRun = $bDryRunParam;