1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00
pgbackrest/test/lib/pgBackRestTest/Module/Common/CommonIniTest.pm
Cynthia Shang b03c26968a Repository encryption support.
Contributed by Cynthia Shang.
2017-11-06 12:51:12 -05:00

569 lines
32 KiB
Perl

####################################################################################################################################
# InfoIniUnitTest.pm - Unit tests for Ini module
####################################################################################################################################
package pgBackRestTest::Module::Common::CommonIniTest;
use parent 'pgBackRestTest::Common::RunTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Config::Config;
use pgBackRest::Storage::Base;
use pgBackRest::Version;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::RunTest;
####################################################################################################################################
# iniHeader
####################################################################################################################################
sub iniHeader
{
my $self = shift;
my $oIni = shift;
my $iFormat = shift;
my $iVersion = shift;
my $strChecksum = shift;
return
"[backrest]" .
"\nbackrest-checksum=\"" .
(defined($strChecksum) ? $strChecksum : $oIni->get(INI_SECTION_BACKREST, INI_KEY_CHECKSUM)) . "\"" .
"\nbackrest-format=" . (defined($iFormat) ? $iFormat : $oIni->get(INI_SECTION_BACKREST, INI_KEY_FORMAT)) .
"\nbackrest-version=\"" . (defined($iVersion) ? $iVersion : $oIni->get(INI_SECTION_BACKREST, INI_KEY_VERSION)) . "\"" .
"\n";
}
####################################################################################################################################
# run
####################################################################################################################################
sub run
{
my $self = shift;
# Test ini file
my $strTestFile = $self->testPath() . '/test.ini';
my $strTestFileCopy = "${strTestFile}.copy";
# Test keys, values
my $strSection = 'test-section';
my $strKey = 'test-key';
my $strSubKey = 'test-subkey';
my $strValue = 'test-value';
################################################################################################################################
if ($self->begin("iniRender()"))
{
#---------------------------------------------------------------------------------------------------------------------------
my $oIni = {section1 => {key => 'value'}, section2 => {key => ['value1', 'value2']}};
$self->testResult(
sub {iniRender($oIni, true)}, "[section1]\nkey=value\n\n[section2]\nkey=value1\nkey=value2\n",
'relaxed formatting');
$self->testResult(
sub {iniRender($oIni, false)}, "[section1]\nkey=\"value\"\n\n[section2]\nkey=[\"value1\",\"value2\"]\n",
'strict formatting');
}
################################################################################################################################
if ($self->begin("iniParse()"))
{
#---------------------------------------------------------------------------------------------------------------------------
my $strIni = "[section]\nkey";
$self->testException(sub {iniParse($strIni)}, ERROR_CONFIG, "unable to find '=' in 'key'");
#---------------------------------------------------------------------------------------------------------------------------
$strIni = "[section]\n# comment\n\nkey=\"value\"";
$self->testResult(sub {iniParse($strIni)}, '{section => {key => value}}', 'ignore blank lines and comments');
#---------------------------------------------------------------------------------------------------------------------------
$strIni = "[section]\nkey=value";
$self->testResult(sub {iniParse($strIni, {bRelaxed => true})}, '{section => {key => value}}', 'relaxed value read');
#---------------------------------------------------------------------------------------------------------------------------
$strIni = "[section]\nkey=value1\nkey=value2\nkey=value3";
$self->testResult(
sub {iniParse($strIni, {bRelaxed => true})}, '{section => {key => (value1, value2, value3)}}', 'relaxed array read');
}
################################################################################################################################
if ($self->begin("Ini->new()"))
{
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(
sub {(new pgBackRest::Common::Ini($strTestFile, {bIgnoreMissing => true}))->exists()}, false, 'ignore missing');
#---------------------------------------------------------------------------------------------------------------------------
my $oIni = new pgBackRest::Common::Ini(
$strTestFile, {bLoad => false, iInitFormat => 4, strInitVersion => '1.01'});
$self->testResult($oIni->exists(), false, 'file does not exist');
$oIni->saveCopy();
$self->testResult($oIni->exists(), false, 'file does not exist after saveCopy()');
$self->testResult(
sub {${storageTest()->get($strTestFile . INI_COPY_EXT)}},
$self->iniHeader(undef, 4, '1.01', '488e5ca1a018cd7cd6d4e15150548f39f493dacd'),
'empty with synthetic format and version');
#---------------------------------------------------------------------------------------------------------------------------
$oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false});
$oIni->saveCopy();
$self->testResult(
sub {${storageTest()->get($strTestFile . INI_COPY_EXT)}},
$self->iniHeader(undef, BACKREST_FORMAT, BACKREST_VERSION, $oIni->hash()),
'empty with default format and version');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(
sub {storageTest()->list($self->testPath())},
'test.ini.copy',
'only copy is saved');
$oIni->save();
$self->testResult(
sub {storageTest()->list($self->testPath())},
'(test.ini, test.ini.copy)',
'both versions are saved');
$self->testException(
sub {$oIni->saveCopy()}, ERROR_ASSERT,
"cannot save copy only when '${strTestFile}' exists");
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'normal load');
#---------------------------------------------------------------------------------------------------------------------------
my $hIni = iniParse(${storageTest()->get($strTestFile)});
$hIni->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = BOGUS;
storageTest()->put($strTestFile, iniRender($hIni));
storageTest()->put($strTestFileCopy, iniRender($hIni));
$self->testException(
sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING,
"unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT);
# "invalid checksum in '${strTestFile}', expected '" .
# $oIni->get(INI_SECTION_BACKREST, INI_KEY_CHECKSUM) . "' but found 'bogus'");
$hIni->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = $oIni->hash();
storageTest()->put($strTestFile, iniRender($hIni));
#---------------------------------------------------------------------------------------------------------------------------
$oIni->numericSet(INI_SECTION_BACKREST, INI_KEY_FORMAT, undef, BACKREST_FORMAT - 1);
$oIni->save();
$self->testException(
sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING,
"unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT);
# "invalid format in '${strTestFile}', expected " . BACKREST_FORMAT . ' but found ' . (BACKREST_FORMAT - 1));
$oIni->numericSet(INI_SECTION_BACKREST, INI_KEY_FORMAT, undef, BACKREST_FORMAT);
$oIni->save();
#---------------------------------------------------------------------------------------------------------------------------
$oIni->set(INI_SECTION_BACKREST, INI_KEY_VERSION, undef, '1.01');
$oIni->save();
$self->testResult(
sub {${storageTest()->get($strTestFile . INI_COPY_EXT)}},
$self->iniHeader($oIni, undef, '1.01'),
'verify old version was written');
$oIni = new pgBackRest::Common::Ini($strTestFile);
$self->testResult(sub {$oIni->get(INI_SECTION_BACKREST, INI_KEY_VERSION)}, BACKREST_VERSION, 'version is updated on load');
$oIni->save();
$self->testResult(
sub {${storageTest()->get($strTestFile . INI_COPY_EXT)}},
$self->iniHeader($oIni, undef, BACKREST_VERSION),
'verify version is updated on load');
$self->testResult(sub {$oIni->save()}, false, 'save again with no changes');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(
sub {new pgBackRest::Common::Ini($strTestFile, {bLoad => false, strContent => ${storageTest()->get($strTestFile)}})},
'[object]', 'new() passing content as a string');
#---------------------------------------------------------------------------------------------------------------------------
executeTest("rm -rf ${strTestFile}*");
$self->testException(
sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING,
"unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT);
#---------------------------------------------------------------------------------------------------------------------------
storageTest()->put($strTestFileCopy, BOGUS);
$self->testException(
sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING,
"unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT);
# "key/value pair 'bogus' found outside of a section");
#---------------------------------------------------------------------------------------------------------------------------
my $oIniSource = new pgBackRest::Common::Ini($strTestFile, {bLoad => false});
storageTest()->put($strTestFileCopy, iniRender($oIniSource->{oContent}));
$self->testException(
sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING,
"unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT);
# "invalid checksum in '${strTestFileCopy}', expected '" .
# $oIniSource->hash() . "' but found [undef]");
#---------------------------------------------------------------------------------------------------------------------------
$oIniSource = new pgBackRest::Common::Ini($strTestFile, {bLoad => false});
$oIniSource->save();
storageTest()->put($strTestFile, BOGUS);
# main invalid, copy ok
$self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'invalid main - load copy');
#---------------------------------------------------------------------------------------------------------------------------
storageTest()->remove($strTestFileCopy);
storageTest()->put($strTestFile, "[section]\n" . BOGUS);
# main invalid, copy missing
$self->testException
(sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING,
"unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT);
#"unable to find '=' in 'bogus'");
#---------------------------------------------------------------------------------------------------------------------------
storageTest()->put($strTestFile, iniRender($oIniSource->{oContent}));
$self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'main ok, copy missing');
#---------------------------------------------------------------------------------------------------------------------------
storageTest()->put($strTestFileCopy, BOGUS);
# main ok, copy invalid
$self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'main ok, copy invalid');
#---------------------------------------------------------------------------------------------------------------------------
storageTest()->put($strTestFile, BOGUS);
# main invalid, copy invalid
$self->testException(
sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING,
"unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT);
# "key/value pair 'bogus' found outside of a section");
#---------------------------------------------------------------------------------------------------------------------------
storageTest()->put($strTestFile, iniRender($hIni));
$hIni->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = BOGUS;
storageTest()->put($strTestFileCopy, iniRender($hIni));
$self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'invalid copy header - load main');
#---------------------------------------------------------------------------------------------------------------------------
$hIni->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = $oIni->hash();
storageTest()->put($strTestFileCopy, iniRender($hIni));
$hIni->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = BOGUS;
storageTest()->put($strTestFile, iniRender($hIni));
$self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'invalid main header - load copy');
#---------------------------------------------------------------------------------------------------------------------------
# Prepend encryption Magic signature to copy (main invalid) to simulate encryption
executeTest('echo "' . CIPHER_MAGIC . '$(cat ' . $strTestFileCopy . ')" > ' . $strTestFileCopy);
$self->testException(sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_CIPHER,
"unable to parse '$strTestFileCopy'" .
"\nHINT: Is or was the repo encrypted?");
# Prepend encryption Magic signature to main to simulate encryption
executeTest('echo "' . CIPHER_MAGIC . '$(cat ' . $strTestFile . ')" > ' . $strTestFile);
$self->testException(sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_CIPHER,
"unable to parse '$strTestFile'" .
"\nHINT: Is or was the repo encrypted?");
# Encryption
#---------------------------------------------------------------------------------------------------------------------------
executeTest("rm -rf ${strTestFile}*");
my $strCipherPass = 'x';
my $strCipherPassSub = 'y';
# Unencrypted storage but a passphrase passed
$self->testException(sub {new pgBackRest::Common::Ini($strTestFile, {bLoad => false,
strCipherPass => $strCipherPass})}, ERROR_ASSERT,
"a user passphrase and sub passphrase are both required when encrypting");
# Unencrypted storage but a sub passphrase passed
$self->testException(sub {new pgBackRest::Common::Ini($strTestFile, {bLoad => false,
strCipherPassSub => $strCipherPassSub})}, ERROR_ASSERT,
"a user passphrase and sub passphrase are both required when encrypting");
# Create Encrypted storage
my $oStorage = new pgBackRest::Storage::Local($self->testPath(), new pgBackRest::Storage::Posix::Driver(),
{strCipherType => CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC, strCipherPassUser => $strCipherPass});
$self->testException(sub {new pgBackRest::Common::Ini($strTestFile, {oStorage => $oStorage})}, ERROR_CIPHER,
"passphrase is required when storage is encrypted");
$self->testException(sub {new pgBackRest::Common::Ini($strTestFile, {bLoad => false, oStorage => $oStorage,
strCipherPass => $strCipherPass})}, ERROR_ASSERT,
"a user passphrase and sub passphrase are both required when encrypting");
$oIni = $self->testResult(sub {
new pgBackRest::Common::Ini(
$strTestFile,
{bLoad => false, oStorage => $oStorage, strCipherPass => $strCipherPass, strCipherPassSub => $strCipherPassSub})},
'[object]', 'create new ini with encryption passphrases');
$self->testResult(sub {($oIni->cipherPassSub() eq $strCipherPassSub) &&
($oIni->cipherPass() eq $strCipherPass)}, true, ' new ini has encryption passphrases');
}
################################################################################################################################
if ($self->begin("Ini->set()"))
{
my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false});
#---------------------------------------------------------------------------------------------------------------------------
$self->testException(sub {$oIni->set()}, ERROR_ASSERT, 'strSection and strKey are required');
$self->testException(sub {$oIni->set($strSection)}, ERROR_ASSERT, 'strSection and strKey are required');
$self->testException(sub {$oIni->set(undef, $strKey)}, ERROR_ASSERT, 'strSection and strKey are required');
#---------------------------------------------------------------------------------------------------------------------------
$oIni->{bModified} = false;
$self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, true, 'set key value');
$self->testResult($oIni->modified(), true, ' check changed flag = true');
#---------------------------------------------------------------------------------------------------------------------------
$oIni->{bModified} = false;
$self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, false, 'set same key value');
$self->testResult($oIni->modified(), false, ' check changed flag remains false');
#---------------------------------------------------------------------------------------------------------------------------
$oIni->{bModified} = false;
$self->testResult(sub {$oIni->set($strSection, $strKey, undef, "${strValue}2")}, true, 'set different key value');
$self->testResult($oIni->modified(), true, ' check changed flag = true');
$self->testResult(sub {$oIni->get($strSection, $strKey)}, "${strValue}2", 'get last key value');
#---------------------------------------------------------------------------------------------------------------------------
$oIni->{bModified} = false;
$self->testResult(sub {$oIni->set($strSection, $strKey, undef, undef)}, true, 'set undef key value');
$self->testResult($oIni->modified(), true, ' check changed flag = true');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->set($strSection, "${strKey}2", $strSubKey, $strValue)}, true, 'set subkey value');
}
################################################################################################################################
if ($self->begin("Ini->get()"))
{
my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false});
#---------------------------------------------------------------------------------------------------------------------------
$self->testException(sub {$oIni->get()}, ERROR_ASSERT, 'strSection is required');
$self->testException(sub {$oIni->get($strSection)}, ERROR_ASSERT, "strSection '${strSection}' is required but not defined");
$self->testException(
sub {$oIni->get($strSection, $strKey, undef)}, ERROR_ASSERT,
"strSection '${strSection}', strKey '${strKey}' is required but not defined");
$self->testException(
sub {$oIni->get($strSection, undef, $strSubKey)}, ERROR_ASSERT,
"strKey is required when strSubKey '${strSubKey}' is requested");
$self->testException(
sub {$oIni->get($strSection, $strKey, $strSubKey, true)}, ERROR_ASSERT,
"strSection '${strSection}', strKey '${strKey}', strSubKey '${strSubKey}' is required but not defined");
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->get($strSection, undef, undef, false)}, '[undef]', 'section value is not required');
$self->testResult(sub {$oIni->get($strSection, undef, undef, false, $strValue)}, $strValue, 'section value is defaulted');
#---------------------------------------------------------------------------------------------------------------------------
$oIni->set($strSection, $strKey, $strSubKey, $strValue);
$self->testResult(sub {$oIni->get($strSection, "${strKey}2", "${strSubKey}2", false)}, undef, 'missing key value');
$self->testResult(sub {$oIni->get($strSection, $strKey, "${strSubKey}2", false)}, undef, 'missing subkey value');
$self->testResult(sub {$oIni->get($strSection, $strKey, $strSubKey)}, $strValue, 'get subkey value');
$self->testResult(sub {$oIni->get($strSection, $strKey)}, "{${strSubKey} => ${strValue}}", 'get key value');
$self->testResult(sub {$oIni->get($strSection)}, "{${strKey} => {${strSubKey} => ${strValue}}}", 'get section value');
}
################################################################################################################################
if ($self->begin("Ini->remove()"))
{
my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false});
#---------------------------------------------------------------------------------------------------------------------------
$self->testException(sub {$oIni->remove()}, ERROR_ASSERT, 'strSection is required');
$self->testException(
sub {$oIni->remove($strSection, undef, $strSubKey)}, ERROR_ASSERT,
"strKey is required when strSubKey '${strSubKey}' is requested");
#---------------------------------------------------------------------------------------------------------------------------
$oIni->{bModified} = false;
$self->testResult(sub {$oIni->remove($strSection)}, false, 'undefined section is not removed');
$self->testResult($oIni->modified(), '0', ' check changed flag remains false');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, true, 'set key');
$oIni->{bModified} = false;
$self->testResult(sub {$oIni->remove($strSection, $strKey)}, true, ' remove key');
$self->testResult($oIni->modified(), '1', ' check changed flag = true');
$self->testResult(sub {$oIni->test($strSection, $strKey)}, false, ' test key');
$self->testResult(sub {$oIni->test($strSection)}, false, ' test section');
$self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, true, 'set key 1');
$self->testResult(sub {$oIni->set($strSection, "${strKey}2", undef, $strValue)}, true, ' set key 2');
$self->testResult(sub {$oIni->remove($strSection, $strKey)}, true, ' remove key 1');
$self->testResult(sub {$oIni->test($strSection, $strKey)}, false, ' test key');
$self->testResult(sub {$oIni->test($strSection)}, true, ' test section');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, true, 'set key');
$self->testResult(sub {$oIni->remove($strSection)}, true, ' remove section');
$self->testResult(sub {$oIni->test($strSection)}, false, ' test section');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->set($strSection, $strKey, $strSubKey, $strValue)}, true, 'set subkey');
$self->testResult(sub {$oIni->remove($strSection, $strKey, $strSubKey)}, true, ' remove subkey');
$self->testResult(sub {$oIni->test($strSection, $strKey, $strSubKey)}, false, ' test subkey');
$self->testResult(sub {$oIni->test($strSection, $strKey)}, true, ' test key');
$self->testResult(sub {$oIni->test($strSection)}, true, ' test section');
$self->testResult(sub {$oIni->set($strSection, $strKey, $strSubKey, $strValue)}, true, 'set subkey 1');
$self->testResult(sub {$oIni->set($strSection, $strKey, "${strSubKey}2", $strValue)}, true, 'set subkey 2');
$self->testResult(sub {$oIni->remove($strSection, $strKey, $strSubKey)}, true, ' remove subkey');
$self->testResult(sub {$oIni->test($strSection, $strKey, $strSubKey)}, false, ' test subkey');
$self->testResult(sub {$oIni->test($strSection, $strKey)}, true, ' test key');
$self->testResult(sub {$oIni->test($strSection)}, true, ' test section');
}
################################################################################################################################
if ($self->begin("Ini->test()"))
{
my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false});
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->test($strSection, $strKey)}, false, 'test undefined key');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, true, 'define key');
$self->testResult(sub {$oIni->test($strSection, $strKey)}, true, 'test key exists');
$self->testResult(sub {$oIni->test($strSection, $strKey, undef, $strValue)}, true, 'test key value');
$self->testResult(sub {$oIni->test($strSection, $strKey, undef, BOGUS)}, false, 'test key invalid value');
}
################################################################################################################################
if ($self->begin("Ini->boolSet() & Ini->boolGet() & Ini->boolTest()"))
{
my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false});
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->boolTest($strSection, $strKey)}, false, 'test bool on undefined key');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->boolGet($strSection, $strKey, undef, false, false)}, false, 'get bool default false value');
$self->testResult(sub {$oIni->boolGet($strSection, $strKey, undef, false, true)}, true, 'get bool default true value');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->boolSet($strSection, $strKey, undef, undef)}, true, 'set bool false (undef) value');
$self->testResult(sub {$oIni->boolGet($strSection, $strKey)}, false, ' check bool false value');
$self->testResult(sub {$oIni->boolTest($strSection, $strKey, undef, false)}, true, 'test bool on false key');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->boolSet($strSection, $strKey, undef, false)}, false, 'set bool false value');
$self->testResult(sub {$oIni->boolGet($strSection, $strKey)}, false, ' check value');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->boolSet($strSection, $strKey, undef, true)}, true, 'set bool false value');
$self->testResult(sub {$oIni->boolGet($strSection, $strKey)}, true, ' check value');
$self->testResult(sub {$oIni->boolTest($strSection, $strKey, undef, true)}, true, 'test bool on true key');
}
################################################################################################################################
if ($self->begin("Ini->numericSet() & Ini->numericGet() & Ini->numericTest()"))
{
my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false});
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->numericSet($strSection, $strKey)}, true, 'set numeric undef value');
$self->testResult(sub {$oIni->test($strSection, $strKey)}, false, 'test numeric undef value');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->numericGet($strSection, $strKey, undef, false, 1000)}, 1000, 'get numeric default value');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->numericSet($strSection, $strKey, undef, 0)}, true, 'set numeric 0 value');
$self->testResult(sub {$oIni->numericGet($strSection, $strKey)}, 0, ' check value');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->numericSet($strSection, $strKey, undef, 0)}, false, 'set numeric 0 value again');
$self->testResult(sub {$oIni->numericGet($strSection, $strKey)}, 0, ' check value');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->numericSet($strSection, $strKey, undef, -100)}, true, 'set numeric -100 value');
$self->testResult(sub {$oIni->numericGet($strSection, $strKey)}, -100, ' check value');
}
################################################################################################################################
if ($self->begin("Ini->keys()"))
{
my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false});
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->keys($strSection)}, '[undef]', 'section undefined');
#---------------------------------------------------------------------------------------------------------------------------
$oIni->set($strSection, 'a', undef, $strValue);
$oIni->set($strSection, 'c', undef, $strValue);
$oIni->set($strSection, 'b', undef, $strValue);
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oIni->keys($strSection)}, '(a, b, c)', 'sort forward (default)');
$self->testResult(sub {$oIni->keys($strSection, INI_SORT_FORWARD)}, '(a, b, c)', 'sort forward');
$self->testResult(sub {$oIni->keys($strSection, INI_SORT_REVERSE)}, '(c, b, a)', 'sort reverse');
$self->testResult(sub {sort($oIni->keys($strSection, INI_SORT_NONE))}, '(a, b, c)', 'sort none');
$self->testException(sub {sort($oIni->keys($strSection, BOGUS))}, ERROR_ASSERT, "invalid strSortOrder '" . BOGUS . "'");
}
}
1;