AsyncReadStreamTest.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. namespace GuzzleHttp\Tests\Stream;
  3. use GuzzleHttp\Stream\AsyncReadStream;
  4. use GuzzleHttp\Stream\BufferStream;
  5. use GuzzleHttp\Stream\FnStream;
  6. use GuzzleHttp\Stream\Stream;
  7. use InvalidArgumentException;
  8. use PHPUnit\Framework\TestCase;
  9. use ReflectionProperty;
  10. class AsyncReadStreamTest extends TestCase
  11. {
  12. public function testValidatesReadableBuffer()
  13. {
  14. $this->expectException(InvalidArgumentException::class);
  15. $this->expectErrorMessage('Buffer must be readable and writable');
  16. new AsyncReadStream(FnStream::decorate(
  17. Stream::factory(),
  18. ['isReadable' => function () { return false; }]
  19. ));
  20. }
  21. public function testValidatesWritableBuffer()
  22. {
  23. $this->expectException(InvalidArgumentException::class);
  24. $this->expectErrorMessage('Buffer must be readable and writable');
  25. new AsyncReadStream(FnStream::decorate(
  26. Stream::factory(),
  27. ['isWritable' => function () { return false; }]
  28. ));
  29. }
  30. public function testValidatesHwmMetadata()
  31. {
  32. $a = new AsyncReadStream(Stream::factory(), [
  33. 'drain' => function() {}
  34. ]);
  35. $drain = new ReflectionProperty(AsyncReadStream::class, 'drain');
  36. $drain->setAccessible(true);
  37. $this->assertNull($drain->getValue($a));
  38. }
  39. public function testValidatesPumpIsCallable()
  40. {
  41. $this->expectException(InvalidArgumentException::class);
  42. $this->expectErrorMessage('pump must be callable');
  43. new AsyncReadStream(new BufferStream(), ['pump' => true]);
  44. }
  45. public function testValidatesDrainIsCallable()
  46. {
  47. $this->expectException(InvalidArgumentException::class);
  48. $this->expectErrorMessage('drain must be callable');
  49. new AsyncReadStream(new BufferStream(), ['drain' => true]);
  50. }
  51. public function testCanInitialize()
  52. {
  53. $buffer = new BufferStream();
  54. $a = new AsyncReadStream($buffer, [
  55. 'size' => 10,
  56. 'drain' => function () {},
  57. 'pump' => function () {},
  58. ]);
  59. $size = new ReflectionProperty(AsyncReadStream::class, 'size');
  60. $size->setAccessible(true);
  61. $drain = new ReflectionProperty(AsyncReadStream::class, 'drain');
  62. $drain->setAccessible(true);
  63. $pump = new ReflectionProperty(AsyncReadStream::class, 'pump');
  64. $pump->setAccessible(true);
  65. $this->assertSame($buffer, $a->stream);
  66. $this->assertTrue(is_callable($drain->getValue($a)));
  67. $this->assertTrue(is_callable($pump->getValue($a)));
  68. $this->assertTrue($a->isReadable());
  69. $this->assertFalse($a->isSeekable());
  70. $this->assertFalse($a->isWritable());
  71. $this->assertFalse($a->write('foo'));
  72. $this->assertEquals(10, $a->getSize());
  73. }
  74. public function testReadsFromBufferWithNoDrainOrPump()
  75. {
  76. $buffer = new BufferStream();
  77. $a = new AsyncReadStream($buffer);
  78. $buffer->write('foo');
  79. $this->assertNull($a->getSize());
  80. $this->assertEquals('foo', $a->read(10));
  81. $this->assertEquals('', $a->read(10));
  82. }
  83. public function testCallsPumpForMoreDataWhenRequested()
  84. {
  85. $called = 0;
  86. $buffer = new BufferStream();
  87. $a = new AsyncReadStream($buffer, [
  88. 'pump' => function ($size) use (&$called) {
  89. $called++;
  90. return str_repeat('.', $size);
  91. }
  92. ]);
  93. $buffer->write('foobar');
  94. $this->assertEquals('foo', $a->read(3));
  95. $this->assertEquals(0, $called);
  96. $this->assertEquals('bar.....', $a->read(8));
  97. $this->assertEquals(1, $called);
  98. $this->assertEquals('..', $a->read(2));
  99. $this->assertEquals(2, $called);
  100. }
  101. public function testCallsDrainWhenNeeded()
  102. {
  103. $called = 0;
  104. $buffer = new BufferStream(5);
  105. $a = new AsyncReadStream($buffer, [
  106. 'drain' => function (BufferStream $b) use (&$called, $buffer) {
  107. $this->assertSame($b, $buffer);
  108. $called++;
  109. }
  110. ]);
  111. $buffer->write('foobar');
  112. $this->assertEquals(6, $buffer->getSize());
  113. $this->assertEquals(0, $called);
  114. $needsDrain = new ReflectionProperty(AsyncReadStream::class, 'needsDrain');
  115. $needsDrain->setAccessible(true);
  116. $a->read(3);
  117. $this->assertTrue($needsDrain->getValue($a));
  118. $this->assertEquals(3, $buffer->getSize());
  119. $this->assertEquals(0, $called);
  120. $a->read(3);
  121. $this->assertEquals(0, $buffer->getSize());
  122. $this->assertFalse($needsDrain->getValue($a));
  123. $this->assertEquals(1, $called);
  124. }
  125. public function testCreatesBufferWithNoConfig()
  126. {
  127. list($buffer, $async) = AsyncReadStream::create();
  128. $this->assertInstanceOf('GuzzleHttp\Stream\BufferStream', $buffer);
  129. $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
  130. }
  131. public function testCreatesBufferWithSpecifiedBuffer()
  132. {
  133. $buf = new BufferStream();
  134. list($buffer, $async) = AsyncReadStream::create(['buffer' => $buf]);
  135. $this->assertSame($buf, $buffer);
  136. $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
  137. }
  138. public function testCreatesNullStream()
  139. {
  140. list($buffer, $async) = AsyncReadStream::create(['max_buffer' => 0]);
  141. $this->assertInstanceOf('GuzzleHttp\Stream\NullStream', $buffer);
  142. $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
  143. }
  144. public function testCreatesDroppingStream()
  145. {
  146. list($buffer, $async) = AsyncReadStream::create(['max_buffer' => 5]);
  147. $this->assertInstanceOf('GuzzleHttp\Stream\DroppingStream', $buffer);
  148. $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
  149. $buffer->write('12345678910');
  150. $this->assertEquals(5, $buffer->getSize());
  151. }
  152. public function testCreatesOnWriteStream()
  153. {
  154. $c = 0;
  155. $b = new BufferStream();
  156. list($buffer, $async) = AsyncReadStream::create([
  157. 'buffer' => $b,
  158. 'write' => function (BufferStream $buf, $data) use (&$c, $b) {
  159. $this->assertSame($buf, $b);
  160. $this->assertEquals('foo', $data);
  161. $c++;
  162. },
  163. ]);
  164. $this->assertInstanceOf('GuzzleHttp\Stream\FnStream', $buffer);
  165. $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
  166. $this->assertEquals(0, $c);
  167. $this->assertEquals(3, $buffer->write('foo'));
  168. $this->assertEquals(1, $c);
  169. $this->assertEquals(3, $buffer->write('foo'));
  170. $this->assertEquals(2, $c);
  171. $this->assertEquals('foofoo', (string) $buffer);
  172. }
  173. }