diff options
author | marvin-borner@live.com | 2018-04-10 21:50:16 +0200 |
---|---|---|
committer | marvin-borner@live.com | 2018-04-10 21:54:48 +0200 |
commit | fc9401f04a3aca5abb22f87ebc210de8afe11d32 (patch) | |
tree | b0b310f3581764ec3955f4e496a05137a32951c3 /assets/php/vendor/react/stream/tests/WritableStreamResourceTest.php | |
parent | 286d643180672f20526f3dc3bd19d7b751e2fa97 (diff) |
Initial Commit
Diffstat (limited to 'assets/php/vendor/react/stream/tests/WritableStreamResourceTest.php')
-rw-r--r-- | assets/php/vendor/react/stream/tests/WritableStreamResourceTest.php | 534 |
1 files changed, 534 insertions, 0 deletions
diff --git a/assets/php/vendor/react/stream/tests/WritableStreamResourceTest.php b/assets/php/vendor/react/stream/tests/WritableStreamResourceTest.php new file mode 100644 index 0000000..05bce9c --- /dev/null +++ b/assets/php/vendor/react/stream/tests/WritableStreamResourceTest.php @@ -0,0 +1,534 @@ +<?php + +namespace React\Tests\Stream; + +use Clue\StreamFilter as Filter; +use React\Stream\WritableResourceStream; + +class WritableResourceStreamTest extends TestCase +{ + /** + * @covers React\Stream\WritableResourceStream::__construct + * @doesNotPerformAssertions + */ + public function testConstructor() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + new WritableResourceStream($stream, $loop); + } + + /** + * @covers React\Stream\WritableResourceStream::__construct + * @doesNotPerformAssertions + */ + public function testConstructorWithExcessiveMode() + { + // excessive flags are ignored for temp streams, so we have to use a file stream + $name = tempnam(sys_get_temp_dir(), 'test'); + $stream = @fopen($name, 'w+eANYTHING'); + unlink($name); + + $loop = $this->createLoopMock(); + $buffer = new WritableResourceStream($stream, $loop); + $buffer->close(); + } + + /** + * @covers React\Stream\WritableResourceStream::__construct + * @expectedException InvalidArgumentException + */ + public function testConstructorThrowsIfNotAValidStreamResource() + { + $stream = null; + $loop = $this->createLoopMock(); + + new WritableResourceStream($stream, $loop); + } + + /** + * @covers React\Stream\WritableResourceStream::__construct + * @expectedException InvalidArgumentException + */ + public function testConstructorThrowsExceptionOnReadOnlyStream() + { + $stream = fopen('php://temp', 'r'); + $loop = $this->createLoopMock(); + + new WritableResourceStream($stream, $loop); + } + + /** + * @covers React\Stream\WritableResourceStream::__construct + * @expectedException InvalidArgumentException + */ + public function testConstructorThrowsExceptionOnReadOnlyStreamWithExcessiveMode() + { + // excessive flags are ignored for temp streams, so we have to use a file stream + $name = tempnam(sys_get_temp_dir(), 'test'); + $stream = fopen($name, 'reANYTHING'); + unlink($name); + + $loop = $this->createLoopMock(); + new WritableResourceStream($stream, $loop); + } + + /** + * @covers React\Stream\WritableResourceStream::__construct + * @expectedException RuntimeException + */ + public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking() + { + if (!in_array('blocking', stream_get_wrappers())) { + stream_wrapper_register('blocking', 'React\Tests\Stream\EnforceBlockingWrapper'); + } + + $stream = fopen('blocking://test', 'r+'); + $loop = $this->createLoopMock(); + + new WritableResourceStream($stream, $loop); + } + + /** + * @covers React\Stream\WritableResourceStream::write + * @covers React\Stream\WritableResourceStream::handleWrite + */ + public function testWrite() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createWriteableLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop); + $buffer->on('error', $this->expectCallableNever()); + + $buffer->write("foobar\n"); + rewind($stream); + $this->assertSame("foobar\n", fread($stream, 1024)); + } + + /** + * @covers React\Stream\WritableResourceStream::write + */ + public function testWriteWithDataDoesAddResourceToLoop() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + $loop->expects($this->once())->method('addWriteStream')->with($this->equalTo($stream)); + + $buffer = new WritableResourceStream($stream, $loop); + + $buffer->write("foobar\n"); + } + + /** + * @covers React\Stream\WritableResourceStream::write + * @covers React\Stream\WritableResourceStream::handleWrite + */ + public function testEmptyWriteDoesNotAddToLoop() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + $loop->expects($this->never())->method('addWriteStream'); + + $buffer = new WritableResourceStream($stream, $loop); + + $buffer->write(""); + $buffer->write(null); + } + + /** + * @covers React\Stream\WritableResourceStream::write + * @covers React\Stream\WritableResourceStream::handleWrite + */ + public function testWriteReturnsFalseWhenWritableResourceStreamIsFull() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createWriteableLoopMock(); + $loop->preventWrites = true; + + $buffer = new WritableResourceStream($stream, $loop, 4); + $buffer->on('error', $this->expectCallableNever()); + + $this->assertTrue($buffer->write("foo")); + $loop->preventWrites = false; + $this->assertFalse($buffer->write("bar\n")); + } + + /** + * @covers React\Stream\WritableResourceStream::write + */ + public function testWriteReturnsFalseWhenWritableResourceStreamIsExactlyFull() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop, 3); + + $this->assertFalse($buffer->write("foo")); + } + + /** + * @covers React\Stream\WritableResourceStream::write + * @covers React\Stream\WritableResourceStream::handleWrite + */ + public function testWriteDetectsWhenOtherSideIsClosed() + { + list($a, $b) = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP); + + $loop = $this->createWriteableLoopMock(); + + $buffer = new WritableResourceStream($a, $loop, 4); + $buffer->on('error', $this->expectCallableOnce()); + + fclose($b); + + $buffer->write("foo"); + } + + /** + * @covers React\Stream\WritableResourceStream::write + * @covers React\Stream\WritableResourceStream::handleWrite + */ + public function testEmitsDrainAfterWriteWhichExceedsBuffer() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop, 2); + $buffer->on('error', $this->expectCallableNever()); + $buffer->on('drain', $this->expectCallableOnce()); + + $buffer->write("foo"); + $buffer->handleWrite(); + } + + /** + * @covers React\Stream\WritableResourceStream::write + * @covers React\Stream\WritableResourceStream::handleWrite + */ + public function testWriteInDrain() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop, 2); + $buffer->on('error', $this->expectCallableNever()); + + $buffer->once('drain', function () use ($buffer) { + $buffer->write("bar\n"); + $buffer->handleWrite(); + }); + + $this->assertFalse($buffer->write("foo\n")); + $buffer->handleWrite(); + + fseek($stream, 0); + $this->assertSame("foo\nbar\n", stream_get_contents($stream)); + } + + /** + * @covers React\Stream\WritableResourceStream::write + * @covers React\Stream\WritableResourceStream::handleWrite + */ + public function testDrainAfterWrite() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop, 2); + + $buffer->on('drain', $this->expectCallableOnce()); + + $buffer->write("foo"); + $buffer->handleWrite(); + } + + /** + * @covers React\Stream\WritableResourceStream::handleWrite + */ + public function testDrainAfterWriteWillRemoveResourceFromLoopWithoutClosing() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + $loop->expects($this->once())->method('removeWriteStream')->with($stream); + + $buffer = new WritableResourceStream($stream, $loop, 2); + + $buffer->on('drain', $this->expectCallableOnce()); + + $buffer->on('close', $this->expectCallableNever()); + + $buffer->write("foo"); + $buffer->handleWrite(); + } + + /** + * @covers React\Stream\WritableResourceStream::handleWrite + */ + public function testClosingDuringDrainAfterWriteWillRemoveResourceFromLoopOnceAndClose() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + $loop->expects($this->once())->method('removeWriteStream')->with($stream); + + $buffer = new WritableResourceStream($stream, $loop, 2); + + $buffer->on('drain', function () use ($buffer) { + $buffer->close(); + }); + + $buffer->on('close', $this->expectCallableOnce()); + + $buffer->write("foo"); + $buffer->handleWrite(); + } + + /** + * @covers React\Stream\WritableResourceStream::end + */ + public function testEndWithoutDataClosesImmediatelyIfWritableResourceStreamIsEmpty() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop); + $buffer->on('error', $this->expectCallableNever()); + $buffer->on('close', $this->expectCallableOnce()); + + $this->assertTrue($buffer->isWritable()); + $buffer->end(); + $this->assertFalse($buffer->isWritable()); + } + + /** + * @covers React\Stream\WritableResourceStream::end + */ + public function testEndWithoutDataDoesNotCloseIfWritableResourceStreamIsFull() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop); + $buffer->on('error', $this->expectCallableNever()); + $buffer->on('close', $this->expectCallableNever()); + + $buffer->write('foo'); + + $this->assertTrue($buffer->isWritable()); + $buffer->end(); + $this->assertFalse($buffer->isWritable()); + } + + /** + * @covers React\Stream\WritableResourceStream::end + */ + public function testEndWithDataClosesImmediatelyIfWritableResourceStreamFlushes() + { + $stream = fopen('php://temp', 'r+'); + $filterBuffer = ''; + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop); + $buffer->on('error', $this->expectCallableNever()); + $buffer->on('close', $this->expectCallableOnce()); + + Filter\append($stream, function ($chunk) use (&$filterBuffer) { + $filterBuffer .= $chunk; + return $chunk; + }); + + $this->assertTrue($buffer->isWritable()); + $buffer->end('final words'); + $this->assertFalse($buffer->isWritable()); + + $buffer->handleWrite(); + $this->assertSame('final words', $filterBuffer); + } + + /** + * @covers React\Stream\WritableResourceStream::end + */ + public function testEndWithDataDoesNotCloseImmediatelyIfWritableResourceStreamIsFull() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop); + $buffer->on('error', $this->expectCallableNever()); + $buffer->on('close', $this->expectCallableNever()); + + $buffer->write('foo'); + + $this->assertTrue($buffer->isWritable()); + $buffer->end('final words'); + $this->assertFalse($buffer->isWritable()); + + rewind($stream); + $this->assertSame('', stream_get_contents($stream)); + } + + /** + * @covers React\Stream\WritableResourceStream::isWritable + * @covers React\Stream\WritableResourceStream::close + */ + public function testClose() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop); + $buffer->on('error', $this->expectCallableNever()); + $buffer->on('close', $this->expectCallableOnce()); + + $this->assertTrue($buffer->isWritable()); + $buffer->close(); + $this->assertFalse($buffer->isWritable()); + + $this->assertEquals(array(), $buffer->listeners('close')); + } + + /** + * @covers React\Stream\WritableResourceStream::close + */ + public function testClosingAfterWriteRemovesStreamFromLoop() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + $buffer = new WritableResourceStream($stream, $loop); + + $loop->expects($this->once())->method('removeWriteStream')->with($stream); + + $buffer->write('foo'); + $buffer->close(); + } + + /** + * @covers React\Stream\WritableResourceStream::close + */ + public function testClosingWithoutWritingDoesNotRemoveStreamFromLoop() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + $buffer = new WritableResourceStream($stream, $loop); + + $loop->expects($this->never())->method('removeWriteStream'); + + $buffer->close(); + } + + /** + * @covers React\Stream\WritableResourceStream::close + */ + public function testDoubleCloseWillEmitOnlyOnce() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop); + $buffer->on('close', $this->expectCallableOnce()); + + $buffer->close(); + $buffer->close(); + } + + /** + * @covers React\Stream\WritableResourceStream::write + * @covers React\Stream\WritableResourceStream::close + */ + public function testWritingToClosedWritableResourceStreamShouldNotWriteToStream() + { + $stream = fopen('php://temp', 'r+'); + $filterBuffer = ''; + $loop = $this->createLoopMock(); + + $buffer = new WritableResourceStream($stream, $loop); + + Filter\append($stream, function ($chunk) use (&$filterBuffer) { + $filterBuffer .= $chunk; + return $chunk; + }); + + $buffer->close(); + + $buffer->write('foo'); + + $buffer->handleWrite(); + $this->assertSame('', $filterBuffer); + } + + /** + * @covers React\Stream\WritableResourceStream::handleWrite + */ + public function testErrorWhenStreamResourceIsInvalid() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createWriteableLoopMock(); + + $error = null; + + $buffer = new WritableResourceStream($stream, $loop); + $buffer->on('error', function ($message) use (&$error) { + $error = $message; + }); + + // invalidate stream resource + fclose($stream); + + $buffer->write('Attempting to write to bad stream'); + + $this->assertInstanceOf('Exception', $error); + + // the error messages differ between PHP versions, let's just check substrings + $this->assertContains('Unable to write to stream: ', $error->getMessage()); + $this->assertContains(' not a valid stream resource', $error->getMessage(), '', true); + } + + public function testWritingToClosedStream() + { + if ('Darwin' === PHP_OS) { + $this->markTestSkipped('OS X issue with shutting down pair for writing'); + } + + list($a, $b) = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP); + $loop = $this->createLoopMock(); + + $error = null; + + $buffer = new WritableResourceStream($a, $loop); + $buffer->on('error', function($message) use (&$error) { + $error = $message; + }); + + $buffer->write('foo'); + $buffer->handleWrite(); + stream_socket_shutdown($b, STREAM_SHUT_RD); + stream_socket_shutdown($a, STREAM_SHUT_RD); + $buffer->write('bar'); + $buffer->handleWrite(); + + $this->assertInstanceOf('Exception', $error); + $this->assertSame('Unable to write to stream: fwrite(): send of 3 bytes failed with errno=32 Broken pipe', $error->getMessage()); + } + + private function createWriteableLoopMock() + { + $loop = $this->createLoopMock(); + $loop->preventWrites = false; + $loop + ->expects($this->any()) + ->method('addWriteStream') + ->will($this->returnCallback(function ($stream, $listener) use ($loop) { + if (!$loop->preventWrites) { + call_user_func($listener, $stream); + } + })); + + return $loop; + } + + private function createLoopMock() + { + return $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + } +} |