2016-12-30 03:59:59 +01:00
|
|
|
<?php
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2015-08-05 16:55:56 +02:00
|
|
|
namespace Amp\File\Test;
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:00:26 +02:00
|
|
|
use Amp\File;
|
2019-08-23 20:23:33 +02:00
|
|
|
use Amp\File\FilesystemException;
|
2019-08-23 20:59:26 +02:00
|
|
|
use Amp\Promise;
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
abstract class DriverTest extends FilesystemTest
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
|
|
|
public function testScandir()
|
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$actual = yield File\scandir($fixtureDir);
|
|
|
|
$expected = ["dir", "small.txt"];
|
|
|
|
$this->assertSame($expected, $actual);
|
2015-07-11 03:59:39 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testScandirThrowsIfPathNotADirectory(): Promise
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:23:33 +02:00
|
|
|
$this->expectException(FilesystemException::class);
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
return File\scandir(__FILE__);
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testScandirThrowsIfPathDoesntExist(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:23:33 +02:00
|
|
|
$this->expectException(FilesystemException::class);
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$path = Fixture::path() . "/nonexistent";
|
|
|
|
(yield File\scandir($path));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testSymlink(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$original = "{$fixtureDir}/small.txt";
|
|
|
|
$link = "{$fixtureDir}/symlink.txt";
|
|
|
|
$this->assertTrue(yield File\symlink($original, $link));
|
|
|
|
$this->assertTrue(\is_link($link));
|
|
|
|
yield File\unlink($link);
|
2015-07-11 03:59:39 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testReadlink(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
2018-07-16 02:32:59 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$original = "{$fixtureDir}/small.txt";
|
|
|
|
$link = "{$fixtureDir}/symlink.txt";
|
|
|
|
\symlink($original, $link);
|
2018-07-16 02:32:59 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame($original, yield File\readlink($link));
|
2018-07-16 02:32:59 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function readlinkPathProvider(): array
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2018-07-16 02:32:59 +02:00
|
|
|
return [
|
|
|
|
'nonExistingPath' => [function () {
|
2018-10-27 17:57:31 +02:00
|
|
|
return Fixture::path() . '/' . \uniqid();
|
2018-07-16 02:32:59 +02:00
|
|
|
}],
|
|
|
|
'notLink' => [function () {
|
|
|
|
return Fixture::path();
|
|
|
|
}],
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider readlinkPathProvider
|
|
|
|
*
|
|
|
|
* @param \Closure $linkResolver
|
|
|
|
*/
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testReadlinkError(\Closure $linkResolver): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:23:33 +02:00
|
|
|
$this->expectException(FilesystemException::class);
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$link = $linkResolver();
|
2018-07-16 02:32:59 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
yield File\readlink($link);
|
2018-07-16 02:32:59 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testLstat(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$target = "{$fixtureDir}/small.txt";
|
|
|
|
$link = "{$fixtureDir}/symlink.txt";
|
|
|
|
$this->assertTrue(yield File\symlink($target, $link));
|
|
|
|
$this->assertIsArray(yield File\lstat($link));
|
|
|
|
yield File\unlink($link);
|
2015-07-11 03:59:39 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testFileStat(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$stat = (yield File\stat("{$fixtureDir}/small.txt"));
|
|
|
|
$this->assertIsArray($stat);
|
|
|
|
$this->assertStatSame(\stat("{$fixtureDir}/small.txt"), $stat);
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testDirStat(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$stat = (yield File\stat("{$fixtureDir}/dir"));
|
|
|
|
$this->assertIsArray($stat);
|
|
|
|
$this->assertStatSame(\stat("{$fixtureDir}/dir"), $stat);
|
2015-07-19 15:24:52 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testNonexistentPathStatResolvesToNull(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$stat = (yield File\stat("{$fixtureDir}/nonexistent"));
|
|
|
|
$this->assertNull($stat);
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testExists(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$this->assertFalse(yield File\exists("{$fixtureDir}/nonexistent"));
|
|
|
|
$this->assertTrue(yield File\exists("{$fixtureDir}/small.txt"));
|
2015-07-19 15:24:52 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testGet(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$this->assertSame("small", yield File\get("{$fixtureDir}/small.txt"));
|
2017-06-17 15:36:51 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testSize(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/small.txt";
|
|
|
|
$stat = (yield File\stat($path));
|
|
|
|
$size = $stat["size"];
|
|
|
|
File\StatCache::clear($path);
|
|
|
|
$this->assertSame($size, (yield File\size($path)));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testSizeFailsOnNonexistentPath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:23:33 +02:00
|
|
|
$this->expectException(FilesystemException::class);
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/nonexistent";
|
|
|
|
yield File\size($path);
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testSizeFailsOnDirectoryPath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:23:33 +02:00
|
|
|
$this->expectException(FilesystemException::class);
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/dir";
|
|
|
|
$this->assertTrue(yield File\isdir($path));
|
|
|
|
File\StatCache::clear($path);
|
|
|
|
yield File\size($path);
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testIsdirResolvesTrueOnDirectoryPath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/dir";
|
|
|
|
$this->assertTrue(yield File\isdir($path));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testIsdirResolvesFalseOnFilePath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/small.txt";
|
|
|
|
$this->assertFalse(yield File\isdir($path));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testIsdirResolvesFalseOnNonexistentPath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/nonexistent";
|
|
|
|
$this->assertFalse(yield File\isdir($path));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testIsfileResolvesTrueOnFilePath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/small.txt";
|
|
|
|
$this->assertTrue(yield File\isfile($path));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testIsfileResolvesFalseOnDirectoryPath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/dir";
|
|
|
|
$this->assertFalse(yield File\isfile($path));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testIsfileResolvesFalseOnNonexistentPath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/nonexistent";
|
|
|
|
$this->assertFalse(yield File\isfile($path));
|
2015-07-11 03:59:39 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testRename(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$contents1 = "rename test";
|
|
|
|
$old = "{$fixtureDir}/rename1.txt";
|
|
|
|
$new = "{$fixtureDir}/rename2.txt";
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
yield File\put($old, $contents1);
|
|
|
|
yield File\rename($old, $new);
|
|
|
|
$contents2 = (yield File\get($new));
|
|
|
|
yield File\unlink($new);
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertSame($contents1, $contents2);
|
2015-07-11 03:59:39 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testUnlink(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$toUnlink = "{$fixtureDir}/unlink";
|
|
|
|
yield File\put($toUnlink, "unlink me");
|
|
|
|
yield File\unlink($toUnlink);
|
|
|
|
$this->assertNull(yield File\stat($toUnlink));
|
2015-07-11 03:59:39 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testMkdirRmdir(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$dir = "{$fixtureDir}/newdir";
|
2015-07-11 03:59:39 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
\umask(0022);
|
2018-03-15 18:35:10 +01:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
yield File\mkdir($dir);
|
|
|
|
$stat = yield File\stat($dir);
|
|
|
|
$this->assertSame('0755', $this->getPermissionsFromStat($stat));
|
|
|
|
yield File\rmdir($dir);
|
|
|
|
$this->assertNull(yield File\stat($dir));
|
2016-09-28 12:39:24 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
// test for 0, because previous array_filter made that not work
|
|
|
|
$dir = "{$fixtureDir}/newdir/with/recursive/creation/0/1/2";
|
2016-09-28 12:39:24 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
yield File\mkdir($dir, 0764, true);
|
|
|
|
$stat = yield File\stat($dir);
|
|
|
|
$this->assertSame('0744', $this->getPermissionsFromStat($stat));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testMtime(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/small.txt";
|
|
|
|
$stat = (yield File\stat($path));
|
|
|
|
$statMtime = $stat["mtime"];
|
|
|
|
File\StatCache::clear($path);
|
|
|
|
$this->assertSame($statMtime, (yield File\mtime($path)));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testMtimeFailsOnNonexistentPath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:23:33 +02:00
|
|
|
$this->expectException(FilesystemException::class);
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/nonexistent";
|
|
|
|
yield File\mtime($path);
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testAtime(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/small.txt";
|
|
|
|
$stat = (yield File\stat($path));
|
|
|
|
$statAtime = $stat["atime"];
|
|
|
|
File\StatCache::clear($path);
|
|
|
|
$this->assertSame($statAtime, (yield File\atime($path)));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testAtimeFailsOnNonexistentPath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:23:33 +02:00
|
|
|
$this->expectException(FilesystemException::class);
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/nonexistent";
|
|
|
|
yield File\atime($path);
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testCtime(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/small.txt";
|
|
|
|
$stat = (yield File\stat($path));
|
|
|
|
$statCtime = $stat["ctime"];
|
|
|
|
File\StatCache::clear($path);
|
|
|
|
$this->assertSame($statCtime, (yield File\ctime($path)));
|
2015-08-08 16:09:07 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testCtimeFailsOnNonexistentPath(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:23:33 +02:00
|
|
|
$this->expectException(FilesystemException::class);
|
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
|
|
|
$path = "{$fixtureDir}/nonexistent";
|
|
|
|
yield File\ctime($path);
|
2015-07-11 03:59:39 +02:00
|
|
|
}
|
2015-07-18 20:53:46 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @group slow
|
|
|
|
*/
|
2019-08-23 20:59:26 +02:00
|
|
|
public function testTouch(): \Generator
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2019-08-23 20:59:26 +02:00
|
|
|
$fixtureDir = Fixture::path();
|
2015-07-18 20:53:46 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$touch = "{$fixtureDir}/touch";
|
|
|
|
yield File\put($touch, "touch me");
|
2015-07-18 20:53:46 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$oldStat = (yield File\stat($touch));
|
|
|
|
yield File\touch($touch, \time() + 10, \time() + 20);
|
|
|
|
File\StatCache::clear($touch);
|
|
|
|
$newStat = (yield File\stat($touch));
|
|
|
|
yield File\unlink($touch);
|
2015-07-18 20:53:46 +02:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
$this->assertTrue($newStat["atime"] > $oldStat["atime"]);
|
|
|
|
$this->assertTrue($newStat["mtime"] > $oldStat["mtime"]);
|
2015-07-18 20:53:46 +02:00
|
|
|
}
|
2018-03-15 18:35:10 +01:00
|
|
|
|
2019-08-23 20:59:26 +02:00
|
|
|
private function assertStatSame(array $expected, array $actual): void
|
2018-10-27 17:57:31 +02:00
|
|
|
{
|
2018-07-18 07:00:53 +02:00
|
|
|
$filter = function (array $stat) {
|
|
|
|
$filtered = \array_filter(
|
|
|
|
$stat,
|
|
|
|
function (string $key): bool {
|
|
|
|
return !\is_numeric($key);
|
|
|
|
},
|
|
|
|
ARRAY_FILTER_USE_KEY
|
|
|
|
);
|
|
|
|
|
2018-10-27 17:57:31 +02:00
|
|
|
\ksort($filtered);
|
2018-07-18 07:00:53 +02:00
|
|
|
|
|
|
|
return $filtered;
|
|
|
|
};
|
|
|
|
|
|
|
|
$this->assertSame($filter($expected), $filter($actual));
|
|
|
|
}
|
|
|
|
|
2018-03-15 18:35:10 +01:00
|
|
|
/**
|
|
|
|
* @param array $stat
|
|
|
|
* @return string
|
|
|
|
*/
|
2018-10-27 17:57:31 +02:00
|
|
|
private function getPermissionsFromStat(array $stat): string
|
|
|
|
{
|
2018-03-15 18:35:10 +01:00
|
|
|
return \substr(\decoct($stat["mode"]), 1);
|
|
|
|
}
|
2015-07-11 03:59:39 +02:00
|
|
|
}
|