From 8f409c7d93ac1aed2b6c4e674971fce24423f82e Mon Sep 17 00:00:00 2001 From: Jan Sorgalla Date: Mon, 6 Jul 2015 10:21:01 +0200 Subject: [PATCH 1/7] Reject some() (and any()) if the input array contains not enough items --- src/functions.php | 21 ++++++++++++++---- tests/FunctionAnyTest.php | 22 +++++++++++++++++-- tests/FunctionSomeTest.php | 44 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 8 deletions(-) diff --git a/src/functions.php b/src/functions.php index 9b361dd9..08b91c1d 100644 --- a/src/functions.php +++ b/src/functions.php @@ -64,12 +64,25 @@ function some($promisesOrValues, $howMany) { return resolve($promisesOrValues) ->then(function ($array) use ($howMany) { - if (!is_array($array) || !$array || $howMany < 1) { - return resolve([]); + if (!is_array($array) || $howMany < 1) { + return []; + } + + $len = count($array); + + if ($len < $howMany) { + throw new \RangeException( + sprintf( + 'Input array must contain at least %d item%s but contains only %s item%s.', + $howMany, + 1 === $howMany ? '' : 's', + $len, + 1 === $len ? '' : 's' + ) + ); } - return new Promise(function ($resolve, $reject, $notify) use ($array, $howMany) { - $len = count($array); + return new Promise(function ($resolve, $reject, $notify) use ($array, $howMany, $len) { $toResolve = min($howMany, $len); $toReject = ($len - $toResolve) + 1; $values = []; diff --git a/tests/FunctionAnyTest.php b/tests/FunctionAnyTest.php index bf8a0db4..9da1ee3f 100644 --- a/tests/FunctionAnyTest.php +++ b/tests/FunctionAnyTest.php @@ -5,15 +5,33 @@ class FunctionAnyTest extends TestCase { /** @test */ - public function shouldResolveToNullWithEmptyInputArray() + public function shouldRejectWithRangeExceptionWithEmptyInputArray() { $mock = $this->createCallableMock(); $mock ->expects($this->once()) ->method('__invoke') - ->with($this->identicalTo(null)); + ->with( + $this->callback(function($exception){ + return $exception instanceof \RangeException && + 'Input array must contain at least 1 item but contains only 0 items.' === $exception->getMessage(); + }) + ); any([]) + ->then($this->expectCallableNever(), $mock); + } + + /** @test */ + public function shouldResolveToNullWithNonArrayInput() + { + $mock = $this->createCallableMock(); + $mock + ->expects($this->once()) + ->method('__invoke') + ->with($this->identicalTo(null)); + + any(null) ->then($mock); } diff --git a/tests/FunctionSomeTest.php b/tests/FunctionSomeTest.php index 09e53504..6a7030ee 100644 --- a/tests/FunctionSomeTest.php +++ b/tests/FunctionSomeTest.php @@ -5,17 +5,57 @@ class FunctionSomeTest extends TestCase { /** @test */ - public function shouldResolveEmptyInput() + public function shouldRejectWithRangeExceptionWithEmptyInputArray() { $mock = $this->createCallableMock(); $mock ->expects($this->once()) ->method('__invoke') - ->with($this->identicalTo([])); + ->with( + $this->callback(function($exception){ + return $exception instanceof \RangeException && + 'Input array must contain at least 1 item but contains only 0 items.' === $exception->getMessage(); + }) + ); some( [], 1 + )->then($this->expectCallableNever(), $mock); + } + + /** @test */ + public function shouldRejectWithRangeExceptionWithInputArrayContainingNotEnoughItems() + { + $mock = $this->createCallableMock(); + $mock + ->expects($this->once()) + ->method('__invoke') + ->with( + $this->callback(function($exception){ + return $exception instanceof \RangeException && + 'Input array must contain at least 4 items but contains only 3 items.' === $exception->getMessage(); + }) + ); + + some( + [1, 2, 3], + 4 + )->then($this->expectCallableNever(), $mock); + } + + /** @test */ + public function shouldResolveToEmptyArrayWithNonArrayInput() + { + $mock = $this->createCallableMock(); + $mock + ->expects($this->once()) + ->method('__invoke') + ->with($this->identicalTo([])); + + some( + null, + 1 )->then($mock); } From 23859e106d0badffa3fb04d6140a66f59c39d005 Mon Sep 17 00:00:00 2001 From: Jan Sorgalla Date: Mon, 6 Jul 2015 10:41:26 +0200 Subject: [PATCH 2/7] Use own RangeException --- src/Exception/RangeException.php | 7 +++++++ src/functions.php | 2 +- tests/FunctionAnyTest.php | 4 +++- tests/FunctionSomeTest.php | 10 ++++++---- 4 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 src/Exception/RangeException.php diff --git a/src/Exception/RangeException.php b/src/Exception/RangeException.php new file mode 100644 index 00000000..ad698eeb --- /dev/null +++ b/src/Exception/RangeException.php @@ -0,0 +1,7 @@ +method('__invoke') ->with( $this->callback(function($exception){ - return $exception instanceof \RangeException && + return $exception instanceof RangeException && 'Input array must contain at least 1 item but contains only 0 items.' === $exception->getMessage(); }) ); diff --git a/tests/FunctionSomeTest.php b/tests/FunctionSomeTest.php index 6a7030ee..8f93f7af 100644 --- a/tests/FunctionSomeTest.php +++ b/tests/FunctionSomeTest.php @@ -2,6 +2,8 @@ namespace React\Promise; +use React\Promise\Exception\RangeException; + class FunctionSomeTest extends TestCase { /** @test */ @@ -13,8 +15,8 @@ public function shouldRejectWithRangeExceptionWithEmptyInputArray() ->method('__invoke') ->with( $this->callback(function($exception){ - return $exception instanceof \RangeException && - 'Input array must contain at least 1 item but contains only 0 items.' === $exception->getMessage(); + return $exception instanceof RangeException && + 'Input array must contain at least 1 item but contains only 0 items.' === $exception->getMessage(); }) ); @@ -33,8 +35,8 @@ public function shouldRejectWithRangeExceptionWithInputArrayContainingNotEnoughI ->method('__invoke') ->with( $this->callback(function($exception){ - return $exception instanceof \RangeException && - 'Input array must contain at least 4 items but contains only 3 items.' === $exception->getMessage(); + return $exception instanceof RangeException && + 'Input array must contain at least 4 items but contains only 3 items.' === $exception->getMessage(); }) ); From be76b5e43b16b44035a8e28acfcd8cb777491bd6 Mon Sep 17 00:00:00 2001 From: Jan Sorgalla Date: Tue, 7 Jul 2015 08:49:21 +0200 Subject: [PATCH 3/7] Add note about underflow rejection of some() --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index d177e047..2d9409d7 100644 --- a/README.md +++ b/README.md @@ -531,6 +531,9 @@ to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items reject). The rejection value will be an array of `(count($promisesOrValues) - $howMany) + 1` rejection reasons. +The returned promise will also reject with a `React\Promise\Exception\RangeException` +if `$promisesOrValues` contains less items than `$howMany`. + #### map() ```php From e29472f5d8a452fda399f16ccd16e8a9871c648c Mon Sep 17 00:00:00 2001 From: Jan Sorgalla Date: Tue, 8 Sep 2015 08:44:39 +0200 Subject: [PATCH 4/7] Add note about rejection for empty input array passed to any() --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 2d9409d7..33f01b05 100644 --- a/README.md +++ b/README.md @@ -515,6 +515,9 @@ will be the resolution value of the triggering item. The returned promise will only reject if *all* items in `$promisesOrValues` are rejected. The rejection value will be an array of all rejection reasons. +The returned promise will also reject with a `React\Promise\Exception\RangeException` +if `$promisesOrValues` contains 0 items. + #### some() ```php From cd6bb56af77d3a5baf073c1cee1f29fe8ad790c3 Mon Sep 17 00:00:00 2001 From: Jan Sorgalla Date: Thu, 21 Jan 2016 20:00:51 +0100 Subject: [PATCH 5/7] Rename RangeException to LengthExeption --- .../{RangeException.php => LengthException.php} | 2 +- src/functions.php | 2 +- tests/FunctionAnyTest.php | 6 +++--- tests/FunctionSomeTest.php | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) rename src/Exception/{RangeException.php => LengthException.php} (50%) diff --git a/src/Exception/RangeException.php b/src/Exception/LengthException.php similarity index 50% rename from src/Exception/RangeException.php rename to src/Exception/LengthException.php index ad698eeb..775c48db 100644 --- a/src/Exception/RangeException.php +++ b/src/Exception/LengthException.php @@ -2,6 +2,6 @@ namespace React\Promise\Exception; -class RangeException extends \RangeException +class LengthException extends \LengthException { } diff --git a/src/functions.php b/src/functions.php index 6f4b8625..a9d984fa 100644 --- a/src/functions.php +++ b/src/functions.php @@ -71,7 +71,7 @@ function some($promisesOrValues, $howMany) $len = count($array); if ($len < $howMany) { - throw new Exception\RangeException( + throw new Exception\LengthException( sprintf( 'Input array must contain at least %d item%s but contains only %s item%s.', $howMany, diff --git a/tests/FunctionAnyTest.php b/tests/FunctionAnyTest.php index 861175a8..efbc2da9 100644 --- a/tests/FunctionAnyTest.php +++ b/tests/FunctionAnyTest.php @@ -2,12 +2,12 @@ namespace React\Promise; -use React\Promise\Exception\RangeException; +use React\Promise\Exception\LengthException; class FunctionAnyTest extends TestCase { /** @test */ - public function shouldRejectWithRangeExceptionWithEmptyInputArray() + public function shouldRejectWithLengthExceptionWithEmptyInputArray() { $mock = $this->createCallableMock(); $mock @@ -15,7 +15,7 @@ public function shouldRejectWithRangeExceptionWithEmptyInputArray() ->method('__invoke') ->with( $this->callback(function($exception){ - return $exception instanceof RangeException && + return $exception instanceof LengthException && 'Input array must contain at least 1 item but contains only 0 items.' === $exception->getMessage(); }) ); diff --git a/tests/FunctionSomeTest.php b/tests/FunctionSomeTest.php index 8f93f7af..64e65b8a 100644 --- a/tests/FunctionSomeTest.php +++ b/tests/FunctionSomeTest.php @@ -2,12 +2,12 @@ namespace React\Promise; -use React\Promise\Exception\RangeException; +use React\Promise\Exception\LengthException; class FunctionSomeTest extends TestCase { /** @test */ - public function shouldRejectWithRangeExceptionWithEmptyInputArray() + public function shouldRejectWithLengthExceptionWithEmptyInputArray() { $mock = $this->createCallableMock(); $mock @@ -15,7 +15,7 @@ public function shouldRejectWithRangeExceptionWithEmptyInputArray() ->method('__invoke') ->with( $this->callback(function($exception){ - return $exception instanceof RangeException && + return $exception instanceof LengthException && 'Input array must contain at least 1 item but contains only 0 items.' === $exception->getMessage(); }) ); @@ -27,7 +27,7 @@ public function shouldRejectWithRangeExceptionWithEmptyInputArray() } /** @test */ - public function shouldRejectWithRangeExceptionWithInputArrayContainingNotEnoughItems() + public function shouldRejectWithLengthExceptionWithInputArrayContainingNotEnoughItems() { $mock = $this->createCallableMock(); $mock @@ -35,7 +35,7 @@ public function shouldRejectWithRangeExceptionWithInputArrayContainingNotEnoughI ->method('__invoke') ->with( $this->callback(function($exception){ - return $exception instanceof RangeException && + return $exception instanceof LengthException && 'Input array must contain at least 4 items but contains only 3 items.' === $exception->getMessage(); }) ); From 95703c99dfae14fcf84d85871943186d4076a268 Mon Sep 17 00:00:00 2001 From: Jan Sorgalla Date: Fri, 25 Mar 2016 17:14:55 +0100 Subject: [PATCH 6/7] Rename RangeException to LengthException in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 33f01b05..ddbd90d9 100644 --- a/README.md +++ b/README.md @@ -515,7 +515,7 @@ will be the resolution value of the triggering item. The returned promise will only reject if *all* items in `$promisesOrValues` are rejected. The rejection value will be an array of all rejection reasons. -The returned promise will also reject with a `React\Promise\Exception\RangeException` +The returned promise will also reject with a `React\Promise\Exception\LengthException` if `$promisesOrValues` contains 0 items. #### some() @@ -534,7 +534,7 @@ to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items reject). The rejection value will be an array of `(count($promisesOrValues) - $howMany) + 1` rejection reasons. -The returned promise will also reject with a `React\Promise\Exception\RangeException` +The returned promise will also reject with a `React\Promise\Exception\LengthException` if `$promisesOrValues` contains less items than `$howMany`. #### map() From e2a82ee32f73a92173fe85283dec5cde68d56b98 Mon Sep 17 00:00:00 2001 From: Jan Sorgalla Date: Fri, 25 Mar 2016 19:44:20 +0100 Subject: [PATCH 7/7] Remove unneeded min() call --- src/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/functions.php b/src/functions.php index 1233b36b..6094247d 100644 --- a/src/functions.php +++ b/src/functions.php @@ -103,7 +103,7 @@ function some($promisesOrValues, $howMany) ); } - $toResolve = min($howMany, $len); + $toResolve = $howMany; $toReject = ($len - $toResolve) + 1; $values = []; $reasons = [];