From 8ef760f53c6f061ee9c2b8f53adb5f23f0485056 Mon Sep 17 00:00:00 2001 From: Aaron Piotrowski Date: Sat, 17 Dec 2016 08:16:17 -0600 Subject: [PATCH] More tests --- test/CallableMakerTest.php | 39 ++++++ test/CoroutineTest.php | 67 +++++++++- test/ProducerTest.php | 247 +++++++++++++++++++++++++++++++++++++ 3 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 test/CallableMakerTest.php create mode 100644 test/ProducerTest.php diff --git a/test/CallableMakerTest.php b/test/CallableMakerTest.php new file mode 100644 index 00000000..cdb7efb4 --- /dev/null +++ b/test/CallableMakerTest.php @@ -0,0 +1,39 @@ +maker = new CallableMaker; + } + + public function testCallableFromInstanceMethod() { + $callable = $this->maker->callableFromInstanceMethod("instanceMethod"); + $this->assertInternalType("callable", $callable); + $this->assertSame(\sprintf("%s::%s", CallableMaker::class, "instanceMethod"), $callable()); + } + + public function testCallableFromStaticMethod() { + $callable = $this->maker->callableFromInstanceMethod("staticMethod"); + $this->assertInternalType("callable", $callable); + $this->assertSame(\sprintf("%s::%s", CallableMaker::class, "staticMethod"), $callable()); + } +} diff --git a/test/CoroutineTest.php b/test/CoroutineTest.php index ff01384b..fd3a05ed 100644 --- a/test/CoroutineTest.php +++ b/test/CoroutineTest.php @@ -113,6 +113,71 @@ public function testInvalidYieldAfterYieldPromise() { $this->assertInstanceOf(InvalidYieldError::class, $reason); } + + /** + * @depends testInvalidYield + */ + public function testInvalidYieldCatchingThrownException() { + $generator = function () { + try { + yield 1; + } catch (\Error $exception) { + // No further yields. + } + }; + + $coroutine = new Coroutine($generator()); + + $coroutine->when(function ($exception) use (&$reason) { + $reason = $exception; + }); + + $this->assertInstanceOf(InvalidYieldError::class, $reason); + } + + /** + * @depends testInvalidYieldCatchingThrownException + */ + public function testInvalidYieldCatchingThrownExceptionAndYieldingAgain() { + $generator = function () { + try { + yield 1; + } catch (\Error $exception) { + yield new Success; + } + }; + + $coroutine = new Coroutine($generator()); + + $coroutine->when(function ($exception) use (&$reason) { + $reason = $exception; + }); + + $this->assertInstanceOf(InvalidYieldError::class, $reason); + } + + /** + * @depends testInvalidYieldCatchingThrownException + */ + public function testInvalidYieldCatchingThrownExceptionAndThrowing() { + $exception = new \Exception; + $generator = function () use ($exception) { + try { + yield 1; + } catch (\Error $error) { + throw $exception; + } + }; + + $coroutine = new Coroutine($generator()); + + $coroutine->when(function ($exception) use (&$reason) { + $reason = $exception; + }); + + $this->assertInstanceOf(InvalidYieldError::class, $reason); + $this->assertSame($exception, $reason->getPrevious()); + } /** * @depends testInvalidYield @@ -296,7 +361,7 @@ public function testGeneratorThrowingExceptionWithFinallyYieldingPendingPromise( try { throw $exception; } finally { - $yielded = (yield new Pause(self::TIMEOUT, $value)); + $yielded = yield new Pause(self::TIMEOUT, $value); } }; diff --git a/test/ProducerTest.php b/test/ProducerTest.php new file mode 100644 index 00000000..c6c698f7 --- /dev/null +++ b/test/ProducerTest.php @@ -0,0 +1,247 @@ +producer = new Producer; + } + + public function testEmit() { + $invoked = false; + $value = 1; + + $callback = function ($emitted) use (&$invoked, $value) { + $invoked = true; + $this->assertSame($emitted, $value); + }; + + $this->producer->subscribe($callback); + $promise = $this->producer->emit($value); + + $this->assertInstanceOf(Promise::class, $promise); + $this->assertTrue($invoked); + } + + /** + * @depends testEmit + */ + public function testEmitSuccessfulPromise() { + $invoked = false; + $value = 1; + $promise = new Success($value); + + $callback = function ($emitted) use (&$invoked, $value) { + $invoked = true; + $this->assertSame($emitted, $value); + }; + + $this->producer->subscribe($callback); + $this->producer->emit($promise); + + $this->assertTrue($invoked); + } + + /** + * @depends testEmit + */ + public function testEmitFailedPromise() { + $invoked = false; + $exception = new \Exception; + $promise = new Failure($exception); + + $callback = function ($emitted) use (&$invoked) { + $invoked = true; + }; + + $this->producer->subscribe($callback); + $this->producer->emit($promise); + + $this->assertFalse($invoked); + + $this->producer->when(function ($exception) use (&$invoked, &$reason) { + $invoked = true; + $reason = $exception; + }); + + $this->assertTrue($invoked); + $this->assertSame($exception, $reason); + } + + /** + * @depends testEmit + */ + public function testEmitPendingPromise() { + $invoked = false; + $value = 1; + $deferred = new Deferred; + + $callback = function ($emitted) use (&$invoked) { + $invoked = true; + }; + + $callback = function ($emitted) use (&$invoked, $value) { + $invoked = true; + $this->assertSame($emitted, $value); + }; + + $this->producer->subscribe($callback); + $this->producer->emit($deferred->promise()); + + $this->assertFalse($invoked); + + $deferred->resolve($value); + + $this->assertTrue($invoked); + } + + /** + * @depends testEmit + */ + public function testEmitPendingPromiseThenNonPromise() { + $invoked = false; + $deferred = new Deferred; + + $callback = function ($emitted) use (&$invoked, &$result) { + $invoked = true; + $result = $emitted; + }; + + $this->producer->subscribe($callback); + $this->producer->emit($deferred->promise()); + + $this->assertFalse($invoked); + + $this->producer->emit(2); + $this->assertTrue($invoked); + $this->assertSame(2, $result); + + $deferred->resolve(1); + $this->assertSame(1, $result); + } + + /** + * @depends testEmit + * @expectedException \Error + * @expectedExceptionMessage The observable has been resolved; cannot emit more values + */ + public function testEmitAfterResolve() { + $this->producer->resolve(); + $this->producer->emit(1); + } + + /** + * @depends testEmit + * @expectedException \Error + * @expectedExceptionMessage The observable was resolved before the promise result could be emitted + */ + public function testEmitPendingPromiseThenResolve() { + $invoked = false; + $deferred = new Deferred; + + $promise = $this->producer->emit($deferred->promise()); + + $this->producer->resolve(); + $deferred->resolve(); + + $promise->when(function ($exception) use (&$invoked, &$reason) { + $invoked = true; + $reason = $exception; + }); + + $this->assertTrue($invoked); + throw $reason; + } + + /** + * @depends testEmit + * @expectedException \Error + * @expectedExceptionMessage The observable was resolved before the promise result could be emitted + */ + public function testEmitPendingPromiseThenFail() { + $invoked = false; + $deferred = new Deferred; + + $promise = $this->producer->emit($deferred->promise()); + + $this->producer->resolve(); + $deferred->fail(new \Exception); + + $promise->when(function ($exception) use (&$invoked, &$reason) { + $invoked = true; + $reason = $exception; + }); + + $this->assertTrue($invoked); + throw $reason; + } + + public function testSubscriberThrows() { + $exception = new \Exception; + + try { + Loop::execute(function () use ($exception) { + $this->producer->subscribe(function () use ($exception) { + throw $exception; + }); + + $this->producer->emit(1); + }); + } catch (\Exception $caught) { + $this->assertSame($exception, $caught); + } + } + + public function testSubscriberReturnsSuccessfulPromise() { + $invoked = true; + $value = 1; + $promise = new Success($value); + + $this->producer->subscribe(function () use ($promise) { + return $promise; + }); + + $promise = $this->producer->emit(1); + $promise->when(function () use (&$invoked) { + $invoked = true; + }); + + $this->assertTrue($invoked); + } + + public function testSubscriberReturnsFailedPromise() { + $exception = new \Exception; + $promise = new Failure($exception); + + try { + Loop::execute(function () use ($exception, $promise) { + $this->producer->subscribe(function () use ($promise) { + return $promise; + }); + + $promise = $this->producer->emit(1); + $promise->when(function () use (&$invoked) { + $invoked = true; + }); + + $this->assertTrue($invoked); + }); + } catch (\Exception $caught) { + $this->assertSame($exception, $caught); + } + } +}