Fix issue when reading Stream size and fstat fails

This commit is contained in:
PJ Dietz 2020-05-01 10:45:10 -04:00
parent d1c7076929
commit 0bea30f434
2 changed files with 46 additions and 9 deletions

View File

@ -92,7 +92,10 @@ class Stream implements StreamInterface
public function getSize() public function getSize()
{ {
$statistics = fstat($this->resource); $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); $position = ftell($this->resource);
if ($position === false) { if ($position === false) {
// @codeCoverageIgnoreStart
throw new \RuntimeException("Unable to retrieve current position of file pointer."); throw new \RuntimeException("Unable to retrieve current position of file pointer.");
// @codeCoverageIgnoreEnd
} }
return $position; return $position;
} }
@ -151,9 +152,7 @@ class Stream implements StreamInterface
$result = fseek($this->resource, $offset, $whence); $result = fseek($this->resource, $offset, $whence);
} }
if ($result === -1) { if ($result === -1) {
// @codeCoverageIgnoreStart
throw new \RuntimeException("Unable to seek to position."); throw new \RuntimeException("Unable to seek to position.");
// @codeCoverageIgnoreEnd
} }
} }
@ -174,9 +173,7 @@ class Stream implements StreamInterface
$result = rewind($this->resource); $result = rewind($this->resource);
} }
if ($result === false) { if ($result === false) {
// @codeCoverageIgnoreStart
throw new \RuntimeException("Unable to seek to position."); throw new \RuntimeException("Unable to seek to position.");
// @codeCoverageIgnoreEnd
} }
} }

View File

@ -10,11 +10,13 @@ use WellRESTed\Test\TestCase;
class StreamTest extends TestCase class StreamTest extends TestCase
{ {
private $resource; private $resource;
private $resourceDevNull;
private $content = "Hello, world!"; private $content = "Hello, world!";
public function setUp(): void public function setUp(): void
{ {
$this->resource = fopen("php://memory", "w+"); $this->resource = fopen("php://memory", "w+");
$this->resourceDevNull = fopen("/dev/null", "r");
fwrite($this->resource, $this->content); fwrite($this->resource, $this->content);
} }
@ -39,6 +41,7 @@ class StreamTest extends TestCase
/** /**
* @dataProvider invalidResourceProvider * @dataProvider invalidResourceProvider
* @param mixed $resource
*/ */
public function testThrowsExceptionWithInvalidResource($resource) public function testThrowsExceptionWithInvalidResource($resource)
{ {
@ -88,6 +91,12 @@ class StreamTest extends TestCase
$this->assertEquals(strlen($this->content), $stream->getSize()); $this->assertEquals(strlen($this->content), $stream->getSize());
} }
public function testReturnsNullForSizeWhenUnableToReadFromFstat()
{
$stream = new Stream($this->resourceDevNull);
$this->assertNull($stream->getSize());
}
public function testTellReturnsHandlePosition() public function testTellReturnsHandlePosition()
{ {
$stream = new Stream($this->resource); $stream = new Stream($this->resource);
@ -95,6 +104,13 @@ class StreamTest extends TestCase
$this->assertEquals(10, $stream->tell()); $this->assertEquals(10, $stream->tell());
} }
public function testTellThrowsRuntimeExceptionWhenUnableToReadStreamPosition()
{
$stream = new Stream($this->resourceDevNull);
$this->expectException(RuntimeException::class);
$stream->tell();
}
public function testReturnsOef() public function testReturnsOef()
{ {
$stream = new Stream($this->resource); $stream = new Stream($this->resource);
@ -118,6 +134,13 @@ class StreamTest extends TestCase
$this->assertEquals(10, ftell($this->resource)); $this->assertEquals(10, ftell($this->resource));
} }
public function testSeekThrowsRuntimeExceptionWhenUnableToSeek()
{
$stream = new Stream($this->resourceDevNull);
$this->expectException(RuntimeException::class);
$stream->seek(10);
}
public function testRewindReturnsToBeginning() public function testRewindReturnsToBeginning()
{ {
$stream = new Stream($this->resource); $stream = new Stream($this->resource);
@ -126,6 +149,13 @@ class StreamTest extends TestCase
$this->assertEquals(0, ftell($this->resource)); $this->assertEquals(0, ftell($this->resource));
} }
public function testRewindThrowsRuntimeExceptionWhenUnableToRewind()
{
$stream = new Stream($this->resourceDevNull);
$this->expectException(RuntimeException::class);
$stream->rewind();
}
public function testWritesToHandle() public function testWritesToHandle()
{ {
$message = "\nThis is a stream."; $message = "\nThis is a stream.";
@ -190,7 +220,12 @@ class StreamTest extends TestCase
$this->assertEquals($metadata["mode"], $stream->getMetadata("mode")); $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) public function testReturnsIsReadableForReadableStreams($mode, $readable, $writable)
{ {
$tmp = tempnam(sys_get_temp_dir(), "php"); $tmp = tempnam(sys_get_temp_dir(), "php");
@ -202,7 +237,12 @@ class StreamTest extends TestCase
$this->assertEquals($readable, $stream->isReadable()); $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) public function testReturnsIsWritableForWritableStreams($mode, $readable, $writable)
{ {
$tmp = tempnam(sys_get_temp_dir(), "php"); $tmp = tempnam(sys_get_temp_dir(), "php");