From 0bea30f434d9bd3a48d14f0ebef7ebda134aa1b2 Mon Sep 17 00:00:00 2001 From: PJ Dietz Date: Fri, 1 May 2020 10:45:10 -0400 Subject: [PATCH] Fix issue when reading Stream size and fstat fails --- src/Message/Stream.php | 11 +++---- test/tests/unit/Message/StreamTest.php | 44 ++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/Message/Stream.php b/src/Message/Stream.php index 61be3b1..54ba4e6 100644 --- a/src/Message/Stream.php +++ b/src/Message/Stream.php @@ -92,7 +92,10 @@ class Stream implements StreamInterface public function getSize() { $statistics = fstat($this->resource); - return $statistics["size"] ?: null; + if ($statistics && $statistics["size"]) { + return $statistics["size"]; + } + return null; } /** @@ -105,9 +108,7 @@ class Stream implements StreamInterface { $position = ftell($this->resource); if ($position === false) { - // @codeCoverageIgnoreStart throw new \RuntimeException("Unable to retrieve current position of file pointer."); - // @codeCoverageIgnoreEnd } return $position; } @@ -151,9 +152,7 @@ class Stream implements StreamInterface $result = fseek($this->resource, $offset, $whence); } if ($result === -1) { - // @codeCoverageIgnoreStart throw new \RuntimeException("Unable to seek to position."); - // @codeCoverageIgnoreEnd } } @@ -174,9 +173,7 @@ class Stream implements StreamInterface $result = rewind($this->resource); } if ($result === false) { - // @codeCoverageIgnoreStart throw new \RuntimeException("Unable to seek to position."); - // @codeCoverageIgnoreEnd } } diff --git a/test/tests/unit/Message/StreamTest.php b/test/tests/unit/Message/StreamTest.php index 6965d03..714b981 100644 --- a/test/tests/unit/Message/StreamTest.php +++ b/test/tests/unit/Message/StreamTest.php @@ -10,11 +10,13 @@ use WellRESTed\Test\TestCase; class StreamTest extends TestCase { private $resource; + private $resourceDevNull; private $content = "Hello, world!"; public function setUp(): void { $this->resource = fopen("php://memory", "w+"); + $this->resourceDevNull = fopen("/dev/null", "r"); fwrite($this->resource, $this->content); } @@ -39,6 +41,7 @@ class StreamTest extends TestCase /** * @dataProvider invalidResourceProvider + * @param mixed $resource */ public function testThrowsExceptionWithInvalidResource($resource) { @@ -88,6 +91,12 @@ class StreamTest extends TestCase $this->assertEquals(strlen($this->content), $stream->getSize()); } + public function testReturnsNullForSizeWhenUnableToReadFromFstat() + { + $stream = new Stream($this->resourceDevNull); + $this->assertNull($stream->getSize()); + } + public function testTellReturnsHandlePosition() { $stream = new Stream($this->resource); @@ -95,6 +104,13 @@ class StreamTest extends TestCase $this->assertEquals(10, $stream->tell()); } + public function testTellThrowsRuntimeExceptionWhenUnableToReadStreamPosition() + { + $stream = new Stream($this->resourceDevNull); + $this->expectException(RuntimeException::class); + $stream->tell(); + } + public function testReturnsOef() { $stream = new Stream($this->resource); @@ -118,6 +134,13 @@ class StreamTest extends TestCase $this->assertEquals(10, ftell($this->resource)); } + public function testSeekThrowsRuntimeExceptionWhenUnableToSeek() + { + $stream = new Stream($this->resourceDevNull); + $this->expectException(RuntimeException::class); + $stream->seek(10); + } + public function testRewindReturnsToBeginning() { $stream = new Stream($this->resource); @@ -126,6 +149,13 @@ class StreamTest extends TestCase $this->assertEquals(0, ftell($this->resource)); } + public function testRewindThrowsRuntimeExceptionWhenUnableToRewind() + { + $stream = new Stream($this->resourceDevNull); + $this->expectException(RuntimeException::class); + $stream->rewind(); + } + public function testWritesToHandle() { $message = "\nThis is a stream."; @@ -190,7 +220,12 @@ class StreamTest extends TestCase $this->assertEquals($metadata["mode"], $stream->getMetadata("mode")); } - /** @dataProvider modeProvider */ + /** + * @dataProvider modeProvider + * @param string $mode Access type used to open the stream + * @param bool $readable The stream should be readable + * @param bool $writable The stream should be writeable + */ public function testReturnsIsReadableForReadableStreams($mode, $readable, $writable) { $tmp = tempnam(sys_get_temp_dir(), "php"); @@ -202,7 +237,12 @@ class StreamTest extends TestCase $this->assertEquals($readable, $stream->isReadable()); } - /** @dataProvider modeProvider */ + /** + * @dataProvider modeProvider + * @param string $mode Access type used to open the stream + * @param bool $readable The stream should be readable + * @param bool $writable The stream should be writeable + */ public function testReturnsIsWritableForWritableStreams($mode, $readable, $writable) { $tmp = tempnam(sys_get_temp_dir(), "php");