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
David Steele de7fc37f88 Storage and IO layer refactor:
Refactor storage layer to allow for new repository filesystems using drivers. (Reviewed by Cynthia Shang.)
Refactor IO layer to allow for new compression formats, checksum types, and other capabilities using filters. (Reviewed by Cynthia Shang.)
2017-06-09 17:51:41 -04:00

516 lines
29 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::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');
}
################################################################################################################################
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;