From d2320c2e2f721fb0a030e6183986b9267dcc4484 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 17:44:27 +0000 Subject: [PATCH 1/2] Initial plan From 252866a6364b0d117209cccad8cfd689025779c1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 17:46:07 +0000 Subject: [PATCH 2/2] Fix stream behavior issues Co-authored-by: asika32764 <1639206+asika32764@users.noreply.github.com> --- packages/stream/src/DecoratorStream.php | 4 +--- packages/stream/src/PhpInputStream.php | 2 +- packages/stream/src/StringStream.php | 7 +++++++ packages/stream/test/DecoratorStreamTest.php | 8 ++++++++ packages/stream/test/PhpInputStreamTest.php | 5 ++++- packages/stream/test/StringStreamTest.php | 14 ++++++++++++++ 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/packages/stream/src/DecoratorStream.php b/packages/stream/src/DecoratorStream.php index 55304acfe..c9b993b7d 100644 --- a/packages/stream/src/DecoratorStream.php +++ b/packages/stream/src/DecoratorStream.php @@ -15,9 +15,7 @@ class DecoratorStream implements StreamInterface public function __construct(?StreamInterface $target = null) { - if ($target) { - $this->stream = $target; - } + $this->stream = $target ?? new Stream(); } public function __toString(): string diff --git a/packages/stream/src/PhpInputStream.php b/packages/stream/src/PhpInputStream.php index 7d2228c18..eb11f5337 100644 --- a/packages/stream/src/PhpInputStream.php +++ b/packages/stream/src/PhpInputStream.php @@ -29,7 +29,7 @@ protected function __construct(?StreamInterface $cache = null) public static function getInstance(?StreamInterface $cache = null): self { - return self::$instance ?? new PhpInputStream($cache); + return self::$instance ??= new self($cache); } public static function getInstanceAndCached(?StreamInterface $cache = null): self diff --git a/packages/stream/src/StringStream.php b/packages/stream/src/StringStream.php index 0490e1b17..7a068bade 100644 --- a/packages/stream/src/StringStream.php +++ b/packages/stream/src/StringStream.php @@ -262,6 +262,10 @@ public function isWritable(): bool */ public function write($string): int { + if (!$this->isWritable()) { + throw new RuntimeException('Stream is not writable'); + } + $length = strlen($string); $start = substr($this->resource, 0, $this->pointer); @@ -326,6 +330,9 @@ public function getContents(): string return ''; } + $this->pointer += strlen($result); + $this->readPosition = $this->pointer; + return $result; } diff --git a/packages/stream/test/DecoratorStreamTest.php b/packages/stream/test/DecoratorStreamTest.php index 87b24ec07..1f02e301f 100644 --- a/packages/stream/test/DecoratorStreamTest.php +++ b/packages/stream/test/DecoratorStreamTest.php @@ -19,6 +19,14 @@ public function constructAcceptsInnerStream(): void $this->assertSame($inner, new DecoratorStream($inner)->getInnerStream()); } + #[Test] + public function constructWithoutTargetCreatesEmptyStream(): void + { + $decorator = new DecoratorStream(); + + $this->assertSame('', $decorator->getContents()); + } + #[Test] public function setInnerStreamReplacesTarget(): void { diff --git a/packages/stream/test/PhpInputStreamTest.php b/packages/stream/test/PhpInputStreamTest.php index 0ed04e8cd..887d66ddc 100644 --- a/packages/stream/test/PhpInputStreamTest.php +++ b/packages/stream/test/PhpInputStreamTest.php @@ -23,6 +23,9 @@ public function getInstanceAndCachedReturnsRewoundStreamWithInputContents(): voi #[Test] public function getInstanceCreatesStreamWithGivenCache(): void { - $this->assertInstanceOf(PhpInputStream::class, PhpInputStream::getInstance()); + $stream = PhpInputStream::getInstance(); + + $this->assertInstanceOf(PhpInputStream::class, $stream); + $this->assertSame($stream, PhpInputStream::getInstance()); } } diff --git a/packages/stream/test/StringStreamTest.php b/packages/stream/test/StringStreamTest.php index a9a5a646b..9b33f6f64 100644 --- a/packages/stream/test/StringStreamTest.php +++ b/packages/stream/test/StringStreamTest.php @@ -284,6 +284,8 @@ public function getContentsReturnsRemainingStringFromPosition(): void $stream->seek(2); $this->assertEquals('O BAR', $stream->getContents()); + $this->assertSame(7, $stream->tell()); + $this->assertSame('', $stream->getContents()); } #[Test] @@ -384,4 +386,16 @@ public function writableControlsIsWritable(): void $this->assertTrue($stream->isWritable()); } + + #[Test] + public function writableFalseBlocksWrite(): void + { + $stream = new StringStream('FOO', READ_WRITE_FROM_BEGIN); + $stream->writable(false); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessageIs('Stream is not writable'); + + $stream->write('BAR'); + } }