index/tests/ScopedStreamTest.php

96 lines
3.3 KiB
PHP

<?php
// ScopedStreamTest.php
// Created: 2025-03-12
// Updated: 2025-03-12
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\{CoversClass,UsesClass};
use Index\Http\Streams\{ScopedStream,Stream};
#[CoversClass(ScopedStream::class)]
#[UsesClass(Stream::class)]
final class ScopedStreamTest extends TestCase {
public function testScopedStream(): void {
// why use test data when you can just use the source file
$stream = Stream::createStreamFromFile(__FILE__, 'rb');
$stream->seek(5, SEEK_SET);
// potentially account for Windows moments
$offset = $stream->read(2) === "\r\n" ? 7 : 6;
$length = 23;
$scoped = new ScopedStream($stream, $offset, $length);
$this->assertEquals('// ScopedStreamTest.php', (string)$scoped);
$this->assertEquals($length, $scoped->getSize());
// rewind the underlying stream, scoped should should account for tell() < 0
$stream->rewind();
$read = $scoped->read(100);
$this->assertEquals($length, strlen($read));
$this->assertEquals('// ScopedStreamTest.php', $read);
// read beyond end + eof
$stream->seek(-50, SEEK_END);
$read = $scoped->read(100);
$this->assertEmpty($read);
$this->assertTrue($scoped->eof());
// SEEK_SET
$scoped->seek(5);
$this->assertEquals($offset + 5, $stream->tell());
$read = $scoped->read(5);
$this->assertEquals($offset + 10, $stream->tell());
$this->assertEquals('opedS', $read);
$scoped->rewind(); // calls seek(offset) internally
$this->assertEquals($offset, $stream->tell());
// SEEK_CUR
$scoped->seek(4, SEEK_CUR);
$read = $scoped->read(4);
$this->assertEquals('cope', $read);
$read = $stream->read(4);
$this->assertEquals('dStr', $read);
$this->assertEquals(12, $scoped->tell());
$this->assertEquals($offset + 12, $stream->tell());
$scoped->seek(100, SEEK_CUR);
$read = $scoped->read(100);
$this->assertEmpty($read);
$this->assertTrue($scoped->eof());
$this->assertFalse($stream->eof());
$scoped->seek(-100, SEEK_CUR);
$read = $scoped->read(5);
$this->assertEquals('// Sc', $read);
// SEEK_END + eof behaviour
$stream->seek(0, SEEK_END);
$read = $stream->read(1);
$this->assertTrue($scoped->eof());
$this->assertTrue($stream->eof());
$scoped->seek(0, SEEK_END);
$this->assertFalse($scoped->eof());
$this->assertFalse($stream->eof());
// double wrap to test the alternate path in getContents
$double = new ScopedStream($scoped, 5, 12);
$double->seek(5, SEEK_CUR);
$this->assertEquals('tre', $double->read(3));
$this->assertEquals('opedStreamTe', (string)$double);
// now you're scoping with scopes
$triple = ScopedStream::scopeTo($double, 2, 12);
$this->assertInstanceOf(ScopedStream::class, $double->stream);
$this->assertInstanceOf(Stream::class, $triple->stream);
$this->assertEquals($offset + 7, $triple->offset);
$this->assertEquals('edStreamTe', (string)$triple);
$triple->rewind();
$this->assertEquals('edStreamTe', $triple->read(100));
$this->assertTrue($triple->eof());
}
}