<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[57753] trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect: Build/Test Tools: Add initial tests for the `WP_Filesystem_Direct` class.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/57753">57753</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/57753","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>swissspidy</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2024-03-02 14:05:38 +0000 (Sat, 02 Mar 2024)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Build/Test Tools: Add initial tests for the `WP_Filesystem_Direct` class.

Since `WP_Filesystem_Direct` is by far the most used filesystem abstraction class, this facilitates future changes with sufficient test coverage.

Props swissspidy, costdev, mukesh27.
Fixes <a href="https://core.trac.wordpress.org/ticket/57774">#57774</a>.</pre>

<h3>Added Paths</h3>
<ul>
<li>trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/</li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectatimephp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/atime.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectbasephp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/base.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectchdirphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chdir.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectchgrpphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chgrp.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectchmodphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chmod.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectchownphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chown.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectconstructphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/construct.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectcopyphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/copy.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectcwdphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/cwd.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectdeletephp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/delete.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectdirlistphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/dirlist.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectexistsphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/exists.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectgetContentsphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getContents.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectgetContentsArrayphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getContentsArray.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectgetchmodphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getchmod.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectisDirphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isDir.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectisFilephp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isFile.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectisReadablephp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isReadable.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectisWritablephp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isWritable.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectmkdirphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/mkdir.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectmovephp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/move.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectmtimephp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/mtime.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectputContentsphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/putContents.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectrmdirphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/rmdir.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirectsizephp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/size.php</a></li>
<li><a href="#trunktestsphpunittestsfilesystemwpFilesystemDirecttouchphp">trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/touch.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunktestsphpunittestsfilesystemwpFilesystemDirectatimephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/atime.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/atime.php                         (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/atime.php   2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,50 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::atime() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::atime
+ */
+class Tests_Filesystem_WpFilesystemDirect_Atime extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::atime()`
+        * returns an integer for a path that exists.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_determine_accessed_time( $path ) {
+               $path = self::$file_structure['test_dir']['path'] . $path;
+
+               $this->assertIsInt( self::$filesystem->atime( $path ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::atime()`
+        * returns false for a path that does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_return_false_for_a_path_that_does_not_exist( $path ) {
+               $path = self::$file_structure['test_dir']['path'] . $path;
+
+               $this->assertFalse( self::$filesystem->atime( $path ) );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/atime.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectbasephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/base.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/base.php                          (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/base.php    2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,197 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Base class for WP_Filesystem_Direct tests.
+ *
+ * @package WordPress
+ */
+abstract class WP_Filesystem_Direct_UnitTestCase extends WP_UnitTestCase {
+
+       /**
+        * The filesystem object.
+        *
+        * @var WP_Filesystem_Direct
+        */
+       protected static $filesystem;
+
+       /**
+        * The file structure for tests.
+        *
+        * @var array
+        */
+       protected static $file_structure = array();
+
+       /**
+        * Sets up test assets before the class.
+        */
+       public static function set_up_before_class() {
+               parent::set_up_before_class();
+
+               require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
+               require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
+
+               self::$filesystem = new WP_Filesystem_Direct( null );
+
+               $filesystem_data_dir = wp_normalize_path( DIR_TESTDATA . '/filesystem/' );
+               if ( ! file_exists( $filesystem_data_dir ) ) {
+                       mkdir( $filesystem_data_dir );
+               }
+
+               /*
+                * These must be created during the tests as they may be modified or deleted
+                * during testing, either intentionally or accidentally as a result of test failure.
+                */
+               $test_data_root_dir = $filesystem_data_dir . 'filesystem_api/';
+               $test_data_dir      = $test_data_root_dir . 'wpFilesystemDirect/';
+
+               self::$file_structure = array(
+                       // Directories first.
+                       'test_dir_root' => array(
+                               'type' => 'd',
+                               'path' => $test_data_root_dir,
+                       ),
+                       'test_dir'      => array(
+                               'type' => 'd',
+                               'path' => $test_data_dir,
+                       ),
+                       'subdir'        => array(
+                               'type' => 'd',
+                               'path' => $test_data_dir . 'subdir/',
+                       ),
+
+                       // Then files.
+                       'visible_file'  => array(
+                               'type'     => 'f',
+                               'path'     => $test_data_dir . 'a_file_that_exists.txt',
+                               'contents' => "Contents of a file.\r\nNext line of a file.\r\n",
+                       ),
+                       'hidden_file'   => array(
+                               'type'     => 'f',
+                               'path'     => $test_data_dir . '.a_hidden_file',
+                               'contents' => "A hidden file.\r\n",
+                       ),
+                       'subfile'       => array(
+                               'type'     => 'f',
+                               'path'     => $test_data_dir . 'subdir/subfile.txt',
+                               'contents' => "A file in a subdirectory.\r\n",
+                       ),
+               );
+       }
+
+       /**
+        * Creates any missing test assets before each test.
+        */
+       public function set_up() {
+               parent::set_up();
+
+               foreach ( self::$file_structure as $entry ) {
+                       if ( 'd' === $entry['type'] ) {
+                               $this->create_directory_if_needed( $entry['path'] );
+                       } elseif ( 'f' === $entry['type'] ) {
+                               $this->create_file_if_needed(
+                                       $entry['path'],
+                                       isset( $entry['contents'] ) ? $entry['contents'] : ''
+                               );
+                       }
+               }
+       }
+
+       /**
+        * Removes any existing test assets after each test.
+        */
+       public function tear_down() {
+               foreach ( array_reverse( self::$file_structure ) as $entry ) {
+                       if ( ! file_exists( $entry['path'] ) ) {
+                               continue;
+                       }
+
+                       if ( 'f' === $entry['type'] ) {
+                               unlink( $entry['path'] );
+                       } elseif ( 'd' === $entry['type'] ) {
+                               rmdir( $entry['path'] );
+                       }
+               }
+
+               parent::tear_down();
+       }
+
+       /**
+        * Creates a directory if it doesn't already exist.
+        *
+        * @throws Exception If the path already exists as a file.
+        *
+        * @param string $path The path to the directory.
+        */
+       public function create_directory_if_needed( $path ) {
+               if ( file_exists( $path ) ) {
+                       if ( is_file( $path ) ) {
+                               throw new Exception( "$path already exists as a file." );
+                       }
+
+                       return;
+               }
+
+               mkdir( $path );
+       }
+
+       /**
+        * Creates a file if it doesn't already exist.
+        *
+        * @throws Exception If the path already exists as a directory.
+        *
+        * @param string $path     The path to the file.
+        * @param string $contents Optional. The contents of the file. Default empty string.
+        */
+       public function create_file_if_needed( $path, $contents = '' ) {
+               if ( file_exists( $path ) ) {
+                       if ( is_dir( $path ) ) {
+                               throw new Exception( "$path already exists as a directory." );
+                       }
+
+                       return;
+               }
+
+               file_put_contents( $path, $contents );
+       }
+
+       /**
+        * Determines whether the operating system is Windows.
+        *
+        * @return bool Whether the operating system is Windows.
+        */
+       public static function is_windows() {
+               return 'WIN' === substr( PHP_OS, 0, 3 );
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_paths_that_exist() {
+               return array(
+                       'a file that exists'      => array(
+                               'path' => 'a_file_that_exists.txt',
+                       ),
+                       'a directory that exists' => array(
+                               'path' => '',
+                       ),
+               );
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_paths_that_do_not_exist() {
+               return array(
+                       'a file that does not exist'      => array(
+                               'path' => 'a_file_that_does_not_exist.txt',
+                       ),
+                       'a directory that does not exist' => array(
+                               'path' => 'a_directory_that_does_not_exist',
+                       ),
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/base.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectchdirphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chdir.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chdir.php                         (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chdir.php   2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,95 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::chdir() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::chdir
+ */
+class Tests_Filesystem_WpFilesystemDirect_Chdir extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::chdir()`
+        * returns false for a path that does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_should_fail_to_change_directory
+        *
+        * @param string $path The path.
+        */
+       public function test_should_fail_to_change_directory( $path ) {
+               $original_cwd = self::$filesystem->cwd();
+               $path         = wp_normalize_path( realpath( self::$file_structure['test_dir']['path'] ) ) . $path;
+               $chdir_result = self::$filesystem->chdir( $path );
+               $cwd_result   = self::$filesystem->cwd();
+
+               // Reset the current working directory.
+               self::$filesystem->chdir( $original_cwd );
+
+               $this->assertFalse(
+                       $chdir_result,
+                       'Changing working directory succeeded.'
+               );
+
+               $this->assertSame(
+                       $original_cwd,
+                       $cwd_result,
+                       'The current working directory was changed.'
+               );
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_should_fail_to_change_directory() {
+               return array(
+                       'a file that exists'              => array(
+                               'path' => 'a_file_that_exists.txt',
+                       ),
+                       'a file that does not exist'      => array(
+                               'path' => 'a_file_that_does_not_exist.txt',
+                       ),
+                       'a directory that does not exist' => array(
+                               'path' => 'a_directory_that_does_not_exist',
+                       ),
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::chdir()` changes to
+        * an existing directory.
+        *
+        * @ticket 57774
+        */
+       public function test_should_change_directory() {
+               $original_cwd = self::$filesystem->cwd();
+               $path         = wp_normalize_path( realpath( self::$file_structure['test_dir']['path'] ) );
+               $chdir_result = self::$filesystem->chdir( $path );
+               $cwd_result   = self::$filesystem->cwd();
+
+               // Reset the current working directory.
+               self::$filesystem->chdir( $original_cwd );
+
+               $this->assertTrue(
+                       $chdir_result,
+                       'Changing working directory failed.'
+               );
+
+               $this->assertSame(
+                       $path,
+                       $cwd_result,
+                       'The current working directory was incorrect.'
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chdir.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectchgrpphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chgrp.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chgrp.php                         (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chgrp.php   2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,32 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::chgrp() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::chgrp
+ */
+class Tests_Filesystem_WpFilesystemDirect_Chgrp extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::chgrp()`
+        * returns false for a path that does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_fail_to_change_file_group( $path ) {
+               $this->assertFalse( self::$filesystem->chgrp( self::$file_structure['test_dir']['path'] . $path, 0 ) );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chgrp.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectchmodphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chmod.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chmod.php                         (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chmod.php   2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,77 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::chmod() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::chmod
+ */
+class Tests_Filesystem_WpFilesystemDirect_Chmod extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::chmod()`
+        * returns false for a path that does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_return_false( $path ) {
+               $this->assertFalse( self::$filesystem->chmod( $path ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::chmod()` should set
+        * $mode when it is not passed.
+        *
+        * This test runs in a separate process so that it can define
+        * constants without impacting other tests.
+        *
+        * This test does not preserve global state to prevent the exception
+        * "Serialization of 'Closure' is not allowed." when running in a
+        * separate process.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_should_set_mode_when_not_passed
+        *
+        * @runInSeparateProcess
+        * @preserveGlobalState disabled
+        *
+        * @param string $path The path.
+        * @param string $type The type of path. "FILE" for file, "DIR" for directory.
+        */
+       public function test_should_handle_set_mode_when_not_passed( $path, $type ) {
+               define( 'FS_CHMOD_' . $type, ( 'FILE' === $type ? 0644 : 0755 ) );
+
+               $this->assertTrue( self::$filesystem->chmod( self::$file_structure['test_dir']['path'] . $path, false ) );
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_should_set_mode_when_not_passed() {
+               return array(
+                       'a file'      => array(
+                               'path' => 'a_file_that_exists.txt',
+                               'type' => 'FILE',
+                       ),
+                       'a directory' => array(
+                               'path' => '',
+                               'type' => 'DIR',
+                       ),
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chmod.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectchownphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chown.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chown.php                         (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chown.php   2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,32 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::chown() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::chown
+ */
+class Tests_Filesystem_WpFilesystemDirect_Chown extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::chown()`
+        * returns false for a path that does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_return_false( $path ) {
+               $this->assertFalse( self::$filesystem->chown( $path, fileowner( __FILE__ ) ) );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/chown.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectconstructphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/construct.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/construct.php                             (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/construct.php       2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,39 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::__construct() method.
+ *
+ * @package WordPress
+ */
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::__construct
+ */
+class Tests_Filesystem_WpFilesystemDirect_Construct extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that the $method and $errors properties are set upon
+        * the instantiation of a WP_Filesystem_Direct object.
+        *
+        * @ticket 57774
+        */
+       public function test_should_set_method_and_errors() {
+               // For coverage reports, a new object must be created in the method.
+               $filesystem = new WP_Filesystem_Direct( null );
+
+               $this->assertSame(
+                       'direct',
+                       $filesystem->method,
+                       'The "$method" property is not set to "direct".'
+               );
+
+               $this->assertInstanceOf(
+                       'WP_Error',
+                       $filesystem->errors,
+                       'The "$errors" property is not set to a WP_Error object.'
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/construct.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectcopyphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/copy.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/copy.php                          (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/copy.php    2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,72 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::copy() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::copy
+ */
+class Tests_Filesystem_WpFilesystemDirect_Copy extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::copy()` overwrites an existing
+        * destination when overwriting is enabled.
+        *
+        * @ticket 57774
+        */
+       public function test_should_overwrite_an_existing_file_when_overwriting_is_enabled() {
+               $source      = self::$file_structure['visible_file']['path'];
+               $destination = self::$file_structure['test_dir']['path'] . 'a_file_that_exists.dest';
+
+               if ( ! file_exists( $destination ) ) {
+                       touch( $destination );
+               }
+
+               $actual = self::$filesystem->copy( $source, $destination, true );
+
+               unlink( $destination );
+
+               $this->assertTrue( $actual );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::copy()` does not overwrite
+        * an existing destination when overwriting is disabled.
+        *
+        * @ticket 57774
+        */
+       public function test_should_not_overwrite_an_existing_file_when_overwriting_is_disabled() {
+               $source      = self::$file_structure['test_dir']['path'] . 'a_file_that_exists.txt';
+               $destination = self::$file_structure['test_dir']['path'] . 'a_file_that_exists.dest';
+
+               if ( ! file_exists( $destination ) ) {
+                       touch( $destination );
+               }
+
+               $actual = self::$filesystem->copy( $source, $destination );
+
+               unlink( $destination );
+
+               $this->assertFalse( $actual );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::copy()` does not overwrite an existing
+        * destination when overwriting is enabled and the source and destination
+        * are the same.
+        *
+        * @ticket 57774
+        */
+       public function test_should_not_overwrite_when_overwriting_is_enabled_and_source_and_destination_are_the_same() {
+               $source = self::$file_structure['test_dir']['path'] . 'a_file_that_exists.txt';
+               $this->assertFalse( self::$filesystem->copy( $source, $source, true ) );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/copy.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectcwdphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/cwd.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/cwd.php                           (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/cwd.php     2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,26 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::cwd() method.
+ *
+ * @package WordPress
+ */
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::cwd
+ */
+class Tests_Filesystem_WpFilesystemDirect_Cwd extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::cwd()` returns the current
+        * working directory.
+        *
+        * @ticket 57774
+        */
+       public function test_should_get_current_working_directory() {
+               $this->assertSame( wp_normalize_path( dirname( ABSPATH ) ), wp_normalize_path( self::$filesystem->cwd() ) );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/cwd.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectdeletephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/delete.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/delete.php                                (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/delete.php  2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,204 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::delete() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::delete
+ */
+class Tests_Filesystem_WpFilesystemDirect_Delete extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::delete()` returns false
+        * for an empty path.
+        *
+        * @ticket 57774
+        */
+       public function test_should_return_false_for_empty_path() {
+               $this->assertFalse( self::$filesystem->delete( '' ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::delete()` deletes an empty directory.
+        *
+        * @ticket 57774
+        */
+       public function test_should_delete_an_empty_directory() {
+               $dir = self::$file_structure['test_dir']['path'] . 'directory-to-delete';
+
+               $this->assertTrue(
+                       mkdir( $dir ),
+                       'The directory was not created.'
+               );
+
+               $this->assertTrue(
+                       self::$filesystem->delete( $dir ),
+                       'The directory was not deleted.'
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::delete()` deletes a directory with contents.
+        *
+        * @ticket 57774
+        */
+       public function test_should_delete_a_directory_with_contents() {
+               $this->assertTrue(
+                       self::$filesystem->delete( self::$file_structure['test_dir']['path'], true ),
+                       'Directory deletion failed.'
+               );
+
+               $this->assertDirectoryDoesNotExist(
+                       self::$file_structure['test_dir']['path'],
+                       'The directory was not deleted.'
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::delete()` deletes a file.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_should_delete_a_file
+        *
+        * @param string $key The key for the file in `self::$filesystem_structure`.
+        */
+       public function test_should_delete_a_file( $file ) {
+               $file = self::$file_structure[ $file ]['path'] . $file;
+
+               $this->assertTrue( self::$filesystem->delete( $file ), 'File deletion failed.' );
+               $this->assertFileDoesNotExist( $file, 'The file was not deleted.' );
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_should_delete_a_file() {
+               return array(
+                       'A visible file' => array(
+                               'key' => 'visible_file',
+                       ),
+                       'A hidden file'  => array(
+                               'key' => 'hidden_file',
+                       ),
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::delete()`
+        * returns true when deleting a path that does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_return_true_when_deleting_path_that_does_not_exist( $path ) {
+               $path = self::$file_structure['test_dir']['path'] . $path;
+
+               /*
+                * Verify that the path doesn't exist before testing.
+                *
+                * assertFileDoesNotExist() uses file_exists(), which returns the same result for both
+                * files and directories.
+                * assertDirectoryDoesNotExist() uses is_dir(), which tests strictly for a directory.
+                *
+                * For more useful debugging in the event of a failure, test for a directory first.
+                */
+               $this->assertDirectoryDoesNotExist( $path, "$path already existed as a directory before testing." );
+               $this->assertFileDoesNotExist( $path, "$path already existed as a file before testing." );
+
+               $this->assertTrue( self::$filesystem->delete( $path ), 'Attempting to delete a non-existent path should return true.' );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::delete()`
+        * returns false when a directory's contents cannot be deleted.
+        *
+        * @ticket 57774
+        */
+       public function test_should_return_false_when_contents_cannot_be_deleted() {
+               global $wp_filesystem;
+
+               $wp_filesystem = new WP_Filesystem_Direct( array() );
+
+               $path = self::$file_structure['test_dir']['path'] . 'dir-to-delete/';
+
+               if ( ! is_dir( $path ) ) {
+                       mkdir( $path );
+               }
+
+               // Set up mock filesystem.
+               $filesystem_mock = $this->getMockBuilder( 'WP_Filesystem_Direct' )
+                                                               ->setConstructorArgs( array( null ) )
+                                                               // Note: setMethods() is deprecated in PHPUnit 9, but still supported.
+                                                               ->setMethods( array( 'dirlist' ) )
+                                                               ->getMock();
+
+               $filesystem_mock->expects( $this->once() )
+                                               ->method( 'dirlist' )
+                                               ->willReturn(
+                                                       array( 'a_file_that_does_not_exist.txt' => array( 'type' => 'f' ) )
+                                               );
+
+               $wp_filesystem_backup = $wp_filesystem;
+               $wp_filesystem        = $filesystem_mock;
+
+               $actual = $filesystem_mock->delete( $path, true );
+
+               if ( $actual ) {
+                       rmdir( $path );
+               }
+
+               $wp_filesystem = $wp_filesystem_backup;
+
+               $this->assertFalse( $actual );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::delete()`
+        * returns false when the path is not a file or directory, but exists.
+        *
+        * @ticket 57774
+        */
+       public function test_should_return_false_when_path_exists_but_is_not_a_file_or_directory() {
+               global $wp_filesystem;
+
+               $wp_filesystem = new WP_Filesystem_Direct( array() );
+
+               // Set up mock filesystem.
+               $filesystem_mock = $this->getMockBuilder( 'WP_Filesystem_Direct' )
+                                                               ->setConstructorArgs( array( null ) )
+                                                               // Note: setMethods() is deprecated in PHPUnit 9, but still supported.
+                                                               ->setMethods( array( 'is_file', 'dirlist' ) )
+                                                               ->getMock();
+
+               $filesystem_mock->expects( $this->once() )
+                                               ->method( 'is_file' )
+                                               ->willReturn( false );
+
+               $filesystem_mock->expects( $this->once() )
+                                               ->method( 'dirlist' )
+                                               ->willReturn( false );
+
+               $wp_filesystem_backup = $wp_filesystem;
+               $wp_filesystem        = $filesystem_mock;
+
+               $actual = $filesystem_mock->delete( self::$file_structure['subdir']['path'], true );
+
+               $wp_filesystem = $wp_filesystem_backup;
+
+               $this->assertFalse( $actual );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/delete.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectdirlistphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/dirlist.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/dirlist.php                               (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/dirlist.php 2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,130 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::dirlist() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::dirlist
+ */
+class Tests_Filesystem_WpFilesystemDirect_Dirlist extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::dirlist()` returns
+        * the expected result for a path.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_should_get_dirlist
+        *
+        * @param string      $path           The path.
+        * @param bool        $include_hidden Whether to include hidden files.
+        * @param bool        $recursive      Whether to recursive into subdirectories.
+        * @param array|false $expected       The expected result.
+        */
+       public function test_should_get_dirlist( $path, $include_hidden, $recursive, $expected ) {
+               $actual = self::$filesystem->dirlist( self::$file_structure['test_dir']['path'] . $path, $include_hidden, $recursive );
+
+               if ( is_array( $expected ) ) {
+                       $this->assertSameSets(
+                               $expected,
+                               array_keys( $actual ),
+                               'The array keys do not match.'
+                       );
+               } else {
+                       $this->assertFalse(
+                               $actual,
+                               '`WP_Filesystem_Direct::dirlist()` did not return false.'
+                       );
+               }
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_should_get_dirlist() {
+               return array(
+                       'a directory that exists excluding hidden files' => array(
+                               'path'           => '',
+                               'include_hidden' => false,
+                               'recursive'      => false,
+                               'expected'       => array(
+                                       'a_file_that_exists.txt',
+                                       'subdir',
+                               ),
+                       ),
+                       'a directory that exists including hidden files' => array(
+                               'path'           => '',
+                               'include_hidden' => true,
+                               'recursive'      => false,
+                               'expected'       => array(
+                                       'a_file_that_exists.txt',
+                                       '.a_hidden_file',
+                                       'subdir',
+                               ),
+                       ),
+                       'a directory that does not exist' => array(
+                               'path'           => 'a_directory_that_does_not_exist/',
+                               'include_hidden' => true,
+                               'recursive'      => false,
+                               'expected'       => false,
+                       ),
+                       'a file that exists'              => array(
+                               'path'           => 'a_file_that_exists.txt',
+                               'include_hidden' => true,
+                               'recursive'      => false,
+                               'expected'       => array(
+                                       'a_file_that_exists.txt',
+                               ),
+                       ),
+                       'a file that does not exist'      => array(
+                               'path'           => 'a_file_that_does_not_exist.txt',
+                               'include_hidden' => true,
+                               'recursive'      => false,
+                               'expected'       => false,
+                       ),
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::dirlist()` recurses
+        * into a subdirectory.
+        *
+        * @ticket 57774
+        */
+       public function test_should_recurse_into_subdirectory() {
+               $actual = self::$filesystem->dirlist( self::$file_structure['test_dir']['path'], true, true );
+
+               $this->assertIsArray( $actual, 'Did not return an array.' );
+               $this->assertArrayHasKey( 'subdir', $actual, 'The subdirectory was not detected.' );
+               $this->assertArrayHasKey( 'files', $actual['subdir'], 'The subdirectory does not have a "files" key.' );
+               $this->assertNotEmpty( $actual['subdir']['files'], "The subdirectory's contents were not retrieved." );
+               $this->assertArrayHasKey( 'subfile.txt', $actual['subdir']['files'], 'The subfile was not detected.' );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::dirlist()` should not recurse
+        * into a subdirectory.
+        *
+        * @ticket 57774
+        */
+       public function test_should_not_recurse_into_subdirectory() {
+
+               $actual = self::$filesystem->dirlist( self::$file_structure['test_dir']['path'], true, false );
+
+               $this->assertIsArray( $actual, 'Did not return an array.' );
+               $this->assertArrayHasKey( 'subdir', $actual, 'The subdirectory was not detected.' );
+               $this->assertArrayHasKey( 'files', $actual['subdir'], 'The "files" key was not set.' );
+               $this->assertIsArray( $actual['subdir']['files'], 'The "files" key was not set to an array.' );
+               $this->assertEmpty( $actual['subdir']['files'], 'The "files" array was not empty.' );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/dirlist.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectexistsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/exists.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/exists.php                                (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/exists.php  2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,44 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::exists() method.
+ *
+ * @package WordPress
+ */
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::exists
+ */
+class Tests_Filesystem_WpFilesystemDirect_Exists extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::exists()` determines that
+        * a path exists.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_exist
+        *
+        * @param string $path The path to check.
+        */
+       public function test_should_determine_that_a_path_exists( $path ) {
+               $this->assertTrue( self::$filesystem->exists( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::exists()` determines that
+        * a path does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path to check.
+        */
+       public function test_should_determine_that_a_path_does_not_exist( $path ) {
+               $this->assertFalse( self::$filesystem->exists( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/exists.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectgetContentsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getContents.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getContents.php                           (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getContents.php     2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,47 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::get_contents() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::get_contents
+ */
+class Tests_Filesystem_WpFilesystemDirect_GetContents extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::get_contents()` gets the
+        * contents of the provided $file.
+        *
+        * @ticket 57774
+        */
+       public function test_should_get_the_contents_of_a_file() {
+               $file = self::$file_structure['visible_file']['path'];
+
+               $this->assertSame(
+                       "Contents of a file.\r\nNext line of a file.\r\n",
+                       self::$filesystem->get_contents( $file )
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::get_contents()`
+        * returns false for a file that does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_return_false( $path ) {
+               $this->assertFalse( self::$filesystem->get_contents( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getContents.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectgetContentsArrayphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getContentsArray.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getContentsArray.php                              (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getContentsArray.php        2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,57 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::get_contents_array() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::get_contents_array
+ */
+class Tests_Filesystem_WpFilesystemDirect_GetContentsArray extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::get_contents_array()` gets
+        * the contents of the provided file.
+        *
+        * @ticket 57774
+        */
+       public function test_should_get_the_contents_of_a_file_as_an_array() {
+               $file     = self::$file_structure['visible_file']['path'];
+               $contents = self::$filesystem->get_contents_array( $file );
+
+               $this->assertIsArray(
+                       $contents,
+                       'The file contents are not an array.'
+               );
+
+               $this->assertSameSetsWithIndex(
+                       array(
+                               "Contents of a file.\r\n",
+                               "Next line of a file.\r\n",
+                       ),
+                       $contents,
+                       'The file contents do not match the expected value.'
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::get_contents_array()`
+        * returns false for a path that does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_return_false( $path ) {
+               $this->assertFalse( self::$filesystem->get_contents_array( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getContentsArray.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectgetchmodphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getchmod.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getchmod.php                              (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getchmod.php        2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,48 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::getchmod() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::getchmod
+ */
+class Tests_Filesystem_WpFilesystemDirect_Getchmod extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::getchmod()` returns
+        * the permissions for a path that exists.
+        *
+        * @dataProvider data_paths_that_exist
+        *
+        * @ticket 57774
+        *
+        * @param string $path The path.
+        */
+       public function test_should_get_chmod_for_a_path_that_exists( $path ) {
+               $actual = self::$filesystem->getchmod( self::$file_structure['test_dir']['path'] . $path );
+               $this->assertNotSame( '', $actual );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::getchmod()` returns
+        * the permissions for a path that does not exist.
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @ticket 57774
+        *
+        * @param string $path The path.
+        */
+       public function test_should_get_chmod_for_a_path_that_does_not_exist( $path ) {
+               $actual = self::$filesystem->getchmod( self::$file_structure['test_dir']['path'] . $path );
+               $this->assertNotSame( '', $actual );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/getchmod.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectisDirphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isDir.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isDir.php                         (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isDir.php   2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,63 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::is_dir() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::is_dir
+ */
+class Tests_Filesystem_WpFilesystemDirect_IsDir extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::is_directory()` determines that
+        * a path is a directory.
+        *
+        * @ticket 57774
+        */
+       public function test_should_determine_that_a_path_is_a_directory() {
+               $this->assertTrue( self::$filesystem->is_dir( self::$file_structure['test_dir']['path'] ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::is_directory()` determines that
+        * a path is not a directory.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_should_determine_that_a_path_is_not_a_directory
+        *
+        * @param string $path The path to check.
+        * @param string $type The type of resource. Accepts 'f' or 'd'.
+        *                     Used to invert $expected due to data provider setup.
+        */
+       public function test_should_determine_that_a_path_is_not_a_directory( $path ) {
+               $this->assertFalse( self::$filesystem->is_dir( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_should_determine_that_a_path_is_not_a_directory() {
+               return array(
+                       'a file that exists'              => array(
+                               'path' => 'a_file_that_exists.txt',
+                       ),
+                       'a file that does not exist'      => array(
+                               'path' => 'a_file_that_does_not_exist.txt',
+                       ),
+                       'a directory that does not exist' => array(
+                               'path' => 'a_directory_that_does_not_exist',
+                       ),
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isDir.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectisFilephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isFile.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isFile.php                                (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isFile.php  2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,61 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::is_file() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::is_file
+ */
+class Tests_Filesystem_WpFilesystemDirect_IsFile extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::is_file()` determies that
+        * a path is a file.
+        *
+        * @ticket 57774
+        */
+       public function test_should_determine_that_a_path_is_a_file() {
+               $this->assertTrue( self::$filesystem->is_file( self::$file_structure['test_dir']['path'] . 'a_file_that_exists.txt' ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::is_file()` determies that
+        * a path is not a file.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_should_determine_if_a_path_is_not_a_file
+        *
+        * @param string $path The path to check.
+        */
+       public function test_should_determine_that_a_path_is_not_a_file( $path ) {
+               $this->assertFalse( self::$filesystem->is_file( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_should_determine_if_a_path_is_not_a_file() {
+               return array(
+                       'a file that does not exist'      => array(
+                               'path' => 'a_file_that_does_not_exist.txt',
+                       ),
+                       'a directory that exists'         => array(
+                               'path' => '',
+                       ),
+                       'a directory that does not exist' => array(
+                               'path' => 'a_directory_that_does_not_exist',
+                       ),
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isFile.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectisReadablephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isReadable.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isReadable.php                            (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isReadable.php      2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,46 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::is_readable() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::is_readable
+ */
+class Tests_Filesystem_WpFilesystemDirect_IsReadable extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::is_readable()` determines that
+        * a path is readable.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_determine_that_a_path_is_readable( $path ) {
+               $this->assertTrue( self::$filesystem->is_readable( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::is_readable()` determines that
+        * a path is not readable.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_determine_that_a_path_is_not_readable( $path ) {
+               $this->assertFalse( self::$filesystem->is_readable( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isReadable.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectisWritablephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isWritable.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isWritable.php                            (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isWritable.php      2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,46 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::is_writable() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::is_writable
+ */
+class Tests_Filesystem_WpFilesystemDirect_IsWritable extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::is_writable()` determines that
+        * a path is writable.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_determine_that_a_path_is_writable( $path ) {
+               $this->assertTrue( self::$filesystem->is_writable( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::is_writable()` determines that
+        * a path is not writable.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_determine_that_a_path_is_not_writable( $path ) {
+               $this->assertFalse( self::$filesystem->is_writable( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/isWritable.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectmkdirphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/mkdir.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/mkdir.php                         (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/mkdir.php   2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,211 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::mkdir() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::mkdir
+ */
+class Tests_Filesystem_WpFilesystemDirect_Mkdir extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::mkdir()` creates a directory.
+        *
+        * This test runs in a separate process so that it can define
+        * constants without impacting other tests.
+        *
+        * This test does not preserve global state to prevent the exception
+        * "Serialization of 'Closure' is not allowed." when running in a
+        * separate process.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_should_create_directory
+        *
+        * @runInSeparateProcess
+        * @preserveGlobalState disabled
+        *
+        * @param mixed $path The path to create.
+        */
+       public function test_should_create_directory( $path ) {
+               define( 'FS_CHMOD_DIR', 0755 );
+
+               $path   = str_replace( 'TEST_DIR', self::$file_structure['test_dir']['path'], $path );
+               $actual = self::$filesystem->mkdir( $path );
+
+               if ( $path !== self::$file_structure['test_dir']['path'] && is_dir( $path ) ) {
+                       rmdir( $path );
+               }
+
+               $this->assertTrue( $actual );
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_should_create_directory() {
+               return array(
+                       'no trailing slash' => array(
+                               'path' => 'TEST_DIR/directory-to-create',
+                       ),
+                       'a trailing slash'  => array(
+                               'path' => 'TEST_DIR/directory-to-create/',
+                       ),
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::mkdir()` does not create a directory.
+        *
+        * This test runs in a separate process so that it can define
+        * constants without impacting other tests.
+        *
+        * This test does not preserve global state to prevent the exception
+        * "Serialization of 'Closure' is not allowed." when running in a
+        * separate process.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_should_not_create_directory
+        *
+        * @runInSeparateProcess
+        * @preserveGlobalState disabled
+        *
+        * @param mixed $path     The path to create.
+        */
+       public function test_should_not_create_directory( $path ) {
+               define( 'FS_CHMOD_DIR', 0755 );
+
+               $path   = str_replace( 'TEST_DIR', self::$file_structure['test_dir']['path'], $path );
+               $actual = self::$filesystem->mkdir( $path );
+
+               if ( $path !== self::$file_structure['test_dir']['path'] && is_dir( $path ) ) {
+                       rmdir( $path );
+               }
+
+               $this->assertFalse( $actual );
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_should_not_create_directory() {
+               return array(
+                       'empty path'         => array(
+                               'path' => '',
+                       ),
+                       'a path that exists' => array(
+                               'path' => 'TEST_DIR',
+                       ),
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::mkdir()` sets chmod.
+        *
+        * @ticket 57774
+        */
+       public function test_should_set_chmod() {
+               $path = self::$file_structure['test_dir']['path'] . 'directory-to-create';
+
+               $created = self::$filesystem->mkdir( $path, 0644 );
+               $chmod   = substr( sprintf( '%o', fileperms( $path ) ), -4 );
+
+               if ( $path !== self::$file_structure['test_dir']['path'] && is_dir( $path ) ) {
+                       rmdir( $path );
+               }
+
+               $expected_permissions = $this->is_windows() ? '0777' : '0644';
+
+               $this->assertTrue( $created, 'The directory was not created.' );
+               $this->assertSame( $expected_permissions, $chmod, 'The permissions are incorrect.' );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::mkdir()` sets the owner.
+        *
+        * This test runs in a separate process so that it can define
+        * constants without impacting other tests.
+        *
+        * This test does not preserve global state to prevent the exception
+        * "Serialization of 'Closure' is not allowed." when running in a
+        * separate process.
+        *
+        * @ticket 57774
+        *
+        * @runInSeparateProcess
+        * @preserveGlobalState disabled
+        */
+       public function test_should_set_owner() {
+               define( 'FS_CHMOD_DIR', 0755 );
+
+               $path = self::$file_structure['test_dir']['path'] . 'directory-to-create';
+
+               // Get the default owner.
+               self::$filesystem->mkdir( $path );
+               $original_owner = fileowner( $path );
+
+               rmdir( $path );
+
+               $expected_group = $this->is_windows() ? $original_owner : $original_owner + 1;
+               $created        = self::$filesystem->mkdir( $path, 0755, $expected_group );
+               $owner          = fileowner( $path );
+
+               if ( $path !== self::$file_structure['test_dir']['path'] && is_dir( $path ) ) {
+                       rmdir( $path );
+               }
+
+               $this->assertTrue( $created, 'The directory was not created.' );
+               $this->assertSame( $expected_group, $owner, 'The owner is incorrect.' );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::mkdir()` sets the group.
+        *
+        * This test runs in a separate process so that it can define
+        * constants without impacting other tests.
+        *
+        * This test does not preserve global state to prevent the exception
+        * "Serialization of 'Closure' is not allowed." when running in a
+        * separate process.
+        *
+        * @ticket 57774
+        *
+        * @runInSeparateProcess
+        * @preserveGlobalState disabled
+        */
+       public function test_should_set_group() {
+               define( 'FS_CHMOD_DIR', 0755 );
+
+               $path = self::$file_structure['test_dir']['path'] . 'directory-to-create';
+
+               // Get the default group.
+               self::$filesystem->mkdir( $path );
+               $original_group = filegroup( $path );
+
+               rmdir( $path );
+
+               $expected_group = $this->is_windows() ? $original_group : $original_group + 1;
+               $created        = self::$filesystem->mkdir( $path, 0755, false, $expected_group );
+               $group          = filegroup( $path );
+
+               if ( $path !== self::$file_structure['test_dir']['path'] && is_dir( $path ) ) {
+                       rmdir( $path );
+               }
+
+               $this->assertTrue( $created, 'The directory was not created.' );
+               $this->assertSame( $expected_group, $group, 'The group is incorrect.' );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/mkdir.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectmovephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/move.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/move.php                          (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/move.php    2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,150 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::move() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::move
+ */
+class Tests_Filesystem_WpFilesystemDirect_Move extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::copy()` overwrites an existing
+        * destination when overwriting is enabled.
+        *
+        * @ticket 57774
+        */
+       public function test_should_overwrite_an_existing_file_when_overwriting_is_enabled() {
+               $source      = self::$file_structure['visible_file']['path'];
+               $destination = self::$file_structure['test_dir']['path'] . 'a_file_that_exists.dest';
+               $actual      = self::$filesystem->move( $source, $destination, true );
+
+               rename( $destination, $source );
+
+               $this->assertTrue( $actual );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::move()` does not overwrite
+        * an existing destination when overwriting is disabled.
+        *
+        * @ticket 57774
+        */
+       public function test_should_not_overwrite_an_existing_file_when_overwriting_is_disabled() {
+               $source      = self::$file_structure['visible_file']['path'];
+               $destination = self::$file_structure['subfile']['path'];
+               $actual      = self::$filesystem->move( $source, $destination );
+
+               $this->assertFalse( $actual );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::move()` moves directories.
+        *
+        * @ticket 57774
+        */
+       public function test_should_move_directories() {
+               $source      = self::$file_structure['test_dir']['path'];
+               $destination = untrailingslashit( self::$file_structure['test_dir']['path'] ) . '-dest';
+               $actual      = self::$filesystem->move( $source, $destination, true );
+
+               $source_exists      = is_dir( $source );
+               $destination_exists = is_dir( $destination );
+
+               if ( $actual ) {
+                       $restored = rename( $destination, $source );
+               }
+
+               $this->assertTrue( $actual, 'The directory was not moved.' );
+               $this->assertFalse( $source_exists, 'The source still exists.' );
+               $this->assertTrue( $destination_exists, 'The destination does not exist.' );
+               $this->assertTrue( $restored, 'The test assets were not cleaned up after the test.' );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::move()` returns false for an
+        * invalid destination.
+        *
+        * @ticket 57774
+        */
+       public function test_should_return_false_for_invalid_destination() {
+               $source      = self::$file_structure['test_dir']['path'];
+               $destination = 'http://example.org';
+
+               $this->assertFalse( self::$filesystem->move( $source, $destination, true ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::move()` returns false for an
+        * invalid destination.
+        *
+        * @ticket 57774
+        */
+       public function test_should_return_false_when_overwriting_is_enabled_the_destination_exists_but_cannot_be_deleted() {
+               global $wp_filesystem;
+               $wpfilesystem_backup = $wp_filesystem;
+
+               // Force failure conditions.
+               $filesystem_mock = $this->getMockBuilder( 'WP_Filesystem_Direct' )
+                                                               // Note: setMethods() is deprecated in PHPUnit 9, but still supported.
+                                                               ->setMethods( array( 'exists', 'delete' ) )
+                                                               ->setConstructorArgs( array( null ) )
+                                                               ->getMock();
+
+               $filesystem_mock->expects( $this->once() )->method( 'exists' )->willReturn( true );
+               $filesystem_mock->expects( $this->once() )->method( 'delete' )->willReturn( false );
+               $wp_filesystem = $filesystem_mock;
+
+               $actual = $wp_filesystem->move(
+                       self::$file_structure['test_dir']['path'],
+                       self::$file_structure['subdir']['path'],
+                       true
+               );
+
+               // Restore the filesystem.
+               $wp_filesystem = $wpfilesystem_backup;
+
+               $this->assertFalse( $actual );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::move()` falls back to a single
+        * file copy when the source and destination do not exist.
+        *
+        * @ticket 57774
+        */
+       public function test_should_fall_back_to_single_file_copy_when_source_and_destination_do_not_exist() {
+               global $wp_filesystem;
+
+               $source      = self::$file_structure['test_dir']['path'] . 'a_file_that_does_not_exist.txt';
+               $destination = self::$file_structure['test_dir']['path'] . 'another_file_that_does_not_exist.txt';
+
+               // Set up mock filesystem.
+               $filesystem_mock = $this->getMockBuilder( 'WP_Filesystem_Direct' )
+                                                               ->setConstructorArgs( array( null ) )
+                                                               // Note: setMethods() is deprecated in PHPUnit 9, but still supported.
+                                                               ->setMethods( array( 'exists', 'delete', 'is_file', 'copy' ) )
+                                                               ->getMock();
+
+               $filesystem_mock->expects( $this->exactly( 2 ) )->method( 'exists' )->willReturn( array( true, true ) );
+               $filesystem_mock->expects( $this->exactly( 2 ) )->method( 'delete' )->willReturn( array( true, false ) );
+               $filesystem_mock->expects( $this->once() )->method( 'is_file' )->willReturn( true );
+               $filesystem_mock->expects( $this->once() )->method( 'copy' )->willReturn( true );
+
+               $wp_filesystem_backup = $wp_filesystem;
+               $wp_filesystem        = $filesystem_mock;
+
+               $actual        = $filesystem_mock->move( $source, $destination, true );
+               $wp_filesystem = $wp_filesystem_backup;
+
+               $this->assertTrue( $actual );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/move.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectmtimephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/mtime.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/mtime.php                         (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/mtime.php   2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,68 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::mtime() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::mtime
+ */
+class Tests_Filesystem_WpFilesystemDirect_Mtime extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::mtime()` determines
+        * the mtime of a path.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_determine_file_modified_time( $path ) {
+               $result    = self::$filesystem->mtime( self::$file_structure['test_dir']['path'] . $path );
+               $has_mtime = false !== $result;
+
+               $this->assertTrue(
+                       $has_mtime,
+                       'The mtime was not determined.'
+               );
+
+               $this->assertIsInt(
+                       $result,
+                       'The mtime is not an integer.'
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::mtime()` does not determine
+        * the mtime of a path.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_not_determine_file_modified_time( $path ) {
+               $result    = self::$filesystem->mtime( self::$file_structure['test_dir']['path'] . $path );
+               $has_mtime = false !== $result;
+
+               $this->assertFalse(
+                       $has_mtime,
+                       'An mtime was determined.'
+               );
+
+               $this->assertIsNotInt(
+                       $result,
+                       'The mtime is an integer.'
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/mtime.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectputContentsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/putContents.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/putContents.php                           (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/putContents.php     2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,42 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::put_contents() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::put_contents
+ */
+class Tests_Filesystem_WpFilesystemDirect_PutContents extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::put_contents()`
+        * returns false for a directory.
+        *
+        * @ticket 57774
+        */
+       public function test_should_return_false_for_a_directory() {
+               $this->assertFalse( self::$filesystem->put_contents( self::$file_structure['test_dir']['path'], 'New content.' ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::put_contents()` inserts
+        * content into the provided file.
+        *
+        * @ticket 57774
+        */
+       public function test_should_insert_contents_into_file() {
+               $file   = self::$file_structure['test_dir']['path'] . 'file-to-create.txt';
+               $actual = self::$filesystem->put_contents( $file, 'New content.', 0644 );
+               unlink( $file );
+
+               $this->assertTrue( $actual, 'The contents were not inserted.' );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/putContents.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectrmdirphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/rmdir.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/rmdir.php                         (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/rmdir.php   2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,200 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::rmdir() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::rmdir
+ */
+class Tests_Filesystem_WpFilesystemDirect_Rmdir extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::rmdir()` returns false
+        * for an empty path.
+        *
+        * @ticket 57774
+        */
+       public function test_should_return_false_for_empty_path() {
+               $this->assertFalse( self::$filesystem->rmdir( '' ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::rmdir()` deletes an empty directory.
+        *
+        * @ticket 57774
+        */
+       public function test_should_delete_an_empty_directory() {
+               $dir = self::$file_structure['test_dir']['path'] . 'directory-to-delete/';
+
+               if ( ! is_dir( $dir ) ) {
+                       mkdir( $dir );
+               }
+
+               $actual = self::$filesystem->rmdir( $dir );
+
+               if ( ! $actual ) {
+                       rmdir( $dir );
+               }
+
+               $this->assertTrue( $actual, 'The directory was not deleted.' );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::rmdir()` recursively deletes
+        * a directory with contents.
+        *
+        * @ticket 57774
+        */
+       public function test_should_recursively_delete_a_directory() {
+               $dir     = self::$file_structure['test_dir']['path'] . 'directory-to-delete/';
+               $file    = $dir . 'file-to-delete.txt';
+               $subdir  = $dir . 'subdirectory-to-delete/';
+               $subfile = $subdir . 'subfile-to-delete.txt';
+
+               mkdir( $dir, 0755 );
+               mkdir( $subdir, 0755 );
+               touch( $file, 0644 );
+               touch( $subfile, 0644 );
+
+               $actual = self::$filesystem->rmdir( self::$file_structure['test_dir']['path'], true );
+
+               if ( ! $actual ) {
+                       unlink( $file );
+                       unlink( $subfile );
+                       rmdir( $subdir );
+                       rmdir( $dir );
+               }
+
+               $this->assertTrue( $actual, 'The directory was deleted.' );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::rmdir()` deletes a file.
+        *
+        * @ticket 57774
+        */
+       public function test_should_delete_a_file() {
+               $file = self::$file_structure['test_dir']['path'] . 'file-to-delete.txt';
+
+               touch( $file );
+
+               $actual = self::$filesystem->rmdir( $file );
+
+               if ( ! $actual ) {
+                       unlink( $file );
+               }
+
+               $this->assertTrue( $actual, 'The directory was not deleted.' );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::rmdir()`
+        * returns true when deleting a path that does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_return_true_when_deleting_path_that_does_not_exist( $path ) {
+               if (
+                       '' === $path
+                       || str_starts_with( $path, '.' )
+                       || str_starts_with( $path, '/' )
+               ) {
+                       $this->markTestSkipped( 'Dangerous delete path.' );
+               }
+
+               $this->assertTrue( self::$filesystem->rmdir( self::$file_structure['test_dir']['path'] . $path ) );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::rmdir()`
+        * returns false when a directory's contents cannot be deleted.
+        *
+        * @ticket 57774
+        */
+       public function test_should_return_false_when_contents_cannot_be_deleted() {
+
+               global $wp_filesystem;
+
+               $wp_filesystem = new WP_Filesystem_Direct( array() );
+
+               $path = self::$file_structure['test_dir']['path'] . 'dir-to-delete/';
+
+               if ( ! is_dir( $path ) ) {
+                       mkdir( $path );
+               }
+
+               // Set up mock filesystem.
+               $filesystem_mock = $this->getMockBuilder( 'WP_Filesystem_Direct' )
+                                                               ->setConstructorArgs( array( null ) )
+                                                               // Note: setMethods() is deprecated in PHPUnit 9, but still supported.
+                                                               ->setMethods( array( 'dirlist' ) )
+                                                               ->getMock();
+
+               $filesystem_mock->expects( $this->once() )
+                                               ->method( 'dirlist' )
+                                               ->willReturn(
+                                                       array( 'a_file_that_does_not_exist.txt' => array( 'type' => 'f' ) )
+                                               );
+
+               $wp_filesystem_backup = $wp_filesystem;
+               $wp_filesystem        = $filesystem_mock;
+
+               $actual = $filesystem_mock->rmdir( $path, true );
+
+               if ( $actual ) {
+                       rmdir( $path );
+               }
+
+               $wp_filesystem = $wp_filesystem_backup;
+
+               $this->assertFalse( $actual );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::rmdir()`
+        * returns false when the path is not a file or directory, but exists.
+        *
+        * @ticket 57774
+        */
+       public function test_should_return_false_when_path_exists_but_is_not_a_file_or_directory() {
+               global $wp_filesystem;
+
+               $wp_filesystem = new WP_Filesystem_Direct( array() );
+
+               // Set up mock filesystem.
+               $filesystem_mock = $this->getMockBuilder( 'WP_Filesystem_Direct' )
+                                                               ->setConstructorArgs( array( null ) )
+                                                               // Note: setMethods() is deprecated in PHPUnit 9, but still supported.
+                                                               ->setMethods( array( 'is_file', 'dirlist' ) )
+                                                               ->getMock();
+
+               $filesystem_mock->expects( $this->once() )
+                                               ->method( 'is_file' )
+                                               ->willReturn( false );
+
+               $filesystem_mock->expects( $this->once() )
+                                               ->method( 'dirlist' )
+                                               ->willReturn( false );
+
+               $wp_filesystem_backup = $wp_filesystem;
+               $wp_filesystem        = $filesystem_mock;
+
+               $actual = $filesystem_mock->rmdir( self::$file_structure['subdir']['path'], true );
+
+               $wp_filesystem = $wp_filesystem_backup;
+
+               $this->assertFalse( $actual );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/rmdir.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirectsizephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/size.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/size.php                          (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/size.php    2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,63 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::size() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::size
+ */
+class Tests_Filesystem_WpFilesystemDirect_Size extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::size()` determines
+        * the file size of a path that exists.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_determine_file_size( $path ) {
+               $result       = self::$filesystem->size( self::$file_structure['test_dir']['path'] . $path );
+               $has_filesize = false !== $result;
+
+               $this->assertTrue(
+                       $has_filesize,
+                       'The file size was not determined.'
+               );
+
+               $this->assertIsInt(
+                       $result,
+                       'The file size is not an integer.'
+               );
+       }
+
+       /**
+        * Tests that `WP_Filesystem_Direct::size()` does not determine
+        * the filesize of a path that does not exist.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_paths_that_do_not_exist
+        *
+        * @param string $path The path.
+        */
+       public function test_should_not_determine_file_size( $path ) {
+               $result       = self::$filesystem->size( self::$file_structure['test_dir']['path'] . $path );
+               $has_filesize = false !== $result;
+
+               $this->assertFalse(
+                       $has_filesize,
+                       'A file size was determined.'
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/size.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsfilesystemwpFilesystemDirecttouchphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/touch.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/touch.php                         (rev 0)
+++ trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/touch.php   2024-03-02 14:05:38 UTC (rev 57753)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,93 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Tests for the WP_Filesystem_Direct::touch() method.
+ *
+ * @package WordPress
+ */
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group admin
+ * @group filesystem
+ * @group filesystem-direct
+ *
+ * @covers WP_Filesystem_Direct::touch
+ */
+class Tests_Filesystem_WpFilesystemDirect_Touch extends WP_Filesystem_Direct_UnitTestCase {
+
+       /**
+        * Tests that `WP_Filesystem_Direct::touch()` creates a file.
+        *
+        * @ticket 57774
+        *
+        * @dataProvider data_should_create_file
+        *
+        * @param string $file  The file path.
+        * @param int    $mtime The modified time to set.
+        * @param int    $atime The accessed time to set.
+        */
+       public function test_should_create_file( $file, $mtime, $atime ) {
+               $file = str_replace( 'TEST_DATA', self::$file_structure['test_dir']['path'], $file );
+
+               if ( is_string( $mtime ) ) {
+                       $mtime = (int) str_replace(
+                               array( 'time plus one minute', time() + MINUTE_IN_SECONDS ),
+                               array( 'time', time() ),
+                               $mtime
+                       );
+               }
+
+               $expected_mtime = 0 === $mtime ? time() : $mtime;
+
+               if ( is_string( $atime ) ) {
+                       $atime = (int) str_replace(
+                               array( 'time plus one minute', time() + MINUTE_IN_SECONDS ),
+                               array( 'time', time() ),
+                               $atime
+                       );
+               }
+
+               $expected_atime = 0 === $atime ? time() : $atime;
+
+               $result = self::$filesystem->touch( $file, $mtime, $atime );
+
+               $actual_atime  = fileatime( $file );
+               $actual_exists = file_exists( $file );
+               $actual_mtime  = filemtime( $file );
+
+               if ( $actual_exists ) {
+                       unlink( $file );
+               }
+
+               $this->assertTrue( $result, 'WP_Filesystem_Direct::touch() did not return true.' );
+               $this->assertTrue( $actual_exists, 'The file does not exist.' );
+               $this->assertSame( $actual_atime, $expected_atime, 'The file does not have the expected atime.' );
+               $this->assertSame( $actual_mtime, $expected_mtime, 'The file does not have the expected mtime.' );
+       }
+
+       /**
+        * Data provider.
+        *
+        * @return array[]
+        */
+       public function data_should_create_file() {
+               return array(
+                       'default mtime or atime'      => array(
+                               'file'  => 'TEST_DATA/file-to-create.txt',
+                               'mtime' => 0,
+                               'atime' => 0,
+                       ),
+                       'set mtime and default atime' => array(
+                               'file'  => 'TEST_DATA/file-to-create.txt',
+                               'mtime' => 'time plus one minute',
+                               'atime' => 'time',
+                       ),
+                       'default mtime and set atime' => array(
+                               'file'  => 'TEST_DATA/file-to-create.txt',
+                               'mtime' => 'time',
+                               'atime' => 'time plus one minute',
+                       ),
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/filesystem/wpFilesystemDirect/touch.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span></div>

</body>
</html>