From 3488270c7820fa9df0f04fd166e602846626b64b Mon Sep 17 00:00:00 2001 From: gordinskiy Date: Mon, 28 Oct 2024 22:14:19 +0100 Subject: [PATCH] Fix comparisons with NAN --- src/Assert.php | 60 +++++++++++++++++++++++++++++++++++++++++++- tests/AssertTest.php | 52 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/Assert.php b/src/Assert.php index f02b8c9..c4435de 100644 --- a/src/Assert.php +++ b/src/Assert.php @@ -162,7 +162,7 @@ public static function float($value, $message = '') */ public static function numeric($value, $message = '') { - if (!\is_numeric($value)) { + if (!\is_numeric($value) || \is_float($value) && \is_nan($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a numeric. Got: %s', static::typeToString($value) @@ -889,6 +889,14 @@ public static function notSame($value, $expect, $message = '') */ public static function greaterThan($value, $limit, $message = '') { + if (is_numeric($value)) { + self::numeric($value); + } + + if (is_numeric($value)) { + self::numeric($limit); + } + if ($value <= $limit) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value greater than %2$s. Got: %s', @@ -909,6 +917,14 @@ public static function greaterThan($value, $limit, $message = '') */ public static function greaterThanEq($value, $limit, $message = '') { + if (is_numeric($value)) { + self::numeric($value); + } + + if (is_numeric($limit)) { + self::numeric($limit); + } + if ($value < $limit) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value greater than or equal to %2$s. Got: %s', @@ -929,6 +945,14 @@ public static function greaterThanEq($value, $limit, $message = '') */ public static function lessThan($value, $limit, $message = '') { + if (is_numeric($value)) { + self::numeric($value); + } + + if (is_numeric($limit)) { + self::numeric($limit); + } + if ($value >= $limit) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value less than %2$s. Got: %s', @@ -949,6 +973,14 @@ public static function lessThan($value, $limit, $message = '') */ public static function lessThanEq($value, $limit, $message = '') { + if (is_numeric($value)) { + self::numeric($value); + } + + if (is_numeric($limit)) { + self::numeric($limit); + } + if ($value > $limit) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value less than or equal to %2$s. Got: %s', @@ -972,6 +1004,18 @@ public static function lessThanEq($value, $limit, $message = '') */ public static function range($value, $min, $max, $message = '') { + if (is_numeric($value)) { + self::numeric($value); + } + + if (is_numeric($min)) { + self::numeric($min); + } + + if (is_numeric($max)) { + self::numeric($max); + } + if ($value < $min || $value > $max) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value between %2$s and %3$s. Got: %s', @@ -1401,6 +1445,8 @@ public static function length($value, $length, $message = '') */ public static function minLength($value, $min, $message = '') { + assert::numeric($min); + if (static::strlen($value) < $min) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain at least %2$s characters. Got: %s', @@ -1423,6 +1469,8 @@ public static function minLength($value, $min, $message = '') */ public static function maxLength($value, $max, $message = '') { + self::numeric($max); + if (static::strlen($value) > $max) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain at most %2$s characters. Got: %s', @@ -1446,6 +1494,9 @@ public static function maxLength($value, $max, $message = '') */ public static function lengthBetween($value, $min, $max, $message = '') { + self::numeric($min); + self::numeric($max); + $length = static::strlen($value); if ($length < $min || $length > $max) { @@ -1805,6 +1856,8 @@ public static function count($array, $number, $message = '') */ public static function minCount($array, $min, $message = '') { + self::numeric($min); + if (\count($array) < $min) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array to contain at least %2$d elements. Got: %d', @@ -1825,6 +1878,8 @@ public static function minCount($array, $min, $message = '') */ public static function maxCount($array, $max, $message = '') { + self::numeric($max); + if (\count($array) > $max) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array to contain at most %2$d elements. Got: %d', @@ -1846,6 +1901,9 @@ public static function maxCount($array, $max, $message = '') */ public static function countBetween($array, $min, $max, $message = '') { + self::numeric($min); + self::numeric($max); + $count = \count($array); if ($count < $min || $count > $max) { diff --git a/tests/AssertTest.php b/tests/AssertTest.php index 87a1bb1..5ae5f08 100644 --- a/tests/AssertTest.php +++ b/tests/AssertTest.php @@ -60,6 +60,10 @@ public function getTests() $normalList = array('foo' => 'b', 3); unset($normalList['foo']); + $pastDate = (new DateTime())->modify('-1 year'); + $todayDate = new DateTime(); + $futureDate = (new DateTime())->modify('+1 year'); + return array( array('string', array('value'), true), array('string', array(''), true), @@ -95,6 +99,8 @@ public function getTests() array('numeric', array(123), true), array('numeric', array('123'), true), array('numeric', array('foo'), false), + array('numeric', array(NAN), false), + array('numeric', array('NAN'), false), array('natural', array(0), true), array('natural', array(1), true), array('natural', array(-1), false), @@ -233,18 +239,47 @@ public function getTests() array('notSame', array(1, true), true), array('greaterThan', array(1, 0), true), array('greaterThan', array(0, 0), false), + array('greaterThan', array(NAN, 1), false), + array('greaterThan', array(1, NAN), false), + array('greaterThan', array(NAN, NAN), false), + array('greaterThan', array($futureDate, $pastDate), true), + array('greaterThan', array($pastDate, $futureDate), false), + array('greaterThan', array($pastDate, $pastDate), false), array('greaterThanEq', array(2, 1), true), array('greaterThanEq', array(1, 1), true), array('greaterThanEq', array(0, 1), false), + array('greaterThanEq', array(NAN, 1), false), + array('greaterThanEq', array($futureDate, $pastDate), true), + array('greaterThanEq', array($pastDate, $pastDate), true), + array('greaterThanEq', array($pastDate, $futureDate), false), array('lessThan', array(0, 1), true), array('lessThan', array(1, 1), false), + array('lessThan', array(NAN, 1), false), + array('lessThan', array(1, NAN), false), + array('lessThan', array(NAN, NAN), false), + array('lessThan', array($pastDate, $futureDate), true), + array('lessThan', array($pastDate, $pastDate), false), + array('lessThan', array($futureDate, $pastDate), false), array('lessThanEq', array(0, 1), true), array('lessThanEq', array(1, 1), true), array('lessThanEq', array(2, 1), false), + array('lessThanEq', array(NAN, 1), false), + array('lessThanEq', array(1, NAN), false), + array('lessThanEq', array(NAN, NAN), false), + array('lessThanEq', array($pastDate, $futureDate), true), + array('lessThanEq', array($pastDate, $pastDate), true), + array('lessThanEq', array($futureDate, $pastDate), false), array('range', array(1, 1, 2), true), array('range', array(2, 1, 2), true), array('range', array(0, 1, 2), false), array('range', array(3, 1, 2), false), + array('range', array(NAN, 1, 2), false), + array('range', array(2, NAN, 2), false), + array('range', array(2, 1, NAN), false), + array('range', array(2, NAN, NAN), false), + array('range', array($todayDate, $pastDate, $futureDate), true), + array('range', array($todayDate, $pastDate, $pastDate), false), + array('range', array($pastDate, $todayDate, $futureDate), false), array('oneOf', array(1, array(1, 2, 3)), true), array('oneOf', array(1, array('1', '2', '3')), false), array('inArray', array(1, array(1, 2, 3)), true), @@ -390,15 +425,18 @@ public function getTests() array('upper', array(''), false), array('length', array('abcd', 4), true), array('length', array('abc', 4), false), + array('length', array('abc', NAN), false), array('length', array('abcde', 4), false), array('length', array('äbcd', 4), true, true), array('length', array('äbc', 4), false, true), array('length', array('äbcde', 4), false, true), array('length', array('あbcd', 4), true, true), // 'HIRAGANA LETTER A' (U+3042) + array('length', array('あbcd', 4), NAN, true), array('length', array('あbc', 4), false, true), array('length', array('あbcde', 4), false, true), array('minLength', array('abcd', 4), true), array('minLength', array('abcde', 4), true), + array('minLength', array('abcde', NAN), false), array('minLength', array('abc', 4), false), array('minLength', array('äbcd', 4), true, true), array('minLength', array('äbcde', 4), true, true), @@ -408,16 +446,21 @@ public function getTests() array('minLength', array('あbc', 4), false, true), array('maxLength', array('abcd', 4), true), array('maxLength', array('abc', 4), true), + array('maxLength', array('abc', NAN), false), array('maxLength', array('abcde', 4), false), array('maxLength', array('äbcd', 4), true, true), array('maxLength', array('äbc', 4), true, true), array('maxLength', array('äbcde', 4), false, true), array('maxLength', array('あbcd', 4), true, true), array('maxLength', array('あbc', 4), true, true), + array('maxLength', array('あbc', NAN), false, true), array('maxLength', array('あbcde', 4), false, true), array('lengthBetween', array('abcd', 3, 5), true), array('lengthBetween', array('abc', 3, 5), true), array('lengthBetween', array('abcde', 3, 5), true), + array('lengthBetween', array('abcde', 3, NAN), false), + array('lengthBetween', array('abcde', NAN, 5), false), + array('lengthBetween', array('abcde', NAN, NAN), false), array('lengthBetween', array('ab', 3, 5), false), array('lengthBetween', array('abcdef', 3, 5), false), array('lengthBetween', array('äbcd', 3, 5), true, true), @@ -428,6 +471,9 @@ public function getTests() array('lengthBetween', array('あbcd', 3, 5), true, true), array('lengthBetween', array('あbc', 3, 5), true, true), array('lengthBetween', array('あbcde', 3, 5), true, true), + array('lengthBetween', array('あbcde', NAN, 5), false, true), + array('lengthBetween', array('あbcde', 3, NAN), false, true), + array('lengthBetween', array('あbcde', NAN, NAN), false, true), array('lengthBetween', array('あb', 3, 5), false, true), array('lengthBetween', array('あbcdef', 3, 5), false, true), array('fileExists', array(__FILE__), true), @@ -486,18 +532,24 @@ public function getTests() array('validArrayKey', array(new ToStringClass('testString')), false), array('validArrayKey', array(self::getResource()), false), array('count', array(array(0, 1, 2), 3), true), + array('count', array(array(0, 1, 2), NAN), false), array('count', array(array(0, 1, 2), 2), false), array('minCount', array(array(0), 2), false), array('minCount', array(array(0, 1), 2), true), array('minCount', array(array(0, 1, 2), 2), true), + array('minCount', array(array(0, 1, 2), NAN), false), array('maxCount', array(array(0, 1, 2), 2), false), array('maxCount', array(array(0, 1), 2), true), array('maxCount', array(array(0), 2), true), + array('maxCount', array(array(0), NAN), false), array('countBetween', array(array(0, 1, 2), 4, 5), false), array('countBetween', array(array(0, 1, 2), 3, 5), true), array('countBetween', array(array(0, 1, 2), 1, 2), false), array('countBetween', array(array(0, 1, 2), 2, 5), true), array('countBetween', array(array(0, 1, 2), 2, 3), true), + array('countBetween', array(array(0, 1, 2), NAN, 3), false), + array('countBetween', array(array(0, 1, 2), 2, NAN), false), + array('countBetween', array(array(0, 1, 2), NAN, NAN), false), array('isList', array(array(1, 2, 3)), true), array('isList', array(array()), true), array('isList', array(array(0 => 1, 2 => 3)), false),