/tools/tcp/vendor/react/stream/tests/ReadableResourceStreamTest.php

https://bitbucket.org/chaike/adt · PHP · 267 lines · 167 code · 62 blank · 38 comment · 3 complexity · cc1f9b7f5c52279bd3d1e22e826135b0 MD5 · raw file

  1. <?php
  2. namespace React\Tests\Stream;
  3. use React\Stream\ReadableResourceStream;
  4. use Clue\StreamFilter as Filter;
  5. class ReadableResourceStreamTest extends TestCase
  6. {
  7. /**
  8. * @covers React\Stream\ReadableResourceStream::__construct
  9. */
  10. public function testConstructor()
  11. {
  12. $stream = fopen('php://temp', 'r+');
  13. $loop = $this->createLoopMock();
  14. new ReadableResourceStream($stream, $loop);
  15. }
  16. /**
  17. * @covers React\Stream\ReadableResourceStream::__construct
  18. */
  19. public function testConstructorThrowsExceptionOnInvalidStream()
  20. {
  21. $loop = $this->createLoopMock();
  22. $this->setExpectedException('InvalidArgumentException');
  23. new ReadableResourceStream(false, $loop);
  24. }
  25. /**
  26. * @covers React\Stream\ReadableResourceStream::__construct
  27. */
  28. public function testConstructorThrowsExceptionOnWriteOnlyStream()
  29. {
  30. if (defined('HHVM_VERSION')) {
  31. $this->markTestSkipped('HHVM does not report fopen mode for STDOUT');
  32. }
  33. $loop = $this->createLoopMock();
  34. $this->setExpectedException('InvalidArgumentException');
  35. new ReadableResourceStream(STDOUT, $loop);
  36. }
  37. /**
  38. * @covers React\Stream\ReadableResourceStream::__construct
  39. */
  40. public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking()
  41. {
  42. if (!in_array('blocking', stream_get_wrappers())) {
  43. stream_wrapper_register('blocking', 'React\Tests\Stream\EnforceBlockingWrapper');
  44. }
  45. $stream = fopen('blocking://test', 'r+');
  46. $loop = $this->createLoopMock();
  47. $this->setExpectedException('RuntimeException');
  48. new ReadableResourceStream($stream, $loop);
  49. }
  50. public function testCloseShouldEmitCloseEvent()
  51. {
  52. $stream = fopen('php://temp', 'r+');
  53. $loop = $this->createLoopMock();
  54. $conn = new ReadableResourceStream($stream, $loop);
  55. $conn->on('close', $this->expectCallableOnce());
  56. $conn->close();
  57. $this->assertFalse($conn->isReadable());
  58. }
  59. public function testCloseTwiceShouldEmitCloseEventOnce()
  60. {
  61. $stream = fopen('php://temp', 'r+');
  62. $loop = $this->createLoopMock();
  63. $conn = new ReadableResourceStream($stream, $loop);
  64. $conn->on('close', $this->expectCallableOnce());
  65. $conn->close();
  66. $conn->close();
  67. }
  68. /**
  69. * @covers React\Stream\ReadableResourceStream::__construct
  70. * @covers React\Stream\ReadableResourceStream::handleData
  71. */
  72. public function testDataEvent()
  73. {
  74. $stream = fopen('php://temp', 'r+');
  75. $loop = $this->createLoopMock();
  76. $capturedData = null;
  77. $conn = new ReadableResourceStream($stream, $loop);
  78. $conn->on('data', function ($data) use (&$capturedData) {
  79. $capturedData = $data;
  80. });
  81. fwrite($stream, "foobar\n");
  82. rewind($stream);
  83. $conn->handleData($stream);
  84. $this->assertSame("foobar\n", $capturedData);
  85. }
  86. /**
  87. * @covers React\Stream\ReadableResourceStream::__construct
  88. * @covers React\Stream\ReadableResourceStream::handleData
  89. */
  90. public function testDataEventDoesEmitOneChunkMatchingBufferSize()
  91. {
  92. $stream = fopen('php://temp', 'r+');
  93. $loop = $this->createLoopMock();
  94. $capturedData = null;
  95. $conn = new ReadableResourceStream($stream, $loop, 4321);
  96. $conn->on('data', function ($data) use (&$capturedData) {
  97. $capturedData = $data;
  98. });
  99. fwrite($stream, str_repeat("a", 100000));
  100. rewind($stream);
  101. $conn->handleData($stream);
  102. $this->assertTrue($conn->isReadable());
  103. $this->assertEquals(4321, strlen($capturedData));
  104. }
  105. /**
  106. * @covers React\Stream\ReadableResourceStream::__construct
  107. * @covers React\Stream\ReadableResourceStream::handleData
  108. */
  109. public function testDataEventDoesEmitOneChunkUntilStreamEndsWhenBufferSizeIsInfinite()
  110. {
  111. $stream = fopen('php://temp', 'r+');
  112. $loop = $this->createLoopMock();
  113. $capturedData = null;
  114. $conn = new ReadableResourceStream($stream, $loop, -1);
  115. $conn->on('data', function ($data) use (&$capturedData) {
  116. $capturedData = $data;
  117. });
  118. fwrite($stream, str_repeat("a", 100000));
  119. rewind($stream);
  120. $conn->handleData($stream);
  121. $this->assertTrue($conn->isReadable());
  122. $this->assertEquals(100000, strlen($capturedData));
  123. }
  124. /**
  125. * @covers React\Stream\ReadableResourceStream::handleData
  126. */
  127. public function testEmptyStreamShouldNotEmitData()
  128. {
  129. $stream = fopen('php://temp', 'r+');
  130. $loop = $this->createLoopMock();
  131. $conn = new ReadableResourceStream($stream, $loop);
  132. $conn->on('data', $this->expectCallableNever());
  133. $conn->handleData($stream);
  134. }
  135. public function testPipeShouldReturnDestination()
  136. {
  137. $stream = fopen('php://temp', 'r+');
  138. $loop = $this->createLoopMock();
  139. $conn = new ReadableResourceStream($stream, $loop);
  140. $dest = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock();
  141. $this->assertSame($dest, $conn->pipe($dest));
  142. }
  143. /**
  144. * @covers React\Stream\ReadableResourceStream::handleData
  145. */
  146. public function testClosingStreamInDataEventShouldNotTriggerError()
  147. {
  148. $stream = fopen('php://temp', 'r+');
  149. $loop = $this->createLoopMock();
  150. $conn = new ReadableResourceStream($stream, $loop);
  151. $conn->on('data', function ($data) use ($conn) {
  152. $conn->close();
  153. });
  154. fwrite($stream, "foobar\n");
  155. rewind($stream);
  156. $conn->handleData($stream);
  157. }
  158. /**
  159. * @covers React\Stream\ReadableResourceStream::handleData
  160. */
  161. public function testDataFiltered()
  162. {
  163. $stream = fopen('php://temp', 'r+');
  164. // add a filter which removes every 'a' when reading
  165. Filter\append($stream, function ($chunk) {
  166. return str_replace('a', '', $chunk);
  167. }, STREAM_FILTER_READ);
  168. $loop = $this->createLoopMock();
  169. $capturedData = null;
  170. $conn = new ReadableResourceStream($stream, $loop);
  171. $conn->on('data', function ($data) use (&$capturedData) {
  172. $capturedData = $data;
  173. });
  174. fwrite($stream, "foobar\n");
  175. rewind($stream);
  176. $conn->handleData($stream);
  177. $this->assertSame("foobr\n", $capturedData);
  178. }
  179. /**
  180. * @covers React\Stream\ReadableResourceStream::handleData
  181. */
  182. public function testDataErrorShouldEmitErrorAndClose()
  183. {
  184. $stream = fopen('php://temp', 'r+');
  185. // add a filter which returns an error when encountering an 'a' when reading
  186. Filter\append($stream, function ($chunk) {
  187. if (strpos($chunk, 'a') !== false) {
  188. throw new \Exception('Invalid');
  189. }
  190. return $chunk;
  191. }, STREAM_FILTER_READ);
  192. $loop = $this->createLoopMock();
  193. $conn = new ReadableResourceStream($stream, $loop);
  194. $conn->on('data', $this->expectCallableNever());
  195. $conn->on('error', $this->expectCallableOnce());
  196. $conn->on('close', $this->expectCallableOnce());
  197. fwrite($stream, "foobar\n");
  198. rewind($stream);
  199. $conn->handleData($stream);
  200. }
  201. private function createLoopMock()
  202. {
  203. return $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
  204. }
  205. }