You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-11-06 08:49:29 +02:00
v0.30: core restructuring and unit tests
* Complete rewrite of BackRest::File module to use a custom protocol for remote operations and Perl native GZIP and SHA operations. Compression is performed in threads rather than forked processes. * Fairly comprehensive unit tests for all the basic operations. More work to be done here for sure, but then there is always more work to be done on unit tests. * Removed dependency on Storable and replaced with a custom ini file implementation. * Added much needed documentation (see INSTALL.md). * Numerous other changes that can only be identified with a diff.
This commit is contained in:
BIN
test/data/test.archive.bin
Normal file
BIN
test/data/test.archive.bin
Normal file
Binary file not shown.
630
test/lib/BackRestTest/BackupTest.pm
Executable file
630
test/lib/BackRestTest/BackupTest.pm
Executable file
@@ -0,0 +1,630 @@
|
||||
#!/usr/bin/perl
|
||||
####################################################################################################################################
|
||||
# BackupTest.pl - Unit Tests for BackRest::File
|
||||
####################################################################################################################################
|
||||
package BackRestTest::BackupTest;
|
||||
|
||||
####################################################################################################################################
|
||||
# Perl includes
|
||||
####################################################################################################################################
|
||||
use strict;
|
||||
use warnings;
|
||||
use Carp;
|
||||
|
||||
use File::Basename;
|
||||
use File::Copy 'cp';
|
||||
use DBI;
|
||||
|
||||
use lib dirname($0) . '/../lib';
|
||||
use BackRest::Utility;
|
||||
use BackRest::File;
|
||||
use BackRest::Remote;
|
||||
|
||||
use BackRestTest::CommonTest;
|
||||
|
||||
use Exporter qw(import);
|
||||
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 $bCheckpoint = shift;
|
||||
|
||||
# Log and execute the statement
|
||||
&log(DEBUG, "SQL: ${strSql}");
|
||||
my $hStatement = $hDb->prepare($strSql);
|
||||
|
||||
$hStatement->execute() or
|
||||
confess &log(ERROR, "Unable to execute: ${strSql}");
|
||||
|
||||
$hStatement->finish();
|
||||
|
||||
# Perform a checkpoint if requested
|
||||
if (defined($bCheckpoint) && $bCheckpoint)
|
||||
{
|
||||
BackRestTestBackup_PgExecute('checkpoint');
|
||||
}
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestBackup_ClusterStop
|
||||
####################################################################################################################################
|
||||
sub BackRestTestBackup_ClusterStop
|
||||
{
|
||||
my $strPath = shift;
|
||||
|
||||
# Disconnect user session
|
||||
BackRestTestBackup_PgDisconnect();
|
||||
|
||||
# If postmaster process is running them stop the cluster
|
||||
if (-e $strPath . '/postmaster.pid')
|
||||
{
|
||||
BackRestTestCommon_Execute(BackRestTestCommon_PgSqlBinPathGet() . "/pg_ctl stop -D ${strPath} -w -s -m fast");
|
||||
}
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestBackup_ClusterRestart
|
||||
####################################################################################################################################
|
||||
sub BackRestTestBackup_ClusterRestart
|
||||
{
|
||||
my $strPath = BackRestTestCommon_DbCommonPathGet();
|
||||
|
||||
# Disconnect user session
|
||||
BackRestTestBackup_PgDisconnect();
|
||||
|
||||
# If postmaster process is running them stop the cluster
|
||||
if (-e $strPath . '/postmaster.pid')
|
||||
{
|
||||
BackRestTestCommon_Execute(BackRestTestCommon_PgSqlBinPathGet() . "/pg_ctl restart -D ${strPath} -w -s");
|
||||
}
|
||||
|
||||
# Connect user session
|
||||
BackRestTestBackup_PgConnect();
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestBackup_ClusterCreate
|
||||
####################################################################################################################################
|
||||
sub BackRestTestBackup_ClusterCreate
|
||||
{
|
||||
my $strPath = shift;
|
||||
my $iPort = shift;
|
||||
|
||||
my $strArchive = BackRestTestCommon_CommandMainGet() . ' --stanza=' . BackRestTestCommon_StanzaGet() .
|
||||
' --config=' . BackRestTestCommon_DbPathGet() . '/pg_backrest.conf archive-push %p';
|
||||
|
||||
BackRestTestCommon_Execute(BackRestTestCommon_PgSqlBinPathGet() . "/initdb -D ${strPath} -A trust");
|
||||
BackRestTestCommon_Execute(BackRestTestCommon_PgSqlBinPathGet() . "/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_DbPathGet() . "'\" " .
|
||||
"-D ${strPath} -l ${strPath}/postgresql.log -w -s");
|
||||
|
||||
# Connect user session
|
||||
BackRestTestBackup_PgConnect();
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestBackup_Drop
|
||||
####################################################################################################################################
|
||||
sub BackRestTestBackup_Drop
|
||||
{
|
||||
# Stop the cluster if one is running
|
||||
BackRestTestBackup_ClusterStop(BackRestTestCommon_DbCommonPathGet());
|
||||
|
||||
# Remove the backrest private directory
|
||||
if (-e BackRestTestCommon_BackupPathGet())
|
||||
{
|
||||
BackRestTestCommon_Execute('rm -rf ' . BackRestTestCommon_BackupPathGet(), true, true);
|
||||
}
|
||||
|
||||
# Remove the test directory
|
||||
system('rm -rf ' . BackRestTestCommon_TestPathGet()) == 0
|
||||
or die 'unable to remove ' . BackRestTestCommon_TestPathGet() . 'path';
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestBackup_Create
|
||||
####################################################################################################################################
|
||||
sub BackRestTestBackup_Create
|
||||
{
|
||||
my $bRemote = shift;
|
||||
my $bCluster = shift;
|
||||
|
||||
# Set defaults
|
||||
$bRemote = defined($bRemote) ? $bRemote : false;
|
||||
$bCluster = defined($bCluster) ? $bCluster : true;
|
||||
|
||||
# Drop the old test directory
|
||||
BackRestTestBackup_Drop();
|
||||
|
||||
# Create the test directory
|
||||
mkdir(BackRestTestCommon_TestPathGet(), oct('0770'))
|
||||
or confess 'Unable to create ' . BackRestTestCommon_TestPathGet() . ' path';
|
||||
|
||||
# Create the db directory
|
||||
mkdir(BackRestTestCommon_DbPathGet(), oct('0700'))
|
||||
or confess 'Unable to create ' . BackRestTestCommon_DbPathGet() . ' path';
|
||||
|
||||
# Create the db/common directory
|
||||
mkdir(BackRestTestCommon_DbCommonPathGet())
|
||||
or confess 'Unable to create ' . BackRestTestCommon_DbCommonPathGet() . ' path';
|
||||
|
||||
# Create the archive directory
|
||||
mkdir(BackRestTestCommon_ArchivePathGet(), oct('0700'))
|
||||
or confess 'Unable to create ' . BackRestTestCommon_ArchivePathGet() . ' path';
|
||||
|
||||
# Create the backup directory
|
||||
if ($bRemote)
|
||||
{
|
||||
BackRestTestCommon_Execute('mkdir -m 700 ' . BackRestTestCommon_BackupPathGet(), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
mkdir(BackRestTestCommon_BackupPathGet(), oct('0700'))
|
||||
or confess 'Unable to create ' . BackRestTestCommon_BackupPathGet() . ' path';
|
||||
}
|
||||
|
||||
# Create the cluster
|
||||
if ($bCluster)
|
||||
{
|
||||
BackRestTestBackup_ClusterCreate(BackRestTestCommon_DbCommonPathGet(), BackRestTestCommon_DbPortGet());
|
||||
}
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestBackup_Test
|
||||
####################################################################################################################################
|
||||
sub BackRestTestBackup_Test
|
||||
{
|
||||
my $strTest = shift;
|
||||
|
||||
# If no test was specified, then run them all
|
||||
if (!defined($strTest))
|
||||
{
|
||||
$strTest = 'all';
|
||||
}
|
||||
|
||||
# Setup global variables
|
||||
$strTestPath = BackRestTestCommon_TestPathGet();
|
||||
$strHost = BackRestTestCommon_HostGet();
|
||||
$strUserBackRest = BackRestTestCommon_UserBackRestGet();
|
||||
|
||||
# Setup test variables
|
||||
my $iRun;
|
||||
my $bCreate;
|
||||
my $strStanza = BackRestTestCommon_StanzaGet();
|
||||
my $strGroup = BackRestTestCommon_GroupGet();
|
||||
|
||||
my $strArchiveChecksum = '1c7e00fd09b9dd11fc2966590b3e3274645dd031';
|
||||
my $iArchiveMax = 3;
|
||||
my $strXlogPath = BackRestTestCommon_DbCommonPathGet() . '/pg_xlog';
|
||||
my $strArchiveTestFile = BackRestTestCommon_DataPathGet() . '/test.archive.bin';
|
||||
my $iThreadMax = 4;
|
||||
|
||||
# Print test banner
|
||||
&log(INFO, 'BACKUP MODULE ******************************************************************');
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
# Create remote
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
my $oRemote = BackRest::Remote->new
|
||||
(
|
||||
strHost => $strHost,
|
||||
strUser => $strUserBackRest,
|
||||
strCommand => BackRestTestCommon_CommandRemoteGet()
|
||||
);
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
# Test archive-push
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
if ($strTest eq 'all' || $strTest eq 'archive-push')
|
||||
{
|
||||
$iRun = 0;
|
||||
$bCreate = true;
|
||||
my $oFile;
|
||||
|
||||
&log(INFO, "Test archive-push\n");
|
||||
|
||||
for (my $bRemote = false; $bRemote <= true; $bRemote++)
|
||||
{
|
||||
for (my $bCompress = false; $bCompress <= true; $bCompress++)
|
||||
{
|
||||
for (my $bChecksum = false; $bChecksum <= true; $bChecksum++)
|
||||
{
|
||||
for (my $bArchiveAsync = false; $bArchiveAsync <= $bRemote; $bArchiveAsync++)
|
||||
{
|
||||
for (my $bCompressAsync = false; $bCompressAsync <= true; $bCompressAsync++)
|
||||
{
|
||||
# Increment the run, log, and decide whether this unit test should be run
|
||||
if (!BackRestTestCommon_Run(++$iRun,
|
||||
"rmt ${bRemote}, cmp ${bCompress}, chk ${bChecksum}, " .
|
||||
"arc_async ${bArchiveAsync}, cmp_async ${bCompressAsync}")) {next}
|
||||
|
||||
# Create the test directory
|
||||
if ($bCreate)
|
||||
{
|
||||
# Create the file object
|
||||
$oFile = (BackRest::File->new
|
||||
(
|
||||
strStanza => $strStanza,
|
||||
strBackupPath => BackRestTestCommon_BackupPathGet(),
|
||||
strRemote => $bRemote ? 'backup' : undef,
|
||||
oRemote => $bRemote ? $oRemote : undef
|
||||
))->clone();
|
||||
|
||||
BackRestTestBackup_Create($bRemote, false);
|
||||
#
|
||||
# # Create the db/common/pg_xlog directory
|
||||
# mkdir($strXlogPath)
|
||||
# or confess 'Unable to create ${strXlogPath} path';
|
||||
|
||||
$bCreate = false;
|
||||
}
|
||||
|
||||
BackRestTestCommon_ConfigCreate('db',
|
||||
($bRemote ? REMOTE_BACKUP : undef),
|
||||
$bCompress,
|
||||
$bChecksum, # checksum
|
||||
undef, # hardlink
|
||||
undef, # thread-max
|
||||
$bArchiveAsync,
|
||||
$bCompressAsync);
|
||||
|
||||
my $strCommand = BackRestTestCommon_CommandMainGet() . ' --config=' . BackRestTestCommon_DbPathGet() .
|
||||
'/pg_backrest.conf --stanza=db archive-push';
|
||||
|
||||
# Loop through backups
|
||||
for (my $iBackup = 1; $iBackup <= 3; $iBackup++)
|
||||
{
|
||||
my $strArchiveFile;
|
||||
|
||||
# Loop through archive files
|
||||
for (my $iArchive = 1; $iArchive <= $iArchiveMax; $iArchive++)
|
||||
{
|
||||
# Construct the archive filename
|
||||
my $iArchiveNo = (($iBackup - 1) * $iArchiveMax + ($iArchive - 1)) + 1;
|
||||
|
||||
if ($iArchiveNo > 255)
|
||||
{
|
||||
confess 'backup total * archive total cannot be greater than 255';
|
||||
}
|
||||
|
||||
$strArchiveFile = uc(sprintf('0000000100000001%08x', $iArchiveNo));
|
||||
|
||||
&log(INFO, ' backup ' . sprintf('%02d', $iBackup) .
|
||||
', archive ' .sprintf('%02x', $iArchive) .
|
||||
" - ${strArchiveFile}");
|
||||
|
||||
my $strSourceFile = "${strXlogPath}/${strArchiveFile}";
|
||||
|
||||
$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
|
||||
|
||||
BackRestTestCommon_Execute($strCommand . " ${strSourceFile}");
|
||||
|
||||
# Build the archive name to check for at the destination
|
||||
my $strArchiveCheck = $strArchiveFile;
|
||||
|
||||
if ($bChecksum)
|
||||
{
|
||||
$strArchiveCheck .= "-${strArchiveChecksum}";
|
||||
}
|
||||
|
||||
if ($bCompress)
|
||||
{
|
||||
$strArchiveCheck .= '.gz';
|
||||
}
|
||||
|
||||
if (!$oFile->exists(PATH_BACKUP_ARCHIVE, $strArchiveCheck))
|
||||
{
|
||||
sleep(1);
|
||||
|
||||
if (!$oFile->exists(PATH_BACKUP_ARCHIVE, $strArchiveCheck))
|
||||
{
|
||||
confess 'unable to find ' . $oFile->path_get(PATH_BACKUP_ARCHIVE, $strArchiveCheck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# !!! Need to put in tests for .backup files here
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$bCreate = true;
|
||||
}
|
||||
|
||||
if (BackRestTestCommon_Cleanup())
|
||||
{
|
||||
&log(INFO, 'cleanup');
|
||||
BackRestTestBackup_Drop();
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
# Test archive-get
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
if ($strTest eq 'all' || $strTest eq 'archive-get')
|
||||
{
|
||||
$iRun = 0;
|
||||
$bCreate = true;
|
||||
my $oFile;
|
||||
|
||||
&log(INFO, "Test archive-get\n");
|
||||
|
||||
for (my $bRemote = false; $bRemote <= true; $bRemote++)
|
||||
{
|
||||
for (my $bCompress = false; $bCompress <= true; $bCompress++)
|
||||
{
|
||||
for (my $bChecksum = false; $bChecksum <= true; $bChecksum++)
|
||||
{
|
||||
for (my $bExists = false; $bExists <= true; $bExists++)
|
||||
{
|
||||
# Increment the run, log, and decide whether this unit test should be run
|
||||
if (!BackRestTestCommon_Run(++$iRun,
|
||||
"rmt ${bRemote}, cmp ${bCompress}, chk ${bChecksum}, exists ${bExists}")) {next}
|
||||
|
||||
# Create the test directory
|
||||
if ($bCreate)
|
||||
{
|
||||
# Create the file object
|
||||
$oFile = (BackRest::File->new
|
||||
(
|
||||
strStanza => $strStanza,
|
||||
strBackupPath => BackRestTestCommon_BackupPathGet(),
|
||||
strRemote => $bRemote ? 'backup' : undef,
|
||||
oRemote => $bRemote ? $oRemote : undef
|
||||
))->clone();
|
||||
|
||||
BackRestTestBackup_Create($bRemote, false);
|
||||
|
||||
# Create the db/common/pg_xlog directory
|
||||
mkdir($strXlogPath)
|
||||
or confess 'Unable to create ${strXlogPath} path';
|
||||
|
||||
$bCreate = false;
|
||||
}
|
||||
|
||||
BackRestTestCommon_ConfigCreate('db', # local
|
||||
($bRemote ? REMOTE_BACKUP : undef), # remote
|
||||
$bCompress, # compress
|
||||
$bChecksum, # checksum
|
||||
undef, # hardlink
|
||||
undef, # thread-max
|
||||
undef, # archive-async
|
||||
undef); # compress-async
|
||||
|
||||
my $strCommand = BackRestTestCommon_CommandMainGet() . ' --config=' . BackRestTestCommon_DbPathGet() .
|
||||
'/pg_backrest.conf --stanza=db archive-get';
|
||||
|
||||
if ($bExists)
|
||||
{
|
||||
# Loop through archive files
|
||||
my $strArchiveFile;
|
||||
|
||||
for (my $iArchiveNo = 1; $iArchiveNo <= $iArchiveMax; $iArchiveNo++)
|
||||
{
|
||||
# Construct the archive filename
|
||||
if ($iArchiveNo > 255)
|
||||
{
|
||||
confess 'backup total * archive total cannot be greater than 255';
|
||||
}
|
||||
|
||||
$strArchiveFile = uc(sprintf('0000000100000001%08x', $iArchiveNo));
|
||||
|
||||
&log(INFO, ' archive ' .sprintf('%02x', $iArchiveNo) .
|
||||
" - ${strArchiveFile}");
|
||||
|
||||
my $strSourceFile = $strArchiveFile;
|
||||
|
||||
if ($bChecksum)
|
||||
{
|
||||
$strSourceFile .= "-${strArchiveChecksum}";
|
||||
}
|
||||
|
||||
if ($bCompress)
|
||||
{
|
||||
$strSourceFile .= '.gz';
|
||||
}
|
||||
|
||||
$oFile->copy(PATH_DB_ABSOLUTE, $strArchiveTestFile, # Source file
|
||||
PATH_BACKUP_ARCHIVE, $strSourceFile, # Destination file
|
||||
false, # Source is not compressed
|
||||
$bCompress, # Destination compress based on test
|
||||
undef, undef, undef, # Unused params
|
||||
true); # Create path if it does not exist
|
||||
|
||||
my $strDestinationFile = "${strXlogPath}/${strArchiveFile}";
|
||||
|
||||
BackRestTestCommon_Execute($strCommand . " ${strArchiveFile} ${strDestinationFile}");
|
||||
|
||||
# Check that the destination file exists
|
||||
if ($oFile->exists(PATH_DB_ABSOLUTE, $strDestinationFile))
|
||||
{
|
||||
if ($oFile->hash(PATH_DB_ABSOLUTE, $strDestinationFile) ne $strArchiveChecksum)
|
||||
{
|
||||
confess "archive file hash does not match ${strArchiveChecksum}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
confess 'archive file is not in destination';
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BackRestTestCommon_Execute($strCommand . " 000000090000000900000009 ${strXlogPath}/RECOVERYXLOG",
|
||||
false, true) != 1)
|
||||
{
|
||||
confess 'archive-get should return 1 when archive log is not present';
|
||||
}
|
||||
}
|
||||
|
||||
$bCreate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BackRestTestCommon_Cleanup())
|
||||
{
|
||||
&log(INFO, 'cleanup');
|
||||
BackRestTestBackup_Drop();
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
# Test full
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
if ($strTest eq 'all' || $strTest eq 'full')
|
||||
{
|
||||
$iRun = 0;
|
||||
$bCreate = true;
|
||||
|
||||
&log(INFO, "Test Full Backup\n");
|
||||
|
||||
for (my $bRemote = false; $bRemote <= true; $bRemote++)
|
||||
{
|
||||
for (my $bLarge = false; $bLarge <= false; $bLarge++)
|
||||
{
|
||||
for (my $bCompress = false; $bCompress <= false; $bCompress++)
|
||||
{
|
||||
for (my $bChecksum = false; $bChecksum <= false; $bChecksum++)
|
||||
{
|
||||
for (my $bHardlink = false; $bHardlink <= true; $bHardlink++)
|
||||
{
|
||||
for (my $bArchiveAsync = false; $bArchiveAsync <= $bRemote; $bArchiveAsync++)
|
||||
{
|
||||
# Increment the run, log, and decide whether this unit test should be run
|
||||
if (!BackRestTestCommon_Run(++$iRun,
|
||||
"rmt ${bRemote}, lrg ${bLarge}, cmp ${bCompress}, chk ${bChecksum}, " .
|
||||
"hardlink ${bHardlink}, arc_async ${bArchiveAsync}")) {next}
|
||||
|
||||
# Create the test directory
|
||||
if ($bCreate)
|
||||
{
|
||||
BackRestTestBackup_Create($bRemote);
|
||||
$bCreate = false;
|
||||
}
|
||||
|
||||
# Create db config
|
||||
BackRestTestCommon_ConfigCreate('db', # local
|
||||
$bRemote ? REMOTE_BACKUP : undef, # remote
|
||||
$bCompress, # compress
|
||||
$bChecksum, # checksum
|
||||
defined($bRemote) ? undef : $bHardlink, # hardlink
|
||||
defined($bRemote) ? undef : $iThreadMax, # thread-max
|
||||
$bArchiveAsync, # archive-async
|
||||
undef); # compress-async
|
||||
|
||||
# Create backup config
|
||||
if ($bRemote)
|
||||
{
|
||||
BackRestTestCommon_ConfigCreate('backup', # local
|
||||
$bRemote ? REMOTE_DB : undef, # remote
|
||||
$bCompress, # compress
|
||||
$bChecksum, # checksum
|
||||
$bHardlink, # hardlink
|
||||
$iThreadMax, # thread-max
|
||||
undef, # archive-async
|
||||
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++)
|
||||
{
|
||||
|
||||
for (my $iIncr = 0; $iIncr <= 2; $iIncr++)
|
||||
{
|
||||
&log(INFO, ' ' . ($iIncr == 0 ? ('full ' . sprintf('%02d', $iFull)) :
|
||||
(' incr ' . sprintf('%02d', $iIncr))));
|
||||
|
||||
# Create a table in each backup to check references
|
||||
BackRestTestBackup_PgExecute("create table test_backup_${iIncr} (id int)", true);
|
||||
|
||||
# Create a table to be dropped to test missing file code
|
||||
BackRestTestBackup_PgExecute('create table test_drop (id int)');
|
||||
|
||||
BackRestTestCommon_ExecuteBegin($strCommand, $bRemote);
|
||||
|
||||
if (BackRestTestCommon_ExecuteEnd(TEST_MANIFEST_BUILD))
|
||||
{
|
||||
BackRestTestBackup_PgExecute('drop table test_drop', true);
|
||||
|
||||
BackRestTestCommon_ExecuteEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
confess &log(ERROR, 'test point ' . TEST_MANIFEST_BUILD . ' was not found');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$bCreate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BackRestTestCommon_Cleanup())
|
||||
{
|
||||
&log(INFO, 'cleanup');
|
||||
BackRestTestBackup_Drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
436
test/lib/BackRestTest/CommonTest.pm
Executable file
436
test/lib/BackRestTest/CommonTest.pm
Executable file
@@ -0,0 +1,436 @@
|
||||
#!/usr/bin/perl
|
||||
####################################################################################################################################
|
||||
# CommonTest.pm - Common globals used for testing
|
||||
####################################################################################################################################
|
||||
package BackRestTest::CommonTest;
|
||||
|
||||
####################################################################################################################################
|
||||
# Perl includes
|
||||
####################################################################################################################################
|
||||
use strict;
|
||||
use warnings;
|
||||
use Carp;
|
||||
|
||||
use File::Basename;
|
||||
use Cwd 'abs_path';
|
||||
use IPC::Open3;
|
||||
use POSIX ':sys_wait_h';
|
||||
use IO::Select;
|
||||
|
||||
use lib dirname($0) . '/../lib';
|
||||
use BackRest::Utility;
|
||||
use BackRest::File;
|
||||
|
||||
use Exporter qw(import);
|
||||
our @EXPORT = qw(BackRestTestCommon_Setup BackRestTestCommon_ExecuteBegin BackRestTestCommon_ExecuteEnd
|
||||
BackRestTestCommon_Execute BackRestTestCommon_ExecuteBackRest
|
||||
BackRestTestCommon_ConfigCreate 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_BackupPathGet BackRestTestCommon_ArchivePathGet
|
||||
BackRestTestCommon_DbPathGet BackRestTestCommon_DbCommonPathGet BackRestTestCommon_DbPortGet);
|
||||
|
||||
my $strPgSqlBin;
|
||||
my $strCommonStanza;
|
||||
my $strCommonCommandMain;
|
||||
my $strCommonCommandRemote;
|
||||
my $strCommonCommandPsql;
|
||||
my $strCommonHost;
|
||||
my $strCommonUser;
|
||||
my $strCommonGroup;
|
||||
my $strCommonUserBackRest;
|
||||
my $strCommonTestPath;
|
||||
my $strCommonDataPath;
|
||||
my $strCommonBackupPath;
|
||||
my $strCommonArchivePath;
|
||||
my $strCommonDbPath;
|
||||
my $strCommonDbCommonPath;
|
||||
my $iCommonDbPort;
|
||||
my $iModuleTestRun;
|
||||
my $bDryRun;
|
||||
my $bNoCleanup;
|
||||
|
||||
# Execution globals
|
||||
my $strErrorLog;
|
||||
my $hError;
|
||||
my $strOutLog;
|
||||
my $hOut;
|
||||
my $pId;
|
||||
my $strCommand;
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestBackup_Run
|
||||
####################################################################################################################################
|
||||
sub BackRestTestCommon_Run
|
||||
{
|
||||
my $iRun = shift;
|
||||
my $strLog = shift;
|
||||
|
||||
if (defined($iModuleTestRun) && $iModuleTestRun != $iRun)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
&log(INFO, 'run ' . sprintf('%03d', $iRun) . ' - ' . $strLog);
|
||||
|
||||
if ($bDryRun)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestBackup_Cleanup
|
||||
####################################################################################################################################
|
||||
sub BackRestTestCommon_Cleanup
|
||||
{
|
||||
return !$bNoCleanup && !$bDryRun;
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestBackup_ExecuteBegin
|
||||
####################################################################################################################################
|
||||
sub BackRestTestCommon_ExecuteBegin
|
||||
{
|
||||
my $strCommandParam = shift;
|
||||
my $bRemote = shift;
|
||||
|
||||
# Set defaults
|
||||
$bRemote = defined($bRemote) ? $bRemote : false;
|
||||
|
||||
if ($bRemote)
|
||||
{
|
||||
$strCommand = "ssh ${strCommonUserBackRest}\@${strCommonHost} '${strCommandParam}'";
|
||||
}
|
||||
else
|
||||
{
|
||||
$strCommand = $strCommandParam;
|
||||
}
|
||||
|
||||
$strErrorLog = '';
|
||||
$hError = undef;
|
||||
$strOutLog = '';
|
||||
$hOut = undef;
|
||||
|
||||
&log(DEBUG, "executing command: ${strCommand}");
|
||||
|
||||
# Execute the command
|
||||
$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();
|
||||
$oErrorSelect->add($hError);
|
||||
my $oOutSelect = IO::Select->new();
|
||||
$oOutSelect->add($hOut);
|
||||
|
||||
# While the process is running drain the stdout and stderr streams
|
||||
while(waitpid($pId, WNOHANG) == 0)
|
||||
{
|
||||
# Drain the stderr stream
|
||||
if ($oErrorSelect->can_read(.1))
|
||||
{
|
||||
while (my $strLine = readline($hError))
|
||||
{
|
||||
$strErrorLog .= $strLine;
|
||||
}
|
||||
}
|
||||
|
||||
# Drain the stdout stream
|
||||
if ($oOutSelect->can_read(.1))
|
||||
{
|
||||
while (my $strLine = readline($hOut))
|
||||
{
|
||||
$strOutLog .= $strLine;
|
||||
|
||||
if (defined($strTest) && test_check($strLine, $strTest))
|
||||
{
|
||||
&log(DEBUG, "Found test ${strTest}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Check the exit status and output an error if needed
|
||||
my $iExitStatus = ${^CHILD_ERROR_NATIVE} >> 8;
|
||||
|
||||
if ($iExitStatus != 0 && !$bSuppressError)
|
||||
{
|
||||
confess &log(ERROR, "command '${strCommand}' returned " . $iExitStatus . "\n" .
|
||||
($strOutLog ne '' ? "STDOUT:\n${strOutLog}" : '') .
|
||||
($strErrorLog ne '' ? "STDERR:\n${strErrorLog}" : ''));
|
||||
}
|
||||
else
|
||||
{
|
||||
&log(DEBUG, "suppressed error was ${iExitStatus}");
|
||||
}
|
||||
|
||||
$hError = undef;
|
||||
$hOut = undef;
|
||||
|
||||
return $iExitStatus;
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestBackup_Execute
|
||||
####################################################################################################################################
|
||||
sub BackRestTestCommon_Execute
|
||||
{
|
||||
my $strCommand = shift;
|
||||
my $bRemote = shift;
|
||||
my $bSuppressError = shift;
|
||||
|
||||
BackRestTestCommon_ExecuteBegin($strCommand, $bRemote);
|
||||
return BackRestTestCommon_ExecuteEnd(undef, $bSuppressError);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestCommon_Setup
|
||||
####################################################################################################################################
|
||||
sub BackRestTestCommon_Setup
|
||||
{
|
||||
my $strTestPathParam = shift;
|
||||
my $strPgSqlBinParam = shift;
|
||||
my $iModuleTestRunParam = shift;
|
||||
my $bDryRunParam = shift;
|
||||
my $bNoCleanupParam = shift;
|
||||
|
||||
my $strBasePath = dirname(dirname(abs_path($0)));
|
||||
|
||||
$strPgSqlBin = $strPgSqlBinParam;
|
||||
|
||||
$strCommonStanza = 'db';
|
||||
$strCommonHost = '127.0.0.1';
|
||||
$strCommonUser = getpwuid($<);
|
||||
$strCommonGroup = getgrgid($();
|
||||
$strCommonUserBackRest = 'backrest';
|
||||
|
||||
if (defined($strTestPathParam))
|
||||
{
|
||||
$strCommonTestPath = $strTestPathParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
$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 = "${strPgSqlBin}/psql -X %option% -h ${strCommonDbPath}";
|
||||
|
||||
$iCommonDbPort = 6543;
|
||||
$iModuleTestRun = $iModuleTestRunParam;
|
||||
$bDryRun = $bDryRunParam;
|
||||
$bNoCleanup = $bNoCleanupParam;
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestCommon_ConfigCreate
|
||||
####################################################################################################################################
|
||||
sub BackRestTestCommon_ConfigCreate
|
||||
{
|
||||
my $strLocal = shift;
|
||||
my $strRemote = shift;
|
||||
my $bCompress = shift;
|
||||
my $bChecksum = shift;
|
||||
my $bHardlink = shift;
|
||||
my $iThreadMax = shift;
|
||||
my $bArchiveLocal = shift;
|
||||
my $bCompressAsync = shift;
|
||||
|
||||
my %oParamHash;
|
||||
|
||||
if (defined($strRemote))
|
||||
{
|
||||
$oParamHash{'global:command'}{'remote'} = $strCommonCommandRemote;
|
||||
}
|
||||
|
||||
$oParamHash{'global:command'}{'psql'} = $strCommonCommandPsql;
|
||||
|
||||
if (defined($strRemote) && $strRemote eq REMOTE_BACKUP)
|
||||
{
|
||||
$oParamHash{'global:backup'}{'host'} = $strCommonHost;
|
||||
$oParamHash{'global:backup'}{'user'} = $strCommonUserBackRest;
|
||||
}
|
||||
elsif (defined($strRemote) && $strRemote eq REMOTE_DB)
|
||||
{
|
||||
$oParamHash{$strCommonStanza}{'host'} = $strCommonHost;
|
||||
$oParamHash{$strCommonStanza}{'user'} = $strCommonUser;
|
||||
}
|
||||
|
||||
$oParamHash{'global:log'}{'level-console'} = 'error';
|
||||
$oParamHash{'global:log'}{'level-file'} = 'trace';
|
||||
|
||||
if ($strLocal eq REMOTE_BACKUP)
|
||||
{
|
||||
if (defined($bHardlink) && $bHardlink)
|
||||
{
|
||||
$oParamHash{'global:backup'}{'hardlink'} = 'y';
|
||||
}
|
||||
}
|
||||
elsif ($strLocal eq REMOTE_DB)
|
||||
{
|
||||
if (defined($strRemote))
|
||||
{
|
||||
$oParamHash{'global:log'}{'level-console'} = 'trace';
|
||||
}
|
||||
|
||||
if ($bArchiveLocal)
|
||||
{
|
||||
$oParamHash{'global:archive'}{path} = BackRestTestCommon_ArchivePathGet();
|
||||
|
||||
if (!$bCompressAsync)
|
||||
{
|
||||
$oParamHash{'global:archive'}{'compress_async'} = 'n';
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
confess "invalid local type ${strLocal}";
|
||||
}
|
||||
|
||||
if (($strLocal eq REMOTE_BACKUP) || ($strLocal eq REMOTE_DB && !defined($strRemote)))
|
||||
{
|
||||
$oParamHash{'db:command:option'}{'psql'} = "--port=${iCommonDbPort}";
|
||||
}
|
||||
|
||||
if (defined($bCompress) && !$bCompress)
|
||||
{
|
||||
$oParamHash{'global:backup'}{'compress'} = 'n';
|
||||
}
|
||||
|
||||
if (defined($bChecksum) && !$bChecksum)
|
||||
{
|
||||
$oParamHash{'global:backup'}{'checksum'} = 'n';
|
||||
}
|
||||
|
||||
$oParamHash{$strCommonStanza}{'path'} = $strCommonDbCommonPath;
|
||||
$oParamHash{'global:backup'}{'path'} = $strCommonBackupPath;
|
||||
|
||||
if (defined($iThreadMax))
|
||||
{
|
||||
$oParamHash{'global:backup'}{'thread-max'} = $iThreadMax;
|
||||
}
|
||||
|
||||
# Write out the configuration file
|
||||
my $strFile = BackRestTestCommon_TestPathGet() . '/pg_backrest.conf';
|
||||
config_save($strFile, \%oParamHash);
|
||||
|
||||
# Move the configuration file based on local
|
||||
if ($strLocal eq 'db')
|
||||
{
|
||||
rename($strFile, BackRestTestCommon_DbPathGet() . '/pg_backrest.conf')
|
||||
or die "unable to move ${strFile} to " . BackRestTestCommon_DbPathGet() . '/pg_backrest.conf path';
|
||||
}
|
||||
elsif ($strLocal eq 'backup' && !defined($strRemote))
|
||||
{
|
||||
rename($strFile, BackRestTestCommon_BackupPathGet() . '/pg_backrest.conf')
|
||||
or die "unable to move ${strFile} to " . BackRestTestCommon_BackupPathGet() . '/pg_backrest.conf path';
|
||||
}
|
||||
else
|
||||
{
|
||||
BackRestTestCommon_Execute("mv ${strFile} " . BackRestTestCommon_BackupPathGet() . '/pg_backrest.conf', true);
|
||||
}
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Get Methods
|
||||
####################################################################################################################################
|
||||
sub BackRestTestCommon_PgSqlBinPathGet
|
||||
{
|
||||
return $strPgSqlBin;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_StanzaGet
|
||||
{
|
||||
return $strCommonStanza;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_CommandMainGet
|
||||
{
|
||||
return $strCommonCommandMain;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_CommandRemoteGet
|
||||
{
|
||||
return $strCommonCommandRemote;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_HostGet
|
||||
{
|
||||
return $strCommonHost;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_UserGet
|
||||
{
|
||||
return $strCommonUser;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_GroupGet
|
||||
{
|
||||
return $strCommonGroup;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_UserBackRestGet
|
||||
{
|
||||
return $strCommonUserBackRest;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_TestPathGet
|
||||
{
|
||||
return $strCommonTestPath;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_DataPathGet
|
||||
{
|
||||
return $strCommonDataPath;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_BackupPathGet
|
||||
{
|
||||
return $strCommonBackupPath;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_ArchivePathGet
|
||||
{
|
||||
return $strCommonArchivePath;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_DbPathGet
|
||||
{
|
||||
return $strCommonDbPath;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_DbCommonPathGet
|
||||
{
|
||||
return $strCommonDbCommonPath;
|
||||
}
|
||||
|
||||
sub BackRestTestCommon_DbPortGet
|
||||
{
|
||||
return $iCommonDbPort;
|
||||
}
|
||||
|
||||
1;
|
||||
1150
test/lib/BackRestTest/FileTest.pm
Executable file
1150
test/lib/BackRestTest/FileTest.pm
Executable file
File diff suppressed because it is too large
Load Diff
128
test/lib/BackRestTest/UtilityTest.pm
Executable file
128
test/lib/BackRestTest/UtilityTest.pm
Executable file
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/perl
|
||||
####################################################################################################################################
|
||||
# BackupTest.pl - Unit Tests for BackRest::File
|
||||
####################################################################################################################################
|
||||
package BackRestTest::UtilityTest;
|
||||
|
||||
####################################################################################################################################
|
||||
# Perl includes
|
||||
####################################################################################################################################
|
||||
use strict;
|
||||
use warnings;
|
||||
use Carp;
|
||||
|
||||
use File::Basename;
|
||||
|
||||
use lib dirname($0) . '/../lib';
|
||||
use BackRest::Utility;
|
||||
use BackRest::File;
|
||||
|
||||
use BackRestTest::CommonTest;
|
||||
|
||||
use Exporter qw(import);
|
||||
our @EXPORT = qw(BackRestTestUtility_Test);
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestUtility_Drop
|
||||
####################################################################################################################################
|
||||
sub BackRestTestUtility_Drop
|
||||
{
|
||||
# Remove the test directory
|
||||
system('rm -rf ' . BackRestTestCommon_TestPathGet()) == 0
|
||||
or die 'unable to remove ' . BackRestTestCommon_TestPathGet() . 'path';
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestUtility_Create
|
||||
####################################################################################################################################
|
||||
sub BackRestTestUtility_Create
|
||||
{
|
||||
# Drop the old test directory
|
||||
BackRestTestUtility_Drop();
|
||||
|
||||
# Create the test directory
|
||||
mkdir(BackRestTestCommon_TestPathGet(), oct('0770'))
|
||||
or confess 'Unable to create ' . BackRestTestCommon_TestPathGet() . ' path';
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# BackRestTestUtility_Test
|
||||
####################################################################################################################################
|
||||
sub BackRestTestUtility_Test
|
||||
{
|
||||
my $strTest = shift;
|
||||
|
||||
# Setup test variables
|
||||
my $iRun;
|
||||
my $bCreate;
|
||||
my $strTestPath = BackRestTestCommon_TestPathGet();
|
||||
|
||||
# Print test banner
|
||||
&log(INFO, 'UTILITY MODULE ******************************************************************');
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
# Test config
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
if ($strTest eq 'all' || $strTest eq 'config')
|
||||
{
|
||||
$iRun = 0;
|
||||
$bCreate = true;
|
||||
my $oFile = BackRest::File->new();
|
||||
|
||||
&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)
|
||||
{
|
||||
BackRestTestUtility_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";
|
||||
config_save($strFile, \%oConfig);
|
||||
|
||||
my $strConfigHash = $oFile->hash(PATH_ABSOLUTE, $strFile);
|
||||
|
||||
# Reload the test config
|
||||
my %oConfigTest;
|
||||
|
||||
config_load($strFile, \%oConfigTest);
|
||||
|
||||
# Resave the test config and compare hashes
|
||||
my $strFileTest = "${strTestPath}/config-test.cfg";
|
||||
config_save($strFileTest, \%oConfigTest);
|
||||
|
||||
my $strConfigTestHash = $oFile->hash(PATH_ABSOLUTE, $strFileTest);
|
||||
|
||||
if ($strConfigHash ne $strConfigTestHash)
|
||||
{
|
||||
confess "config hash ${strConfigHash} != ${strConfigTestHash}";
|
||||
}
|
||||
|
||||
if (BackRestTestCommon_Cleanup())
|
||||
{
|
||||
&log(INFO, 'cleanup');
|
||||
BackRestTestUtility_Drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
330
test/test.pl
330
test/test.pl
@@ -1,244 +1,148 @@
|
||||
#!/usr/bin/perl
|
||||
####################################################################################################################################
|
||||
# test.pl - BackRest Unit Tests
|
||||
####################################################################################################################################
|
||||
|
||||
# /Library/PostgreSQL/9.3/bin/pg_ctl start -o "-c port=7000" -D /Users/backrest/test/backup/db/20140205-103801F/base -l /Users/backrest/test/backup/db/20140205-103801F/base/postgresql.log -w -s
|
||||
####################################################################################################################################
|
||||
# Perl includes
|
||||
####################################################################################################################################
|
||||
use strict;
|
||||
use warnings;
|
||||
use Carp;
|
||||
|
||||
#use strict;
|
||||
use DBI;
|
||||
use IPC::System::Simple qw(capture);
|
||||
use Config::IniFiles;
|
||||
use File::Find;
|
||||
use File::Basename;
|
||||
use Getopt::Long;
|
||||
use Cwd 'abs_path';
|
||||
use Cwd;
|
||||
|
||||
sub trim
|
||||
use lib dirname($0) . '/../lib';
|
||||
use BackRest::Utility;
|
||||
|
||||
use lib dirname($0) . '/lib';
|
||||
use BackRestTest::CommonTest;
|
||||
use BackRestTest::UtilityTest;
|
||||
use BackRestTest::FileTest;
|
||||
use BackRestTest::BackupTest;
|
||||
|
||||
####################################################################################################################################
|
||||
# Command line parameters
|
||||
####################################################################################################################################
|
||||
my $strLogLevel = 'off'; # Log level for tests
|
||||
my $strModule = 'all';
|
||||
my $strModuleTest = 'all';
|
||||
my $iModuleTestRun = undef;
|
||||
my $bDryRun = false;
|
||||
my $bNoCleanup = false;
|
||||
my $strPgSqlBin;
|
||||
my $strTestPath;
|
||||
|
||||
GetOptions ('pgsql-bin=s' => \$strPgSqlBin,
|
||||
'test-path=s' => \$strTestPath,
|
||||
'log-level=s' => \$strLogLevel,
|
||||
'module=s' => \$strModule,
|
||||
'module-test=s' => \$strModuleTest,
|
||||
'module-test-run=s' => \$iModuleTestRun,
|
||||
'dry-run' => \$bDryRun,
|
||||
'no-cleanup' => \$bNoCleanup)
|
||||
or die 'error in command line arguments';
|
||||
|
||||
####################################################################################################################################
|
||||
# Setup
|
||||
####################################################################################################################################
|
||||
# Set a neutral umask so tests work as expected
|
||||
umask(0);
|
||||
|
||||
# Set console log level to trace for testing
|
||||
log_level_set(undef, uc($strLogLevel));
|
||||
|
||||
if ($strModuleTest ne 'all' && $strModule eq 'all')
|
||||
{
|
||||
local($strBuffer) = @_;
|
||||
|
||||
$strBuffer =~ s/^\s+|\s+$//g;
|
||||
|
||||
return $strBuffer;
|
||||
confess "--module must be provided for test \"${strModuleTest}\"";
|
||||
}
|
||||
|
||||
sub execute
|
||||
if (defined($iModuleTestRun) && $strModuleTest eq 'all')
|
||||
{
|
||||
local($strCommand) = @_;
|
||||
my $strOutput;
|
||||
confess "--module-test must be provided for run \"${iModuleTestRun}\"";
|
||||
}
|
||||
|
||||
print("$strCommand");
|
||||
$strOutput = trim(capture($strCommand));
|
||||
# Make sure PG bin has been defined
|
||||
if (!defined($strPgSqlBin))
|
||||
{
|
||||
confess 'pgsql-bin was not defined';
|
||||
}
|
||||
|
||||
if ($strOutput eq "")
|
||||
{
|
||||
print(" ... complete\n\n");
|
||||
}
|
||||
else
|
||||
####################################################################################################################################
|
||||
# Make sure version number matches in README.md and VERSION
|
||||
####################################################################################################################################
|
||||
my $hReadMe;
|
||||
my $strLine;
|
||||
my $bMatch = false;
|
||||
my $strVersion = version_get();
|
||||
|
||||
if (!open($hReadMe, '<', dirname($0) . '/../README.md'))
|
||||
{
|
||||
confess 'unable to open README.md';
|
||||
}
|
||||
|
||||
while ($strLine = readline($hReadMe))
|
||||
{
|
||||
if ($strLine =~ /^\#\#\# v/)
|
||||
{
|
||||
print(" ... complete\n$strOutput\n\n");
|
||||
$bMatch = substr($strLine, 5, length($strVersion)) eq $strVersion;
|
||||
last;
|
||||
}
|
||||
|
||||
return $strOutput;
|
||||
}
|
||||
|
||||
sub pg_create
|
||||
if (!$bMatch)
|
||||
{
|
||||
local($strPgBinPath, $strTestPath, $strTestDir, $strArchiveDir, $strBackupDir) = @_;
|
||||
|
||||
execute("mkdir $strTestPath");
|
||||
execute("mkdir $strTestPath/$strTestDir");
|
||||
execute("mkdir $strTestPath/$strTestDir/ts1");
|
||||
execute("mkdir $strTestPath/$strTestDir/ts2");
|
||||
execute($strPgBinPath . "/initdb -D $strTestPath/$strTestDir/common -A trust -k");
|
||||
execute("mkdir $strTestPath/$strBackupDir");
|
||||
# execute("mkdir -p $strTestPath/$strArchiveDir");
|
||||
confess "unable to find version ${strVersion} as last revision in README.md";
|
||||
}
|
||||
|
||||
sub pg_start
|
||||
####################################################################################################################################
|
||||
# Clean whitespace only if test.pl is being run from the test directory in the backrest repo
|
||||
####################################################################################################################################
|
||||
my $hVersion;
|
||||
|
||||
if (-e './test.pl' && -e '../bin/pg_backrest.pl' && open($hVersion, '<', '../VERSION'))
|
||||
{
|
||||
local($strPgBinPath, $strDbPath, $strPort, $strAchiveCommand) = @_;
|
||||
my $strCommand = "$strPgBinPath/pg_ctl start -o \"-c port=$strPort -c checkpoint_segments=1 -c wal_level=archive -c archive_mode=on -c archive_command=\'$strAchiveCommand\'\" -D $strDbPath -l $strDbPath/postgresql.log -w -s";
|
||||
|
||||
execute($strCommand);
|
||||
}
|
||||
my $strTestVersion = readline($hVersion);
|
||||
|
||||
sub pg_password_set
|
||||
{
|
||||
local($strPgBinPath, $strPath, $strUser, $strPort) = @_;
|
||||
my $strCommand = "$strPgBinPath/psql --port=$strPort -c \"alter user $strUser with password 'password'\" postgres";
|
||||
|
||||
execute($strCommand);
|
||||
}
|
||||
|
||||
sub pg_stop
|
||||
{
|
||||
local($strPgBinPath, $strPath) = @_;
|
||||
my $strCommand = "$strPgBinPath/pg_ctl stop -D $strPath -w -s -m fast";
|
||||
|
||||
execute($strCommand);
|
||||
}
|
||||
|
||||
sub pg_drop
|
||||
{
|
||||
local($strTestPath) = @_;
|
||||
my $strCommand = "rm -rf $strTestPath";
|
||||
|
||||
execute($strCommand);
|
||||
}
|
||||
|
||||
sub pg_execute
|
||||
{
|
||||
local($dbh, $strSql) = @_;
|
||||
|
||||
print($strSql);
|
||||
$sth = $dbh->prepare($strSql);
|
||||
$sth->execute() or die;
|
||||
$sth->finish();
|
||||
|
||||
print(" ... complete\n\n");
|
||||
}
|
||||
|
||||
sub archive_command_build
|
||||
{
|
||||
my $strBackRestBinPath = shift;
|
||||
my $strDestinationPath = shift;
|
||||
my $bCompression = shift;
|
||||
my $bChecksum = shift;
|
||||
|
||||
my $strCommand = "$strBackRestBinPath/pg_backrest.pl --stanza=db --config=$strBackRestBinPath/pg_backrest.conf";
|
||||
|
||||
# if (!$bCompression)
|
||||
# {
|
||||
# $strCommand .= " --no-compression"
|
||||
# }
|
||||
#
|
||||
# if (!$bChecksum)
|
||||
# {
|
||||
# $strCommand .= " --no-checksum"
|
||||
# }
|
||||
|
||||
return $strCommand . " archive-push %p";
|
||||
}
|
||||
|
||||
sub wait_for_file
|
||||
{
|
||||
my $strDir = shift;
|
||||
my $strRegEx = shift;
|
||||
my $iSeconds = shift;
|
||||
|
||||
my $lTime = time();
|
||||
my $hDir;
|
||||
|
||||
while ($lTime > time() - $iSeconds)
|
||||
if (defined($strTestVersion) && $strVersion eq trim($strTestVersion))
|
||||
{
|
||||
opendir $hDir, $strDir or die "Could not open dir: $!\n";
|
||||
my @stryFile = grep(/$strRegEx/i, readdir $hDir);
|
||||
close $hDir;
|
||||
|
||||
if (scalar @stryFile == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
BackRestTestCommon_Execute(
|
||||
"find .. -type f -not -path \"../.git/*\" -not -path \"*.DS_Store\" -not -path \"../test/test/*\" " .
|
||||
"-not -path \"../test/data/*\" " .
|
||||
"-exec sh -c 'for i;do echo \"\$i\" && sed 's/[[:space:]]*\$//' \"\$i\">/tmp/.\$\$ && cat /tmp/.\$\$ " .
|
||||
"> \"\$i\";done' arg0 {} + > /dev/null", false, true);
|
||||
}
|
||||
|
||||
die "could not find $strDir/$strRegEx after $iSeconds second(s)";
|
||||
close($hVersion);
|
||||
}
|
||||
|
||||
sub pgbr_backup
|
||||
####################################################################################################################################
|
||||
# Runs tests
|
||||
####################################################################################################################################
|
||||
BackRestTestCommon_Setup($strTestPath, $strPgSqlBin, $iModuleTestRun, $bDryRun, $bNoCleanup);
|
||||
|
||||
# &log(INFO, "Testing with test_path = " . BackRestTestCommon_TestPathGet() . ", host = {strHost}, user = {strUser}, " .
|
||||
# "group = {strGroup}");
|
||||
|
||||
if ($strModule eq 'all' || $strModule eq 'utility')
|
||||
{
|
||||
my $strBackRestBinPath = shift;
|
||||
my $strCluster = shift;
|
||||
|
||||
my $strCommand = "$strBackRestBinPath/pg_backrest.pl --config=$strBackRestBinPath/pg_backrest.conf backup $strCluster";
|
||||
|
||||
execute($strCommand);
|
||||
BackRestTestUtility_Test($strModuleTest);
|
||||
}
|
||||
|
||||
my $strUser = execute('whoami');
|
||||
|
||||
my $strTestPath = "/Users/dsteele/test";
|
||||
my $strDbDir = "db";
|
||||
my $strArchiveDir = "backup/db/archive";
|
||||
my $strBackupDir = "backup";
|
||||
|
||||
my $strPgBinPath = "/Library/PostgreSQL/9.3/bin";
|
||||
my $strPort = "6001";
|
||||
|
||||
my $strBackRestBinPath = "/Users/dsteele/pg_backrest";
|
||||
my $strArchiveCommand = archive_command_build($strBackRestBinPath, "$strTestPath/$strArchiveDir", 0, 0);
|
||||
|
||||
################################################################################
|
||||
# Stop the current test cluster if it is running and create a new one
|
||||
################################################################################
|
||||
eval {pg_stop($strPgBinPath, "$strTestPath/$strDbDir")};
|
||||
|
||||
if ($@)
|
||||
if ($strModule eq 'all' || $strModule eq 'file')
|
||||
{
|
||||
print(" ... unable to stop pg server (ignoring): " . trim($@) . "\n\n")
|
||||
BackRestTestFile_Test($strModuleTest);
|
||||
}
|
||||
|
||||
pg_drop($strTestPath);
|
||||
pg_create($strPgBinPath, $strTestPath, $strDbDir, $strArchiveDir, $strBackupDir);
|
||||
pg_start($strPgBinPath, "$strTestPath/$strDbDir/common", $strPort, $strArchiveCommand);
|
||||
pg_password_set($strPgBinPath, "$strTestPath/$strDbDir/common", $strUser, $strPort);
|
||||
if ($strModule eq 'all' || $strModule eq 'backup')
|
||||
{
|
||||
BackRestTestBackup_Test($strModuleTest);
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Connect and start tests
|
||||
################################################################################
|
||||
$dbh = DBI->connect("dbi:Pg:dbname=postgres;port=$strPort;host=127.0.0.1", $strUser,
|
||||
'password', {AutoCommit => 1});
|
||||
|
||||
pg_execute($dbh, "create tablespace ts1 location '$strTestPath/$strDbDir/ts1'");
|
||||
pg_execute($dbh, "create tablespace ts2 location '$strTestPath/$strDbDir/ts2'");
|
||||
|
||||
pg_execute($dbh, "create table test (id int)");
|
||||
pg_execute($dbh, "create table test_ts1 (id int) tablespace ts1");
|
||||
pg_execute($dbh, "create table test_ts2 (id int) tablespace ts1");
|
||||
|
||||
pg_execute($dbh, "insert into test values (1)");
|
||||
pg_execute($dbh, "select pg_switch_xlog()");
|
||||
|
||||
execute("mkdir -p $strTestPath/$strArchiveDir/0000000100000000");
|
||||
|
||||
# Test for archive log file 000000010000000000000001
|
||||
wait_for_file("$strTestPath/$strArchiveDir/0000000100000000", "^000000010000000000000001\$", 5);
|
||||
|
||||
# Turn on log checksum for the next test
|
||||
$dbh->disconnect();
|
||||
pg_stop($strPgBinPath, "$strTestPath/$strDbDir/common");
|
||||
$strArchiveCommand = archive_command_build($strBackRestBinPath, "$strTestPath/$strArchiveDir", 0, 1);
|
||||
pg_start($strPgBinPath, "$strTestPath/$strDbDir/common", $strPort, $strArchiveCommand);
|
||||
$dbh = DBI->connect("dbi:Pg:dbname=postgres;port=$strPort;host=127.0.0.1", $strUser,
|
||||
'password', {AutoCommit => 1});
|
||||
|
||||
# Write another value into the test table
|
||||
pg_execute($dbh, "insert into test values (2)");
|
||||
pg_execute($dbh, "select pg_switch_xlog()");
|
||||
|
||||
# Test for archive log file 000000010000000000000002
|
||||
wait_for_file("$strTestPath/$strArchiveDir/0000000100000000", "^000000010000000000000002-([a-f]|[0-9]){40}\$", 5);
|
||||
|
||||
# Turn on log compression and checksum for the next test
|
||||
$dbh->disconnect();
|
||||
pg_stop($strPgBinPath, "$strTestPath/$strDbDir/common");
|
||||
$strArchiveCommand = archive_command_build($strBackRestBinPath, "$strTestPath/$strArchiveDir", 1, 1);
|
||||
pg_start($strPgBinPath, "$strTestPath/$strDbDir/common", $strPort, $strArchiveCommand);
|
||||
$dbh = DBI->connect("dbi:Pg:dbname=postgres;port=$strPort;host=127.0.0.1", $strUser,
|
||||
'password', {AutoCommit => 1});
|
||||
|
||||
# Write another value into the test table
|
||||
pg_execute($dbh, "insert into test values (3)");
|
||||
pg_execute($dbh, "select pg_switch_xlog()");
|
||||
|
||||
# Test for archive log file 000000010000000000000003
|
||||
wait_for_file("$strTestPath/$strArchiveDir/0000000100000000", "^000000010000000000000003-([a-f]|[0-9]){40}\\.gz\$", 5);
|
||||
|
||||
$dbh->disconnect();
|
||||
|
||||
################################################################################
|
||||
# Stop the server
|
||||
################################################################################
|
||||
#pg_stop($strPgBinPath, "$strTestPath/$strDbDir/common");
|
||||
|
||||
################################################################################
|
||||
# Start an offline backup
|
||||
################################################################################
|
||||
#pgbr_backup($strBackRestBinPath, "db");
|
||||
if (!$bDryRun)
|
||||
{
|
||||
&log(ASSERT, 'TESTS COMPLETED SUCCESSFULLY (DESPITE ANY ERROR MESSAGES YOU SAW)');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user