2016-12-30 03:59:59 +01:00
|
|
|
<?php
|
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;
|
2017-05-18 05:58:39 +02:00
|
|
|
use Amp\PHPUnit\TestCase;
|
2015-08-13 01:02:41 +02:00
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
abstract class HandleTest extends TestCase
|
|
|
|
{
|
|
|
|
protected function setUp()
|
|
|
|
{
|
2015-08-13 01:02:41 +02:00
|
|
|
Fixture::init();
|
2017-06-17 01:12:42 +02:00
|
|
|
File\StatCache::clear();
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
protected function tearDown()
|
|
|
|
{
|
2015-08-13 01:02:41 +02:00
|
|
|
Fixture::clear();
|
|
|
|
}
|
|
|
|
|
2017-06-17 01:12:42 +02:00
|
|
|
abstract protected function execute(callable $cb);
|
2016-07-21 01:33:03 +02:00
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testWrite()
|
|
|
|
{
|
2017-06-17 01:12:42 +02:00
|
|
|
$this->execute(function () {
|
2015-08-13 01:02:41 +02:00
|
|
|
$path = Fixture::path() . "/write";
|
2017-06-20 07:06:12 +02:00
|
|
|
/** @var \Amp\File\Handle $handle */
|
2017-06-17 01:12:42 +02:00
|
|
|
$handle = yield File\open($path, "c+");
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
|
|
|
|
2017-06-20 07:58:30 +02:00
|
|
|
$handle->write("foo");
|
2015-08-13 01:02:41 +02:00
|
|
|
yield $handle->write("bar");
|
2017-06-20 07:06:12 +02:00
|
|
|
yield $handle->seek(0);
|
|
|
|
$contents = yield $handle->read();
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame(6, $handle->tell());
|
|
|
|
$this->assertTrue($handle->eof());
|
|
|
|
$this->assertSame("foobar", $contents);
|
|
|
|
|
|
|
|
yield $handle->close();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-01-07 18:32:42 +01:00
|
|
|
public function testEmptyWrite()
|
|
|
|
{
|
|
|
|
$this->execute(function () {
|
|
|
|
$path = Fixture::path() . "/write";
|
|
|
|
|
|
|
|
$handle = yield File\open($path, "c+");
|
|
|
|
$this->assertSame(0, $handle->tell());
|
|
|
|
|
|
|
|
yield $handle->write("");
|
|
|
|
$this->assertSame(0, $handle->tell());
|
|
|
|
|
|
|
|
yield $handle->close();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testWriteAfterClose()
|
|
|
|
{
|
2017-06-21 11:01:19 +02:00
|
|
|
$this->execute(function () {
|
|
|
|
$path = Fixture::path() . "/write";
|
|
|
|
/** @var \Amp\File\Handle $handle */
|
|
|
|
$handle = yield File\open($path, "c+");
|
|
|
|
yield $handle->close();
|
|
|
|
|
|
|
|
$this->expectException(ClosedException::class);
|
|
|
|
yield $handle->write("bar");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testDoubleClose()
|
|
|
|
{
|
2017-06-21 14:07:49 +02:00
|
|
|
$this->execute(function () {
|
|
|
|
$path = Fixture::path() . "/write";
|
|
|
|
/** @var \Amp\File\Handle $handle */
|
|
|
|
$handle = yield File\open($path, "c+");
|
|
|
|
yield $handle->close();
|
|
|
|
$this->assertNull(yield $handle->close());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testWriteAfterEnd()
|
|
|
|
{
|
2017-06-21 11:01:19 +02:00
|
|
|
$this->execute(function () {
|
|
|
|
$path = Fixture::path() . "/write";
|
|
|
|
/** @var \Amp\File\Handle $handle */
|
|
|
|
$handle = yield File\open($path, "c+");
|
|
|
|
$this->assertSame(0, $handle->tell());
|
|
|
|
yield $handle->end("foo");
|
|
|
|
|
|
|
|
$this->expectException(ClosedException::class);
|
|
|
|
yield $handle->write("bar");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testReadingToEof()
|
|
|
|
{
|
2017-06-17 01:12:42 +02:00
|
|
|
$this->execute(function () {
|
2017-06-20 07:06:12 +02:00
|
|
|
/** @var \Amp\File\Handle $handle */
|
2017-06-17 01:12:42 +02:00
|
|
|
$handle = yield File\open(__FILE__, "r");
|
2015-08-13 01:02:41 +02:00
|
|
|
$contents = "";
|
|
|
|
$position = 0;
|
|
|
|
|
2017-06-17 01:12:42 +02:00
|
|
|
$stat = yield File\stat(__FILE__);
|
2016-08-24 07:01:41 +02:00
|
|
|
$chunkSize = (int) \floor(($stat["size"] / 5));
|
2015-08-13 01:02:41 +02:00
|
|
|
|
|
|
|
while (!$handle->eof()) {
|
2017-06-17 01:12:42 +02:00
|
|
|
$chunk = yield $handle->read($chunkSize);
|
2015-08-13 01:02:41 +02:00
|
|
|
$contents .= $chunk;
|
|
|
|
$position += \strlen($chunk);
|
|
|
|
$this->assertSame($position, $handle->tell());
|
|
|
|
}
|
|
|
|
|
2017-06-20 18:25:37 +02:00
|
|
|
$this->assertNull(yield $handle->read());
|
2017-06-20 07:06:12 +02:00
|
|
|
$this->assertSame(yield File\get(__FILE__), $contents);
|
2017-05-18 17:31:20 +02:00
|
|
|
|
|
|
|
yield $handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testSequentialReads()
|
|
|
|
{
|
2017-06-17 01:12:42 +02:00
|
|
|
$this->execute(function () {
|
2017-06-20 07:06:12 +02:00
|
|
|
/** @var \Amp\File\Handle $handle */
|
2017-06-17 01:12:42 +02:00
|
|
|
$handle = yield File\open(__FILE__, "r");
|
2015-08-13 01:02:41 +02:00
|
|
|
|
|
|
|
$contents = "";
|
2017-06-20 07:06:12 +02:00
|
|
|
$contents .= yield $handle->read(10);
|
|
|
|
$contents .= yield $handle->read(10);
|
2015-08-13 01:02:41 +02:00
|
|
|
|
2017-06-20 07:06:12 +02:00
|
|
|
$expected = \substr(yield File\get(__FILE__), 0, 20);
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame($expected, $contents);
|
2017-05-18 17:31:20 +02:00
|
|
|
|
|
|
|
yield $handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testReadingFromOffset()
|
|
|
|
{
|
2017-06-17 01:12:42 +02:00
|
|
|
$this->execute(function () {
|
2017-06-20 07:06:12 +02:00
|
|
|
/** @var \Amp\File\Handle $handle */
|
2017-06-17 01:12:42 +02:00
|
|
|
$handle = yield File\open(__FILE__, "r");
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2016-08-30 21:05:14 +02:00
|
|
|
yield $handle->seek(10);
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame(10, $handle->tell());
|
2017-06-20 07:06:12 +02:00
|
|
|
$chunk = yield $handle->read(90);
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame(100, $handle->tell());
|
2017-06-20 07:06:12 +02:00
|
|
|
$expected = \substr(yield File\get(__FILE__), 10, 90);
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame($expected, $chunk);
|
2017-05-18 17:31:20 +02:00
|
|
|
|
|
|
|
yield $handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-08-30 21:05:14 +02:00
|
|
|
* @expectedException \Error
|
2015-08-13 01:02:41 +02:00
|
|
|
*/
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testSeekThrowsOnInvalidWhence()
|
|
|
|
{
|
2017-06-17 01:12:42 +02:00
|
|
|
$this->execute(function () {
|
2017-05-18 17:31:20 +02:00
|
|
|
try {
|
2017-06-20 07:06:12 +02:00
|
|
|
/** @var \Amp\File\Handle $handle */
|
2017-06-17 01:12:42 +02:00
|
|
|
$handle = yield File\open(__FILE__, "r");
|
2017-05-18 17:31:20 +02:00
|
|
|
yield $handle->seek(0, 99999);
|
|
|
|
} finally {
|
|
|
|
yield $handle->close();
|
|
|
|
}
|
2015-08-13 01:02:41 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testSeekSetCur()
|
|
|
|
{
|
2017-06-17 01:12:42 +02:00
|
|
|
$this->execute(function () {
|
2017-06-20 07:06:12 +02:00
|
|
|
/** @var \Amp\File\Handle $handle */
|
2017-06-17 01:12:42 +02:00
|
|
|
$handle = yield File\open(__FILE__, "r");
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2016-08-30 21:05:14 +02:00
|
|
|
yield $handle->seek(10);
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame(10, $handle->tell());
|
2016-08-30 21:05:14 +02:00
|
|
|
yield $handle->seek(-10, \SEEK_CUR);
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2017-05-18 17:31:20 +02:00
|
|
|
yield $handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testSeekSetEnd()
|
|
|
|
{
|
2017-06-17 01:12:42 +02:00
|
|
|
$this->execute(function () {
|
|
|
|
$size = yield File\size(__FILE__);
|
2017-06-20 07:06:12 +02:00
|
|
|
/** @var \Amp\File\Handle $handle */
|
2017-06-17 01:12:42 +02:00
|
|
|
$handle = yield File\open(__FILE__, "r");
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame(0, $handle->tell());
|
2016-08-30 21:05:14 +02:00
|
|
|
yield $handle->seek(-10, \SEEK_END);
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame($size - 10, $handle->tell());
|
2017-05-18 17:31:20 +02:00
|
|
|
yield $handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testPath()
|
|
|
|
{
|
2017-06-17 01:12:42 +02:00
|
|
|
$this->execute(function () {
|
2017-06-20 07:06:12 +02:00
|
|
|
/** @var \Amp\File\Handle $handle */
|
2017-06-17 01:12:42 +02:00
|
|
|
$handle = yield File\open(__FILE__, "r");
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame(__FILE__, $handle->path());
|
2017-05-18 17:31:20 +02:00
|
|
|
yield $handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testMode()
|
|
|
|
{
|
2017-06-17 01:12:42 +02:00
|
|
|
$this->execute(function () {
|
2017-06-20 07:06:12 +02:00
|
|
|
/** @var \Amp\File\Handle $handle */
|
2017-06-17 01:12:42 +02:00
|
|
|
$handle = yield File\open(__FILE__, "r");
|
2015-08-13 01:02:41 +02:00
|
|
|
$this->assertSame("r", $handle->mode());
|
2017-05-18 17:31:20 +02:00
|
|
|
yield $handle->close();
|
2015-08-13 01:02:41 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
public function testClose()
|
|
|
|
{
|
2017-06-17 01:12:42 +02:00
|
|
|
$this->execute(function () {
|
2017-06-20 07:06:12 +02:00
|
|
|
/** @var \Amp\File\Handle $handle */
|
2017-06-17 01:12:42 +02:00
|
|
|
$handle = yield File\open(__FILE__, "r");
|
2015-08-13 01:02:41 +02:00
|
|
|
yield $handle->close();
|
2017-06-21 11:01:19 +02:00
|
|
|
|
|
|
|
$this->expectException(ClosedException::class);
|
2017-06-17 01:21:56 +02:00
|
|
|
yield $handle->read();
|
2015-08-13 01:02:41 +02:00
|
|
|
});
|
|
|
|
}
|
2018-10-29 05:55:11 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @depends testWrite
|
|
|
|
*/
|
|
|
|
public function testTruncateToSmallerSize()
|
|
|
|
{
|
|
|
|
$this->execute(function () {
|
|
|
|
$path = Fixture::path() . "/write";
|
|
|
|
/** @var \Amp\File\Handle $handle */
|
|
|
|
$handle = yield File\open($path, "c+");
|
|
|
|
|
|
|
|
$handle->write("foo");
|
|
|
|
yield $handle->write("bar");
|
|
|
|
yield $handle->truncate(4);
|
|
|
|
yield $handle->seek(0);
|
|
|
|
$contents = yield $handle->read();
|
|
|
|
$this->assertTrue($handle->eof());
|
|
|
|
$this->assertSame("foob", $contents);
|
|
|
|
|
|
|
|
yield $handle->write("bar");
|
|
|
|
$this->assertSame(7, $handle->tell());
|
|
|
|
yield $handle->seek(0);
|
|
|
|
$contents = yield $handle->read();
|
|
|
|
$this->assertSame("foobbar", $contents);
|
|
|
|
|
|
|
|
yield $handle->close();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @depends testWrite
|
|
|
|
*/
|
|
|
|
public function testTruncateToLargerSize()
|
|
|
|
{
|
|
|
|
$this->execute(function () {
|
|
|
|
$path = Fixture::path() . "/write";
|
|
|
|
/** @var \Amp\File\Handle $handle */
|
|
|
|
$handle = yield File\open($path, "c+");
|
|
|
|
|
|
|
|
yield $handle->write("foo");
|
|
|
|
yield $handle->truncate(6);
|
|
|
|
$this->assertSame(3, $handle->tell());
|
|
|
|
yield $handle->seek(0);
|
|
|
|
$contents = yield $handle->read();
|
|
|
|
$this->assertTrue($handle->eof());
|
|
|
|
$this->assertSame("foo\0\0\0", $contents);
|
|
|
|
|
|
|
|
yield $handle->write("bar");
|
|
|
|
$this->assertSame(9, $handle->tell());
|
|
|
|
yield $handle->seek(0);
|
|
|
|
$contents = yield $handle->read();
|
|
|
|
$this->assertSame("foo\0\0\0bar", $contents);
|
|
|
|
|
|
|
|
yield $handle->close();
|
|
|
|
});
|
|
|
|
}
|
2015-08-13 01:02:41 +02:00
|
|
|
}
|