1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-04-15 11:36:40 +02:00

Converted path_create(), improved unit tests.

This commit is contained in:
David Steele 2014-06-03 21:22:07 -04:00
parent ffa45d07bf
commit 1b9782cb9e
5 changed files with 307 additions and 141 deletions

View File

@ -23,13 +23,14 @@ use pg_backrest_file;
####################################################################################################################################
use constant
{
OP_LIST => "list",
OP_EXISTS => "exists",
OP_HASH => "hash",
OP_REMOVE => "remove",
OP_MANIFEST => "manifest",
OP_COMPRESS => "compress",
OP_MOVE => "move"
OP_LIST => "list",
OP_EXISTS => "exists",
OP_HASH => "hash",
OP_REMOVE => "remove",
OP_MANIFEST => "manifest",
OP_COMPRESS => "compress",
OP_MOVE => "move",
OP_PATH_CREATE => "path_create"
};
####################################################################################################################################
@ -38,11 +39,13 @@ use constant
my $bIgnoreMissing = false; # Ignore errors due to missing file
my $bDestinationPathCreate = false; # Create destination path if it does not exist
my $strExpression = undef; # Expression to use for filtering (undef = no filtering)
my $strPermission = undef; # Permission when creating directory or file (undef = default)
my $strSort = undef; # Sort order (undef = forward)
GetOptions ("ignore-missing" => \$bIgnoreMissing,
"dest-path-create" => \$bDestinationPathCreate,
"expression=s" => \$strExpression,
"permission=s" => \$strPermission,
"sort=s" => \$strSort)
or die("Error in command line arguments\n");
@ -73,7 +76,7 @@ if ($strOperation eq OP_LIST)
if (!defined($strPath))
{
confess "path must be specified for list operation";
confess "path must be specified for ${strOperation} operation";
}
my $bFirst = true;
@ -97,7 +100,7 @@ if ($strOperation eq OP_EXISTS)
if (!defined($strFile))
{
confess "filename must be specified for exist operation";
confess "filename must be specified for ${strOperation} operation";
}
print $oFile->exists(PATH_ABSOLUTE, $strFile) ? "Y" : "N";
@ -114,7 +117,7 @@ if ($strOperation eq OP_HASH)
if (!defined($strFile))
{
confess "filename must be specified for hash operation";
confess "filename must be specified for ${strOperation} operation";
}
print $oFile->hash(PATH_ABSOLUTE, $strFile);
@ -131,7 +134,7 @@ if ($strOperation eq OP_REMOVE)
if (!defined($strFile))
{
confess "filename must be specified for remove operation";
confess "filename must be specified for ${strOperation} operation";
}
print $oFile->remove(PATH_ABSOLUTE, $strFile, undef, $bIgnoreMissing) ? "Y" : "N";
@ -148,7 +151,7 @@ if ($strOperation eq OP_MANIFEST)
if (!defined($strPath))
{
confess "path must be specified for manifest operation";
confess "path must be specified for ${strOperation} operation";
}
my %oManifestHash;
@ -183,7 +186,7 @@ if ($strOperation eq OP_COMPRESS)
if (!defined($strFile))
{
confess "file must be specified for compress operation";
confess "file must be specified for ${strOperation} operation";
}
$oFile->compress(PATH_ABSOLUTE, $strFile);
@ -200,14 +203,14 @@ if ($strOperation eq OP_MOVE)
if (!defined($strFileSource))
{
confess "source file source must be specified for compress operation";
confess "source file source must be specified for ${strOperation} operation";
}
my $strFileDestination = $ARGV[2];
if (!defined($strFileDestination))
{
confess "destination file must be specified for compress operation";
confess "destination file must be specified for ${strOperation} operation";
}
$oFile->move(PATH_ABSOLUTE, $strFileSource, PATH_ABSOLUTE, $strFileDestination, $bDestinationPathCreate);
@ -215,4 +218,21 @@ if ($strOperation eq OP_MOVE)
exit 0;
}
####################################################################################################################################
# PATH_CREATE Command
####################################################################################################################################
if ($strOperation eq OP_PATH_CREATE)
{
my $strPath = $ARGV[1];
if (!defined($strPath))
{
confess "path must be specified for ${strOperation} operation";
}
$oFile->path_create(PATH_ABSOLUTE, $strPath, $strPermission);
exit 0;
}
confess &log(ERROR, "invalid operation ${strOperation}");

