From cc2372d2260d3a7a284b844c4b85ebf13ad2f479 Mon Sep 17 00:00:00 2001 From: Tim van Dijen <tvdijen@gmail.com> Date: Sat, 5 Feb 2022 12:28:09 +0100 Subject: [PATCH] Refactor getInteger/getOptionalInteger --- lib/SimpleSAML/Auth/State.php | 2 +- lib/SimpleSAML/Configuration.php | 116 +++++++++++------- lib/SimpleSAML/Locale/Language.php | 2 +- lib/SimpleSAML/Logger.php | 2 +- .../Logger/SyslogLoggingHandler.php | 2 +- lib/SimpleSAML/Memcache.php | 2 +- lib/SimpleSAML/Metadata/SAMLBuilder.php | 7 +- lib/SimpleSAML/Module.php | 2 +- lib/SimpleSAML/Session.php | 8 +- lib/SimpleSAML/SessionHandler.php | 2 +- lib/SimpleSAML/SessionHandlerStore.php | 2 +- lib/SimpleSAML/Store/RedisStore.php | 4 +- .../lib/Auth/Process/ExtendIdPSession.php | 2 +- modules/core/www/idp/logout-iframe-post.php | 4 +- modules/saml/lib/Auth/Source/SP.php | 8 +- modules/saml/lib/IdP/SAML2.php | 12 +- modules/saml/lib/Message.php | 10 +- tests/lib/SimpleSAML/ConfigurationTest.php | 104 +++++++++++----- 18 files changed, 184 insertions(+), 107 deletions(-) diff --git a/lib/SimpleSAML/Auth/State.php b/lib/SimpleSAML/Auth/State.php index b43f48f1b..69544cf8f 100644 --- a/lib/SimpleSAML/Auth/State.php +++ b/lib/SimpleSAML/Auth/State.php @@ -181,7 +181,7 @@ class State { if (self::$stateTimeout === null) { $globalConfig = Configuration::getInstance(); - self::$stateTimeout = $globalConfig->getInteger('session.state.timeout', 60 * 60); + self::$stateTimeout = $globalConfig->getOptionalInteger('session.state.timeout', 60 * 60); } return self::$stateTimeout; diff --git a/lib/SimpleSAML/Configuration.php b/lib/SimpleSAML/Configuration.php index e20140ac7..d06328a2c 100644 --- a/lib/SimpleSAML/Configuration.php +++ b/lib/SimpleSAML/Configuration.php @@ -653,36 +653,47 @@ class Configuration implements Utils\ClearableState /** * This function retrieves an integer configuration option. * - * An exception will be thrown if this option isn't an integer, or if this option isn't found, and no default value - * is given. - * - * @param string $name The name of the option. - * @param mixed $default A default value which will be returned if the option isn't found. The option will be - * required if this parameter isn't given. The default value can be any value, including - * null. + * An exception will be thrown if this option isn't an integer, or if this option isn't found. * - * @return int|mixed The option with the given name, or $default if the option isn't found and $default is - * specified. + * @param string $name The name of the option. + * @return int The option with the given name. * - * @throws \Exception If the option is not an integer. + * @throws \SimpleSAML\Assert\AssertionFailedException If the option is not an integer. */ - public function getInteger(string $name, $default = self::REQUIRED_OPTION) + public function getInteger(string $name): int { - $ret = $this->getValue($name, $default); + $ret = $this->getValue($name); - if ($ret === $default) { - // the option wasn't found, or it matches the default value. In any case, return this value - return $ret; - } + Assert::integer( + $ret, + sprintf('%s: The option %s is not a valid integer value.', $this->location, var_export($name, true)), + ); - if (!is_int($ret)) { - throw new \Exception( - $this->location . ': The option ' . var_export($name, true) . - ' is not a valid integer value.' - ); + return $ret; + } + + + /** + * This function retrieves an optional integer configuration option. + * + * An exception will be thrown if this option isn't an integer. + * + * @param string $name The name of the option. + * @param mixed $default A default value which will be returned if the option isn't found. + * The default value can be null or an integer. + * + * @return int|null The option with the given name, or $default if the option isn't found. + * + * @throws \SimpleSAML\Assert\AssertionFailedException If the option is not an integer. + */ + public function getOptionalInteger(string $name, ?int $default): ?int + { + if (!$this->hasValue($name)) { + // the option wasn't found, or it matches the default value. In any case, return this value + return $default; } - return $ret; + return $this->getInteger($name); } @@ -697,33 +708,56 @@ class Configuration implements Utils\ClearableState * @param string $name The name of the option. * @param int $minimum The smallest value which is allowed. * @param int $maximum The largest value which is allowed. - * @param mixed $default A default value which will be returned if the option isn't found. The option will be - * required if this parameter isn't given. The default value can be any value, including - * null. * - * @return int|mixed The option with the given name, or $default if the option isn't found and $default is - * specified. + * @return int The option with the given name. * - * @throws \Exception If the option is not in the range specified. + * @throws \SimpleSAML\Assert\AssertionFailedException If the option is not in the range specified. */ - public function getIntegerRange(string $name, int $minimum, int $maximum, $default = self::REQUIRED_OPTION) + public function getIntegerRange(string $name, int $minimum, int $maximum): int { - $ret = $this->getInteger($name, $default); + $ret = $this->getInteger($name); - if ($ret === $default) { - // the option wasn't found, or it matches the default value. In any case, return this value - return $ret; - } + Assert::range( + $ret, + $minimum, + $maximum, + sprintf( + '%s: Value of option %s is out of range. Value is %%s, allowed range is [%%2$s - %%3$s]', + $this->location, + var_export($name, true), + ), + ); - if ($ret < $minimum || $ret > $maximum) { - throw new \Exception( - $this->location . ': Value of option ' . var_export($name, true) . - ' is out of range. Value is ' . $ret . ', allowed range is [' - . $minimum . ' - ' . $maximum . ']' - ); + return $ret; + } + + + /** + * This function retrieves an optional integer configuration option where the value must be in the specified range. + * + * An exception will be thrown if: + * - the option isn't an integer + * - the value is outside of the allowed range + * + * @param string $name The name of the option. + * @param int $minimum The smallest value which is allowed. + * @param int $maximum The largest value which is allowed. + * @param int|null $default A default value which will be returned if the option isn't found. + * The default value can be null or an integer. + * + * @return int|null The option with the given name, or $default if the option isn't found and $default is + * specified. + * + * @throws \SimpleSAML\Assert\AssertionFailedException If the option is not in the range specified. + */ + public function getOptionalIntegerRange(string $name, int $minimum, int $maximum, ?int $default): ?int + { + if (!$this->hasValue($name)) { + // the option wasn't found, or it matches the default value. In any case, return this value + return $default; } - return $ret; + return $this->getInteger($name, $minimum, $maximum); } diff --git a/lib/SimpleSAML/Locale/Language.php b/lib/SimpleSAML/Locale/Language.php index 30b5e51bc..ba8b826cf 100644 --- a/lib/SimpleSAML/Locale/Language.php +++ b/lib/SimpleSAML/Locale/Language.php @@ -434,7 +434,7 @@ class Language $name = $config->getOptionalString('language.cookie.name', 'language'); $params = [ - 'lifetime' => ($config->getInteger('language.cookie.lifetime', 60 * 60 * 24 * 900)), + 'lifetime' => ($config->getOptionalInteger('language.cookie.lifetime', 60 * 60 * 24 * 900)), 'domain' => ($config->getOptionalString('language.cookie.domain', '')), 'path' => ($config->getOptionalString('language.cookie.path', '/')), 'secure' => ($config->getOptionalBoolean('language.cookie.secure', false)), diff --git a/lib/SimpleSAML/Logger.php b/lib/SimpleSAML/Logger.php index c6cb93848..15575a58e 100644 --- a/lib/SimpleSAML/Logger.php +++ b/lib/SimpleSAML/Logger.php @@ -449,7 +449,7 @@ class Logger $config = Configuration::getInstance(); // setting minimum log_level - self::$logLevel = $config->getInteger('logging.level', self::INFO); + self::$logLevel = $config->getOptionalInteger('logging.level', self::INFO); // get the metadata handler option from the configuration if (is_null($handler)) { diff --git a/lib/SimpleSAML/Logger/SyslogLoggingHandler.php b/lib/SimpleSAML/Logger/SyslogLoggingHandler.php index 9f7afb60c..40a0923f6 100644 --- a/lib/SimpleSAML/Logger/SyslogLoggingHandler.php +++ b/lib/SimpleSAML/Logger/SyslogLoggingHandler.php @@ -27,7 +27,7 @@ class SyslogLoggingHandler implements LoggingHandlerInterface */ public function __construct(Configuration $config) { - $facility = $config->getInteger('logging.facility', defined('LOG_LOCAL5') ? constant('LOG_LOCAL5') : LOG_USER); + $facility = $config->getOptionalInteger('logging.facility', defined('LOG_LOCAL5') ? constant('LOG_LOCAL5') : LOG_USER); // Remove any non-printable characters before storing $processname = preg_replace( diff --git a/lib/SimpleSAML/Memcache.php b/lib/SimpleSAML/Memcache.php index 1969fa09b..493db7f30 100644 --- a/lib/SimpleSAML/Memcache.php +++ b/lib/SimpleSAML/Memcache.php @@ -375,7 +375,7 @@ class Memcache $config = Configuration::getInstance(); // get the expire-value from the configuration - $expire = $config->getInteger('memcache_store.expires', 0); + $expire = $config->getOptionalInteger('memcache_store.expires', 0); // it must be a positive integer if ($expire < 0) { diff --git a/lib/SimpleSAML/Metadata/SAMLBuilder.php b/lib/SimpleSAML/Metadata/SAMLBuilder.php index d0bfd6e0a..7e4933078 100644 --- a/lib/SimpleSAML/Metadata/SAMLBuilder.php +++ b/lib/SimpleSAML/Metadata/SAMLBuilder.php @@ -431,9 +431,12 @@ class SAMLBuilder * of requested attributes */ $attributeconsumer = new AttributeConsumingService(); - $attributeconsumer->setIndex($metadata->getOptionalInteger('attributes.index', 0)); - $attributeconsumer->setIsDefault($metadata->getOptionalBoolean('attributes.isDefault', false)); + + if ($metadata->hasValue('attributes.isDefault')) { + $attributeconsumer->setIsDefault($metadata->getBoolean('attributes.isDefault', false)); + } + $attributeconsumer->setServiceName($name); $attributeconsumer->setServiceDescription($metadata->getLocalizedString('description', [])); diff --git a/lib/SimpleSAML/Module.php b/lib/SimpleSAML/Module.php index d3ea8d94a..cc3c132cc 100644 --- a/lib/SimpleSAML/Module.php +++ b/lib/SimpleSAML/Module.php @@ -307,7 +307,7 @@ class Module // "public" allows response caching even if the request was authenticated, // which is exactly what we want for static resources 'public' => true, - 'max_age' => strval($cacheConfig->getInteger('max_age', 86400)) + 'max_age' => strval($cacheConfig->getOptionalInteger('max_age', 86400)) ]); $response->setAutoLastModified(); if ($cacheConfig->getOptionalBoolean('etag', false)) { diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php index f108f8e56..2e25d0ebf 100644 --- a/lib/SimpleSAML/Session.php +++ b/lib/SimpleSAML/Session.php @@ -575,7 +575,7 @@ class Session implements Utils\ClearableState public function setRememberMeExpire(int $lifetime = null): void { if ($lifetime === null) { - $lifetime = self::$config->getInteger('session.rememberme.lifetime', 14 * 86400); + $lifetime = self::$config->getOptionalInteger('session.rememberme.lifetime', 14 * 86400); } $this->rememberMeExpire = time() + $lifetime; @@ -611,7 +611,7 @@ class Session implements Utils\ClearableState $data['AuthnInstant'] = time(); } - $maxSessionExpire = time() + self::$config->getInteger('session.duration', 8 * 60 * 60); + $maxSessionExpire = time() + self::$config->getOptionalInteger('session.duration', 8 * 60 * 60); if (!isset($data['Expire']) || $data['Expire'] > $maxSessionExpire) { // unset, or beyond our session lifetime. Clamp it to our maximum session lifetime $data['Expire'] = $maxSessionExpire; @@ -809,7 +809,7 @@ class Session implements Utils\ClearableState $this->markDirty(); if ($expire === null) { - $expire = time() + self::$config->getInteger('session.duration', 8 * 60 * 60); + $expire = time() + self::$config->getOptionalInteger('session.duration', 8 * 60 * 60); } $this->authData[$authority]['Expire'] = $expire; @@ -884,7 +884,7 @@ class Session implements Utils\ClearableState if ($timeout === null) { // use the default timeout - $timeout = self::$config->getInteger('session.datastore.timeout', null); + $timeout = self::$config->getOptionalInteger('session.datastore.timeout', null); if ($timeout !== null) { if ($timeout <= 0) { throw new \Exception( diff --git a/lib/SimpleSAML/SessionHandler.php b/lib/SimpleSAML/SessionHandler.php index 402631f6d..b15f0513d 100644 --- a/lib/SimpleSAML/SessionHandler.php +++ b/lib/SimpleSAML/SessionHandler.php @@ -158,7 +158,7 @@ abstract class SessionHandler $config = Configuration::getInstance(); return [ - 'lifetime' => $config->getInteger('session.cookie.lifetime', 0), + 'lifetime' => $config->getOptionalInteger('session.cookie.lifetime', 0), 'path' => $config->getOptionalString('session.cookie.path', '/'), 'domain' => $config->getOptionalString('session.cookie.domain', null), 'secure' => $config->getOptionalBoolean('session.cookie.secure', false), diff --git a/lib/SimpleSAML/SessionHandlerStore.php b/lib/SimpleSAML/SessionHandlerStore.php index f4f89e710..a995551d8 100644 --- a/lib/SimpleSAML/SessionHandlerStore.php +++ b/lib/SimpleSAML/SessionHandlerStore.php @@ -79,7 +79,7 @@ class SessionHandlerStore extends SessionHandlerCookie $sessionId = $session->getSessionId(); $config = Configuration::getInstance(); - $sessionDuration = $config->getInteger('session.duration', 8 * 60 * 60); + $sessionDuration = $config->getOptionalInteger('session.duration', 8 * 60 * 60); $expire = time() + $sessionDuration; $this->store->set('session', $sessionId, $session, $expire); diff --git a/lib/SimpleSAML/Store/RedisStore.php b/lib/SimpleSAML/Store/RedisStore.php index 53f08675c..7781d3c10 100644 --- a/lib/SimpleSAML/Store/RedisStore.php +++ b/lib/SimpleSAML/Store/RedisStore.php @@ -36,10 +36,10 @@ class RedisStore implements StoreInterface $config = Configuration::getInstance(); $host = $config->getOptionalString('store.redis.host', 'localhost'); - $port = $config->getInteger('store.redis.port', 6379); + $port = $config->getOptionalInteger('store.redis.port', 6379); $prefix = $config->getOptionalString('store.redis.prefix', 'SimpleSAMLphp'); $password = $config->getOptionalString('store.redis.password', null); - $database = $config->getInteger('store.redis.database', 0); + $database = $config->getOptionalInteger('store.redis.database', 0); $redis = new Client( [ diff --git a/modules/core/lib/Auth/Process/ExtendIdPSession.php b/modules/core/lib/Auth/Process/ExtendIdPSession.php index 40f43e37a..f3931f506 100644 --- a/modules/core/lib/Auth/Process/ExtendIdPSession.php +++ b/modules/core/lib/Auth/Process/ExtendIdPSession.php @@ -28,7 +28,7 @@ class ExtendIdPSession extends Auth\ProcessingFilter $delta = $state['Expire'] - $now; $globalConfig = Configuration::getInstance(); - $sessionDuration = $globalConfig->getInteger('session.duration', 28800); // 8*60*60 + $sessionDuration = $globalConfig->getOptionalInteger('session.duration', 28800); // 8*60*60 // Extend only if half of session duration already passed if ($delta >= ($sessionDuration * 0.5)) { diff --git a/modules/core/www/idp/logout-iframe-post.php b/modules/core/www/idp/logout-iframe-post.php index 31217b217..d20af29fc 100644 --- a/modules/core/www/idp/logout-iframe-post.php +++ b/modules/core/www/idp/logout-iframe-post.php @@ -30,9 +30,9 @@ $lr = \SimpleSAML\Module\saml\Message::buildLogoutRequest($idpMetadata, $spMetad $lr->setSessionIndex($association['saml:SessionIndex']); $lr->setNameId($association['saml:NameID']); -$assertionLifetime = $spMetadata->getInteger('assertion.lifetime', null); +$assertionLifetime = $spMetadata->getOptionalInteger('assertion.lifetime', null); if ($assertionLifetime === null) { - $assertionLifetime = $idpMetadata->getInteger('assertion.lifetime', 300); + $assertionLifetime = $idpMetadata->getOptionalInteger('assertion.lifetime', 300); } $lr->setNotOnOrAfter(time() + $assertionLifetime); diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php index 81ef882de..0c49cae5f 100644 --- a/modules/saml/lib/Auth/Source/SP.php +++ b/modules/saml/lib/Auth/Source/SP.php @@ -539,10 +539,10 @@ class SP extends \SimpleSAML\Auth\Source if (isset($state['saml:ProxyCount']) && $state['saml:ProxyCount'] !== null) { $ar->setProxyCount($state['saml:ProxyCount']); - } elseif ($idpMetadata->getInteger('ProxyCount', null) !== null) { - $ar->setProxyCount($idpMetadata->getInteger('ProxyCount', null)); - } elseif ($this->metadata->getInteger('ProxyCount', null) !== null) { - $ar->setProxyCount($this->metadata->getInteger('ProxyCount', null)); + } elseif ($idpMetadata->hasValue('ProxyCount')) { + $ar->setProxyCount($idpMetadata->getInteger('ProxyCount')); + } elseif ($this->metadata->hasValue('ProxyCount')) { + $ar->setProxyCount($this->metadata->getInteger('ProxyCount')); } $requesterID = []; diff --git a/modules/saml/lib/IdP/SAML2.php b/modules/saml/lib/IdP/SAML2.php index 733c0b113..c068e524e 100644 --- a/modules/saml/lib/IdP/SAML2.php +++ b/modules/saml/lib/IdP/SAML2.php @@ -458,7 +458,7 @@ class SAML2 $IDPList = array_unique(array_merge($IDPList, $spMetadata->getArrayizeString('IDPList', []))); if ($ProxyCount === null) { - $ProxyCount = $spMetadata->getInteger('ProxyCount', null); + $ProxyCount = $spMetadata->getOptionalInteger('ProxyCount', null); } if (!$forceAuthn) { @@ -1151,9 +1151,9 @@ class SAML2 $a->setNotBefore($now - 30); - $assertionLifetime = $spMetadata->getInteger('assertion.lifetime', null); + $assertionLifetime = $spMetadata->getOptionalInteger('assertion.lifetime', null); if ($assertionLifetime === null) { - $assertionLifetime = $idpMetadata->getInteger('assertion.lifetime', 300); + $assertionLifetime = $idpMetadata->getOptionalInteger('assertion.lifetime', 300); } $a->setNotOnOrAfter($now + $assertionLifetime); @@ -1171,7 +1171,7 @@ class SAML2 $sessionStart = $state['AuthnInstant']; } - $sessionLifetime = $config->getInteger('session.duration', 8 * 60 * 60); + $sessionLifetime = $config->getOptionalInteger('session.duration', 8 * 60 * 60); $a->setSessionNotOnOrAfter($sessionStart + $sessionLifetime); $randomUtils = new Utils\Random(); @@ -1397,9 +1397,9 @@ class SAML2 $lr->setSessionIndex($association['saml:SessionIndex']); $lr->setNameId($association['saml:NameID']); - $assertionLifetime = $spMetadata->getInteger('assertion.lifetime', null); + $assertionLifetime = $spMetadata->getOptionalInteger('assertion.lifetime', null); if ($assertionLifetime === null) { - $assertionLifetime = $idpMetadata->getInteger('assertion.lifetime', 300); + $assertionLifetime = $idpMetadata->getOptionalInteger('assertion.lifetime', 300); } $lr->setNotOnOrAfter(time() + $assertionLifetime); diff --git a/modules/saml/lib/Message.php b/modules/saml/lib/Message.php index ade161862..8eb1c8428 100644 --- a/modules/saml/lib/Message.php +++ b/modules/saml/lib/Message.php @@ -495,8 +495,12 @@ class Message $issuer = new Issuer(); $issuer->setValue($spMetadata->getString('entityid')); $ar->setIssuer($issuer); - $ar->setAssertionConsumerServiceIndex($spMetadata->getInteger('AssertionConsumerServiceIndex', null)); - $ar->setAttributeConsumingServiceIndex($spMetadata->getInteger('AttributeConsumingServiceIndex', null)); + $ar->setAssertionConsumerServiceIndex( + $spMetadata->getOptionalInteger('AssertionConsumerServiceIndex', null) + ); + $ar->setAttributeConsumingServiceIndex( + $spMetadata->getOptionalInteger('AttributeConsumingServiceIndex', null) + ); if ($spMetadata->hasValue('AuthnContextClassRef')) { $accr = $spMetadata->getArrayizeString('AuthnContextClassRef'); @@ -652,7 +656,7 @@ class Message // check various properties of the assertion $config = Configuration::getInstance(); - $allowed_clock_skew = $config->getInteger('assertion.allowed_clock_skew', 180); + $allowed_clock_skew = $config->getOptionalInteger('assertion.allowed_clock_skew', 180); $options = [ 'options' => [ 'default' => 180, diff --git a/tests/lib/SimpleSAML/ConfigurationTest.php b/tests/lib/SimpleSAML/ConfigurationTest.php index 38cdee13c..ba7a5dd5c 100644 --- a/tests/lib/SimpleSAML/ConfigurationTest.php +++ b/tests/lib/SimpleSAML/ConfigurationTest.php @@ -354,33 +354,42 @@ class ConfigurationTest extends ClearStateTestCase { $c = Configuration::loadFromArray([ 'int_opt' => 42, + 'wrong_opt' => 'test', ]); - $this->assertEquals($c->getInteger('missing_opt', '--missing--'), '--missing--'); - $this->assertEquals($c->getInteger('int_opt', '--missing--'), 42); - } + // Normal use + $this->assertEquals($c->getInteger('int_opt'), 42); - /** - * Test \SimpleSAML\Configuration::getInteger() missing option - */ - public function testGetIntegerMissing(): void - { - $this->expectException(Exception::class); - $c = Configuration::loadFromArray([]); + // Missing option + $this->expectException(AssertionFailedException::class); $c->getInteger('missing_opt'); + + // Invalid option type + $this->expectException(AssertionFailedException::class); + $c->getInteger('wrong_opt'); } /** - * Test \SimpleSAML\Configuration::getInteger() wrong option + * Test \SimpleSAML\Configuration::getOptionalInteger() */ - public function testGetIntegerWrong(): void + public function testGetOptionalInteger(): void { - $this->expectException(Exception::class); $c = Configuration::loadFromArray([ - 'wrong' => '42', + 'int_opt' => 42, + 'wrong_opt' => 'test', ]); - $c->getInteger('wrong'); + + + // Normal use + $this->assertEquals($c->getOptionalInteger('int_opt', 42), 42); + + // Missing option + $this->assertEquals($c->getOptionalInteger('missing_opt', 32), 32); + + // Invalid option type + $this->expectException(AssertionFailedException::class); + $c->getOptionalInteger('wrong_opt', 10); } @@ -390,36 +399,63 @@ class ConfigurationTest extends ClearStateTestCase public function testGetIntegerRange(): void { $c = Configuration::loadFromArray([ - 'int_opt' => 42, + 'min_opt' => 0, + 'max_opt' => 100, + 'wrong_opt' => 'test', ]); - $this->assertEquals($c->getIntegerRange('missing_opt', 0, 100, '--missing--'), '--missing--'); - $this->assertEquals($c->getIntegerRange('int_opt', 0, 100), 42); - } + // Normal use + $this->assertEquals($c->getIntegerRange('min_opt', 0, 100), 0); + $this->assertEquals($c->getIntegerRange('max_opt', 0, 100), 100); - /** - * Test \SimpleSAML\Configuration::getIntegerRange() below limit - */ - public function testGetIntegerRangeBelow(): void - { - $this->expectException(Exception::class); - $c = Configuration::loadFromArray([ - 'int_opt' => 9, - ]); - $this->assertEquals($c->getIntegerRange('int_opt', 10, 100), 42); + // Missing option + $this->expectException(AssertionFailedException::class); + $c->getIntegerRange('missing_opt', 0, 100); + + // Invalid option type + $this->expectException(AssertionFailedException::class); + $c->getIntegerRange('wrong_opt', 0, 100); + + // Below range + $this->expectException(AssertionFailedException::class); + $c->getIntegerRange('min_opt', 1, 100); + + // Above range + $this->expectException(AssertionFailedException::class); + $c->getIntegerRange('max_opt', 0, 99); } /** - * Test \SimpleSAML\Configuration::getIntegerRange() above limit + * Test \SimpleSAML\Configuration::getOptionalIntegerRange() */ - public function testGetIntegerRangeAbove(): void + public function testGetOptionalIntegerRange(): void { - $this->expectException(Exception::class); $c = Configuration::loadFromArray([ - 'int_opt' => 101, + 'min_opt' => 0, + 'max_opt' => 100, + 'wrong_opt' => 'test', ]); - $this->assertEquals($c->getIntegerRange('int_opt', 10, 100), 42); + + + // Normal use + $this->assertEquals($c->getOptionalIntegerRange('min_opt', 0, 100, 50), 0); + $this->assertEquals($c->getOptionalIntegerRange('max_opt', 0, 100, 50), 100); + + // Missing option + $this->assertEquals($c->getOptionalIntegerRange('missing_opt', 0, 100, 50), 50); + + // Invalid option type + $this->expectException(AssertionFailedException::class); + $c->getOptionalIntegerRange('wrong_opt', 0, 100, null); + + // Below range + $this->expectException(AssertionFailedException::class); + $c->getOptionalIntegerRange('min_opt', 1, 100, null); + + // Above range + $this->expectException(AssertionFailedException::class); + $c->getOptionalIntegerRange('max_opt', 0, 99, null); } -- GitLab