CoroutineTest.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. namespace GuzzleHttp\Promise\Tests;
  3. use GuzzleHttp\Promise\Coroutine;
  4. use GuzzleHttp\Promise\Promise;
  5. use GuzzleHttp\Promise\PromiseInterface;
  6. use PHPUnit\Framework\TestCase;
  7. use ReflectionClass;
  8. class CoroutineTest extends TestCase
  9. {
  10. /**
  11. * @dataProvider promiseInterfaceMethodProvider
  12. *
  13. * @param string $method
  14. * @param array $args
  15. */
  16. public function testShouldProxyPromiseMethodsToResultPromise($method, $args = [])
  17. {
  18. $coroutine = new Coroutine(function () { yield 0; });
  19. $mockPromise = $this->getMockForAbstractClass(PromiseInterface::class);
  20. call_user_func_array([$mockPromise->expects($this->once())->method($method), 'with'], $args);
  21. $resultPromiseProp = (new ReflectionClass(Coroutine::class))->getProperty('result');
  22. $resultPromiseProp->setAccessible(true);
  23. $resultPromiseProp->setValue($coroutine, $mockPromise);
  24. call_user_func_array([$coroutine, $method], $args);
  25. }
  26. public function promiseInterfaceMethodProvider()
  27. {
  28. return [
  29. ['then', [null, null]],
  30. ['otherwise', [function () {}]],
  31. ['wait', [true]],
  32. ['getState', []],
  33. ['resolve', [null]],
  34. ['reject', [null]],
  35. ];
  36. }
  37. public function testShouldCancelResultPromiseAndOutsideCurrentPromise()
  38. {
  39. $coroutine = new Coroutine(function () { yield 0; });
  40. $mockPromises = [
  41. 'result' => $this->getMockForAbstractClass(PromiseInterface::class),
  42. 'currentPromise' => $this->getMockForAbstractClass(PromiseInterface::class),
  43. ];
  44. foreach ($mockPromises as $propName => $mockPromise) {
  45. /**
  46. * @var $mockPromise \PHPUnit_Framework_MockObject_MockObject
  47. */
  48. $mockPromise->expects($this->once())
  49. ->method('cancel')
  50. ->with();
  51. $promiseProp = (new ReflectionClass(Coroutine::class))->getProperty($propName);
  52. $promiseProp->setAccessible(true);
  53. $promiseProp->setValue($coroutine, $mockPromise);
  54. }
  55. $coroutine->cancel();
  56. }
  57. public function testWaitShouldResolveChainedCoroutines()
  58. {
  59. $promisor = function () {
  60. return \GuzzleHttp\Promise\coroutine(function () {
  61. yield $promise = new Promise(function () use (&$promise) {
  62. $promise->resolve(1);
  63. });
  64. });
  65. };
  66. $promise = $promisor()->then($promisor)->then($promisor);
  67. $this->assertSame(1, $promise->wait());
  68. }
  69. public function testWaitShouldHandleIntermediateErrors()
  70. {
  71. $promise = \GuzzleHttp\Promise\coroutine(function () {
  72. yield $promise = new Promise(function () use (&$promise) {
  73. $promise->resolve(1);
  74. });
  75. })
  76. ->then(function () {
  77. return \GuzzleHttp\Promise\coroutine(function () {
  78. yield $promise = new Promise(function () use (&$promise) {
  79. $promise->reject(new \Exception);
  80. });
  81. });
  82. })
  83. ->otherwise(function (\Exception $error = null) {
  84. if (!$error) {
  85. self::fail('Error did not propagate.');
  86. }
  87. return 3;
  88. });
  89. $this->assertSame(3, $promise->wait());
  90. }
  91. }