View File

@ -70,7 +70,8 @@ use constant
COMMAND_ERR_FILE_MOVE => 3,
COMMAND_ERR_FILE_TYPE => 4,
COMMAND_ERR_LINK_READ => 5,
COMMAND_ERR_PATH_MISSING => 6
COMMAND_ERR_PATH_MISSING => 6,
COMMAND_ERR_PATH_CREATE => 7
};
####################################################################################################################################
@ -106,10 +107,10 @@ sub BUILD
# Create the ssh options string
if (defined($self->{strBackupHost}) || defined($self->{strDbHost}))
{
# if (defined($self->{strBackupHost}) && defined($self->{strDbHost}))
# {
# confess &log(ASSERT, "backup and db hosts cannot both be remote");
# }
if (defined($self->{strBackupHost}) && defined($self->{strDbHost}))
{
confess &log(ASSERT, "backup and db hosts cannot both be remote");
}
my $strOptionSSHRequestTTY = "RequestTTY=yes";
my $strOptionSSHCompression = "Compression=no";
@ -345,6 +346,64 @@ sub path_get
confess &log(ASSERT, "no known path types in '${strType}'");
}
####################################################################################################################################
# IS_REMOTE
#
# Determine whether any operations are being performed remotely. If $strPathType is defined, the function will return true if that
# path is remote. If $strPathType is not defined, then function will return true if any path is remote.
####################################################################################################################################
sub is_remote
{
my $self = shift;
my $strPathType = shift;
# If the SSH object is defined then some paths are remote
if (defined($self->{oDbSSH}) || defined($self->{oBackupSSH}))
{
# If path type is not defined but the SSH object is, then some paths are remote
if (!defined($strPathType))
{
return true;
}
# If a host is defined for the path then it is remote
if (defined($self->{strBackupHost}) && $self->path_type_get($strPathType) eq PATH_BACKUP ||
defined($self->{strDbHost}) && $self->path_type_get($strPathType) eq PATH_DB)
{
return true;
}
}
return false;
}
####################################################################################################################################
# REMOTE_GET
#
# Get remote SSH object depending on the path type.
####################################################################################################################################
sub remote_get
{
my $self = shift;
my $strPathType = shift;
# Get the db SSH object
if ($self->path_type_get($strPathType) eq PATH_DB && defined($self->{oDbSSH}))
{
return $self->{oDbSSH};
}
# Get the backup SSH object
if ($self->path_type_get($strPathType) eq PATH_BACKUP && defined($self->{oBackupSSH}))
{
return $self->{oBackupSSH}
}
# Error when no ssh object is found
confess &log(ASSERT, "path type ${strPathType} does not have a defined ssh object");
}
####################################################################################################################################
# LINK_CREATE
####################################################################################################################################
@ -444,93 +503,47 @@ sub path_create
my $strPath = shift;
my $strPermission = shift;
# If no permissions are given then use the default
if (!defined($strPermission))
# Setup standard variables
my $strErrorPrefix = "File->path_create";
my $bRemote = $self->is_remote($strPathType);
my $strPathOp = $self->path_get($strPathType, $strPath);
&log(TRACE, "${strErrorPrefix}: " . ($bRemote ? "remote" : "local") . " ${strPathType}:${strPath}, " .
"permission " . (defined($strPermission) ? $strPermission : "[undef]"));
if ($bRemote)
{
$strPermission = $self->{strDefaultPathPermission};
}
# Get the path to create
my $strPathCreate = $strPath;
if (defined($strPathType))
{
$strPathCreate = $self->path_get($strPathType, $strPath);
}
my $strCommand = "mkdir -p -m ${strPermission} ${strPathCreate}";
# Run remotely
if ($self->is_remote($strPathType))
{
&log(TRACE, "path_create: remote ${strPathType} '${strCommand}'");
# Run remotely
my $oSSH = $self->remote_get($strPathType);
$oSSH->system($strCommand) or confess &log("unable to create remote path ${strPathType}:${strPath}");
my $strOutput = $oSSH->capture($self->{strCommand} .
(defined($strPermission) ? " --permission=${strPermission}" : "") .
" path_create ${strPath}");
# Capture any errors
if ($oSSH->error)
{
confess &log(ERROR, "${strErrorPrefix} remote: " . (defined($strOutput) ? $strOutput : $oSSH->error));
}
}
# Run locally
else
{
&log(TRACE, "path_create: local '${strCommand}'");
system($strCommand) == 0 or confess &log(ERROR, "unable to create path ${strPath}");
}
}
####################################################################################################################################
# IS_REMOTE
#
# Determine whether any operations are being performed remotely. If $strPathType is defined, the function will return true if that
# path is remote. If $strPathType is not defined, then function will return true if any path is remote.
####################################################################################################################################
sub is_remote
{
my $self = shift;
my $strPathType = shift;
# If the SSH object is defined then some paths are remote
if (defined($self->{oDbSSH}) || defined($self->{oBackupSSH}))
{
# If path type is not defined but the SSH object is, then some paths are remote
if (!defined($strPathType))
# Attempt the create the directory
if (!mkdir($strPathOp, oct(defined($strPermission) ? $strPermission : $self->{strDefaultPathPermission})))
{
return true;
}
# Capture the error
my $strError = "${strPath} could not be created: " . $!;
# If a host is defined for the path then it is remote
if (defined($self->{strBackupHost}) && $self->path_type_get($strPathType) eq PATH_BACKUP ||
defined($self->{strDbHost}) && $self->path_type_get($strPathType) eq PATH_DB)
{
return true;
# If running on command line the return directly
if ($strPathType eq PATH_ABSOLUTE)
{
print $strError;
exit COMMAND_ERR_PATH_CREATE;
}
# Error the normal way
confess &log(ERROR, "${strErrorPrefix}: " . $strError);
}
}
return false;
}
####################################################################################################################################
# REMOTE_GET
#
# Get remote SSH object depending on the path type.
####################################################################################################################################
sub remote_get
{
my $self = shift;
my $strPathType = shift;
# Get the db SSH object
if ($self->path_type_get($strPathType) eq PATH_DB && defined($self->{oDbSSH}))
{
return $self->{oDbSSH};
}
# Get the backup SSH object
if ($self->path_type_get($strPathType) eq PATH_BACKUP && defined($self->{oBackupSSH}))
{
return $self->{oBackupSSH}
}
# Error when no ssh object is found
confess &log(ASSERT, "path type ${strPathType} does not have a defined ssh object");
}
####################################################################################################################################

