From 7278a550a1ccf510e2daca3aa7c74cc194263bc9 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Fri, 7 Dec 2018 14:20:10 +0100 Subject: [PATCH 1/5] Add failing test for gzip stream modes See #115 --- tests/StreamTest.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/StreamTest.php b/tests/StreamTest.php index bf4653c0..83fbcd25 100644 --- a/tests/StreamTest.php +++ b/tests/StreamTest.php @@ -231,6 +231,32 @@ public function testStreamReadingFreadError() self::$isFReadError = false; $stream->close(); } + + /** + * @dataProvider gzipModeProvider + * + * @param string $mode + * @param bool $readable + * @param bool $writable + */ + public function testGzipStreamModes($mode, $readable, $writable) + { + $r = gzopen('php://temp', $mode); + $stream = new Stream($r); + + $this->assertSame($readable, $stream->isReadable()); + $this->assertSame($writable, $stream->isWritable()); + + $stream->close(); + } + + public function gzipModeProvider() + { + return [ + ['mode' => 'rb9', 'readable' => true, 'writable' => false], + ['mode' => 'wb2', 'readable' => false, 'writable' => true], + ]; + } } namespace GuzzleHttp\Psr7; From 34b46615a953e3971292752c4dceb432130ee934 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Fri, 7 Dec 2018 14:25:16 +0100 Subject: [PATCH 2/5] Use regex for matching read and write modes of a stream See https://github.com/guzzle/psr7/issues/183#issuecomment-380952107 --- src/Stream.php | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/Stream.php b/src/Stream.php index 73d24f43..7decd52b 100644 --- a/src/Stream.php +++ b/src/Stream.php @@ -10,6 +10,17 @@ */ class Stream implements StreamInterface { + /** + * Resource modes. + * + * @var string + * + * @see http://php.net/manual/function.fopen.php + * @see http://php.net/manual/en/function.gzopen.php + */ + const READABLE_MODES = '/r|a\+|ab\+|w\+|wb\+|x\+|xb\+|c\+|cb\+/'; + const WRITABLE_MODES = '/a|w|r\+|rw|x|c/'; + private $stream; private $size; private $seekable; @@ -18,22 +29,6 @@ class Stream implements StreamInterface private $uri; private $customMetadata; - /** @var array Hash of readable and writable stream types */ - private static $readWriteHash = [ - 'read' => [ - 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, - 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, - 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true, - 'x+t' => true, 'c+t' => true, 'a+' => true, 'rb+' => true, - ], - 'write' => [ - 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, - 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, 'rb+' => true, - 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true, - 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true - ] - ]; - /** * This constructor accepts an associative array of options. * @@ -65,8 +60,8 @@ public function __construct($stream, $options = []) $this->stream = $stream; $meta = stream_get_meta_data($this->stream); $this->seekable = $meta['seekable']; - $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]); - $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]); + $this->readable = (bool)preg_match(self::READABLE_MODES, $meta['mode']); + $this->writable = (bool)preg_match(self::WRITABLE_MODES, $meta['mode']); $this->uri = $this->getMetadata('uri'); } From 72ac89c9a4b93bcff6139da5b2758af8f8096202 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Fri, 7 Dec 2018 14:30:08 +0100 Subject: [PATCH 3/5] Add tests for read and write modes --- tests/StreamTest.php | 77 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/tests/StreamTest.php b/tests/StreamTest.php index 83fbcd25..7844c55b 100644 --- a/tests/StreamTest.php +++ b/tests/StreamTest.php @@ -257,6 +257,83 @@ public function gzipModeProvider() ['mode' => 'wb2', 'readable' => false, 'writable' => true], ]; } + + /** + * @dataProvider readableModeProvider + * + * @param string $mode + */ + public function testReadableStream($mode) + { + $r = fopen('php://temp', $mode); + $stream = new Stream($r); + + $this->assertTrue($stream->isReadable()); + + $stream->close(); + } + + public function readableModeProvider() + { + return [ + ['r'], + ['w+'], + ['r+'], + ['x+'], + ['c+'], + ['rb'], + ['w+b'], + ['r+b'], + ['x+b'], + ['c+b'], + ['rt'], + ['w+t'], + ['r+t'], + ['x+t'], + ['c+t'], + ['a+'], + ['rb+'], + ]; + } + + /** + * @dataProvider writableModeProvider + * + * @param string $mode + */ + public function testWritableStream($mode) + { + $r = fopen('php://temp', $mode); + $stream = new Stream($r); + + $this->assertTrue($stream->isWritable()); + + $stream->close(); + } + + public function writableModeProvider() + { + return [ + ['w'], + ['w+'], + ['rw'], + ['r+'], + ['x+'], + ['c+'], + ['wb'], + ['w+b'], + ['r+b'], + ['rb+'], + ['x+b'], + ['c+b'], + ['w+t'], + ['r+t'], + ['x+t'], + ['c+t'], + ['a'], + ['a+'], + ]; + } } namespace GuzzleHttp\Psr7; From 799aa4797a60a74634378fb1e4a5d86197fc1239 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Fri, 7 Dec 2018 15:01:37 +0100 Subject: [PATCH 4/5] Fix tests on hhvm --- src/Stream.php | 2 +- tests/StreamTest.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Stream.php b/src/Stream.php index 7decd52b..d9e7409c 100644 --- a/src/Stream.php +++ b/src/Stream.php @@ -19,7 +19,7 @@ class Stream implements StreamInterface * @see http://php.net/manual/en/function.gzopen.php */ const READABLE_MODES = '/r|a\+|ab\+|w\+|wb\+|x\+|xb\+|c\+|cb\+/'; - const WRITABLE_MODES = '/a|w|r\+|rw|x|c/'; + const WRITABLE_MODES = '/a|w|r\+|rb\+|rw|x|c/'; private $stream; private $size; diff --git a/tests/StreamTest.php b/tests/StreamTest.php index 7844c55b..a100ebd7 100644 --- a/tests/StreamTest.php +++ b/tests/StreamTest.php @@ -241,6 +241,10 @@ public function testStreamReadingFreadError() */ public function testGzipStreamModes($mode, $readable, $writable) { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('This does not work on HHVM.'); + } + $r = gzopen('php://temp', $mode); $stream = new Stream($r); From aeb07f45c07e24aed06facafceed4ce8b4d0d0c9 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 20 Feb 2019 09:41:01 +0100 Subject: [PATCH 5/5] Add tests for read and write only streams --- tests/StreamTest.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/StreamTest.php b/tests/StreamTest.php index a100ebd7..63421ce5 100644 --- a/tests/StreamTest.php +++ b/tests/StreamTest.php @@ -300,6 +300,16 @@ public function readableModeProvider() ]; } + public function testWriteOnlyStreamIsNotReadable() + { + $r = fopen('php://output', 'w'); + $stream = new Stream($r); + + $this->assertFalse($stream->isReadable()); + + $stream->close(); + } + /** * @dataProvider writableModeProvider * @@ -338,6 +348,16 @@ public function writableModeProvider() ['a+'], ]; } + + public function testReadOnlyStreamIsNotWritable() + { + $r = fopen('php://input', 'r'); + $stream = new Stream($r); + + $this->assertFalse($stream->isWritable()); + + $stream->close(); + } } namespace GuzzleHttp\Psr7;