1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-06-20 23:59:28 +02:00
Files
.github
build
doc
lib
libc
src
test
certificate
code-count
data
expect
lib
pgBackRestTest
Common
Env
Module
Backup
Command
Common
CommonEncodePerlTest.pm
CommonIniPerlTest.pm
CommonIoBufferedPerlTest.pm
CommonIoHandlePerlTest.pm
CommonIoProcessPerlTest.pm
CommonLogPerlTest.pm
Info
Manifest
Mock
Performance
Protocol
Real
Storage
src
.gitignore
README.md
Vagrantfile
container.yaml
define.yaml
test.pl
travis.pl
.gitignore
.travis.yml
CODING.md
CONTRIBUTING.md
LICENSE
README.md
pgbackrest/test/lib/pgBackRestTest/Module/Common/CommonIniPerlTest.pm

534 lines
30 KiB
Perl

####################################################################################################################################
# Unit tests for Ini module
####################################################################################################################################
package pgBackRestTest::Module::Common::CommonIniPerlTest;
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]\n" .
"backrest-format=" . (defined($iFormat) ? $iFormat : $oIni->get(INI_SECTION_BACKREST, INI_KEY_FORMAT)) . "\n" .
"backrest-version=\"" . (defined($iVersion) ? $iVersion : $oIni->get(INI_SECTION_BACKREST, INI_KEY_VERSION)) . "\"\n" .
"\n" .
"[backrest]\n" .
"backrest-checksum=\"" .
(defined($strChecksum) ? $strChecksum : $oIni->get(INI_SECTION_BACKREST, INI_KEY_CHECKSUM)) . "\"\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, REPOSITORY_FORMAT, PROJECT_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, REPOSITORY_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 " . REPOSITORY_FORMAT . ' but found ' . (REPOSITORY_FORMAT - 1));
$oIni->numericSet(INI_SECTION_BACKREST, INI_KEY_FORMAT, undef, REPOSITORY_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)}, PROJECT_VERSION, 'version is updated on load');
$oIni->save();
$self->testResult(
sub {${storageTest()->get($strTestFile . INI_COPY_EXT)}},
$self->iniHeader($oIni, undef, PROJECT_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_CRYPTO,
"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_CRYPTO,
"unable to parse '$strTestFile'" .
"\nHINT: is or was the repo encrypted?");
}
################################################################################################################################
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;