resource = fopen("php://memory", "w+"); $this->resourceDevNull = fopen("/dev/null", "r"); fwrite($this->resource, $this->content); StreamHelper::$fail = false; } public function tearDown(): void { if (is_resource($this->resource)) { fclose($this->resource); } } public function testCreatesInstanceWithStreamResource() { $stream = new Stream($this->resource); $this->assertNotNull($stream); } public function testCreatesInstanceWithString() { $stream = new Stream("Hello, world!"); $this->assertNotNull($stream); } /** * @dataProvider invalidResourceProvider * @param mixed $resource */ public function testThrowsExceptionWithInvalidResource($resource) { $this->expectException(InvalidArgumentException::class); new Stream($resource); } public function invalidResourceProvider() { return [ [null], [true], [4], [[]] ]; } public function testCastsToString() { $stream = new Stream($this->resource); $this->assertEquals($this->content, (string) $stream); } public function testClosesHandle() { $stream = new Stream($this->resource); $stream->close(); $this->assertFalse(is_resource($this->resource)); } public function testDetachReturnsHandle() { $stream = new Stream($this->resource); $this->assertSame($this->resource, $stream->detach()); } public function testDetachUnsetsInstanceVariable() { $stream = new Stream($this->resource); $stream->detach(); $this->assertNull($stream->detach()); } public function testReturnsSize() { $stream = new Stream($this->resource); $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); fseek($this->resource, 10); $this->assertEquals(10, $stream->tell()); } public function testTellThrowsRuntimeExceptionWhenUnableToReadStreamPosition() { StreamHelper::$fail = true; $stream = new Stream($this->resource); $this->expectException(RuntimeException::class); $stream->tell(); } public function testReturnsOef() { $stream = new Stream($this->resource); $stream->rewind(); $stream->getContents(); $this->assertTrue($stream->eof()); } public function testReadsSeekableStatusFromMetadata() { $stream = new Stream($this->resource); $metadata = stream_get_meta_data($this->resource); $seekable = $metadata["seekable"] == 1; $this->assertEquals($seekable, $stream->isSeekable()); } public function testSeeksToPosition() { $stream = new Stream($this->resource); $stream->seek(10); $this->assertEquals(10, ftell($this->resource)); } public function testSeekThrowsRuntimeExceptionWhenUnableToSeek() { StreamHelper::$fail = true; $stream = new Stream($this->resource); $this->expectException(RuntimeException::class); $stream->seek(10); } public function testRewindReturnsToBeginning() { $stream = new Stream($this->resource); $stream->seek(10); $stream->rewind(); $this->assertEquals(0, ftell($this->resource)); } public function testRewindThrowsRuntimeExceptionWhenUnableToRewind() { StreamHelper::$fail = true; $stream = new Stream($this->resource); $this->expectException(RuntimeException::class); $stream->rewind(); } public function testWritesToHandle() { $message = "\nThis is a stream."; $stream = new Stream($this->resource); $stream->write($message); $this->assertEquals($this->content . $message, (string) $stream); } public function testThrowsExceptionOnErrorWriting() { $this->expectException(RuntimeException::class); $filename = tempnam(sys_get_temp_dir(), "php"); $handle = fopen($filename, "r"); $stream = new Stream($handle); $stream->write("Hello, world!"); } public function testThrowsExceptionOnErrorReading() { $this->expectException(RuntimeException::class); $filename = tempnam(sys_get_temp_dir(), "php"); $handle = fopen($filename, "w"); $stream = new Stream($handle); $stream->read(10); } public function testReadsFromStream() { $stream = new Stream($this->resource); $stream->seek(7); $string = $stream->read(5); $this->assertEquals("world", $string); } public function testThrowsExceptionOnErrorReadingToEnd() { $this->expectException(RuntimeException::class); $filename = tempnam(sys_get_temp_dir(), "php"); $handle = fopen($filename, "w"); $stream = new Stream($handle); $stream->getContents(); } public function testReadsToEnd() { $stream = new Stream($this->resource); $stream->seek(7); $string = $stream->getContents(); $this->assertEquals("world!", $string); } public function testReturnsMetadataArray() { $stream = new Stream($this->resource); $this->assertEquals(stream_get_meta_data($this->resource), $stream->getMetadata()); } public function testReturnsMetadataItem() { $stream = new Stream($this->resource); $metadata = stream_get_meta_data($this->resource); $this->assertEquals($metadata["mode"], $stream->getMetadata("mode")); } /** * @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"); if ($mode[0] === "x") { unlink($tmp); } $resource = fopen($tmp, $mode); $stream = new Stream($resource); $this->assertEquals($readable, $stream->isReadable()); } /** * @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"); if ($mode[0] === "x") { unlink($tmp); } $resource = fopen($tmp, $mode); $stream = new Stream($resource); $this->assertEquals($writable, $stream->isWritable()); } public function modeProvider() { return [ ["r", true, false], ["r+", true, true], ["w", false, true], ["w+", true, true], ["a", false, true], ["a+", true, true], ["x", false, true], ["x+", true, true], ["c", false, true], ["c+", true, true] ]; } }