2022-12-17 22:52:21 +01:00
|
|
|
<?php declare(strict_types=1);
|
2015-08-13 01:02:41 +02:00
|
|
|
|
|
|
|
namespace Amp\File\Test;
|
|
|
|
|
2017-06-21 11:01:19 +02:00
|
|
|
use Amp\ByteStream\ClosedException;
|
2017-06-17 01:12:42 +02:00
|
|
|
use Amp\File;
|
2022-11-20 17:39:47 +01:00
|
|
|
use function Amp\async;
|
2015-08-13 01:02:41 +02:00
|
|
|
|
2019-08-23 21:47:03 +02:00
|
|
|
abstract class FileTest extends FilesystemTest
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2022-02-08 19:49:16 +01:00
|
|
|
protected File\FilesystemDriver $driver;
|
2020-06-30 21:45:09 +02:00
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testWrite(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$path = Fixture::path() . "/write";
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile($path, "c+");
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2015-08-13 01:02:41 +02:00
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
$handle->write("foo");
|
|
|
|
$handle->write("bar");
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->seek(0);
|
|
|
|
$contents = $handle->read();
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(6, $handle->tell());
|
2022-02-09 01:28:59 +01:00
|
|
|
$this->assertTrue($handle->eof());
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame("foobar", $contents);
|
2015-08-13 01:02:41 +02:00
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testEmptyWrite(): void
|
2019-01-07 18:32:42 +01:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$path = Fixture::path() . "/write";
|
2019-01-07 18:32:42 +01:00
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile($path, "c+");
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2019-01-07 18:32:42 +01:00
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
$handle->write("");
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2019-01-07 18:32:42 +01:00
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2019-01-07 18:32:42 +01:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testWriteAfterClose(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$path = Fixture::path() . "/write";
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile($path, "c+");
|
|
|
|
$handle->close();
|
2017-06-21 11:01:19 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->expectException(ClosedException::class);
|
2021-12-22 22:54:20 +01:00
|
|
|
$handle->write("bar");
|
2017-06-21 11:01:19 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testDoubleClose(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$path = Fixture::path() . "/write";
|
2020-06-30 21:45:09 +02:00
|
|
|
/** @var File\File $handle */
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile($path, "c+");
|
|
|
|
$handle->close();
|
2021-10-16 04:53:50 +02:00
|
|
|
$handle->close();
|
|
|
|
|
|
|
|
$this->expectNotToPerformAssertions();
|
2017-06-21 14:07:49 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testWriteAfterEnd(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$path = Fixture::path() . "/write";
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile($path, "c+");
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2021-12-22 22:54:20 +01:00
|
|
|
$handle->end("foo");
|
2017-06-21 11:01:19 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->expectException(ClosedException::class);
|
2021-12-22 22:54:20 +01:00
|
|
|
$handle->write("bar");
|
2017-06-21 11:01:19 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testWriteInAppendMode(): void
|
2019-03-01 17:38:04 +01:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$path = Fixture::path() . "/write";
|
2022-09-08 20:44:18 +02:00
|
|
|
$this->driver->write($path, 'previous');
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile($path, "a+");
|
2022-09-08 21:01:50 +02:00
|
|
|
$this->assertSame(8, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->write("bar");
|
|
|
|
$handle->write("foo");
|
2021-12-22 22:54:20 +01:00
|
|
|
$handle->write("baz");
|
2022-09-08 21:01:50 +02:00
|
|
|
$this->assertSame(17, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->seek(0);
|
2022-09-08 21:01:50 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2022-09-08 20:44:18 +02:00
|
|
|
$this->assertSame("previousbarfoobaz", $handle->read());
|
2019-03-01 17:38:04 +01:00
|
|
|
}
|
|
|
|
|
2022-09-08 21:05:43 +02:00
|
|
|
public function testReadInAppendMode(): void
|
|
|
|
{
|
|
|
|
$path = Fixture::path() . "/read-append";
|
|
|
|
$this->driver->write($path, 'previous');
|
|
|
|
$handle = $this->driver->openFile($path, "a+");
|
|
|
|
$this->assertSame(8, $handle->tell());
|
|
|
|
$this->assertNull($handle->read());
|
|
|
|
$this->assertSame(0, $handle->seek(0));
|
|
|
|
$this->assertSame('previous', $handle->read());
|
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testReadingToEnd(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile(__FILE__, "r");
|
2019-08-23 20:59:26 +02:00
|
|
|
$contents = "";
|
|
|
|
$position = 0;
|
2015-08-13 01:02:41 +02:00
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$stat = $this->driver->getStatus(__FILE__);
|
2019-08-23 20:59:26 +02:00
|
|
|
$chunkSize = (int) \floor(($stat["size"] / 5));
|
2015-08-13 01:02:41 +02:00
|
|
|
|
2022-02-09 01:28:59 +01:00
|
|
|
while (!$handle->eof()) {
|
2021-11-21 20:12:23 +01:00
|
|
|
$chunk = $handle->read(length: $chunkSize);
|
2019-08-23 20:59:26 +02:00
|
|
|
$contents .= $chunk;
|
2021-10-16 04:53:50 +02:00
|
|
|
$position += \strlen($chunk ?? '');
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame($position, $handle->tell());
|
|
|
|
}
|
2015-08-13 01:02:41 +02:00
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$this->assertNull($handle->read());
|
|
|
|
$this->assertSame($this->driver->read(__FILE__), $contents);
|
2017-05-18 17:31:20 +02:00
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testSequentialReads(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile(__FILE__, "r");
|
2015-08-13 01:02:41 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$contents = "";
|
2021-11-21 20:12:23 +01:00
|
|
|
$contents .= $handle->read(length: 10);
|
|
|
|
$contents .= $handle->read(length: 10);
|
2015-08-13 01:02:41 +02:00
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$expected = \substr($this->driver->read(__FILE__), 0, 20);
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame($expected, $contents);
|
2017-05-18 17:31:20 +02:00
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testReadingFromOffset(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile(__FILE__, "r");
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->seek(10);
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(10, $handle->tell());
|
2021-11-21 20:12:23 +01:00
|
|
|
$chunk = $handle->read(length: 90);
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(100, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$expected = \substr($this->driver->read(__FILE__), 10, 90);
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame($expected, $chunk);
|
2017-05-18 17:31:20 +02:00
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testSeekThrowsOnInvalidWhence(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:23:33 +02:00
|
|
|
$this->expectException(\Error::class);
|
|
|
|
|
2021-11-21 20:12:23 +01:00
|
|
|
$handle = $this->driver->openFile(__FILE__, "r");
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
try {
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->seek(0, 99999);
|
2019-08-23 20:59:26 +02:00
|
|
|
} finally {
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2019-08-23 20:59:26 +02:00
|
|
|
}
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testSeekSetCur(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile(__FILE__, "r");
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->seek(10);
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(10, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->seek(-10, \SEEK_CUR);
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testSeekSetEnd(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2020-07-01 07:23:23 +02:00
|
|
|
$size = \filesize(__FILE__);
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile(__FILE__, "r");
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->seek(-10, \SEEK_END);
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame($size - 10, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testPath(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile(__FILE__, "r");
|
2020-06-30 21:45:09 +02:00
|
|
|
$this->assertSame(__FILE__, $handle->getPath());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testMode(): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile(__FILE__, "r");
|
2020-06-30 21:45:09 +02:00
|
|
|
$this->assertSame("r", $handle->getMode());
|
2022-11-20 17:40:40 +01:00
|
|
|
$this->assertFalse($handle->isWritable());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2019-08-23 20:59:26 +02:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testClose(): void
|
2019-08-23 20:59:26 +02:00
|
|
|
{
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile(__FILE__, "r");
|
|
|
|
$handle->close();
|
2017-06-21 11:01:19 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->expectException(ClosedException::class);
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->read();
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|
2018-10-29 05:55:11 +01:00
|
|
|
|
2022-11-20 17:39:47 +01:00
|
|
|
public function testCloseWithPendingWrites(): void
|
|
|
|
{
|
|
|
|
$path = Fixture::path() . "/write";
|
|
|
|
|
|
|
|
$handle = $this->driver->openFile($path, "c+");
|
|
|
|
|
|
|
|
$data = "data";
|
|
|
|
$writeFuture = async($handle->write(...), $data);
|
|
|
|
$closeFuture = async($handle->close(...));
|
|
|
|
|
|
|
|
$writeFuture->await();
|
|
|
|
$closeFuture->await();
|
|
|
|
|
|
|
|
$this->assertSame($data, $this->driver->read($path));
|
|
|
|
}
|
|
|
|
|
2018-10-29 05:55:11 +01:00
|
|
|
/**
|
|
|
|
* @depends testWrite
|
|
|
|
*/
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testTruncateToSmallerSize(): void
|
2018-10-29 05:55:11 +01:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$path = Fixture::path() . "/write";
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile($path, "c+");
|
2018-10-29 05:55:11 +01:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$handle->write("foo");
|
2021-12-22 22:54:20 +01:00
|
|
|
$handle->write("bar");
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->truncate(4);
|
|
|
|
$handle->seek(0);
|
|
|
|
$contents = $handle->read();
|
2022-02-09 01:28:59 +01:00
|
|
|
$this->assertTrue($handle->eof());
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame("foob", $contents);
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
$handle->write("bar");
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(7, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->seek(0);
|
|
|
|
$contents = $handle->read();
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame("foobbar", $contents);
|
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2018-10-29 05:55:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @depends testWrite
|
|
|
|
*/
|
2021-12-22 22:54:20 +01:00
|
|
|
public function testTruncateToLargerSize(): void
|
2019-08-23 20:59:26 +02:00
|
|
|
{
|
|
|
|
$path = Fixture::path() . "/write";
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle = $this->driver->openFile($path, "c+");
|
2019-08-23 20:59:26 +02:00
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
$handle->write("foo");
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->truncate(6);
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(3, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->seek(0);
|
|
|
|
$contents = $handle->read();
|
2022-02-09 01:28:59 +01:00
|
|
|
$this->assertTrue($handle->eof());
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame("foo\0\0\0", $contents);
|
|
|
|
|
2021-12-22 22:54:20 +01:00
|
|
|
$handle->write("bar");
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame(9, $handle->tell());
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->seek(0);
|
|
|
|
$contents = $handle->read();
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame("foo\0\0\0bar", $contents);
|
|
|
|
|
2020-10-08 16:23:44 +02:00
|
|
|
$handle->close();
|
2018-10-29 05:55:11 +01:00
|
|
|
}
|
2020-06-30 21:45:09 +02:00
|
|
|
|
2022-02-08 19:49:16 +01:00
|
|
|
abstract protected function createDriver(): File\FilesystemDriver;
|
2020-06-30 21:45:09 +02:00
|
|
|
|
|
|
|
protected function setUp(): void
|
|
|
|
{
|
|
|
|
parent::setUp();
|
|
|
|
|
|
|
|
$this->driver = $this->createDriver();
|
|
|
|
}
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|