View File

@ -291,18 +291,25 @@ sub log_level_set
my $strLevelFileParam = shift;
my $strLevelConsoleParam = shift;
if (!defined($oLogLevelRank{"${strLevelFileParam}"}{rank}))
if (defined($strLevelFileParam))
{
confess &log(ERROR, "file log level ${strLevelFileParam} does not exist");
if (!defined($oLogLevelRank{"${strLevelFileParam}"}{rank}))
{
confess &log(ERROR, "file log level ${strLevelFileParam} does not exist");
}
$strLogLevelFile = $strLevelFileParam;
}
if (!defined($oLogLevelRank{"${strLevelConsoleParam}"}{rank}))
if (defined($strLevelConsoleParam))
{
confess &log(ERROR, "console log level ${strLevelConsoleParam} does not exist");
}
if (!defined($oLogLevelRank{"${strLevelConsoleParam}"}{rank}))
{
confess &log(ERROR, "console log level ${strLevelConsoleParam} does not exist");
}
$strLogLevelFile = $strLevelFileParam;
$strLogLevelConsole = $strLevelConsoleParam;
$strLogLevelConsole = $strLevelConsoleParam;
}
}
####################################################################################################################################

View File

@ -1,6 +1,6 @@
#!/usr/bin/perl
####################################################################################################################################
# File.pl - Unit Tests for BackRest::File
# FileTest.pl - Unit Tests for BackRest::File
####################################################################################################################################
####################################################################################################################################
@ -13,15 +13,17 @@ use english;
use Carp;
use File::Basename;
use Cwd 'abs_path';
use File::stat;
use Fcntl ':mode';
use lib dirname($0) . "/..";
use pg_backrest_file;
use pg_backrest_utility;
use Exporter qw(import);
our @EXPORT = qw(BackRestTestFile);
our @EXPORT = qw(BackRestFileTest);
sub BackRestTestFile
sub BackRestFileTest
{
my $strLockPath = dirname(abs_path($0)) . "/lock";
my $strTestPath = dirname(abs_path($0)) . "/test";
@ -32,19 +34,121 @@ sub BackRestTestFile
my $strHost = "127.0.0.1";
my $strUser = getpwuid($<);
my $strGroup = getgrgid($();
umask(0);
# print "user = ${strUser}, group = ${strGroup}";
log_level_set(TRACE, TRACE);
# Print test parameters
&log(INFO, "Testing with test_path = ${strTestPath}, host = ${strHost}, user = ${strUser}, group = ${strGroup}");
&log(INFO, "FILE MODULE ********************************************************************");
#-------------------------------------------------------------------------------------------------------------------------------
# Test path_create()
#-------------------------------------------------------------------------------------------------------------------------------
$iRun = 0;
&log(INFO, "Test File->path_create()\n");
# Loop through local/remote
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
my $oFile = pg_backrest_file->new
(
strStanza => $strStanza,
bNoCompression => true,
strCommand => $strCommand,
strBackupClusterPath => ${strTestPath},
strBackupPath => ${strTestPath},
strBackupHost => $bRemote ? $strHost : undef,
strBackupUser => $bRemote ? $strUser : undef
);
# Loop through exists (does the paren path exist?)
for (my $bExists = 0; $bExists <= 1; $bExists++)
{
# Loop through permission (permission will be set on true)
for (my $bPermission = 0; $bPermission <= $bExists; $bPermission++)
{
$iRun++;
&log(INFO, "run ${iRun} - " .
"remote $bRemote, exists $bExists, permission $bPermission");
# Drop the old test directory and create a new one
system("rm -rf test");
system("mkdir test") == 0 or confess "Unable to create test directory";
my $strPath = "${strTestPath}/path";
my $strPermission;
# If permission then set one (other than the default)
if ($bPermission)
{
$strPermission = "0700";
# Make sure that we are not testing with the default permission
if ($strPermission eq $oFile->{strDefaultPathPermission})
{
confess 'cannot set test permission ${strPermission} equal to default permission' .
$oFile->{strDefaultPathPermission};
}
}
# If not exists then set the path to something bogus
if (!$bExists)
{
$strPath = "${strTestPath}/error/path";
}
# Execute in eval to catch errors
eval
{
$oFile->path_create(PATH_BACKUP_ABSOLUTE, $strPath, $strPermission);
};
# Check for errors
if ($@)
{
# Ignore errors if the path did not exist
if (!$bExists)
{
next;
}
confess "error raised: " . $@ . "\n";
}
else
{
# Make sure the path was actually created
unless (-e $strPath)
{
confess "path was not created";
}
# Check that the permissions were set correctly
my $oStat = lstat($strPath);
if (!defined($oStat))
{
confess "unable to stat ${strPath}";
}
my $strPermissionCompare = defined($strPermission) ? $strPermission : $oFile->{strDefaultPathPermission};
if ($strPermissionCompare ne sprintf("%04o", S_IMODE($oStat->mode)))
{
confess "permissions were not set to {$strPermissionCompare}";
}
}
}
}
}
#-------------------------------------------------------------------------------------------------------------------------------
# Test move()
#-------------------------------------------------------------------------------------------------------------------------------
$iRun = 0;
print "\ntest File->move()\n";
&log(INFO, "--------------------------------------------------------------------------------");
&log(INFO, "Test File->move()\n");
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
@ -70,8 +174,8 @@ sub BackRestTestFile
{
$iRun++;
print "run ${iRun} - " .
"remote $bRemote, src_exists $bSourceExists, dst_exists $bDestinationExists, create $bCreate\n";
&log(INFO, "run ${iRun} - " .
"remote $bRemote, src_exists $bSourceExists, dst_exists $bDestinationExists, create $bCreate");
# Drop the old test directory and create a new one
system("rm -rf test");
@ -110,7 +214,7 @@ sub BackRestTestFile
confess "error raised: " . $@ . "\n";
}
if (!$bSourceExists || !$bDestinationExists)
{
confess "error should have been raised";
@ -124,15 +228,14 @@ sub BackRestTestFile
}
}
}
return;
#-------------------------------------------------------------------------------------------------------------------------------
# Test compress()
#-------------------------------------------------------------------------------------------------------------------------------
$iRun = 0;
print "\ntest File->compress()\n";
&log(INFO, "--------------------------------------------------------------------------------");
&log(INFO, "Test File->compress()\n");
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
@ -152,8 +255,8 @@ sub BackRestTestFile
{
$iRun++;
print "run ${iRun} - " .
"remote $bRemote, exists $bExists\n";
&log(INFO, "run ${iRun} - " .
"remote $bRemote, exists $bExists");
# Drop the old test directory and create a new one
system("rm -rf test");
@ -184,7 +287,8 @@ sub BackRestTestFile
#-------------------------------------------------------------------------------------------------------------------------------
$iRun = 0;
print "\ntest File->manifest()\n";
&log(INFO, "--------------------------------------------------------------------------------");
&log(INFO, "Test File->manifest()\n");
# Create the test data
system("rm -rf test");
@ -242,8 +346,8 @@ sub BackRestTestFile
{
$iRun++;
print "run ${iRun} - " .
"remote $bRemote, error $bError\n";
&log(INFO, "run ${iRun} - " .
"remote $bRemote, error $bError");
my $strPath = $strTestPath;
@ -313,7 +417,8 @@ sub BackRestTestFile
#-------------------------------------------------------------------------------------------------------------------------------
$iRun = 0;
print "\ntest File->list()\n";
&log(INFO, "--------------------------------------------------------------------------------");
&log(INFO, "Test File->list()\n");
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
@ -354,10 +459,10 @@ sub BackRestTestFile
{
$iRun++;
print "run ${iRun} - " .
"remote $bRemote, exists $bExists, " .
"expression " . (defined($strExpression) ? $strExpression : "[undef]") . ", " .
"sort " . (defined($strSort) ? $strSort : "[undef]") . "\n";
&log(INFO, "run ${iRun} - " .
"remote $bRemote, exists $bExists, " .
"expression " . (defined($strExpression) ? $strExpression : "[undef]") . ", " .
"sort " . (defined($strSort) ? $strSort : "[undef]"));
my $strPath = "${strTestPath}";
@ -411,7 +516,9 @@ sub BackRestTestFile
# Test remove()
#-------------------------------------------------------------------------------------------------------------------------------
$iRun = 0;
print "test File->remove()\n";
&log(INFO, "--------------------------------------------------------------------------------");
&log(INFO, "Test File->remove()\n");
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
@ -440,8 +547,8 @@ sub BackRestTestFile
{
$iRun++;
print "run ${iRun} - " .
"remote ${bRemote}, exists ${bExists}, temp ${bTemp}, ignore missing ${bIgnoreMissing}\n";
&log(INFO, "run ${iRun} - " .
"remote ${bRemote}, exists ${bExists}, temp ${bTemp}, ignore missing ${bIgnoreMissing}");
# Drop the old test directory and create a new one
system("rm -rf test");
@ -482,7 +589,8 @@ sub BackRestTestFile
#-------------------------------------------------------------------------------------------------------------------------------
$iRun = 0;
print "\ntest File->hash()\n";
&log(INFO, "--------------------------------------------------------------------------------");
&log(INFO, "test File->hash()\n");
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
@ -502,8 +610,8 @@ sub BackRestTestFile
{
$iRun++;
print "run ${iRun} - " .
"remote $bRemote, exists $bExists\n";
&log(INFO, "run ${iRun} - " .
"remote $bRemote, exists $bExists");
# Drop the old test directory and create a new one
system("rm -rf test");
@ -540,7 +648,8 @@ sub BackRestTestFile
#-------------------------------------------------------------------------------------------------------------------------------
$iRun = 0;
print "\ntest File->exists()\n";
&log(INFO, "--------------------------------------------------------------------------------");
&log(INFO, "test File->exists()\n");
for (my $bRemote = 0; $bRemote <= 1; $bRemote++)
{
@ -560,8 +669,8 @@ sub BackRestTestFile
{
$iRun++;
print "run ${iRun} - " .
"remote $bRemote, exists $bExists\n";
&log(INFO, "run ${iRun} - " .
"remote $bRemote, exists $bExists");
# Drop the old test directory and create a new one
system("rm -rf test");

View File

@ -18,8 +18,25 @@ use lib dirname($0) . "/lib";
use BackRestTest::FileTest;
####################################################################################################################################
# Perl includes
# Command line parameters
####################################################################################################################################
BackRestTestFile();
my $strLogLevel = "OFF"; # Log level for tests
GetOptions ("log-level=s" => \$strLogLevel)
or die("Error in command line arguments\n");
####################################################################################################################################
# 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));
####################################################################################################################################
# Runs tests
####################################################################################################################################
BackRestFileTest();
print "\nTEST COMPLETED SUCCESSFULLY (DESPITE ANY ERROR MESSAGES YOU SAW)\n";