CachingStreamTest.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. namespace RingCentral\Tests\Psr7;
  3. use RingCentral\Psr7;
  4. use RingCentral\Psr7\CachingStream;
  5. /**
  6. * @covers RingCentral\Psr7\CachingStream
  7. */
  8. class CachingStreamTest extends \PHPUnit_Framework_TestCase
  9. {
  10. /** @var CachingStream */
  11. protected $body;
  12. protected $decorated;
  13. public function setUp()
  14. {
  15. $this->decorated = Psr7\stream_for('testing');
  16. $this->body = new CachingStream($this->decorated);
  17. }
  18. public function tearDown()
  19. {
  20. $this->decorated->close();
  21. $this->body->close();
  22. }
  23. public function testUsesRemoteSizeIfPossible()
  24. {
  25. $body = Psr7\stream_for('test');
  26. $caching = new CachingStream($body);
  27. $this->assertEquals(4, $caching->getSize());
  28. }
  29. public function testReadsUntilCachedToByte()
  30. {
  31. $this->body->seek(5);
  32. $this->assertEquals('n', $this->body->read(1));
  33. $this->body->seek(0);
  34. $this->assertEquals('t', $this->body->read(1));
  35. }
  36. public function testCanSeekNearEndWithSeekEnd()
  37. {
  38. $baseStream = Psr7\stream_for(implode('', range('a', 'z')));
  39. $cached = new CachingStream($baseStream);
  40. $cached->seek(1, SEEK_END);
  41. $this->assertEquals(24, $baseStream->tell());
  42. $this->assertEquals('y', $cached->read(1));
  43. $this->assertEquals(26, $cached->getSize());
  44. }
  45. public function testCanSeekToEndWithSeekEnd()
  46. {
  47. $baseStream = Psr7\stream_for(implode('', range('a', 'z')));
  48. $cached = new CachingStream($baseStream);
  49. $cached->seek(0, SEEK_END);
  50. $this->assertEquals(25, $baseStream->tell());
  51. $this->assertEquals('z', $cached->read(1));
  52. $this->assertEquals(26, $cached->getSize());
  53. }
  54. public function testCanUseSeekEndWithUnknownSize()
  55. {
  56. $baseStream = Psr7\stream_for('testing');
  57. $decorated = Psr7\FnStream::decorate($baseStream, array(
  58. 'getSize' => function () { return null; }
  59. ));
  60. $cached = new CachingStream($decorated);
  61. $cached->seek(1, SEEK_END);
  62. $this->assertEquals('ng', $cached->read(2));
  63. }
  64. public function testRewindUsesSeek()
  65. {
  66. $a = Psr7\stream_for('foo');
  67. $d = $this->getMockBuilder('RingCentral\Psr7\CachingStream')
  68. ->setMethods(array('seek'))
  69. ->setConstructorArgs(array($a))
  70. ->getMock();
  71. $d->expects($this->once())
  72. ->method('seek')
  73. ->with(0)
  74. ->will($this->returnValue(true));
  75. $d->seek(0);
  76. }
  77. public function testCanSeekToReadBytes()
  78. {
  79. $this->assertEquals('te', $this->body->read(2));
  80. $this->body->seek(0);
  81. $this->assertEquals('test', $this->body->read(4));
  82. $this->assertEquals(4, $this->body->tell());
  83. $this->body->seek(2);
  84. $this->assertEquals(2, $this->body->tell());
  85. $this->body->seek(2, SEEK_CUR);
  86. $this->assertEquals(4, $this->body->tell());
  87. $this->assertEquals('ing', $this->body->read(3));
  88. }
  89. public function testWritesToBufferStream()
  90. {
  91. $this->body->read(2);
  92. $this->body->write('hi');
  93. $this->body->seek(0);
  94. $this->assertEquals('tehiing', (string) $this->body);
  95. }
  96. public function testSkipsOverwrittenBytes()
  97. {
  98. $decorated = Psr7\stream_for(
  99. implode("\n", array_map(function ($n) {
  100. return str_pad($n, 4, '0', STR_PAD_LEFT);
  101. }, range(0, 25)))
  102. );
  103. $body = new CachingStream($decorated);
  104. $this->assertEquals("0000\n", Psr7\readline($body));
  105. $this->assertEquals("0001\n", Psr7\readline($body));
  106. // Write over part of the body yet to be read, so skip some bytes
  107. $this->assertEquals(5, $body->write("TEST\n"));
  108. $this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes'));
  109. // Read, which skips bytes, then reads
  110. $this->assertEquals("0003\n", Psr7\readline($body));
  111. $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
  112. $this->assertEquals("0004\n", Psr7\readline($body));
  113. $this->assertEquals("0005\n", Psr7\readline($body));
  114. // Overwrite part of the cached body (so don't skip any bytes)
  115. $body->seek(5);
  116. $this->assertEquals(5, $body->write("ABCD\n"));
  117. $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
  118. $this->assertEquals("TEST\n", Psr7\readline($body));
  119. $this->assertEquals("0003\n", Psr7\readline($body));
  120. $this->assertEquals("0004\n", Psr7\readline($body));
  121. $this->assertEquals("0005\n", Psr7\readline($body));
  122. $this->assertEquals("0006\n", Psr7\readline($body));
  123. $this->assertEquals(5, $body->write("1234\n"));
  124. $this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes'));
  125. // Seek to 0 and ensure the overwritten bit is replaced
  126. $body->seek(0);
  127. $this->assertEquals("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", $body->read(50));
  128. // Ensure that casting it to a string does not include the bit that was overwritten
  129. $this->assertContains("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", (string) $body);
  130. }
  131. public function testClosesBothStreams()
  132. {
  133. $s = fopen('php://temp', 'r');
  134. $a = Psr7\stream_for($s);
  135. $d = new CachingStream($a);
  136. $d->close();
  137. $this->assertFalse(is_resource($s));
  138. }
  139. /**
  140. * @expectedException \InvalidArgumentException
  141. */
  142. public function testEnsuresValidWhence()
  143. {
  144. $this->body->seek(10, -123456);
  145. }
  146. }