diff --git a/Algorithm/Maze/MazeGenerator.php b/Algorithm/Maze/MazeGenerator.php index c559e5495..4fce9db3c 100644 --- a/Algorithm/Maze/MazeGenerator.php +++ b/Algorithm/Maze/MazeGenerator.php @@ -63,7 +63,7 @@ class MazeGenerator } } - while (0 < $n) { + while ($n > 0) { $potential = [ [$pos[0] + 1, $pos[1]], [$pos[0], $pos[1] + 1], @@ -97,7 +97,6 @@ class MazeGenerator $pos = \array_pop($path); if ($pos === null) { - $n = 0; break; } } diff --git a/Localization/Localization.php b/Localization/Localization.php index a5d9ea22c..f59915d71 100644 --- a/Localization/Localization.php +++ b/Localization/Localization.php @@ -256,7 +256,7 @@ class Localization implements \JsonSerializable $files = \glob(__DIR__ . '/../Localization/Defaults/Definitions/' . $langCode . '_' . $countryCode . '*'); if ($files === false) { - $files = []; + $files = []; // @codeCoverageIgnore } foreach ($files as $file) { diff --git a/Localization/Money.php b/Localization/Money.php index aadcd4428..a6be947f2 100644 --- a/Localization/Money.php +++ b/Localization/Money.php @@ -203,7 +203,7 @@ final class Money implements \Serializable $right = \substr($value, -self::MAX_DECIMALS); if ($right === false) { - throw new \Exception(); + throw new \Exception(); // @codeCoverageIgnore } return ($decimals > 0) ? \number_format((float) $left, 0, $this->decimal, $this->thousands) . $this->decimal . \substr($right, 0, $decimals) : \str_pad($left, 1, '0'); diff --git a/Math/Statistic/Forecast/Error.php b/Math/Statistic/Forecast/Error.php index a3768aeae..0a06dcc90 100644 --- a/Math/Statistic/Forecast/Error.php +++ b/Math/Statistic/Forecast/Error.php @@ -125,6 +125,26 @@ final class Error return MeasureOfDispersion::meanAbsoluteDeviation($errors); } + /** + * Get mean absolute deviation (MAD). + * + * @param array $observed Observed values + * @param array $forecasted Forecasted values + * + * @return float + * + * @since 1.0.0 + */ + public static function getMeanAbsoulteDeviation(array $observed, array $forecasted) : float + { + $deviation = 0.0; + foreach ($observed as $key => $value) { + $deviation += \abs($value - $forecasted[$key]); + } + + return $deviation / \count($observed); + } + /** * Get mean squared error (MSE). * @@ -209,62 +229,6 @@ final class Error return 1 - (1 - $R) * ($observations - 1) / ($observations - $predictors - 1); } - /** - * Get Aike's information criterion (AIC) - * - * @param float $sse SSE - * @param int $observations Amount of observations - * @param int $predictors Amount of predictors - * - * @return float - * - * @todo Orange-Management/phpOMS#167 - * Create unit test. - * - * @since 1.0.0 - */ - public static function getAkaikeInformationCriterion(float $sse, int $observations, int $predictors) : float - { - return $observations * \log($sse / $observations) + 2 * ($predictors + 2); - } - - /** - * Get corrected Aike's information criterion (AIC) - * - * Correction for small amount of observations - * - * @param float $aic AIC - * @param int $observations Amount of observations - * @param int $predictors Amount of predictors - * - * @return float - * - * @since 1.0.0 - */ - public static function getCorrectedAkaikeInformationCriterion(float $aic, int $observations, int $predictors) : float - { - return $aic + (2 * ($predictors + 2) * ($predictors + 3)) / ($observations - $predictors - 3); - } - - /** - * Get Bayesian information criterion (BIC) - * - * @param float $sse SSE - * @param int $observations Amount of observations - * @param int $predictors Amount of predictors - * - * @return float - * - * @todo Orange-Management/phpOMS#168 - * Create unit test. - * - * @since 1.0.0 - */ - public static function getSchwarzBayesianInformationCriterion(float $sse, int $observations, int $predictors) : float - { - return $observations * \log($sse / $observations) + ($predictors + 2) * \log($observations); - } - /** * Get mean absolute percentage error (MAPE). * @@ -273,9 +237,6 @@ final class Error * * @return float * - * @todo Orange-Management/phpOMS#169 - * Create unit test. - * * @since 1.0.0 */ public static function getMeanAbsolutePercentageError(array $observed, array $forecasted) : float @@ -291,9 +252,6 @@ final class Error * * @return float * - * @todo Orange-Management/phpOMS#170 - * Create unit test. - * * @since 1.0.0 */ public static function getSymmetricMeanAbsolutePercentageError(array $observed, array $forecasted) : float @@ -301,62 +259,12 @@ final class Error $error = []; foreach ($observed as $key => $value) { - $error[] = 200 * \abs($value - $forecasted[$key]) / ($value + $forecasted[$key]); + $error[] = \abs($value - $forecasted[$key]) / ($value + $forecasted[$key]) / 2; } return Average::arithmeticMean($error); } - /** - * Get cross sectional scaled errors (CSSE) - * - * @param array $errors Errors - * @param float[] $observed Dataset - * - * @return float[] - * - * @todo Orange-Management/phpOMS#172 - * Create unit test. - * - * @since 1.0.0 - */ - public static function getCrossSectionalScaledErrorArray(array $errors, array $observed) : array - { - $scaled = []; - $deviation = MeasureOfDispersion::meanDeviation($observed); - - foreach ($errors as $error) { - $scaled[] = $error / $deviation; - } - - return $scaled; - } - - /** - * Get cross sectional scaled errors (CSSE) - * - * @param float $error Errors - * @param float[] $observed Dataset - * - * @return float - * - * @todo Orange-Management/phpOMS#171 - * Create unit test. - * - * @since 1.0.0 - */ - public static function getCrossSectionalScaledError(float $error, array $observed) : float - { - $mean = Average::arithmeticMean($observed); - $sum = 0.0; - - foreach ($observed as $value) { - $sum += \abs($value - $mean); - } - - return $error / MeasureOfDispersion::meanDeviation($observed); - } - /** * Get mean absolute scaled error (MASE) * @@ -372,15 +280,12 @@ final class Error } /** - * Get mean absolute scaled error (MSSE) + * Get mean squared scaled error (MSSE) * * @param array $scaledErrors Scaled errors * * @return float * - * @todo Orange-Management/phpOMS#173 - * Create unit test. - * * @since 1.0.0 */ public static function getMeanSquaredScaledError(array $scaledErrors) : float diff --git a/Math/Statistic/MeasureOfDispersion.php b/Math/Statistic/MeasureOfDispersion.php index f87fd4e7d..7e3d2245e 100644 --- a/Math/Statistic/MeasureOfDispersion.php +++ b/Math/Statistic/MeasureOfDispersion.php @@ -352,7 +352,7 @@ final class MeasureOfDispersion } /** - * Get mean absolute deviation. + * Get mean absolute deviation (MAD). * * @param array $x Values * @param float $mean Mean diff --git a/System/File/DirectoryInterface.php b/System/File/DirectoryInterface.php index 37837abc6..c3693cc26 100644 --- a/System/File/DirectoryInterface.php +++ b/System/File/DirectoryInterface.php @@ -43,11 +43,20 @@ interface DirectoryInterface extends \ArrayAccess, \Iterator, ContainerInterface /** * Add file or directory. * - * @param mixed $file File to add + * @param ContainerInterface $file File to add * - * @return bool + * @return self * * @since 1.0.0 */ - public function addNode($file) : bool; + public function addNode(ContainerInterface $file) : self; + + /** + * Get files in directory. + * + * @return array + * + * @since 1.0.0 + */ + public function getList() : array; } diff --git a/System/File/FileUtils.php b/System/File/FileUtils.php index ad2524369..4b62aaafc 100644 --- a/System/File/FileUtils.php +++ b/System/File/FileUtils.php @@ -128,7 +128,7 @@ final class FileUtils } elseif (!empty($path)) { \array_pop($path); } else { - throw new PathException($origPath); + throw new PathException($origPath); // @codeCoverageIgnore } } @@ -138,23 +138,25 @@ final class FileUtils /** * Change encoding of file * - * @param string $file Path to file which should be re-encoded - * @param string $encoding New file encoding + * @param string $input Path to file which should be re-encoded + * @param string $output Output file path + * @param string $outputEncoding New file encoding + * @param string $inputEncoding Old file encoding * * @return void * * @since 1.0.0 */ - public static function changeFileEncoding(string $file, string $encoding) : void + public static function changeFileEncoding(string $input, string $output, string $outputEncoding, string $inputEncoding = '') : void { - $content = \file_get_contents($file); + $content = \file_get_contents($input); if ($content === false) { - return; + return; // @codeCoverageIgnore } - $detected = \mb_detect_encoding($content); - \file_put_contents($file, \mb_convert_encoding($content, $encoding, $detected === false ? \mb_list_encodings() : $detected)); + $detected = empty($inputEncoding) ? \mb_detect_encoding($content) : $inputEncoding; + \file_put_contents($output, \mb_convert_encoding($content, $outputEncoding, $detected === false ? \mb_list_encodings() : $detected)); } /** diff --git a/System/File/Ftp/Directory.php b/System/File/Ftp/Directory.php index 143c4331f..0c60d85f8 100644 --- a/System/File/Ftp/Directory.php +++ b/System/File/Ftp/Directory.php @@ -546,13 +546,15 @@ class Directory extends FileAbstract implements DirectoryInterface, FtpContainer /** * {@inheritdoc} */ - public function addNode($file) : bool + public function addNode(ContainerInterface $node) : self { - $this->count += $file->getCount(); - $this->size += $file->getSize(); - $this->nodes[$file->getName()] = $file; + $this->count += $node->getCount(); + $this->size += $node->getSize(); + $this->nodes[$node->getName()] = $node; - return $file->createNode(); + $node->createNode(); + + return $this; } /** @@ -691,4 +693,12 @@ class Directory extends FileAbstract implements DirectoryInterface, FtpContainer return 0; } + + /** + * {@inheritdoc} + */ + public function getList() : array + { + return []; + } } diff --git a/System/File/Local/Directory.php b/System/File/Local/Directory.php index e3f9129c3..7a0765fdc 100644 --- a/System/File/Local/Directory.php +++ b/System/File/Local/Directory.php @@ -47,6 +47,14 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC */ private array $nodes = []; + /** + * Is directory initialized + * + * @var bool + * @since 1.0.0 + */ + private bool $isInitialized = false; + /** * Constructor. * @@ -55,12 +63,12 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC * * @since 1.0.0 */ - public function __construct(string $path, string $filter = '*') + public function __construct(string $path, string $filter = '*', bool $initialize = true) { $this->filter = \ltrim($filter, '\\/'); parent::__construct($path); - if (\file_exists($this->path)) { + if ($initialize && \file_exists($this->path)) { $this->index(); } } @@ -85,7 +93,8 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC $path = \rtrim($path, '\\/'); $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), - \RecursiveIteratorIterator::SELF_FIRST); + \RecursiveIteratorIterator::SELF_FIRST + ); if ($filter !== '*') { $iterator = new \RegexIterator($iterator, '/' . $filter . '/i', \RecursiveRegexIterator::GET_MATCH); @@ -138,11 +147,16 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC */ public function index() : void { + if ($this->isInitialized) { + return; + } + + $this->isInitialized = true; parent::index(); foreach (\glob($this->path . \DIRECTORY_SEPARATOR . $this->filter) as $filename) { if (!StringUtils::endsWith(\trim($filename), '.')) { - $file = \is_dir($filename) ? new self($filename) : new File($filename); + $file = \is_dir($filename) ? new self($filename, '*', false) : new File($filename); $this->addNode($file); } @@ -152,13 +166,27 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC /** * {@inheritdoc} */ - public function addNode($file) : bool + public function addNode(ContainerInterface $node) : self { - $this->count += $file->getCount(); - $this->size += $file->getSize(); - $this->nodes[$file->getName()] = $file; + $this->count += $node->getCount(); + $this->size += $node->getSize(); + $this->nodes[$node->getName()] = $node; - return $file->createNode(); + $node->createNode(); + + return $this; + } + + /** + * Create node + * + * @return bool + * + * @since 1.0.0 + */ + public function createNode() : bool + { + return self::create($this->path, $this->permission, true); } /** @@ -174,7 +202,7 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC $directories = \scandir($dir); if ($directories === false) { - return $countSize; + return $countSize; // @codeCoverageIgnore } foreach ($directories as $key => $filename) { @@ -218,7 +246,7 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC $ignore[] = '..'; if ($files === false) { - return $size; + return $size; // @codeCoverageIgnore } foreach ($files as $t) { @@ -249,7 +277,7 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC $files = \scandir($path); if ($files === false) { - return false; + return false; // @codeCoverageIgnore } /* Removing . and .. */ @@ -354,6 +382,7 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC self::create($to, 0755, true); } elseif ($overwrite && \file_exists($to)) { self::delete($to); + self::create($to, 0755, true); } else { return false; } @@ -417,19 +446,11 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC */ public function getNode(string $name) : ?ContainerInterface { - return $this->nodes[$name] ?? null; - } + if (isset($this->nodes[$name]) && $this->nodes[$name] instanceof self) { + $this->nodes[$name]->index(); + } - /** - * {@inheritdoc} - */ - public function createNode() : bool - { - return self::create($this->path, $this->permission, true); - /** - * @todo Orange-Management/phpOMS#??? [p:low] [t:todo] [d:medium] - * Add node to current node list - */ + return $this->nodes[$name] ?? null; } /** @@ -453,7 +474,7 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC try { \mkdir($path, $permission, $recursive); } catch (\Throwable $t) { - return false; + return false; // @codeCoverageIgnore } return true; @@ -462,28 +483,6 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC return false; } - /** - * {@inheritdoc} - */ - public function remove(string $name) : bool - { - if (isset($this->nodes[$name])) { - $this->count -= $this->nodes[$name]->getCount(); - $this->size -= $this->nodes[$name]->getSize(); - - unset($this->nodes[$name]); - - /** - * @todo Orange-Management/phpOMS#??? [p:low] [t:question] [d:medium] - * Should this also remove the resource? \unlink(); - */ - - return true; - } - - return false; - } - /** * {@inheritdoc} */ @@ -497,7 +496,13 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC */ public function current() { - return \current($this->nodes); + $current = \current($this->nodes); + + if (isset($current) && $current instanceof self) { + $current->index(); + } + + return $current; } /** @@ -513,7 +518,13 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC */ public function next() { - return \next($this->nodes); + $next = \next($this->nodes); + + if (isset($next) && $next instanceof self) { + $next->index(); + } + + return $next; } /** @@ -617,21 +628,44 @@ final class Directory extends FileAbstract implements DirectoryInterface, LocalC */ public function deleteNode() : bool { - return self::delete($this->path); - /** - * @todo Orange-Management/phpOMS#??? [p:low] [t:todo] [d:medium] - * Remove node from node list - */ + self::delete($this->path); + + if (!isset($this->nodes[$this->path])) { + return false; + } + + $this->count -= $this->nodes[$this->path]->getCount(); + $this->size -= $this->nodes[$this->path]->getSize(); + + unset($this->nodes[$this->path]); + + return true; } /** * {@inheritdoc} */ - public function offsetGet($offset) : void + public function offsetGet($offset) { - /** - * @todo Orange-Management/phpOMS#??? [p:low] [t:todo] [d:medium] - * Implement offsetGet() - */ + if (isset($this->nodes[$offset]) && $this->nodes[$offset] instanceof self) { + $this->nodes[$offset]->index(); + } + + return $this->nodes[$offset] ?? null; + } + + /** + * {@inheritdoc} + */ + public function getList() : array + { + $pathLength = \strlen($this->path); + $content = []; + + foreach ($this->nodes as $node) { + $content[] = \substr($node->getPath(), $pathLength + 1); + } + + return $content; } } diff --git a/System/MimeType.php b/System/MimeType.php index 96279635c..fa35149ed 100644 --- a/System/MimeType.php +++ b/System/MimeType.php @@ -2009,14 +2009,4 @@ abstract class MimeType extends Enum public const M_ZMM = 'application/vnd.handheld-entertainment+xml'; public const M_123 = 'application/vnd.lotus-1-2-3'; - - /** {@inheritdoc} */ - public static function getByName(string $name) - { - if (!self::isValidName($name)) { - return 'application/octet-stream'; - } - - return \constant('self::' . $name); - } } diff --git a/Utils/Compression/LZW.php b/Utils/Compression/LZW.php index 2adfe6682..4dd66bb2c 100644 --- a/Utils/Compression/LZW.php +++ b/Utils/Compression/LZW.php @@ -69,7 +69,7 @@ class LZW implements CompressionInterface $entry = ''; $dictSize = 256; - if (empty($compressed) || $compressed === false) { + if (empty($compressed) || $compressed === [''] || $compressed === false) { return ''; } diff --git a/Utils/Converter/Currency.php b/Utils/Converter/Currency.php index 2959b375a..659e95749 100644 --- a/Utils/Converter/Currency.php +++ b/Utils/Converter/Currency.php @@ -97,26 +97,28 @@ final class Currency */ public static function getEcbEuroRates() : array { - if (empty(self::$ecbCurrencies)) { - $request = new HttpRequest(new HttpUri('https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml')); - $request->setMethod(RequestMethod::GET); + if (!empty(self::$ecbCurrencies)) { + return self::$ecbCurrencies; + } - try { - $xml = new \SimpleXMLElement(Rest::request($request)->getBody()); + $request = new HttpRequest(new HttpUri('https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml')); + $request->setMethod(RequestMethod::GET); - if (!isset($xml->Cube)) { - throw new \Exception('Invalid xml path'); - } + try { + $xml = new \SimpleXMLElement(Rest::request($request)->getBody()); - $node = $xml->Cube->Cube->Cube; - self::$ecbCurrencies = []; - - foreach ($node as $key => $value) { - self::$ecbCurrencies[\strtoupper((string) $value->attributes()['currency'])] = (float) $value->attributes()['rate']; - } - } catch (\Throwable $t) { - self::$ecbCurrencies = []; + if (!isset($xml->Cube)) { + throw new \Exception('Invalid xml path'); // @codeCoverageIgnore } + + $node = $xml->Cube->Cube->Cube; + self::$ecbCurrencies = []; + + foreach ($node as $key => $value) { + self::$ecbCurrencies[\strtoupper((string) $value->attributes()['currency'])] = (float) $value->attributes()['rate']; + } + } catch (\Throwable $t) { + self::$ecbCurrencies = []; // @codeCoverageIgnore } return self::$ecbCurrencies; diff --git a/Utils/IO/Csv/CsvSettings.php b/Utils/IO/Csv/CsvSettings.php index 145b8411c..baf553cd2 100644 --- a/Utils/IO/Csv/CsvSettings.php +++ b/Utils/IO/Csv/CsvSettings.php @@ -35,14 +35,14 @@ class CsvSettings * * @since 1.0.0 */ - public static function getFileDelimiter($file, int $checkLines = 2, array $delimiters = [',', '\t', ';', '|', ':']) : string + public static function getFileDelimiter($file, int $checkLines = 2, array $delimiters = [',', "\t", ';', '|', ':']) : string { $results = []; $i = 0; $line = \fgets($file); if ($line === false) { - return ';'; + return ';'; // @codeCoverageIgnore } while ($line !== false && $i < $checkLines) { @@ -53,7 +53,7 @@ class CsvSettings $fields = \preg_split($regExp, $line); if ($fields === false) { - return ';'; + return ';'; // @codeCoverageIgnore } if (\count($fields) > 1) { diff --git a/Utils/IO/Zip/Tar.php b/Utils/IO/Zip/Tar.php index f50e68408..1dbe70125 100644 --- a/Utils/IO/Zip/Tar.php +++ b/Utils/IO/Zip/Tar.php @@ -46,25 +46,18 @@ class Tar implements ArchiveInterface * @var string $relative */ foreach ($sources as $source => $relative) { - if (\is_numeric($source) && \realpath($relative) !== false) { - $source = $relative; - $relative = ''; - } - - $source = \realpath($source); - - if ($source === false) { - continue; - } - - $source = \str_replace('\\', '/', $source); - - if (!\file_exists($source)) { + if (($source = \realpath($source)) === false + || ($source = \str_replace('\\', '/', $source)) === false + || !\file_exists($source) + ) { continue; } if (\is_dir($source)) { - $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source), \RecursiveIteratorIterator::SELF_FIRST); + $files = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($source), + \RecursiveIteratorIterator::SELF_FIRST + ); foreach ($files as $file) { $file = \str_replace('\\', '/', $file); @@ -103,12 +96,16 @@ class Tar implements ArchiveInterface return false; } - $destination = \str_replace('\\', '/', $destination); - $destination = \rtrim($destination, '/'); - $tar = new \PharData($source); + try { + $destination = \str_replace('\\', '/', $destination); + $destination = \rtrim($destination, '/'); + $tar = new \PharData($source); - $tar->extractTo($destination . '/'); + $tar->extractTo($destination . '/'); - return true; + return true; + } catch (\Throwable $t) { + return false; + } } } diff --git a/Utils/IO/Zip/Zip.php b/Utils/IO/Zip/Zip.php index b5cb0ce06..92ead5d82 100644 --- a/Utils/IO/Zip/Zip.php +++ b/Utils/IO/Zip/Zip.php @@ -49,25 +49,18 @@ class Zip implements ArchiveInterface * @var string $relative */ foreach ($sources as $source => $relative) { - if (\is_numeric($source) && \realpath($relative) !== false) { - $source = $relative; - $relative = ''; - } - - $source = \realpath($source); - - if ($source === false) { - continue; - } - - $source = \str_replace('\\', '/', $source); - - if (!\file_exists($source)) { + if (($source = \realpath($source)) === false + || ($source = \str_replace('\\', '/', $source)) === false + || !\file_exists($source) + ) { continue; } if (\is_dir($source)) { - $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source), \RecursiveIteratorIterator::SELF_FIRST); + $files = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($source), + \RecursiveIteratorIterator::SELF_FIRST + ); foreach ($files as $file) { $file = \str_replace('\\', '/', $file); @@ -109,13 +102,17 @@ class Zip implements ArchiveInterface $destination = \str_replace('\\', '/', $destination); $destination = \rtrim($destination, '/'); - $zip = new \ZipArchive(); - if (!$zip->open($source)) { + try { + $zip = new \ZipArchive(); + if (!$zip->open($source)) { + return false; + } + + $zip->extractTo($destination . '/'); + + return $zip->close(); + } catch (\Throwable $t) { return false; } - - $zip->extractTo($destination . '/'); - - return $zip->close(); } } diff --git a/Utils/StringCompare.php b/Utils/StringCompare.php index 5589bac95..a6a437ae5 100644 --- a/Utils/StringCompare.php +++ b/Utils/StringCompare.php @@ -94,6 +94,8 @@ final class StringCompare * * @return int * + * @todo: Consider to remove previous matches in words2. Otherwise the distance may be checked against the same word over and over. + * * @since 1.0.0 */ public static function valueWords(string $s1, string $s2) : int diff --git a/tests/Algorithm/JobScheduling/WeightedTest.php b/tests/Algorithm/JobScheduling/WeightedTest.php index 2c70fc359..ff7e15ad6 100644 --- a/tests/Algorithm/JobScheduling/WeightedTest.php +++ b/tests/Algorithm/JobScheduling/WeightedTest.php @@ -32,10 +32,12 @@ class WeightedTest extends \PHPUnit\Framework\TestCase public function testNoOverlappingScheduling() : void { $jobs = [ + new Job(10, new \DateTime('2000-01-01'), null, '0'), new Job(20, new \DateTime('2003-01-01'), new \DateTime('2010-01-01'), 'A'), new Job(50, new \DateTime('2001-01-01'), new \DateTime('2002-01-01'), 'B'), new Job(100, new \DateTime('2006-01-01'), new \DateTime('2019-01-01'), 'C'), new Job(200, new \DateTime('2002-01-01'), new \DateTime('2020-01-01'), 'D'), + new Job(300, new \DateTime('2004-01-01'), null, '1'), ]; $filtered = WeighteD::solve($jobs); @@ -48,11 +50,11 @@ class WeightedTest extends \PHPUnit\Framework\TestCase $names[] = $job->getName(); } - self::assertEqualsWithDelta(250, $value, 0.01); + self::assertEqualsWithDelta(350, $value, 0.01); self::assertTrue( \in_array('B', $names) - && \in_array('D', $names) + && \in_array('1', $names) ); } diff --git a/tests/Math/Statistic/Forecast/ErrorTest.php b/tests/Math/Statistic/Forecast/ErrorTest.php index 028685ac1..ff059adaa 100644 --- a/tests/Math/Statistic/Forecast/ErrorTest.php +++ b/tests/Math/Statistic/Forecast/ErrorTest.php @@ -16,6 +16,7 @@ namespace phpOMS\tests\Math\Statistic\Forecast; use phpOMS\Math\Statistic\Forecast\Error; use phpOMS\Math\Statistic\MeasureOfDispersion; +use phpOMS\Utils\ArrayUtils; /** * @internal @@ -93,6 +94,27 @@ class ErrorTest extends \PHPUnit\Framework\TestCase self::assertEqualsWithDelta(0.0983, Error::getMeanAbsoluteScaledError($scaledErrors), 0.01); } + public function testMSSE() : void + { + $observed = [ + -2.9, -2.83, -0.95, -0.88, 1.21, -1.67, 0.83, -0.27, 1.36, + -0.34, 0.48, -2.83, -0.95, -0.88, 1.21, -1.67, -2.99, 1.24, 0.64, + ]; + + $forecast = [ + -2.95, -2.7, -1.00, -0.68, 1.50, -1.00, 0.90, -0.37, 1.26, + -0.54, 0.58, -2.13, -0.75, -0.89, 1.25, -1.65, -3.20, 1.29, 0.60, + ]; + + $errors = Error::getForecastErrorArray($observed, $forecast); + $scaledErrors = Error::getScaledErrorArray($errors, $observed); + + self::assertEqualsWithDelta( + Error::getMeanAbsoluteScaledError(ArrayUtils::powerInt($scaledErrors, 2)), + Error::getMeanSquaredScaledError($scaledErrors), 0.01 + ); + } + public function testScaledError() : void { self::assertEquals( @@ -117,4 +139,28 @@ class ErrorTest extends \PHPUnit\Framework\TestCase self::assertEqualsWithDelta(0.922085138, Error::getAdjustedCoefficientOfDetermination(0.944346527, 8, 2), 0.001); } + + public function testMAPE() : void + { + self::assertEqualsWithDelta(0.17551, Error::getMeanAbsolutePercentageError( + [112.3, 108.4, 148.9, 117.4], + [124.7, 103.7, 116.6, 78.5], + ), 0.001); + } + + public function testSMAPE() : void + { + self::assertEqualsWithDelta(0.049338, Error::getSymmetricMeanAbsolutePercentageError( + [112.3, 108.4, 148.9, 117.4], + [124.7, 103.7, 116.6, 78.5], + ), 0.001); + } + + public function testMAD() : void + { + self::assertEqualsWithDelta(22.075, Error::getMeanAbsoulteDeviation( + [112.3, 108.4, 148.9, 117.4], + [124.7, 103.7, 116.6, 78.5], + ), 0.001); + } } diff --git a/tests/Module/PackageManagerTest.php b/tests/Module/PackageManagerTest.php index 854da5fea..4e97ef193 100644 --- a/tests/Module/PackageManagerTest.php +++ b/tests/Module/PackageManagerTest.php @@ -75,7 +75,7 @@ class PackageManagerTest extends \PHPUnit\Framework\TestCase // create zip Zip::pack( [ - __DIR__ . '/testPackage', + __DIR__ . '/testPackage' => __DIR__ . '/testPackage', ], __DIR__ . '/testPackage.zip' ); diff --git a/tests/Stdlib/Base/LocationTest.php b/tests/Stdlib/Base/LocationTest.php index 7b69a876a..64560e06e 100644 --- a/tests/Stdlib/Base/LocationTest.php +++ b/tests/Stdlib/Base/LocationTest.php @@ -212,5 +212,6 @@ class LocationTest extends \PHPUnit\Framework\TestCase $this->location->setGeo(['lat' => 12.1, 'long' => 11.2,]); self::assertEquals($expected, $this->location->jsonSerialize()); + self::assertEquals(\json_encode($this->location->jsonSerialize()), $this->location->serialize()); } } diff --git a/tests/System/File/FileUtilsTest.php b/tests/System/File/FileUtilsTest.php index d7aa74a89..d0931aae7 100644 --- a/tests/System/File/FileUtilsTest.php +++ b/tests/System/File/FileUtilsTest.php @@ -68,8 +68,25 @@ class FileUtilsTest extends \PHPUnit\Framework\TestCase self::assertEquals(0742, FileUtils::permissionToOctal('rwxr---w-')); } + /** + * @testdox The encoding of a file can be changed + * @covers phpOMS\System\File\FileUtils + * @group framework + */ public function testChangeFileEncoding() : void { - self::markTestIncomplete(); + if (\file_exists(__DIR__ . '/UTF-8.txt')) { + \unlink(__DIR__ . '/UTF-8.txt'); + } + + FileUtils::changeFileEncoding(__DIR__ . '/Windows-1252.txt', __DIR__ . '/UTF-8.txt', 'UTF-8', 'Windows-1252'); + + self::assertFileExists(__DIR__ . '/UTF-8.txt'); + self::assertNotEquals("This is a test file with some¶\ncontent Ø Æ.", \file_get_contents(__DIR__ . '/Windows-1252.txt')); + self::assertEquals("This is a test file with some¶\ncontent Ø Æ.", \file_get_contents(__DIR__ . '/UTF-8.txt')); + + if (\file_exists(__DIR__ . '/UTF-8.txt')) { + \unlink(__DIR__ . '/UTF-8.txt'); + } } } diff --git a/tests/System/File/Local/DirectoryTest.php b/tests/System/File/Local/DirectoryTest.php index a73790553..88cf15dea 100644 --- a/tests/System/File/Local/DirectoryTest.php +++ b/tests/System/File/Local/DirectoryTest.php @@ -37,6 +37,11 @@ class DirectoryTest extends \PHPUnit\Framework\TestCase \rmdir($dirPath); } + public function testStaticRemove() : void + { + self::markTestIncomplete(); + } + /** * @testdox A directory can be checked for existence * @covers phpOMS\System\File\Local\Directory @@ -277,6 +282,36 @@ class DirectoryTest extends \PHPUnit\Framework\TestCase Directory::delete(__DIR__ . '/newdirtest'); } + /** + * @testdox A directory can be forced to be copied to a different location even if the destination already exists + * @covers phpOMS\System\File\Local\Directory + * @group framework + */ + public function testStaticCopyOverwrite() : void + { + $dirTestPath = __DIR__ . '/dirtest'; + self::assertTrue(Directory::copy($dirTestPath, __DIR__ . '/newdirtest')); + self::assertFalse(Directory::copy($dirTestPath, __DIR__ . '/newdirtest', false)); + self::assertTrue(Directory::copy($dirTestPath, __DIR__ . '/newdirtest', true)); + self::assertFileExists(__DIR__ . '/newdirtest/sub/path/test3.txt'); + + Directory::delete(__DIR__ . '/newdirtest'); + } + + /** + * @testdox By default a directory is not overwritten on copy + * @covers phpOMS\System\File\Local\Directory + * @group framework + */ + public function testStaticInvalidCopyOverwrite() : void + { + $dirTestPath = __DIR__ . '/dirtest'; + self::assertTrue(Directory::copy($dirTestPath, __DIR__ . '/newdirtest')); + self::assertFalse(Directory::copy($dirTestPath, __DIR__ . '/newdirtest', false)); + + Directory::delete(__DIR__ . '/newdirtest'); + } + /** * @testdox A directory can be moved/renamed to a different path * @covers phpOMS\System\File\Local\Directory @@ -286,8 +321,42 @@ class DirectoryTest extends \PHPUnit\Framework\TestCase { $dirTestPath = __DIR__ . '/dirtest'; + self::assertTrue(Directory::move($dirTestPath, __DIR__ . '/parent/newdirtest')); + self::assertFileExists(__DIR__ . '/parent/newdirtest/sub/path/test3.txt'); + + Directory::move(__DIR__ . '/parent/newdirtest', $dirTestPath); + \rmdir(__DIR__ . '/parent'); + } + + /** + * @testdox By default a directory is not overwritten on move + * @covers phpOMS\System\File\Local\Directory + * @group framework + */ + public function testStaticInvalidMoveOverwrite() : void + { + $dirTestPath = __DIR__ . '/dirtest'; + self::assertTrue(Directory::move($dirTestPath, __DIR__ . '/newdirtest')); - self::assertFileExists(__DIR__ . '/newdirtest/sub/path/test3.txt'); + self::assertFalse(Directory::move(__DIR__ . '/newdirtest', __DIR__ . '/newdirtest', false)); + + Directory::move(__DIR__ . '/newdirtest', $dirTestPath); + } + + /** + * @testdox A directory can be forced to be moved/renamed to a different path even if the destination already exists + * @covers phpOMS\System\File\Local\Directory + * @group framework + */ + public function testStaticMoveOverwrite() : void + { + $dirTestPath = __DIR__ . '/dirtest'; + + self::assertTrue(Directory::move($dirTestPath, __DIR__ . '/newdirtest')); + + self::assertTrue(Directory::copy(__DIR__ . '/newdirtest', $dirTestPath)); + self::assertFalse(Directory::move($dirTestPath, __DIR__ . '/newdirtest', false)); + self::assertTrue(Directory::move($dirTestPath, __DIR__ . '/newdirtest', true)); Directory::move(__DIR__ . '/newdirtest', $dirTestPath); } @@ -334,6 +403,7 @@ class DirectoryTest extends \PHPUnit\Framework\TestCase { $dirTestPath = __DIR__ . '/dirtest'; self::assertCount(6, Directory::list($dirTestPath)); + self::assertEquals(['sub/test2.txt', 'sub/test4.md', 'sub/path/test3.txt'], Directory::list($dirTestPath, 'test[0-9]+.*')); } /** @@ -347,6 +417,27 @@ class DirectoryTest extends \PHPUnit\Framework\TestCase self::assertCount(3, Directory::listByExtension($dirTestPath, 'txt')); } + /** + * @testdox The owner of a directory can be returned + * @covers phpOMS\System\File\Local\Directory + * @group framework + */ + public function testStaticOwner() : void + { + $dirTestPath = __DIR__ . '/dirtest'; + self::assertNotEmpty(Directory::owner($dirTestPath)); + } + + /** + * @testdox Invalid directory names and paths can be sanitized + * @covers phpOMS\System\File\Local\Directory + * @group framework + */ + public function testDirectoryNameSanitizing() : void + { + self::assertEquals(':/some/test/[path', Directory::sanitize(':#&^$/some%/test/[path!')); + } + /** * @testdox A none-existing directory returns a empty list of files and sub-directories * @covers phpOMS\System\File\Local\Directory @@ -422,4 +513,139 @@ class DirectoryTest extends \PHPUnit\Framework\TestCase Directory::owner(__DIR__ . '/invalid'); } + + public function testList() : void + { + $dirTestPath = __DIR__ . '/dirtest'; + $dir = new Directory($dirTestPath); + + self::assertEquals([ + 'sub', + 'test.txt' + ], $dir->getList()); + } + + public function testNodeOutput() : void + { + $dirTestPath = __DIR__ . '/dirtest'; + $dir = new Directory($dirTestPath); + + self::assertInstanceOf(Directory::class, $dir->getNode('sub')); + } + + public function testNodeCreate() : void + { + $dir = new Directory(__DIR__); + $dir->addNode(new Directory(__DIR__ . '/nodedir')); + + self::assertTrue(\file_exists(__DIR__ . '/nodedir')); + \rmdir(__DIR__ . '/nodedir'); + + $dir = new Directory(__DIR__ . '/nodedir2'); + $dir->createNode(); + + self::assertTrue(\file_exists(__DIR__ . '/nodedir2')); + \rmdir(__DIR__ . '/nodedir2'); + } + + public function testNodeDelete() : void + { + $dir = new Directory(__DIR__); + $dir->addNode(new Directory(__DIR__ . '/nodedir')); + + self::assertTrue(\file_exists(__DIR__ . '/nodedir')); + self::assertTrue($dir->deleteNode()); + self::assertFalse(\file_exists(__DIR__ . '/nodedir')); + } + + public function testNodeCopy() : void + { + self::markTestIncomplete(); + } + + public function testNodeMove() : void + { + self::markTestIncomplete(); + } + + public function testNodeExists() : void + { + self::markTestIncomplete(); + } + + public function testParentOutput() : void + { + self::markTestIncomplete(); + } + + + public function testNodeNext() : void + { + self::markTestIncomplete(); + } + + public function testNodeCurrent() : void + { + self::markTestIncomplete(); + } + + public function testNodeKey() : void + { + self::markTestIncomplete(); + } + + public function testNodeArrayRead() : void + { + self::markTestIncomplete(); + } + + public function testNodeArraySet() : void + { + self::markTestIncomplete(); + } + + public function testNodeArrayRemove() : void + { + self::markTestIncomplete(); + } + + public function testNodeArrayExists() : void + { + self::markTestIncomplete(); + } + + public function testNodeCreatedAt() : void + { + self::markTestIncomplete(); + } + + public function testNodeChangedAt() : void + { + self::markTestIncomplete(); + } + + public function testNodeOwner() : void + { + self::markTestIncomplete(); + } + + public function testNodePermission() : void + { + self::markTestIncomplete(); + } + + public function testDirname() : void + { + self::markTestIncomplete(); + } + + public function testName() : void + { + self::markTestIncomplete(); + } + + public function testDirpath() : void + { + self::markTestIncomplete(); + } } diff --git a/tests/System/File/Windows-1252.txt b/tests/System/File/Windows-1252.txt new file mode 100644 index 000000000..b47915684 --- /dev/null +++ b/tests/System/File/Windows-1252.txt @@ -0,0 +1,2 @@ +This is a test file with some¶ +content Ø Æ. \ No newline at end of file diff --git a/tests/Utils/Compression/LZWTest.php b/tests/Utils/Compression/LZWTest.php index 6f87f331d..3ca365e3a 100644 --- a/tests/Utils/Compression/LZWTest.php +++ b/tests/Utils/Compression/LZWTest.php @@ -33,5 +33,6 @@ class LZWTest extends \PHPUnit\Framework\TestCase $expected = 'This is a test'; $compression = new LZW(); self::assertEquals($expected, $compression->decompress($compression->compress($expected))); + self::assertEquals('', $compression->decompress('')); } } diff --git a/tests/Utils/Converter/CurrencyTest.php b/tests/Utils/Converter/CurrencyTest.php index 344605bc4..bf70b39ca 100644 --- a/tests/Utils/Converter/CurrencyTest.php +++ b/tests/Utils/Converter/CurrencyTest.php @@ -16,6 +16,10 @@ namespace phpOMS\tests\Utils\Converter; use phpOMS\Localization\ISO4217CharEnum; use phpOMS\Utils\Converter\Currency; +use phpOMS\Message\Http\HttpRequest; +use phpOMS\Uri\HttpUri; +use phpOMS\Message\Http\RequestMethod; +use phpOMS\Message\Http\Rest; /** * @testdox phpOMS\tests\Utils\Converter\CurrencyTest: Currency converter @@ -24,11 +28,33 @@ use phpOMS\Utils\Converter\Currency; */ class CurrencyTest extends \PHPUnit\Framework\TestCase { + private static $reachable; + + protected function setUp() : void + { + if (!isset(self::$reachable)) { + try { + $request = new HttpRequest(new HttpUri('https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml')); + $request->setMethod(RequestMethod::GET); + + Rest::request($request)->getBody(); + self::$reachable = true; + } catch (\Throwable $t) { + self::$reachable = false; + } + } + + if (!self::$reachable) { + $this->markTestSkipped( + 'External currency conversion not available.' + ); + } + } + /** * @testdox A currency can be converted from euro to another currency * @covers phpOMS\Utils\Converter\Currency * @group framework - * @group maybe */ public function testCurrencyFromEur() : void { @@ -39,7 +65,6 @@ class CurrencyTest extends \PHPUnit\Framework\TestCase * @testdox A currency can be converted to euro from another currency * @covers phpOMS\Utils\Converter\Currency * @group framework - * @group maybe */ public function testCurrencyToEur() : void { @@ -50,7 +75,6 @@ class CurrencyTest extends \PHPUnit\Framework\TestCase * @testdox A currency can be converted from one currency to another currency * @covers phpOMS\Utils\Converter\Currency * @group framework - * @group maybe */ public function testCurrency() : void { @@ -62,7 +86,6 @@ class CurrencyTest extends \PHPUnit\Framework\TestCase * @testdox A currency conversion from eur to a invalid currency throws a InvalidArgumentException * @covers phpOMS\Utils\Converter\Currency * @group framework - * @group maybe */ public function testInvalidFromEur() : void { @@ -75,7 +98,6 @@ class CurrencyTest extends \PHPUnit\Framework\TestCase * @testdox A currency conversion from a invalid currency to eur throws a InvalidArgumentException * @covers phpOMS\Utils\Converter\Currency * @group framework - * @group maybe */ public function testInvalidToEur() : void { @@ -88,7 +110,6 @@ class CurrencyTest extends \PHPUnit\Framework\TestCase * @testdox A currency conversion from a invalid currency to a invalid currency throws a InvalidArgumentException * @covers phpOMS\Utils\Converter\Currency * @group framework - * @group maybe */ public function testInvalidConvert() : void { diff --git a/tests/Utils/Converter/NumericTest.php b/tests/Utils/Converter/NumericTest.php index 199995ef9..dbbd41cb0 100644 --- a/tests/Utils/Converter/NumericTest.php +++ b/tests/Utils/Converter/NumericTest.php @@ -92,5 +92,7 @@ class NumericTest extends \PHPUnit\Framework\TestCase self::assertEquals('123', Numeric::convertBase('173', '01234567', '0123456789')); self::assertEquals('173', Numeric::convertBase('173', '01234567', '01234567')); + + self::assertEquals('2', Numeric::convertBase('2', '0123456789', '0123456789ABCDEF')); } } diff --git a/tests/Utils/Encoding/CaesarTest.php b/tests/Utils/Encoding/CaesarTest.php index 2bd188dd4..7c4966636 100644 --- a/tests/Utils/Encoding/CaesarTest.php +++ b/tests/Utils/Encoding/CaesarTest.php @@ -30,8 +30,14 @@ class CaesarTest extends \PHPUnit\Framework\TestCase */ public function testEncoding() : void { - $raw = StringUtils::generateString(1, 100); - $key = StringUtils::generateString(1, 100); + $raw = StringUtils::generateString(11, 100); + $key = StringUtils::generateString(5, 10); + + self::assertNotEquals($raw, Caesar::encode($raw, $key)); + self::assertEquals($raw, Caesar::decode(Caesar::encode($raw, $key), $key)); + + $raw = StringUtils::generateString(5, 10); + $key = StringUtils::generateString(11, 100); self::assertNotEquals($raw, Caesar::encode($raw, $key)); self::assertEquals($raw, Caesar::decode(Caesar::encode($raw, $key), $key)); diff --git a/tests/Utils/IO/Zip/TarGzTest.php b/tests/Utils/IO/Zip/TarGzTest.php index 9584bd4da..da350b729 100644 --- a/tests/Utils/IO/Zip/TarGzTest.php +++ b/tests/Utils/IO/Zip/TarGzTest.php @@ -109,6 +109,15 @@ class TarGzTest extends \PHPUnit\Framework\TestCase )); \unlink(__DIR__ . '/test2.tar.gz'); + + self::assertFalse(TarGz::pack( + [ + __DIR__ . '/test a.txt' => 'test a.txt', + __DIR__ . '/test b.md' => 'test b.md', + __DIR__ . '/test' => 'test', + ], + __DIR__ . '/invalidpack.tar.gz' + )); } /** @@ -139,7 +148,17 @@ class TarGzTest extends \PHPUnit\Framework\TestCase TarGz::unpack(__DIR__ . '/abc/test3.tar.gz', __DIR__); self::assertFalse(TarGz::unpack(__DIR__ . '/abc/test3.tar.gz', __DIR__)); - \unlink(__DIR__ . '/test3.tar.gz'); + + self::assertTrue(TarGz::pack( + [ + __DIR__ . '/test a.txt' => 'test a.txt', + __DIR__ . '/test b.md' => 'test b.md', + __DIR__ . '/test' => 'test', + ], + __DIR__ . '/invalidunpack.tar.gz' + )); + self::assertFalse(TarGz::unpack(__DIR__ . '/invalidunpack.tar.gz', __DIR__)); + \unlink(__DIR__ . '/invalidunpack.tar.gz'); } } diff --git a/tests/Utils/IO/Zip/TarTest.php b/tests/Utils/IO/Zip/TarTest.php index 67df17d87..786a3c6b5 100644 --- a/tests/Utils/IO/Zip/TarTest.php +++ b/tests/Utils/IO/Zip/TarTest.php @@ -83,6 +83,24 @@ class TarTest extends \PHPUnit\Framework\TestCase \unlink(__DIR__ . '/test.tar'); } + /** + * @testdox Extracting invalid tar files fail + * @covers phpOMS\Utils\IO\Zip\Tar + * @group framework + */ + public function testInvalidTarUnpack() : void + { + self::assertFalse(Tar::unpack( + __DIR__ . '/invalid.tar', + __DIR__ + )); + + self::assertFalse(Tar::unpack( + __DIR__ . '/test a.txt', + __DIR__ + )); + } + /** * @testdox A tar archive cannot be overwritten by default * @covers phpOMS\Utils\IO\Zip\Tar diff --git a/tests/Utils/IO/Zip/ZipTest.php b/tests/Utils/IO/Zip/ZipTest.php index 9dfc5d681..937d9b6d9 100644 --- a/tests/Utils/IO/Zip/ZipTest.php +++ b/tests/Utils/IO/Zip/ZipTest.php @@ -43,6 +43,7 @@ class ZipTest extends \PHPUnit\Framework\TestCase [ __DIR__ . '/test a.txt' => 'test a.txt', __DIR__ . '/test b.md' => 'test b.md', + __DIR__ . '/invalid.so' => 'invalid.so', __DIR__ . '/test' => 'test', ], __DIR__ . '/test.zip' @@ -83,6 +84,41 @@ class ZipTest extends \PHPUnit\Framework\TestCase \unlink(__DIR__ . '/test.zip'); } + /** + * @testdox The output of the zip archive needs to be properly defined + * @covers phpOMS\Utils\IO\Zip\Zip + * @group framework + */ + public function testInvalidZipDestination() : void + { + self::assertFalse(Zip::pack( + [ + __DIR__ . '/test a.txt' => 'test a.txt', + __DIR__ . '/test b.md' => 'test b.md', + __DIR__ . '/test' => 'test', + ], + __DIR__ + )); + } + + /** + * @testdox Extracting invalid zip files fail + * @covers phpOMS\Utils\IO\Zip\Zip + * @group framework + */ + public function testInvalidZipUnpack() : void + { + self::assertFalse(Zip::unpack( + __DIR__ . '/invalid.zip', + __DIR__ + )); + + self::assertFalse(Zip::unpack( + __DIR__ . '/test a.txt', + __DIR__ + )); + } + /** * @testdox A zip archive cannot be overwritten by default * @covers phpOMS\Utils\IO\Zip\Zip diff --git a/tests/Utils/IO/Zip/invalidpack.tar.gz.tmp b/tests/Utils/IO/Zip/invalidpack.tar.gz.tmp new file mode 100644 index 000000000..e69de29bb diff --git a/tests/Utils/IO/Zip/invalidunpack.tmp b/tests/Utils/IO/Zip/invalidunpack.tmp new file mode 100644 index 000000000..e69de29bb diff --git a/tests/Utils/StringCompareTest.php b/tests/Utils/StringCompareTest.php index a688d6a1b..d5f2d5a03 100644 --- a/tests/Utils/StringCompareTest.php +++ b/tests/Utils/StringCompareTest.php @@ -80,4 +80,18 @@ class StringCompareTest extends \PHPUnit\Framework\TestCase $this->dict->add('Carton'); self::assertEquals('Carton', $this->dict->matchDictionary('carton')); } + + /** + * @testdox Two texts can be compared on a per word basis for similarity + * @covers phpOMS\Utils\StringCompare + * @group framework + */ + public function testValueWords() : void + { + // every word in s1 is found in s2, therefore a "perfect" match + self::assertEquals(0, StringCompare::valueWords('This is a test', 'This is not a test')); + + // a is compared to is which has a distance of 2 + self::assertEquals(2, StringCompare::valueWords('This is a test', 'This is not test')); + } } diff --git a/tests/Utils/TaskSchedule/SchedulerFactoryTest.php b/tests/Utils/TaskSchedule/SchedulerFactoryTest.php index 7e1f85653..34dce5104 100644 --- a/tests/Utils/TaskSchedule/SchedulerFactoryTest.php +++ b/tests/Utils/TaskSchedule/SchedulerFactoryTest.php @@ -27,7 +27,7 @@ class SchedulerFactoryTest extends \PHPUnit\Framework\TestCase { /** * @testdox The correct scheduler is crated depending on the operating system - * @covers phpOMS\Utils\TaskSchedule\SchedulerAbstract + * @covers phpOMS\Utils\TaskSchedule\SchedulerFactory * @group framework */ public function testCreate() : void diff --git a/tests/Utils/TaskSchedule/TaskAbstractTest.php b/tests/Utils/TaskSchedule/TaskAbstractTest.php index bf55bc882..457d3e168 100644 --- a/tests/Utils/TaskSchedule/TaskAbstractTest.php +++ b/tests/Utils/TaskSchedule/TaskAbstractTest.php @@ -15,6 +15,7 @@ declare(strict_types=1); namespace phpOMS\tests\Utils\TaskSchedule; use phpOMS\Utils\TaskSchedule\TaskAbstract; +use phpOMS\Utils\TaskSchedule\TaskFactory; /** * @testdox phpOMS\tests\Utils\TaskSchedule\TaskAbstractTest: Job/task abstraction @@ -35,6 +36,7 @@ class TaskAbstractTest extends \PHPUnit\Framework\TestCase public static function createWith(array $jobData) : TaskAbstract { + return TaskFactory::create(); } }; } @@ -66,6 +68,17 @@ class TaskAbstractTest extends \PHPUnit\Framework\TestCase self::assertEquals('Command', $this->class->getCommand()); } + /** + * @testdox The interval can be set and returned + * @covers phpOMS\Utils\TaskSchedule\TaskAbstract + * @group framework + */ + public function testIntervalInputOutput() : void + { + $this->class->setInterval('Interval'); + self::assertEquals('Interval', $this->class->getInterval()); + } + /** * @testdox The status can be set and returned * @covers phpOMS\Utils\TaskSchedule\TaskAbstract diff --git a/tests/Validation/ValidatorTest.php b/tests/Validation/ValidatorTest.php index 205b11cfa..33d5cbe0f 100644 --- a/tests/Validation/ValidatorTest.php +++ b/tests/Validation/ValidatorTest.php @@ -109,4 +109,21 @@ class ValidatorTest extends \PHPUnit\Framework\TestCase self::assertTrue(Validator::matches('ThisTestVar', '/TestVar/')); self::assertFalse(Validator::matches('ThisTestVar', '/ThisTest$/')); } + + public function testErrorMessage() : void + { + self::assertEquals('', Validator::getMessage()); + } + + public function testErrorCode() : void + { + self::assertEquals(0, Validator::getErrorCode()); + } + + public function testResetError() : void + { + Validator::resetError(); + self::assertEquals('', Validator::getMessage()); + self::assertEquals(0, Validator::getErrorCode()); + } }