diff --git a/packages/support/src/Filesystem/functions.php b/packages/support/src/Filesystem/functions.php index d09af9661..06ac8d0f8 100644 --- a/packages/support/src/Filesystem/functions.php +++ b/packages/support/src/Filesystem/functions.php @@ -220,7 +220,7 @@ function delete(string $path, bool $recursive = true): void return; } - if (namespace\is_file($path)) { + if (namespace\is_file($path) || namespace\is_symbolic_link($path)) { namespace\delete_file($path); } elseif (namespace\is_directory($path)) { namespace\delete_directory($path, $recursive); diff --git a/packages/support/tests/Filesystem/UnixFunctionsTest.php b/packages/support/tests/Filesystem/UnixFunctionsTest.php index 1ddeafa5b..8308e7bf6 100644 --- a/packages/support/tests/Filesystem/UnixFunctionsTest.php +++ b/packages/support/tests/Filesystem/UnixFunctionsTest.php @@ -4,6 +4,7 @@ use PHPUnit\Framework\Attributes\PostCondition; use PHPUnit\Framework\Attributes\PreCondition; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use Tempest\Support\Filesystem; @@ -43,7 +44,8 @@ protected function cleanup(): void $this->assertFalse(is_dir($this->fixtures)); } - public function test_create_directory(): void + #[Test] + public function create_directory(): void { $directory = $this->fixtures . '/tmp'; @@ -52,7 +54,8 @@ public function test_create_directory(): void $this->assertTrue(is_dir($directory)); } - public function test_create_directory_when_file_exists(): void + #[Test] + public function create_directory_when_file_exists(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessageMatches('/^Failed to create directory.*/'); @@ -64,7 +67,8 @@ public function test_create_directory_when_file_exists(): void Filesystem\create_directory($file); } - public function test_create_directory_for_file(): void + #[Test] + public function create_directory_for_file(): void { $file = $this->fixtures . '/tmp/file.txt'; @@ -73,7 +77,8 @@ public function test_create_directory_for_file(): void $this->assertTrue(is_dir(dirname($file))); } - public function test_create_file(): void + #[Test] + public function create_file(): void { $file = $this->fixtures . '/tmp/file.txt'; @@ -82,7 +87,8 @@ public function test_create_file(): void $this->assertTrue(is_file($file)); } - public function test_exists(): void + #[Test] + public function exists(): void { $dir = $this->fixtures . '/tmp'; $file = $this->fixtures . '/tmp/file.txt'; @@ -94,7 +100,8 @@ public function test_exists(): void $this->assertTrue(Filesystem\exists($file)); } - public function test_delete(): void + #[Test] + public function delete(): void { $dir = $this->fixtures . '/tmp'; $file = $this->fixtures . '/tmp/file.txt'; @@ -112,7 +119,28 @@ public function test_delete(): void Filesystem\delete($dir . '/non-existent-path'); } - public function test_delete_directory(): void + #[Test] + public function delete_dir_symlink(): void + { + $dir = $this->fixtures . '/tmp'; + $symlink = $this->fixtures . '/tmp-link'; + + mkdir($dir); + symlink($dir, $symlink); + + $this->assertTrue(is_link($symlink)); + $this->assertTrue(is_dir($dir)); + + Filesystem\delete($symlink); + + $this->assertFalse(is_link($symlink)); + $this->assertFalse(is_dir($symlink)); + $this->assertFalse(is_file($symlink)); + $this->assertTrue(is_dir($dir)); + } + + #[Test] + public function delete_directory(): void { $dir = $this->fixtures . '/tmp'; @@ -123,7 +151,8 @@ public function test_delete_directory(): void $this->assertFalse(is_dir($dir)); } - public function test_delete_directory_on_file(): void + #[Test] + public function delete_directory_on_file(): void { $this->expectException(PathWasNotADirectory::class); @@ -134,7 +163,8 @@ public function test_delete_directory_on_file(): void Filesystem\delete_directory($file); } - public function test_delete_directory_recursive(): void + #[Test] + public function delete_directory_recursive(): void { $dir = $this->fixtures . '/tmp'; @@ -148,7 +178,8 @@ public function test_delete_directory_recursive(): void $this->assertFalse(is_dir($dir)); } - public function test_delete_directory_non_recursive(): void + #[Test] + public function delete_directory_non_recursive(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessageMatches('/.*directory not empty.*/'); @@ -163,7 +194,8 @@ public function test_delete_directory_non_recursive(): void Filesystem\delete_directory($dir, recursive: false); } - public function test_detele_file(): void + #[Test] + public function detele_file(): void { $file = $this->fixtures . '/file.txt'; @@ -174,7 +206,8 @@ public function test_detele_file(): void $this->assertFalse(is_file($file)); } - public function test_detele_file_not_found(): void + #[Test] + public function detele_file_not_found(): void { $this->expectException(PathWasNotFound::class); @@ -183,7 +216,8 @@ public function test_detele_file_not_found(): void Filesystem\delete_file($file); } - public function test_detele_file_on_dir(): void + #[Test] + public function detele_file_on_dir(): void { $this->expectException(PathWasNotAFile::class); @@ -193,7 +227,8 @@ public function test_detele_file_on_dir(): void Filesystem\delete_file($dir); } - public function test_get_permissions(): void + #[Test] + public function get_permissions(): void { $file = $this->fixtures . '/file.txt'; @@ -204,14 +239,16 @@ public function test_get_permissions(): void $this->assertEquals(0o644, $permissions & 0o777); } - public function test_get_permissions_not_found(): void + #[Test] + public function get_permissions_not_found(): void { $this->expectException(PathWasNotFound::class); Filesystem\get_permissions($this->fixtures . '/file.txt'); } - public function test_ensure_directory_empty(): void + #[Test] + public function ensure_directory_empty(): void { $dir = $this->fixtures . '/tmp'; @@ -224,7 +261,8 @@ public function test_ensure_directory_empty(): void $this->assertTrue(is_dir($dir)); } - public function test_ensure_directory_empty_on_file(): void + #[Test] + public function ensure_directory_empty_on_file(): void { $this->expectException(PathWasNotADirectory::class); @@ -235,7 +273,8 @@ public function test_ensure_directory_empty_on_file(): void Filesystem\ensure_directory_empty($file); } - public function test_ensure_directory_empty_keeps_permissions(): void + #[Test] + public function ensure_directory_empty_keeps_permissions(): void { $dir = $this->fixtures . '/tmp'; @@ -249,7 +288,8 @@ public function test_ensure_directory_empty_keeps_permissions(): void $this->assertEquals(0o755, $permissions & 0o777); } - public function test_is_file(): void + #[Test] + public function is_file(): void { $file = $this->fixtures . '/file.txt'; @@ -259,7 +299,8 @@ public function test_is_file(): void $this->assertFalse(Filesystem\is_file($this->fixtures)); } - public function test_is_directory(): void + #[Test] + public function is_directory(): void { $dir = $this->fixtures . '/tmp'; @@ -269,7 +310,8 @@ public function test_is_directory(): void $this->assertFalse(Filesystem\is_directory($this->fixtures . '/file.txt')); } - public function test_is_readable(): void + #[Test] + public function is_readable(): void { $file = $this->fixtures . '/file.txt'; @@ -279,7 +321,8 @@ public function test_is_readable(): void $this->assertTrue(Filesystem\is_readable($this->fixtures)); } - public function test_is_symbolic_link(): void + #[Test] + public function is_symbolic_link(): void { $file = $this->fixtures . '/file.txt'; $link = $this->fixtures . '/link.txt'; @@ -291,7 +334,8 @@ public function test_is_symbolic_link(): void $this->assertFalse(Filesystem\is_symbolic_link($file)); } - public function test_is_writable(): void + #[Test] + public function is_writable(): void { $file = $this->fixtures . '/file.txt'; @@ -301,7 +345,8 @@ public function test_is_writable(): void $this->assertTrue(Filesystem\is_writable($this->fixtures)); } - public function test_list_directory(): void + #[Test] + public function list_directory(): void { $dir = $this->fixtures . '/tmp'; @@ -320,7 +365,8 @@ public function test_list_directory(): void } } - public function test_list_directory_on_non_directory(): void + #[Test] + public function list_directory_on_non_directory(): void { $this->expectException(PathWasNotADirectory::class); @@ -331,7 +377,8 @@ public function test_list_directory_on_non_directory(): void Filesystem\list_directory($file); } - public function test_read_symbolic_link(): void + #[Test] + public function read_symbolic_link(): void { $file = $this->fixtures . '/file.txt'; $link = $this->fixtures . '/link.txt'; @@ -344,7 +391,8 @@ public function test_read_symbolic_link(): void $this->assertEquals(realpath($file), $target); } - public function test_read_symbolic_link_on_non_symlink(): void + #[Test] + public function read_symbolic_link_on_non_symlink(): void { $this->expectException(PathWasNotASymbolicLink::class); @@ -355,7 +403,8 @@ public function test_read_symbolic_link_on_non_symlink(): void Filesystem\read_symbolic_link($file); } - public function test_get_directory(): void + #[Test] + public function get_directory(): void { $file = $this->fixtures . '/file.txt'; @@ -366,7 +415,8 @@ public function test_get_directory(): void $this->assertEquals(realpath($this->fixtures), realpath($directory)); } - public function test_copy(): void + #[Test] + public function copy(): void { $source = $this->fixtures . '/file.txt'; $destination = $this->fixtures . '/tmp/file.txt'; @@ -378,7 +428,8 @@ public function test_copy(): void $this->assertTrue(is_file($destination)); } - public function test_copy_directory(): void + #[Test] + public function copy_directory(): void { $this->expectException(PathWasNotAFile::class); @@ -391,7 +442,8 @@ public function test_copy_directory(): void Filesystem\copy_file($source, $destination); } - public function test_copy_non_existing_file(): void + #[Test] + public function copy_non_existing_file(): void { $this->expectException(PathWasNotFound::class); @@ -401,7 +453,8 @@ public function test_copy_non_existing_file(): void Filesystem\copy_file($source, $destination); } - public function test_copy_non_readable_file(): void + #[Test] + public function copy_non_readable_file(): void { $this->expectException(PathWasNotReadable::class); @@ -414,7 +467,8 @@ public function test_copy_non_readable_file(): void Filesystem\copy_file($source, $destination); } - public function test_copy_overwrite(): void + #[Test] + public function copy_overwrite(): void { $source = $this->fixtures . '/file.txt'; $destination = $this->fixtures . '/file2.txt'; @@ -427,7 +481,8 @@ public function test_copy_overwrite(): void $this->assertEquals('Hello', file_get_contents($destination)); } - public function test_move(): void + #[Test] + public function move(): void { $source = $this->fixtures . '/file.txt'; $destination = $this->fixtures . '/tmp/file.txt'; @@ -440,7 +495,8 @@ public function test_move(): void $this->assertFalse(is_file($source)); } - public function test_move_overwrite(): void + #[Test] + public function move_overwrite(): void { $source = $this->fixtures . '/file.txt'; $destination = $this->fixtures . '/tmp/file.txt'; @@ -454,7 +510,8 @@ public function test_move_overwrite(): void $this->assertFalse(is_file($source)); } - public function test_move_no_overwrite(): void + #[Test] + public function move_no_overwrite(): void { $source = $this->fixtures . '/file.txt'; $destination = $this->fixtures . '/tmp/file.txt'; @@ -468,7 +525,8 @@ public function test_move_no_overwrite(): void $this->assertEquals('World', file_get_contents($destination)); } - public function test_move_directory(): void + #[Test] + public function move_directory(): void { $source = $this->fixtures . '/tmp'; $destination = $this->fixtures . '/tmp2'; @@ -483,7 +541,8 @@ public function test_move_directory(): void $this->assertFalse(is_dir($source)); } - public function test_move_directory_overwrite(): void + #[Test] + public function move_directory_overwrite(): void { $source = $this->fixtures . '/tmp'; $destination = $this->fixtures . '/tmp2'; @@ -500,7 +559,8 @@ public function test_move_directory_overwrite(): void $this->assertFalse(is_dir($source)); } - public function test_move_directory_no_overwrite(): void + #[Test] + public function move_directory_no_overwrite(): void { $source = $this->fixtures . '/tmp'; $destination = $this->fixtures . '/tmp2'; @@ -518,7 +578,8 @@ public function test_move_directory_no_overwrite(): void $this->assertSame('world', file_get_contents($destination . '/file.txt')); } - public function test_move_not_readable(): void + #[Test] + public function move_not_readable(): void { $this->expectException(PathWasNotReadable::class); @@ -531,7 +592,8 @@ public function test_move_not_readable(): void Filesystem\move($source, $destination); } - public function test_rename(): void + #[Test] + public function rename(): void { $source = $this->fixtures . '/file.txt'; $newName = 'renamed-file.txt'; @@ -544,7 +606,8 @@ public function test_rename(): void $this->assertFalse(is_file($source)); } - public function test_rename_overwrite(): void + #[Test] + public function rename_overwrite(): void { $source = $this->fixtures . '/file.txt'; $newName = 'renamed-file.txt'; @@ -558,7 +621,8 @@ public function test_rename_overwrite(): void $this->assertFalse(is_file($source)); } - public function test_rename_with_full_path(): void + #[Test] + public function rename_with_full_path(): void { $this->expectException(NameWasInvalid::class); @@ -573,7 +637,8 @@ public function test_rename_with_full_path(): void $this->assertFalse(is_file($source)); } - public function test_write_file(): void + #[Test] + public function write_file(): void { $file = $this->fixtures . '/tmp/file.txt'; @@ -584,8 +649,9 @@ public function test_write_file(): void #[TestWith([['key' => 'value'], '{"key":"value"}'])] #[TestWith(['basic string', '"basic string"'])] - #[TestWith(['{"foo": "bar"}', '{"foo":"bar"}'])] - public function test_write_json(mixed $data, string $expected): void + #[TestWith(['{"f + #[Test]oo": "bar"}', '{"foo":"bar"}'])] + public function write_json(mixed $data, string $expected): void { $file = $this->fixtures . '/tmp/file.json'; @@ -594,7 +660,8 @@ public function test_write_json(mixed $data, string $expected): void $this->assertEquals($expected, file_get_contents($file)); } - public function test_write_json_serializable(): void + #[Test] + public function write_json_serializable(): void { $file = $this->fixtures . '/tmp/file.json'; @@ -610,7 +677,8 @@ public function jsonSerialize(): array $this->assertEquals('{"key":"value"}', file_get_contents($file)); } - public function test_write_non_writable_file(): void + #[Test] + public function write_non_writable_file(): void { $this->expectException(RuntimeException::class); @@ -622,7 +690,8 @@ public function test_write_non_writable_file(): void Filesystem\write_file($file, 'Hello'); } - public function test_read_json(): void + #[Test] + public function read_json(): void { $file = $this->fixtures . '/tmp/file.json'; @@ -633,7 +702,8 @@ public function test_read_json(): void $this->assertEquals(['key' => 'value'], $data); } - public function test_read_file(): void + #[Test] + public function read_file(): void { $file = $this->fixtures . '/file.txt'; @@ -644,7 +714,8 @@ public function test_read_file(): void $this->assertEquals('Hello', $content); } - public function test_read_file_non_readable_file(): void + #[Test] + public function read_file_non_readable_file(): void { $this->expectException(PathWasNotReadable::class); @@ -656,7 +727,8 @@ public function test_read_file_non_readable_file(): void Filesystem\read_file($file); } - public function test_read_file_not_found(): void + #[Test] + public function read_file_not_found(): void { $this->expectException(PathWasNotFound::class); @@ -665,7 +737,8 @@ public function test_read_file_not_found(): void Filesystem\read_file($file); } - public function test_ensure_directory_exists(): void + #[Test] + public function ensure_directory_exists(): void { $dir = $this->fixtures . '/tmp'; @@ -674,7 +747,8 @@ public function test_ensure_directory_exists(): void $this->assertTrue(is_dir($dir)); } - public function test_ensure_directory_exists_on_existent_directory(): void + #[Test] + public function ensure_directory_exists_on_existent_directory(): void { $dir = $this->fixtures . '/tmp'; @@ -685,7 +759,8 @@ public function test_ensure_directory_exists_on_existent_directory(): void $this->assertTrue(is_dir($dir)); } - public function test_delete_file_for_invalid_symlink(): void + #[Test] + public function delete_file_for_invalid_symlink(): void { $file = $this->fixtures . '/file.txt'; \file_put_contents($file, 'hello'); @@ -699,7 +774,8 @@ public function test_delete_file_for_invalid_symlink(): void $this->assertFalse(is_link($link)); } - public function test_normalize_path_in_phar(): void + #[Test] + public function normalize_path_in_phar(): void { if (\Phar::canWrite() === false) { $this->markTestSkipped('phar.readonly is enabled in php.ini.');