Skip to content

Commit

Permalink
Merge pull request #248 from guzzle/fix-stream-modes
Browse files Browse the repository at this point in the history
Fix stream modes
  • Loading branch information
sagikazarmark committed Apr 1, 2019
2 parents dcc698d + aeb07f4 commit a346647
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 18 deletions.
31 changes: 13 additions & 18 deletions src/Stream.php
Expand Up @@ -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\+|rb\+|rw|x|c/';

private $stream;
private $size;
private $seekable;
Expand All @@ -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.
*
Expand Down Expand Up @@ -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');
}

Expand Down
127 changes: 127 additions & 0 deletions tests/StreamTest.php
Expand Up @@ -231,6 +231,133 @@ 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)
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('This does not work on HHVM.');
}

$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],
];
}

/**
* @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+'],
];
}

public function testWriteOnlyStreamIsNotReadable()
{
$r = fopen('php://output', 'w');
$stream = new Stream($r);

$this->assertFalse($stream->isReadable());

$stream->close();
}

/**
* @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+'],
];
}

public function testReadOnlyStreamIsNotWritable()
{
$r = fopen('php://input', 'r');
$stream = new Stream($r);

$this->assertFalse($stream->isWritable());

$stream->close();
}
}

namespace GuzzleHttp\Psr7;
Expand Down

0 comments on commit a346647

Please sign in to comment.