diff --git a/README.md b/README.md
index 52e20413a..a8fb62baa 100644
--- a/README.md
+++ b/README.md
@@ -85,6 +85,8 @@ Available Matchers
------------------
* [Array](../master/README.md#array)
* [Collection](../master/README.md#collection)
+* [Core](../master/README.md#core)
+* [File](../master/README.md#file)
* [Object](../master/README.md#object)
* [Numbers](../master/README.md#numbers)
* [Type checking](../master/README.md#type-checking)
@@ -227,6 +229,99 @@ assertThat([2, 4, 6], hasItem(equalTo(2)));
assertThat([1, 3, 5], hasItems(equalTo(1), equalTo(3)));
```
+### File
+
+All file matchers accepts `\SplFileInfo` objects or `string` paths only.
+
+* `anExistingDirectory` - evaluates to true if the file exists and is a directory
+```php
+$directory = new \SplFileInfo('/var/log');
+assertThat($directory, anExistingDirectory());
+
+assertThat('/var/log', anExistingDirectory());
+```
+
+* `anExistingFile` - evaluates to true if the file exists and is a regular file
+```php
+$file = new \SplFileInfo('/var/log/php-fpm.log');
+assertThat($file, anExistingFile());
+
+assertThat('/var/log/php-fpm.log', anExistingFile());
+```
+
+* `anExistingFileOrDirectory` - evaluates to true if the file exists and is a regular file or a directory
+```php
+$directory = new \SplFileInfo('/var/log');
+$file = new \SplFileInfo('/var/log/php-fpm.log');
+assertThat($directory, anExistingFileOrDirectory());
+assertThat($file, anExistingFileOrDirectory());
+
+assertThat('/var/log', anExistingFileOrDirectory());
+assertThat('/var/log/php-fpm.log', anExistingFileOrDirectory());
+```
+
+* `aReadableFile` - evaluates to true if the file is readable
+```php
+$file = new \SplFileInfo('/var/log/php-fpm.log');
+assertThat($file, aReadableFile());
+
+assertThat('/var/log/php-fpm.log', aReadableFile());
+```
+
+* `aWritableFile` - evaluates to true if the file is writable
+```php
+$file = new \SplFileInfo('/var/log/php-fpm.log');
+assertThat($file, aWritableFile());
+
+assertThat('/var/log/php-fpm.log', aWritableFile());
+```
+
+* `aFileWithSize` - evaluates to true if the file size is equal to given value or the provided matcher matches the file size
+```php
+$file = new \SplFileInfo('/var/log/php-fpm.log');
+assertThat($file, aFileWithSize(42));
+assertThat($file, aFileWithSize(greaterThan(42)));
+
+assertThat('/var/log/php-fpm.log', aFileWithSize(42));
+assertThat('/var/log/php-fpm.log', aFileWithSize(greaterThan(42)));
+```
+
+* `anEmptyFile` - evaluates to true if the file is empty
+```php
+$file = new \SplFileInfo('/var/log/php-fpm.log');
+assertThat($file, anEmptyFile());
+
+assertThat('/var/log/php-fpm.log', anEmptyFile());
+```
+
+* `aNonEmptyFile` - evaluates to true if the file is not empty
+```php
+$file = new \SplFileInfo('/var/log/php-fpm.log');
+assertThat($file, aNonEmptyFile());
+
+assertThat('/var/log/php-fpm.log', aNonEmptyFile());
+```
+
+* `aFileNamed` - evaluates to true if the file name is equal to given value or the provided matcher matches the file name
+```php
+$file = new \SplFileInfo('/var/log/php-fpm.log');
+assertThat($file, aFileNamed('php-fpm.log'));
+assertThat($file, aFileNamed(startsWith('php')));
+
+assertThat('/var/log/php-fpm.log', aFileNamed('php-fpm.log'));
+assertThat('/var/log/php-fpm.log', aFileNamed(startsWith('php')));
+```
+
+* `aFileWithCanonicalPath` - evaluates to true if the file canonical path is equal to given value or the provided matcher matches the canonical path of the file
+```php
+$file = new \SplFileInfo('/var/log/./php-fpm.log');
+assertThat($file, aFileWithCanonicalPath('/var/log/php-fpm.log'));
+assertThat($file, aFileWithCanonicalPath(endsWith('log/php-fpm.log')));
+
+assertThat('/var/log/./php-fpm.log', aFileWithCanonicalPath('/var/log/php-fpm.log'));
+assertThat('/var/log/./php-fpm.log', aFileWithCanonicalPath(endsWith('log/php-fpm.log')));
+```
+
### Object
* `hasToString` - check `__toString` or `toString` method
diff --git a/hamcrest/Hamcrest.php b/hamcrest/Hamcrest.php
index 55a2dd8c5..bf11dac6f 100644
--- a/hamcrest/Hamcrest.php
+++ b/hamcrest/Hamcrest.php
@@ -507,6 +507,142 @@ function notSet($property)
}
}
+if (!function_exists('anExistingDirectory')) {
+ /**
+ * Evaluates to true if the file exists and is a directory.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsExistingDirectory
+ */
+ function anExistingDirectory()
+ {
+ return \Hamcrest\File\IsExistingDirectory::anExistingDirectory();
+ }
+}
+
+if (!function_exists('anExistingFile')) {
+ /**
+ * Evaluates to true if the file exists and is a regular file.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsExistingFile
+ */
+ function anExistingFile()
+ {
+ return \Hamcrest\File\IsExistingFile::anExistingFile();
+ }
+}
+
+if (!function_exists('anExistingFileOrDirectory')) {
+ /**
+ * Evaluates to true if the file exists and is a regular file or a directory.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsExistingFileOrDirectory
+ */
+ function anExistingFileOrDirectory()
+ {
+ return \Hamcrest\File\IsExistingFileOrDirectory::anExistingFileOrDirectory();
+ }
+}
+
+if (!function_exists('aFileNamed')) {
+ /**
+ * Does file name satisfy a given matcher?
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @param \Hamcrest\Matcher|string $name as a {@link \Hamcrest\Matcher} or a value.
+ *
+ * @return \Hamcrest\File\IsFileNamed
+ */
+ function aFileNamed($name)
+ {
+ return \Hamcrest\File\IsFileNamed::aFileNamed($name);
+ }
+}
+
+if (!function_exists('aFileWithCanonicalPath')) {
+ /**
+ * Does canonical path satisfy a given matcher?
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @param \Hamcrest\Matcher|string $path as a {@link \Hamcrest\Matcher} or a value.
+ *
+ * @return \Hamcrest\File\IsFileWithCanonicalPath
+ */
+ function aFileWithCanonicalPath($path)
+ {
+ return \Hamcrest\File\IsFileWithCanonicalPath::aFileWithCanonicalPath($path);
+ }
+}
+
+if (!function_exists('aFileWithSize')) {
+ /**
+ * Does file size satisfy a given matcher?
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @param \Hamcrest\Matcher|int $size as a {@link \Hamcrest\Matcher} or a value.
+ *
+ * @return \Hamcrest\File\IsFileWithSize
+ */
+ function aFileWithSize($size)
+ {
+ return \Hamcrest\File\IsFileWithSize::aFileWithSize($size);
+ }
+}
+
+if (!function_exists('anEmptyFile')) {
+ /**
+ * Matches an empty file.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\Core\DescribedAs
+ */
+ function anEmptyFile()
+ {
+ return \Hamcrest\File\IsFileWithSize::anEmptyFile();
+ }
+}
+
+if (!function_exists('aNonEmptyFile')) {
+ /**
+ * Matches a non-empty file.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\Core\DescribedAs
+ */
+ function aNonEmptyFile()
+ {
+ return \Hamcrest\File\IsFileWithSize::aNonEmptyFile();
+ }
+}
+
+if (!function_exists('aReadableFile')) {
+ /**
+ * Evaluates to true if the file is readable.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsReadableFile
+ */
+ function aReadableFile()
+ {
+ return \Hamcrest\File\IsReadableFile::aReadableFile();
+ }
+}
+
+if (!function_exists('aWritableFile')) {
+ /**
+ * Evaluates to true if the file is writable.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsWritableFile
+ */
+ function aWritableFile()
+ {
+ return \Hamcrest\File\IsWritableFile::aWritableFile();
+ }
+}
+
if (!function_exists('closeTo')) {
/**
* Matches if value is a number equal to $value within some range of
diff --git a/hamcrest/Hamcrest/Core/DescribedAs.php b/hamcrest/Hamcrest/Core/DescribedAs.php
index 5b2583fa7..3d917d221 100644
--- a/hamcrest/Hamcrest/Core/DescribedAs.php
+++ b/hamcrest/Hamcrest/Core/DescribedAs.php
@@ -51,6 +51,11 @@ public function describeTo(Description $description)
}
}
+ public function describeMismatch($item, Description $description)
+ {
+ $this->_matcher->describeMismatch($item, $description);
+ }
+
/**
* Wraps an existing matcher and overrides the description when it fails.
*
diff --git a/hamcrest/Hamcrest/File/FileMatcher.php b/hamcrest/Hamcrest/File/FileMatcher.php
new file mode 100644
index 000000000..24d1e1a27
--- /dev/null
+++ b/hamcrest/Hamcrest/File/FileMatcher.php
@@ -0,0 +1,91 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\BaseMatcher;
+use Hamcrest\Description;
+
+abstract class FileMatcher extends BaseMatcher
+{
+ /**
+ * Description of the matcher that will be returned from the {@link describeTo()} method.
+ *
+ * @var string
+ */
+ private $ownDescription;
+
+ /**
+ * Description of a mismatch for the matcher, it will be prepended by the actual value that does not match.
+ *
+ * @var string
+ */
+ private $failureDescription;
+
+ /**
+ * @param string $ownDescription
+ * @param string $failureDescription
+ */
+ public function __construct($ownDescription = '', $failureDescription = '')
+ {
+ $this->ownDescription = $ownDescription;
+ $this->failureDescription = $failureDescription;
+ }
+
+ public function describeTo(Description $description)
+ {
+ $description->appendText($this->ownDescription);
+ }
+
+ final public function matches($item)
+ {
+ return $this->isSafeType($item) && $this->matchesFile($this->createSplFileInfoObjectFromPath($item));
+ }
+
+ final public function describeMismatch($item, Description $mismatchDescription)
+ {
+ if ($this->isSafeType($item)) {
+ $this->describeFileMismatch($this->createSplFileInfoObjectFromPath($item), $mismatchDescription);
+ } else {
+ parent::describeMismatch($item, $mismatchDescription);
+ }
+ }
+
+ /**
+ * Implement this method to provide the actual functionality of the matcher.
+ * It is guaranteed that the {@link $file} parameter is always {@code \SplFileInfo}.
+ *
+ * @param \SplFileInfo $file
+ * @return bool
+ */
+ abstract protected function matchesFile(\SplFileInfo $file);
+
+ protected function describeFileMismatch(\SplFileInfo $file, Description $mismatchDescription)
+ {
+ $mismatchDescription->appendValue($file)->appendText(' ')->appendText($this->failureDescription);
+ }
+
+ /**
+ * @param $value
+ * @return bool
+ */
+ private function isSafeType($value)
+ {
+ return $value instanceof \SplFileInfo || is_string($value);
+ }
+
+ /**
+ * @param string|\SplFileInfo $item
+ * @return \SplFileInfo
+ */
+ private function createSplFileInfoObjectFromPath($item)
+ {
+ if (is_string($item))
+ return new \SplFileInfo($item);
+
+ return $item;
+ }
+}
diff --git a/hamcrest/Hamcrest/File/IsExistingDirectory.php b/hamcrest/Hamcrest/File/IsExistingDirectory.php
new file mode 100644
index 000000000..d8e39ba0e
--- /dev/null
+++ b/hamcrest/Hamcrest/File/IsExistingDirectory.php
@@ -0,0 +1,32 @@
+
+ */
+
+namespace Hamcrest\File;
+
+class IsExistingDirectory extends FileMatcher
+{
+ public function __construct()
+ {
+ parent::__construct('an existing directory', 'is not a directory');
+ }
+
+ protected function matchesFile(\SplFileInfo $file)
+ {
+ return $file->isDir();
+ }
+
+ /**
+ * Evaluates to true if the file exists and is a directory.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsExistingDirectory
+ * @factory
+ */
+ public static function anExistingDirectory()
+ {
+ return new self();
+ }
+}
diff --git a/hamcrest/Hamcrest/File/IsExistingFile.php b/hamcrest/Hamcrest/File/IsExistingFile.php
new file mode 100644
index 000000000..3dc20685c
--- /dev/null
+++ b/hamcrest/Hamcrest/File/IsExistingFile.php
@@ -0,0 +1,32 @@
+
+ */
+
+namespace Hamcrest\File;
+
+class IsExistingFile extends FileMatcher
+{
+ public function __construct()
+ {
+ parent::__construct('an existing file', 'is not a file');
+ }
+
+ protected function matchesFile(\SplFileInfo $file)
+ {
+ return $file->isFile();
+ }
+
+ /**
+ * Evaluates to true if the file exists and is a regular file.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsExistingFile
+ * @factory
+ */
+ public static function anExistingFile()
+ {
+ return new self();
+ }
+}
diff --git a/hamcrest/Hamcrest/File/IsExistingFileOrDirectory.php b/hamcrest/Hamcrest/File/IsExistingFileOrDirectory.php
new file mode 100644
index 000000000..d7ae8ec6b
--- /dev/null
+++ b/hamcrest/Hamcrest/File/IsExistingFileOrDirectory.php
@@ -0,0 +1,32 @@
+
+ */
+
+namespace Hamcrest\File;
+
+class IsExistingFileOrDirectory extends FileMatcher
+{
+ public function __construct()
+ {
+ parent::__construct('an existing file or directory', 'does not exist');
+ }
+
+ protected function matchesFile(\SplFileInfo $file)
+ {
+ return $file->isFile() || $file->isDir();
+ }
+
+ /**
+ * Evaluates to true if the file exists and is a regular file or a directory.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsExistingFileOrDirectory
+ * @factory
+ */
+ public static function anExistingFileOrDirectory()
+ {
+ return new self();
+ }
+}
diff --git a/hamcrest/Hamcrest/File/IsFileNamed.php b/hamcrest/Hamcrest/File/IsFileNamed.php
new file mode 100644
index 000000000..13b2b19b8
--- /dev/null
+++ b/hamcrest/Hamcrest/File/IsFileNamed.php
@@ -0,0 +1,60 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\Description;
+use Hamcrest\Matcher;
+use Hamcrest\Util;
+
+class IsFileNamed extends FileMatcher
+{
+ /**
+ * Matcher that will match the actual name of the file.
+ *
+ * @var Matcher
+ */
+ private $nameMatcher;
+
+ public function __construct(Matcher $nameMatcher)
+ {
+ parent::__construct();
+ $this->nameMatcher = $nameMatcher;
+ }
+
+ final public function describeTo(Description $description)
+ {
+ $description->appendText('a file with name ')->appendDescriptionOf($this->nameMatcher);
+ }
+
+ protected function matchesFile(\SplFileInfo $file)
+ {
+ $fileName = $file->getFilename();
+
+ return $this->nameMatcher->matches($fileName);
+ }
+
+ protected function describeFileMismatch(\SplFileInfo $file, Description $mismatchDescription)
+ {
+ $fileName = $file->getFilename();
+ $mismatchDescription->appendText('name was ')->appendValue($fileName);
+ }
+
+
+ /**
+ * Does file name satisfy a given matcher?
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @param \Hamcrest\Matcher|string $name as a {@link \Hamcrest\Matcher} or a value.
+ *
+ * @return \Hamcrest\File\IsFileNamed
+ * @factory
+ */
+ public static function aFileNamed($name)
+ {
+ return new self(Util::wrapValueWithIsEqual($name));
+ }
+}
diff --git a/hamcrest/Hamcrest/File/IsFileWithCanonicalPath.php b/hamcrest/Hamcrest/File/IsFileWithCanonicalPath.php
new file mode 100644
index 000000000..a9e0987a6
--- /dev/null
+++ b/hamcrest/Hamcrest/File/IsFileWithCanonicalPath.php
@@ -0,0 +1,60 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\Description;
+use Hamcrest\Matcher;
+use Hamcrest\Util;
+
+class IsFileWithCanonicalPath extends FileMatcher
+{
+ /**
+ * Matcher that will match the actual canonical path of the file.
+ *
+ * @var Matcher
+ */
+ private $pathMatcher;
+
+ public function __construct(Matcher $pathMatcher)
+ {
+ parent::__construct();
+ $this->pathMatcher = $pathMatcher;
+ }
+
+ final public function describeTo(Description $description)
+ {
+ $description->appendText('a file with canonical path ')->appendDescriptionOf($this->pathMatcher);
+ }
+
+ protected function matchesFile(\SplFileInfo $file)
+ {
+ $realPath = $file->getRealPath();
+
+ return $this->pathMatcher->matches($realPath);
+ }
+
+ protected function describeFileMismatch(\SplFileInfo $file, Description $mismatchDescription)
+ {
+ $realPath = $file->getRealPath();
+ $mismatchDescription->appendText('canonical path was ')->appendValue($realPath);
+ }
+
+
+ /**
+ * Does canonical path satisfy a given matcher?
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @param \Hamcrest\Matcher|string $path as a {@link \Hamcrest\Matcher} or a value.
+ *
+ * @return \Hamcrest\File\IsFileWithCanonicalPath
+ * @factory
+ */
+ public static function aFileWithCanonicalPath($path)
+ {
+ return new self(Util::wrapValueWithIsEqual($path));
+ }
+}
diff --git a/hamcrest/Hamcrest/File/IsFileWithSize.php b/hamcrest/Hamcrest/File/IsFileWithSize.php
new file mode 100644
index 000000000..6535a6ac0
--- /dev/null
+++ b/hamcrest/Hamcrest/File/IsFileWithSize.php
@@ -0,0 +1,92 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\Core\DescribedAs;
+use Hamcrest\Core\IsNot;
+use Hamcrest\Description;
+use Hamcrest\Matcher;
+use Hamcrest\Util;
+
+class IsFileWithSize extends FileMatcher
+{
+ /**
+ * Matcher that will match the actual size of the file.
+ *
+ * @var Matcher
+ */
+ private $sizeMatcher;
+
+ public function __construct(Matcher $sizeMatcher)
+ {
+ parent::__construct();
+ $this->sizeMatcher = $sizeMatcher;
+ }
+
+ final public function describeTo(Description $description)
+ {
+ $description->appendText('a file with size ')->appendDescriptionOf($this->sizeMatcher);
+ }
+
+ protected function matchesFile(\SplFileInfo $file)
+ {
+ $fileSize = $file->getSize();
+
+ return $this->sizeMatcher->matches($fileSize);
+ }
+
+ protected function describeFileMismatch(\SplFileInfo $file, Description $mismatchDescription)
+ {
+ $fileSize = $file->getSize();
+ $mismatchDescription->appendText('size was ')->appendValue($fileSize);
+ }
+
+
+ /**
+ * Does file size satisfy a given matcher?
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @param \Hamcrest\Matcher|int $size as a {@link \Hamcrest\Matcher} or a value.
+ *
+ * @return \Hamcrest\File\IsFileWithSize
+ * @factory
+ */
+ public static function aFileWithSize($size)
+ {
+ return new self(Util::wrapValueWithIsEqual($size));
+ }
+
+ /**
+ * Matches an empty file.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\Core\DescribedAs
+ * @factory
+ */
+ public static function anEmptyFile()
+ {
+ return DescribedAs::describedAs(
+ 'an empty file',
+ self::aFileWithSize(0)
+ );
+ }
+
+ /**
+ * Matches a non-empty file.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\Core\DescribedAs
+ * @factory
+ */
+ public static function aNonEmptyFile()
+ {
+ return DescribedAs::describedAs(
+ 'a non-empty file',
+ self::aFileWithSize(IsNot::not(0))
+ );
+ }
+}
diff --git a/hamcrest/Hamcrest/File/IsReadableFile.php b/hamcrest/Hamcrest/File/IsReadableFile.php
new file mode 100644
index 000000000..54ce4d125
--- /dev/null
+++ b/hamcrest/Hamcrest/File/IsReadableFile.php
@@ -0,0 +1,32 @@
+
+ */
+
+namespace Hamcrest\File;
+
+class IsReadableFile extends FileMatcher
+{
+ public function __construct()
+ {
+ parent::__construct('a readable file', 'cannot be read');
+ }
+
+ protected function matchesFile(\SplFileInfo $file)
+ {
+ return $file->isReadable();
+ }
+
+ /**
+ * Evaluates to true if the file is readable.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsReadableFile
+ * @factory
+ */
+ public static function aReadableFile()
+ {
+ return new self();
+ }
+}
diff --git a/hamcrest/Hamcrest/File/IsWritableFile.php b/hamcrest/Hamcrest/File/IsWritableFile.php
new file mode 100644
index 000000000..9603f79af
--- /dev/null
+++ b/hamcrest/Hamcrest/File/IsWritableFile.php
@@ -0,0 +1,32 @@
+
+ */
+
+namespace Hamcrest\File;
+
+class IsWritableFile extends FileMatcher
+{
+ public function __construct()
+ {
+ parent::__construct('a writable file', 'cannot be written to');
+ }
+
+ protected function matchesFile(\SplFileInfo $file)
+ {
+ return $file->isWritable();
+ }
+
+ /**
+ * Evaluates to true if the file is writable.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsWritableFile
+ * @factory
+ */
+ public static function aWritableFile()
+ {
+ return new self();
+ }
+}
diff --git a/hamcrest/Hamcrest/Matchers.php b/hamcrest/Hamcrest/Matchers.php
index 23232e450..70251d6ba 100644
--- a/hamcrest/Hamcrest/Matchers.php
+++ b/hamcrest/Hamcrest/Matchers.php
@@ -411,6 +411,122 @@ public static function notSet($property)
return \Hamcrest\Core\Set::notSet($property);
}
+ /**
+ * Evaluates to true if the file exists and is a directory.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsExistingDirectory
+ */
+ public static function anExistingDirectory()
+ {
+ return \Hamcrest\File\IsExistingDirectory::anExistingDirectory();
+ }
+
+ /**
+ * Evaluates to true if the file exists and is a regular file.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsExistingFile
+ */
+ public static function anExistingFile()
+ {
+ return \Hamcrest\File\IsExistingFile::anExistingFile();
+ }
+
+ /**
+ * Evaluates to true if the file exists and is a regular file or a directory.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsExistingFileOrDirectory
+ */
+ public static function anExistingFileOrDirectory()
+ {
+ return \Hamcrest\File\IsExistingFileOrDirectory::anExistingFileOrDirectory();
+ }
+
+ /**
+ * Does file name satisfy a given matcher?
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @param \Hamcrest\Matcher|string $name as a {@link \Hamcrest\Matcher} or a value.
+ *
+ * @return \Hamcrest\File\IsFileNamed
+ */
+ public static function aFileNamed($name)
+ {
+ return \Hamcrest\File\IsFileNamed::aFileNamed($name);
+ }
+
+ /**
+ * Does canonical path satisfy a given matcher?
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @param \Hamcrest\Matcher|string $path as a {@link \Hamcrest\Matcher} or a value.
+ *
+ * @return \Hamcrest\File\IsFileWithCanonicalPath
+ */
+ public static function aFileWithCanonicalPath($path)
+ {
+ return \Hamcrest\File\IsFileWithCanonicalPath::aFileWithCanonicalPath($path);
+ }
+
+ /**
+ * Does file size satisfy a given matcher?
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @param \Hamcrest\Matcher|int $size as a {@link \Hamcrest\Matcher} or a value.
+ *
+ * @return \Hamcrest\File\IsFileWithSize
+ */
+ public static function aFileWithSize($size)
+ {
+ return \Hamcrest\File\IsFileWithSize::aFileWithSize($size);
+ }
+
+ /**
+ * Matches an empty file.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\Core\DescribedAs
+ */
+ public static function anEmptyFile()
+ {
+ return \Hamcrest\File\IsFileWithSize::anEmptyFile();
+ }
+
+ /**
+ * Matches a non-empty file.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\Core\DescribedAs
+ */
+ public static function aNonEmptyFile()
+ {
+ return \Hamcrest\File\IsFileWithSize::aNonEmptyFile();
+ }
+
+ /**
+ * Evaluates to true if the file is readable.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsReadableFile
+ */
+ public static function aReadableFile()
+ {
+ return \Hamcrest\File\IsReadableFile::aReadableFile();
+ }
+
+ /**
+ * Evaluates to true if the file is writable.
+ * Accepts only \SplFileInfo
objects or string
paths.
+ *
+ * @return \Hamcrest\File\IsWritableFile
+ */
+ public static function aWritableFile()
+ {
+ return \Hamcrest\File\IsWritableFile::aWritableFile();
+ }
+
/**
* Matches if value is a number equal to $value within some range of
* acceptable error $delta.
diff --git a/tests/Hamcrest/File/IsExistingDirectoryTest.php b/tests/Hamcrest/File/IsExistingDirectoryTest.php
new file mode 100644
index 000000000..01929402e
--- /dev/null
+++ b/tests/Hamcrest/File/IsExistingDirectoryTest.php
@@ -0,0 +1,134 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\AbstractMatcherTest;
+
+class IsExistingDirectoryTest extends AbstractMatcherTest
+{
+ private static $EXISTING_DIRECTORY_PATH;
+ private static $NON_EXISTING_DIRECTORY_PATH;
+ private static $EXISTING_FILE_PATH;
+
+ private static $EXISTING_DIRECTORY;
+ private static $NON_EXISTING_DIRECTORY;
+ private static $EXISTING_FILE;
+
+ /**
+ * @beforeClass
+ */
+ public static function initializeFiles()
+ {
+ self::$EXISTING_DIRECTORY_PATH = __DIR__;
+ self::$NON_EXISTING_DIRECTORY_PATH = __DIR__ . '/does-not-exist';
+ self::$EXISTING_FILE_PATH = __FILE__;
+
+ self::$EXISTING_DIRECTORY = new \SplFileInfo(self::$EXISTING_DIRECTORY_PATH);
+ self::$NON_EXISTING_DIRECTORY = new \SplFileInfo(self::$NON_EXISTING_DIRECTORY_PATH);
+ self::$EXISTING_FILE = new \SplFileInfo(self::$EXISTING_FILE_PATH);
+ }
+
+ protected function createMatcher()
+ {
+ return IsExistingDirectory::anExistingDirectory();
+ }
+
+ public function testMatchesAnExistingDirectory()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$EXISTING_DIRECTORY,
+ "should match a directory that actualy exists"
+ );
+ }
+
+ public function testMatchesAnExistingDirectoryPath()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$EXISTING_DIRECTORY_PATH,
+ "should match a path to directory that actualy exists"
+ );
+ }
+
+ public function testDoesNotMatchADirectoryThatDoesNotExist()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$NON_EXISTING_DIRECTORY,
+ "should not match a directory that does not exist"
+ );
+ }
+
+ public function testDoesNotMatchADirectoryPathThatDoesNotExist()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$NON_EXISTING_DIRECTORY_PATH,
+ "should not match a path to directory that does not exist"
+ );
+ }
+
+ public function testDoesNotMatchAnExistingFileThatIsNotADirectory()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$EXISTING_FILE,
+ "should not match an existing file that is not a directory"
+ );
+ }
+
+ public function testDoesNotMatchAnExistingFilePathThatIsNotADirectory()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$EXISTING_FILE_PATH,
+ "should not match a path to existing file that is not a directory"
+ );
+ }
+
+ public function testDoesNotMatchNull()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ null,
+ 'should not match null'
+ );
+ }
+
+ public function testHasAReadableDescription()
+ {
+ $this->assertDescription('an existing directory', $this->createMatcher());
+ }
+
+ public function testHasAReadableMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ '<' . self::$NON_EXISTING_DIRECTORY . '> is not a directory',
+ $this->createMatcher(),
+ self::$NON_EXISTING_DIRECTORY
+ );
+ }
+
+ public function testHasAReadableMissmatchDescriptionForPath()
+ {
+ $this->assertMismatchDescription(
+ '<' . self::$NON_EXISTING_DIRECTORY_PATH . '> is not a directory',
+ $this->createMatcher(),
+ self::$NON_EXISTING_DIRECTORY_PATH
+ );
+ }
+
+ public function testHasAReadableTypeMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'was ',
+ $this->createMatcher(),
+ new \stdClass()
+ );
+ }
+}
diff --git a/tests/Hamcrest/File/IsExistingFileOrDirectoryTest.php b/tests/Hamcrest/File/IsExistingFileOrDirectoryTest.php
new file mode 100644
index 000000000..6bf2e2d7a
--- /dev/null
+++ b/tests/Hamcrest/File/IsExistingFileOrDirectoryTest.php
@@ -0,0 +1,134 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\AbstractMatcherTest;
+
+class IsExistingFileOrDirectoryTest extends AbstractMatcherTest
+{
+ private static $EXISTING_FILE_PATH;
+ private static $EXISTING_DIRECTORY_PATH;
+ private static $NON_EXISTING_FILE_PATH;
+
+ private static $EXISTING_FILE;
+ private static $EXISTING_DIRECTORY;
+ private static $NON_EXISTING_FILE;
+
+ /**
+ * @beforeClass
+ */
+ public static function initializeFiles()
+ {
+ self::$EXISTING_FILE_PATH = __FILE__;
+ self::$EXISTING_DIRECTORY_PATH = __DIR__;
+ self::$NON_EXISTING_FILE_PATH = __DIR__ . '/does-not-exist';
+
+ self::$EXISTING_FILE = new \SplFileInfo(self::$EXISTING_FILE_PATH);
+ self::$EXISTING_DIRECTORY = new \SplFileInfo(self::$EXISTING_DIRECTORY_PATH);
+ self::$NON_EXISTING_FILE = new \SplFileInfo(self::$NON_EXISTING_FILE_PATH);
+ }
+
+ protected function createMatcher()
+ {
+ return IsExistingFileOrDirectory::anExistingFileOrDirectory();
+ }
+
+ public function testMatchesAnExistingFile()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$EXISTING_FILE,
+ "should match a file that actualy exists"
+ );
+ }
+
+ public function testMatchesAnExistingFilePath()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$EXISTING_FILE_PATH,
+ "should match a path to file that actualy exists"
+ );
+ }
+
+ public function testMatchesAnExistingDirectory()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$EXISTING_DIRECTORY,
+ "should match an existing directory"
+ );
+ }
+
+ public function testMatchesAnExistingDirectoryPath()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$EXISTING_DIRECTORY_PATH,
+ "should match a path to existing directory"
+ );
+ }
+
+ public function testDoesNotMatchAFileThatDoesNotExist()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$NON_EXISTING_FILE,
+ "should not match a file that does not exist"
+ );
+ }
+
+ public function testDoesNotMatchAFilePathThatDoesNotExist()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$NON_EXISTING_FILE_PATH,
+ "should not match a path to file that does not exist"
+ );
+ }
+
+ public function testDoesNotMatchNull()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ null,
+ 'should not match null'
+ );
+ }
+
+ public function testHasAReadableDescription()
+ {
+ $this->assertDescription('an existing file or directory', $this->createMatcher());
+ }
+
+ public function testHasAReadableMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ '<' . self::$NON_EXISTING_FILE . '> does not exist',
+ $this->createMatcher(),
+ self::$NON_EXISTING_FILE
+ );
+ }
+
+ public function testHasAReadableMissmatchDescriptionForPath()
+ {
+ $this->assertMismatchDescription(
+ '<' . self::$NON_EXISTING_FILE_PATH . '> does not exist',
+ $this->createMatcher(),
+ self::$NON_EXISTING_FILE_PATH
+ );
+ }
+
+ public function testHasAReadableTypeMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'was ',
+ $this->createMatcher(),
+ new \stdClass()
+ );
+ }
+}
diff --git a/tests/Hamcrest/File/IsExistingFileTest.php b/tests/Hamcrest/File/IsExistingFileTest.php
new file mode 100644
index 000000000..574c96554
--- /dev/null
+++ b/tests/Hamcrest/File/IsExistingFileTest.php
@@ -0,0 +1,134 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\AbstractMatcherTest;
+
+class IsExistingFileTest extends AbstractMatcherTest
+{
+ private static $EXISTING_FILE_PATH;
+ private static $NON_EXISTING_FILE_PATH;
+ private static $EXISTING_DIRECTORY_PATH;
+
+ private static $EXISTING_FILE;
+ private static $NON_EXISTING_FILE;
+ private static $EXISTING_DIRECTORY;
+
+ /**
+ * @beforeClass
+ */
+ public static function initializeFiles()
+ {
+ self::$EXISTING_FILE_PATH = __FILE__;
+ self::$NON_EXISTING_FILE_PATH = __DIR__ . '/does-not-exist';
+ self::$EXISTING_DIRECTORY_PATH = __DIR__;
+
+ self::$EXISTING_FILE = new \SplFileInfo(self::$EXISTING_FILE_PATH);
+ self::$NON_EXISTING_FILE = new \SplFileInfo(self::$NON_EXISTING_FILE_PATH);
+ self::$EXISTING_DIRECTORY = new \SplFileInfo(self::$EXISTING_DIRECTORY_PATH);
+ }
+
+ protected function createMatcher()
+ {
+ return IsExistingFile::anExistingFile();
+ }
+
+ public function testMatchesAnExistingFile()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$EXISTING_FILE,
+ "should match a file that actualy exists"
+ );
+ }
+
+ public function testMatchesAnExistingFilePath()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$EXISTING_FILE_PATH,
+ "should match a path to file that actualy exists"
+ );
+ }
+
+ public function testDoesNotMatchAFileThatDoesNotExist()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$NON_EXISTING_FILE,
+ "should not match a file that does not exist"
+ );
+ }
+
+ public function testDoesNotMatchAFilePathThatDoesNotExist()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$NON_EXISTING_FILE_PATH,
+ "should not match a path to file that does not exist"
+ );
+ }
+
+ public function testDoesNotMatchAnExistingDirectory()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$EXISTING_DIRECTORY,
+ "should not match an existing directory"
+ );
+ }
+
+ public function testDoesNotMatchAnExistingDirectoryPath()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$EXISTING_DIRECTORY_PATH,
+ "should not match a path to existing directory"
+ );
+ }
+
+ public function testDoesNotMatchNull()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ null,
+ 'should not match null'
+ );
+ }
+
+ public function testHasAReadableDescription()
+ {
+ $this->assertDescription('an existing file', $this->createMatcher());
+ }
+
+ public function testHasAReadableMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ '<' . self::$NON_EXISTING_FILE . '> is not a file',
+ $this->createMatcher(),
+ self::$NON_EXISTING_FILE
+ );
+ }
+
+ public function testHasAReadableMissmatchDescriptionForPath()
+ {
+ $this->assertMismatchDescription(
+ '<' . self::$NON_EXISTING_FILE_PATH . '> is not a file',
+ $this->createMatcher(),
+ self::$NON_EXISTING_FILE_PATH
+ );
+ }
+
+ public function testHasAReadableTypeMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'was ',
+ $this->createMatcher(),
+ new \stdClass()
+ );
+ }
+}
diff --git a/tests/Hamcrest/File/IsFileNamedTest.php b/tests/Hamcrest/File/IsFileNamedTest.php
new file mode 100644
index 000000000..0c06d6cc7
--- /dev/null
+++ b/tests/Hamcrest/File/IsFileNamedTest.php
@@ -0,0 +1,133 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\AbstractMatcherTest;
+
+class IsFileNamedTest extends AbstractMatcherTest
+{
+ private static $FILE_PATH;
+ private static $FILE;
+ private static $ACTUAL_NAME;
+ private static $ACTUAL_NAME_START;
+
+ /**
+ * @beforeClass
+ */
+ public static function initializeFiles()
+ {
+ self::$FILE_PATH = __FILE__;
+ self::$FILE = new \SplFileInfo(self::$FILE_PATH);
+ self::$ACTUAL_NAME = pathinfo(self::$FILE_PATH, PATHINFO_BASENAME);
+ self::$ACTUAL_NAME_START = substr(self::$ACTUAL_NAME, 0, 5);
+ }
+
+ protected function createMatcher()
+ {
+ return IsFileNamed::aFileNamed(not(anything()));
+ }
+
+ public function testMatchesAFileWithEqualName()
+ {
+ $this->assertMatches(
+ aFileNamed(self::$ACTUAL_NAME),
+ self::$FILE,
+ 'should match a file that has equal name'
+ );
+ }
+
+ public function testMatchesAFilePathWithEqualName()
+ {
+ $this->assertMatches(
+ aFileNamed(self::$ACTUAL_NAME),
+ self::$FILE_PATH,
+ 'should match a file path that has equal name'
+ );
+ }
+
+ public function testDoesNotMatchAFileWithDifferentName()
+ {
+ $this->assertDoesNotMatch(
+ aFileNamed(self::$ACTUAL_NAME . '_suffix'),
+ self::$FILE,
+ 'should not match a file that has a different name'
+ );
+ }
+
+ public function testDoesNotMatchAFilePathWithDifferentName()
+ {
+ $this->assertDoesNotMatch(
+ aFileNamed(self::$ACTUAL_NAME . '_suffix'),
+ self::$FILE_PATH,
+ 'should not match a file path that has a different file name'
+ );
+ }
+
+ public function testMatchesAFileWithNameMatchedByAnotherMatcher()
+ {
+ $this->assertMatches(
+ aFileNamed(startsWith(self::$ACTUAL_NAME_START)),
+ self::$FILE,
+ 'should match a file with name that is matched by another matcher'
+ );
+ }
+
+ public function testMatchesAFilePathWithNameMatchedByAnotherMatcher()
+ {
+ $this->assertMatches(
+ aFileNamed(startsWith(self::$ACTUAL_NAME_START)),
+ self::$FILE_PATH,
+ 'should match a file path with name that is matched by another matcher'
+ );
+ }
+
+ public function testDoesNotMatchAFileWithNameNotMatchedByAnotherMatcher()
+ {
+ $this->assertDoesNotMatch(
+ aFileNamed(endsWith(self::$ACTUAL_NAME_START)),
+ self::$FILE,
+ 'should not match a file with name that is not matched by another matcher'
+ );
+ }
+
+ public function testDoesNotMatchNull()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ null,
+ 'should not match null'
+ );
+ }
+
+ public function testHasAReadableDescription()
+ {
+ $this->assertDescription('a file with name "my-file.txt"', aFileNamed('my-file.txt'));
+ }
+
+ public function testHasAReadableDescriptionWithAnotherMatcher()
+ {
+ $this->assertDescription('a file with name a string starting with "my-file"', aFileNamed(startsWith('my-file')));
+ }
+
+ public function testHasAReadableMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'name was "' . self::$ACTUAL_NAME . '"',
+ $this->createMatcher(),
+ self::$FILE
+ );
+ }
+
+ public function testHasAReadableTypeMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'was ',
+ $this->createMatcher(),
+ new \stdClass()
+ );
+ }
+}
diff --git a/tests/Hamcrest/File/IsFileWithCanonicalPathTest.php b/tests/Hamcrest/File/IsFileWithCanonicalPathTest.php
new file mode 100644
index 000000000..2a98f1943
--- /dev/null
+++ b/tests/Hamcrest/File/IsFileWithCanonicalPathTest.php
@@ -0,0 +1,137 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\AbstractMatcherTest;
+
+class IsFileWithCanonicalPathTest extends AbstractMatcherTest
+{
+ private static $CANONICAL_PATH;
+ private static $FILENAME;
+ private static $FILE_PATH;
+ private static $FILE;
+
+ private static $DIFFERENT_CANONICAL_PATH;
+
+ /**
+ * @beforeClass
+ */
+ public static function initializeFiles()
+ {
+ self::$CANONICAL_PATH = __FILE__;
+ self::$FILENAME = pathinfo(__FILE__, PATHINFO_BASENAME);
+ self::$FILE_PATH = __DIR__ . '/./' . self::$FILENAME;
+ self::$FILE = new \SplFileInfo(self::$FILE_PATH);
+
+ self::$DIFFERENT_CANONICAL_PATH = __DIR__ . '/different-file.txt';
+ }
+
+ protected function createMatcher()
+ {
+ return IsFileWithCanonicalPath::aFileWithCanonicalPath(not(anything()));
+ }
+
+ public function testMatchesAFileWithEqualCanonicalPath()
+ {
+ $this->assertMatches(
+ aFileWithCanonicalPath(self::$CANONICAL_PATH),
+ self::$FILE,
+ 'should match a file that has equal canonical path'
+ );
+ }
+
+ public function testMatchesAFilePathWithEqualCanonicalPath()
+ {
+ $this->assertMatches(
+ aFileWithCanonicalPath(self::$CANONICAL_PATH),
+ self::$FILE_PATH,
+ 'should match a file path that has equal canonical path'
+ );
+ }
+
+ public function testDoesNotMatchAFileWithDifferentCanonicalPath()
+ {
+ $this->assertDoesNotMatch(
+ aFileWithCanonicalPath(self::$DIFFERENT_CANONICAL_PATH),
+ self::$FILE,
+ 'should not match a file that has a different canonical path'
+ );
+ }
+
+ public function testDoesNotMatchAFilePathWithDifferentCanonicalPath()
+ {
+ $this->assertDoesNotMatch(
+ aFileWithCanonicalPath(self::$DIFFERENT_CANONICAL_PATH),
+ self::$FILE_PATH,
+ 'should not match a file path that has a different canonical path'
+ );
+ }
+
+ public function testMatchesAFileWithCanonicalPathMatchedByAnotherMatcher()
+ {
+ $this->assertMatches(
+ aFileWithCanonicalPath(endsWith(self::$FILENAME)),
+ self::$FILE,
+ 'should match a file with canonical path that is matched by another matcher'
+ );
+ }
+
+ public function testMatchesAFilePathWithCanonicalPathMatchedByAnotherMatcher()
+ {
+ $this->assertMatches(
+ aFileWithCanonicalPath(endsWith(self::$FILENAME)),
+ self::$FILE_PATH,
+ 'should match a file path with canonical path that is matched by another matcher'
+ );
+ }
+
+ public function testDoesNotMatchAFileWithCanonicalPathNotMatchedByAnotherMatcher()
+ {
+ $this->assertDoesNotMatch(
+ aFileWithCanonicalPath(startsWith(self::$FILENAME)),
+ self::$FILE,
+ 'should not match a file with canonical path that is not matched by another matcher'
+ );
+ }
+
+ public function testDoesNotMatchNull()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ null,
+ 'should not match null'
+ );
+ }
+
+ public function testHasAReadableDescription()
+ {
+ $this->assertDescription('a file with canonical path "/tmp/my-file.txt"', aFileWithCanonicalPath('/tmp/my-file.txt'));
+ }
+
+ public function testHasAReadableDescriptionWithAnotherMatcher()
+ {
+ $this->assertDescription('a file with canonical path a string ending with "my-file"', aFileWithCanonicalPath(endsWith('my-file')));
+ }
+
+ public function testHasAReadableMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'canonical path was "' . self::$CANONICAL_PATH . '"',
+ $this->createMatcher(),
+ self::$FILE
+ );
+ }
+
+ public function testHasAReadableTypeMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'was ',
+ $this->createMatcher(),
+ new \stdClass()
+ );
+ }
+}
diff --git a/tests/Hamcrest/File/IsFileWithSizeTest.php b/tests/Hamcrest/File/IsFileWithSizeTest.php
new file mode 100644
index 000000000..bdae67c83
--- /dev/null
+++ b/tests/Hamcrest/File/IsFileWithSizeTest.php
@@ -0,0 +1,204 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\AbstractMatcherTest;
+
+class IsFileWithSizeTest extends AbstractMatcherTest
+{
+ private static $FILE_PATH;
+ private static $FILE;
+ private static $ACTUAL_SIZE;
+
+ private static $EMPTY_FILE;
+
+ /**
+ * @beforeClass
+ */
+ public static function initializeFiles()
+ {
+ self::$FILE_PATH = __FILE__;
+ self::$FILE = new \SplFileInfo(self::$FILE_PATH);
+ self::$ACTUAL_SIZE = filesize(self::$FILE_PATH);
+
+ self::$EMPTY_FILE = new class('/tmp/empty') extends \SplFileInfo {
+ public function getSize()
+ {
+ return 0;
+ }
+ };
+ }
+
+ protected function createMatcher()
+ {
+ return IsFileWithSize::aFileWithSize(not(anything()));
+ }
+
+ public function testMatchesAFileWithEqualSize()
+ {
+ $this->assertMatches(
+ aFileWithSize(self::$ACTUAL_SIZE),
+ self::$FILE,
+ "should match a file that has equal size"
+ );
+ }
+
+ public function testMatchesAFilePathWithEqualSize()
+ {
+ $this->assertMatches(
+ aFileWithSize(self::$ACTUAL_SIZE),
+ self::$FILE_PATH,
+ "should match a file path that has equal size"
+ );
+ }
+
+ public function testDoesNotMatchAFileWithDifferentSize()
+ {
+ $this->assertDoesNotMatch(
+ aFileWithSize(self::$ACTUAL_SIZE + 1),
+ self::$FILE,
+ "should not match a file that has a different size"
+ );
+ }
+
+ public function testDoesNotMatchAFilePathWithDifferentSize()
+ {
+ $this->assertDoesNotMatch(
+ aFileWithSize(self::$ACTUAL_SIZE + 1),
+ self::$FILE_PATH,
+ "should not match a file path that has a different size"
+ );
+ }
+
+ public function testMatchesAFileWithSizeMatchedByAnotherMatcher()
+ {
+ $this->assertMatches(
+ aFileWithSize(greaterThan(self::$ACTUAL_SIZE - 1)),
+ self::$FILE,
+ "should match a file with size that is matched by another matcher"
+ );
+ }
+
+ public function testMatchesAFilePathWithSizeMatchedByAnotherMatcher()
+ {
+ $this->assertMatches(
+ aFileWithSize(greaterThan(self::$ACTUAL_SIZE - 1)),
+ self::$FILE_PATH,
+ "should match a file path with size that is matched by another matcher"
+ );
+ }
+
+ public function testDoesNotMatchAFileWithSizeNotMatchedByAnotherMatcher()
+ {
+ $this->assertDoesNotMatch(
+ aFileWithSize(greaterThan(self::$ACTUAL_SIZE)),
+ self::$FILE,
+ "should not match a file with size that is not matched by another matcher"
+ );
+ }
+
+ public function testEmptyFileMatcherMatchesEmptyFile()
+ {
+ $this->assertMatches(
+ anEmptyFile(),
+ self::$EMPTY_FILE,
+ "should match an empty file"
+ );
+ }
+
+ public function testEmptyFileMatcherDoesNotMatchNonEmptyFile()
+ {
+ $this->assertDoesNotMatch(
+ anEmptyFile(),
+ self::$FILE,
+ "should not match non-empty file"
+ );
+ }
+
+ public function testNonEmptyFileMatcherMatchesNonEmptyFile()
+ {
+ $this->assertMatches(
+ aNonEmptyFile(),
+ self::$FILE,
+ "should match a non-empty file"
+ );
+ }
+
+ public function testNonEmptyFileMatcherDoesNotMatchEmptyFile()
+ {
+ $this->assertDoesNotMatch(
+ aNonEmptyFile(),
+ self::$EMPTY_FILE,
+ "should not match empty file"
+ );
+ }
+
+ public function testDoesNotMatchNull()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ null,
+ 'should not match null'
+ );
+ }
+
+ public function testHasAReadableDescription()
+ {
+ $this->assertDescription('a file with size <42>', aFileWithSize(42));
+ }
+
+ public function testHasAReadableDescriptionWithAnotherMatcher()
+ {
+ $this->assertDescription('a file with size a value greater than <42>', aFileWithSize(greaterThan(42)));
+ }
+
+ public function testEmptyFileMatcherHasAReadableDescription()
+ {
+ $this->assertDescription('an empty file', anEmptyFile());
+ }
+
+ public function testNonEmptyFileMatcherHasAReadableDescription()
+ {
+ $this->assertDescription('a non-empty file', aNonEmptyFile());
+ }
+
+ public function testHasAReadableMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'size was <' . self::$ACTUAL_SIZE . '>',
+ $this->createMatcher(),
+ self::$FILE
+ );
+ }
+
+ public function testEmptyFileMatcherHasAReadableMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'size was <' . self::$ACTUAL_SIZE . '>',
+ anEmptyFile(),
+ self::$FILE
+ );
+ }
+
+ public function testNonEmptyFileMatcherHasAReadableMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'size was <0>',
+ aNonEmptyFile(),
+ self::$EMPTY_FILE
+ );
+ }
+
+ public function testHasAReadableTypeMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'was ',
+ $this->createMatcher(),
+ new \stdClass()
+ );
+ }
+}
diff --git a/tests/Hamcrest/File/IsReadableFileTest.php b/tests/Hamcrest/File/IsReadableFileTest.php
new file mode 100644
index 000000000..ac8954a1c
--- /dev/null
+++ b/tests/Hamcrest/File/IsReadableFileTest.php
@@ -0,0 +1,98 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\AbstractMatcherTest;
+
+class IsReadableFileTest extends AbstractMatcherTest
+{
+ private static $READABLE_FILE_PATH;
+
+ private static $READABLE_FILE;
+ private static $NON_READABLE_FILE;
+
+ /**
+ * @beforeClass
+ */
+ public static function initializeFiles()
+ {
+ self::$READABLE_FILE_PATH = __FILE__;
+
+ self::$READABLE_FILE = new \SplFileInfo(self::$READABLE_FILE_PATH);
+
+ self::$NON_READABLE_FILE = new class('/tmp/non-readable') extends \SplFileInfo {
+ public function isReadable()
+ {
+ return false;
+ }
+ };
+ }
+
+ protected function createMatcher()
+ {
+ return IsReadableFile::aReadableFile();
+ }
+
+ public function testMatchesAReadableFile()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$READABLE_FILE,
+ "should match a file that is readable"
+ );
+ }
+
+ public function testMatchesAReadableFilePath()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$READABLE_FILE_PATH,
+ "should match a path to file that is readable"
+ );
+ }
+
+ public function testDoesNotMatchAFileThatIsNotReadable()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$NON_READABLE_FILE,
+ "should not match a file that is not readable"
+ );
+ }
+
+ public function testDoesNotMatchNull()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ null,
+ 'should not match null'
+ );
+ }
+
+ public function testHasAReadableDescription()
+ {
+ $this->assertDescription('a readable file', $this->createMatcher());
+ }
+
+ public function testHasAReadableMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ '<' . self::$NON_READABLE_FILE . '> cannot be read',
+ $this->createMatcher(),
+ self::$NON_READABLE_FILE
+ );
+ }
+
+ public function testHasAReadableTypeMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'was ',
+ $this->createMatcher(),
+ new \stdClass()
+ );
+ }
+}
diff --git a/tests/Hamcrest/File/IsWritableFileTest.php b/tests/Hamcrest/File/IsWritableFileTest.php
new file mode 100644
index 000000000..686a420b6
--- /dev/null
+++ b/tests/Hamcrest/File/IsWritableFileTest.php
@@ -0,0 +1,98 @@
+
+ */
+
+namespace Hamcrest\File;
+
+use Hamcrest\AbstractMatcherTest;
+
+class IsWritableFileTest extends AbstractMatcherTest
+{
+ private static $WRITABLE_FILE_PATH;
+
+ private static $WRITABLE_FILE;
+ private static $NON_WRITABLE_FILE;
+
+ /**
+ * @beforeClass
+ */
+ public static function initializeFiles()
+ {
+ self::$WRITABLE_FILE_PATH = __FILE__;
+
+ self::$WRITABLE_FILE = new \SplFileInfo(self::$WRITABLE_FILE_PATH);
+
+ self::$NON_WRITABLE_FILE = new class('/tmp/non-writable') extends \SplFileInfo {
+ public function isWritable()
+ {
+ return false;
+ }
+ };
+ }
+
+ protected function createMatcher()
+ {
+ return IsWritableFile::aWritableFile();
+ }
+
+ public function testMatchesAWritableFile()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$WRITABLE_FILE,
+ "should match a file that is writable"
+ );
+ }
+
+ public function testMatchesAWritableFilePath()
+ {
+ $this->assertMatches(
+ $this->createMatcher(),
+ self::$WRITABLE_FILE_PATH,
+ "should match a path to file that is writable"
+ );
+ }
+
+ public function testDoesNotMatchAFileThatIsNotWritable()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ self::$NON_WRITABLE_FILE,
+ "should not match a file that is not writable"
+ );
+ }
+
+ public function testDoesNotMatchNull()
+ {
+ $this->assertDoesNotMatch(
+ $this->createMatcher(),
+ null,
+ 'should not match null'
+ );
+ }
+
+ public function testHasAReadableDescription()
+ {
+ $this->assertDescription('a writable file', $this->createMatcher());
+ }
+
+ public function testHasAReadableMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ '<' . self::$NON_WRITABLE_FILE . '> cannot be written to',
+ $this->createMatcher(),
+ self::$NON_WRITABLE_FILE
+ );
+ }
+
+ public function testHasAReadableTypeMissmatchDescription()
+ {
+ $this->assertMismatchDescription(
+ 'was ',
+ $this->createMatcher(),
+ new \stdClass()
+ );
+ }
+}