From bbdd04b36ea9887baef1fc8bb21f67ff99785132 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 18 Apr 2020 18:33:48 +0200 Subject: [PATCH] add tests and fix bugs --- Account/NullGroup.php | 2 +- Algorithm/JobScheduling/Weighted.php | 8 ++ Application/ApplicationManager.php | 3 + DataStorage/Database/DataMapperAbstract.php | 26 +++++- DataStorage/Database/Query/Builder.php | 16 ---- Event/EventManager.php | 3 + Localization/L11nManager.php | 3 + Log/FileLogger.php | 5 ++ Message/Http/Rest.php | 2 + Router/WebRouter.php | 8 ++ Utils/IO/Zip/Tar.php | 4 + Utils/IO/Zip/Zip.php | 4 + Utils/MbStringUtils.php | 6 +- Utils/StringUtils.php | 8 +- tests/Account/NullAccountTest.php | 6 ++ .../Connection/MysqlConnectionTest.php | 4 +- .../Connection/NullConnectionTest.php | 2 +- .../Connection/PostgresConnectionTest.php | 4 +- .../Connection/SQLiteConnectionTest.php | 4 +- .../Connection/SqlServerConnectionTest.php | 4 +- .../Database/DataMapperAbstractTest.php | 86 +++++++++++++++++-- .../Exception/InvalidMapperExceptionTest.php | 3 + .../Database/Query/BuilderTest.php | 48 ++++++++++- .../Database/TestModel/BaseModel.php | 2 + .../Database/TestModel/BaseModelMapper.php | 17 ++-- .../Database/TestModel/Conditional.php | 26 ++++++ .../Database/TestModel/ConditionalMapper.php | 57 ++++++++++++ tests/Math/Statistic/AverageTest.php | 19 +++- tests/Math/Topology/MetricsNDTest.php | 86 ++++++++++++++++++- tests/Message/Http/HttpRequestTest.php | 2 +- tests/Module/ModuleAbstractTest.php | 11 +++ tests/Utils/MbStringUtilsTest.php | 21 +++++ 32 files changed, 452 insertions(+), 48 deletions(-) create mode 100644 tests/DataStorage/Database/TestModel/Conditional.php create mode 100644 tests/DataStorage/Database/TestModel/ConditionalMapper.php diff --git a/Account/NullGroup.php b/Account/NullGroup.php index 0baee204f..ef3fae2b4 100644 --- a/Account/NullGroup.php +++ b/Account/NullGroup.php @@ -15,7 +15,7 @@ declare(strict_types=1); namespace phpOMS\Account; /** - * Null account class. + * Null group class. * * @package phpOMS\Account * @license OMS License 1.0 diff --git a/Algorithm/JobScheduling/Weighted.php b/Algorithm/JobScheduling/Weighted.php index fefb88d42..673ed5ffa 100644 --- a/Algorithm/JobScheduling/Weighted.php +++ b/Algorithm/JobScheduling/Weighted.php @@ -42,6 +42,10 @@ final class Weighted * * @return int * + * @todo Orange-Management/phpOMS#243 + * [JobScheduling] Implement sortByEnd test coverage + * All 3 if cases are not covered. Implement the tests! + * * @since 1.0.0 */ private static function sortByEnd(JobInterface $j1, JobInterface $j2) : int @@ -104,6 +108,10 @@ final class Weighted * * @return JobInterface[] * + * @todo Orange-Management/phpOMS#244 + * [JobScheduling] Implement test for Jobs with same value. + * There is no test case for the else clause in the `solve` function. Implement it. + * * @since 1.0.0 */ public static function solve(array $jobs) : array diff --git a/Application/ApplicationManager.php b/Application/ApplicationManager.php index 20a8db4d9..6d2c01c22 100644 --- a/Application/ApplicationManager.php +++ b/Application/ApplicationManager.php @@ -91,6 +91,9 @@ final class ApplicationManager * * @return void * + * @todo Orange-Management/phpOMS#245 + * [ApplicationManager] Implement test for invalid source and invalid destination + * * @since 1.0.0 */ public function install(string $source, string $destination) : void diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index 9266f3492..31305b80d 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -763,7 +763,12 @@ class DataMapperAbstract implements DataMapperInterface throw new InvalidMapperException(); } - $values = $obj[$propertyName]; + $values = $obj[$propertyName] ?? null; + + if (!\is_array($values)) { + // conditionals + continue; + } /** @var self $mapper */ $mapper = static::$hasMany[$propertyName]['mapper']; @@ -1028,6 +1033,11 @@ class DataMapperAbstract implements DataMapperInterface $values = $property->getValue($obj); + if (!\is_array($values)) { + // conditionals + continue; + } + if (!$isPublic) { $property->setAccessible(false); } @@ -1109,7 +1119,12 @@ class DataMapperAbstract implements DataMapperInterface throw new InvalidMapperException(); } - $values = $obj[$propertyName]; + $values = $obj[$propertyName] ?? null; + + if (!\is_array($values)) { + // conditionals + continue; + } /** @var self $mapper */ $mapper = static::$hasMany[$propertyName]['mapper']; @@ -1566,6 +1581,11 @@ class DataMapperAbstract implements DataMapperInterface $values = $property->getValue($obj); + if (!\is_array($values)) { + // conditionals + continue; + } + if (!$isPublic) { $property->setAccessible(false); } @@ -2159,7 +2179,7 @@ class DataMapperAbstract implements DataMapperInterface } foreach (static::$hasMany as $member => $def) { - $column = $def['mapper']::getColumnByMember($member); + $column = $def['mapper']::getColumnByMember($def['column'] ?? $member); $alias = $column . '_' . ($depth - 1); if (!\array_key_exists($alias, $result) || !isset($def['column'])) { diff --git a/DataStorage/Database/Query/Builder.php b/DataStorage/Database/Query/Builder.php index 9bbf5e3d6..1764e1ad9 100644 --- a/DataStorage/Database/Query/Builder.php +++ b/DataStorage/Database/Query/Builder.php @@ -571,22 +571,6 @@ class Builder extends BuilderAbstract return $this; } - /** - * Get column of where condition - * - * One column can have multiple where conditions. - * - * @param mixed $column Column - * - * @return null|array - * - * @since 1.0.0 - */ - public function getWhereByColumn($column) : ?array - { - return $this->wheres[self::getPublicColumnName($column)] ?? null; - } - /** * Where and sub condition. * diff --git a/Event/EventManager.php b/Event/EventManager.php index b094021c0..260053e5c 100644 --- a/Event/EventManager.php +++ b/Event/EventManager.php @@ -152,6 +152,9 @@ final class EventManager implements \Countable * * @return bool returns true on successfully triggering the event, false if the event couldn't be triggered which also includes sub-requirements missing * + * @todo Orange-Management/phpOMS#241 + * [EventManager] Create an event with a regex id/name and trigger it + * * @since 1.0.0 */ public function trigger(string $group, string $id = '', $data = null) : bool diff --git a/Localization/L11nManager.php b/Localization/L11nManager.php index b1cfd8050..49f196557 100644 --- a/Localization/L11nManager.php +++ b/Localization/L11nManager.php @@ -249,6 +249,9 @@ final class L11nManager * * @return string * + * @todo Orange-Management/phpOMS#247 + * [L11nManager] Create currency rendering test for million and billion dividers + * * @since 1.0.0 */ public function getCurrency(Localization $l11n, $currency, string $format = null, string $symbol = null, int $divide = 1) : string diff --git a/Log/FileLogger.php b/Log/FileLogger.php index 60d1d9b36..73ff6c2e6 100644 --- a/Log/FileLogger.php +++ b/Log/FileLogger.php @@ -133,6 +133,11 @@ final class FileLogger implements LoggerInterface * * @return FileLogger * + * @todo Orange-Management/phpOMS#248 + * [FileLogger] Create test for getInstance + * Maybe unset the instance static variable first because it might be defined already. + * In order to do this use the `TestUtils` functionality. + * * @since 1.0.0 */ public static function getInstance(string $path = '', bool $verbose = false) : self diff --git a/Message/Http/Rest.php b/Message/Http/Rest.php index 331ef1426..6e4747849 100644 --- a/Message/Http/Rest.php +++ b/Message/Http/Rest.php @@ -57,6 +57,8 @@ final class Rest \curl_setopt($curl, \CURLOPT_HTTPHEADER, $headers); \curl_setopt($curl, \CURLOPT_HEADER, true); + \curl_setopt($curl, \CURLOPT_CONNECTTIMEOUT, 5); + \curl_setopt($curl, \CURLOPT_TIMEOUT, 30); switch ($request->getMethod()) { case RequestMethod::GET: diff --git a/Router/WebRouter.php b/Router/WebRouter.php index f1ba70cf6..fd4c4e43f 100644 --- a/Router/WebRouter.php +++ b/Router/WebRouter.php @@ -147,6 +147,10 @@ final class WebRouter implements RouterInterface } // if validation check is invalid + /** + * @todo Orange-Management/phpOMS#251 + * [WebRouter] Implement test to validate the provided data + */ if (isset($d['validation'])) { foreach ($d['validation'] as $name => $pattern) { if (!isset($data[$name]) || \preg_match($pattern, $data[$name]) !== 1) { @@ -158,6 +162,10 @@ final class WebRouter implements RouterInterface $temp = ['dest' => $d['dest']]; // fill data + /** + * @todo Orange-Management/phpOMS#252 + * [WebRouter] Implement test for defining data from route + */ if (isset($d['pattern'])) { \preg_match($d['pattern'], $route, $matches); diff --git a/Utils/IO/Zip/Tar.php b/Utils/IO/Zip/Tar.php index f50e68408..ace9a660e 100644 --- a/Utils/IO/Zip/Tar.php +++ b/Utils/IO/Zip/Tar.php @@ -30,6 +30,10 @@ class Tar implements ArchiveInterface { /** * {@inheritdoc} + * + * @todo Orange-Management/phpOMS#250 + * [Tar] Create tar test without destination path/name + * Simply call `Tar::pack([src1, src2, ...], 'output.tar')` */ public static function pack($sources, string $destination, bool $overwrite = false) : bool { diff --git a/Utils/IO/Zip/Zip.php b/Utils/IO/Zip/Zip.php index b5cb0ce06..a7348818e 100644 --- a/Utils/IO/Zip/Zip.php +++ b/Utils/IO/Zip/Zip.php @@ -30,6 +30,10 @@ class Zip implements ArchiveInterface { /** * {@inheritdoc} + * + * @todo Orange-Management/phpOMS#249 + * [Zip] Create zip test without destination path/name + * Simply call `Zip::pack([src1, src2, ...], 'output.zip')` */ public static function pack($sources, string $destination, bool $overwrite = false) : bool { diff --git a/Utils/MbStringUtils.php b/Utils/MbStringUtils.php index 938b2effe..2afb813f9 100644 --- a/Utils/MbStringUtils.php +++ b/Utils/MbStringUtils.php @@ -241,16 +241,16 @@ final class MbStringUtils */ public static function mb_entropy(string $value) : float { - $entroy = 0.0; + $entropy = 0.0; $size = \mb_strlen($value); $countChars = self::mb_count_chars($value); foreach ($countChars as $v) { $p = $v / $size; - $entroy -= $p * \log($p) / \log(2); + $entropy -= $p * \log($p) / \log(2); } - return $entroy; + return $entropy; } /** diff --git a/Utils/StringUtils.php b/Utils/StringUtils.php index 8485a221c..1f183788f 100644 --- a/Utils/StringUtils.php +++ b/Utils/StringUtils.php @@ -173,16 +173,16 @@ final class StringUtils */ public static function entropy(string $value) : float { - $entroy = 0.0; + $entropy = 0.0; $size = \strlen($value); - $countChars = \count_chars($value); + $countChars = \count_chars($value, 1); foreach ($countChars as $v) { $p = $v / $size; - $entroy -= $p * \log($p) / \log(2); + $entropy -= $p * \log($p) / \log(2); } - return $entroy; + return $entropy; } /** diff --git a/tests/Account/NullAccountTest.php b/tests/Account/NullAccountTest.php index 246cd2066..35b713cdb 100644 --- a/tests/Account/NullAccountTest.php +++ b/tests/Account/NullAccountTest.php @@ -27,4 +27,10 @@ final class NullAccountTest extends \PHPUnit\Framework\TestCase { self::assertInstanceOf('\phpOMS\Account\Account', new NullAccount()); } + + public function testId() : void + { + $null = new NullAccount(2); + self::assertEquals(2, $null->getId()); + } } diff --git a/tests/DataStorage/Database/Connection/MysqlConnectionTest.php b/tests/DataStorage/Database/Connection/MysqlConnectionTest.php index c1846723d..2a5f94e19 100644 --- a/tests/DataStorage/Database/Connection/MysqlConnectionTest.php +++ b/tests/DataStorage/Database/Connection/MysqlConnectionTest.php @@ -16,6 +16,7 @@ namespace phpOMS\tests\DataStorage\Database\Connection; use phpOMS\DataStorage\Database\Connection\MysqlConnection; use phpOMS\DataStorage\Database\DatabaseStatus; +use phpOMS\DataStorage\Database\DatabaseType; /** * @testdox phpOMS\tests\DataStorage\Database\Connection\MysqlConnectionTest: Mysql connection @@ -35,7 +36,7 @@ class MysqlConnectionTest extends \PHPUnit\Framework\TestCase /** * @testdox Valid mysql connection data result in a valid database connection - * @covers phpOMS\DataStorage\Database\Connection\MysqlConnection + * @covers phpOMS\DataStorage\Database\Connection\MysqlConnection * @group framework */ public function testConnect() : void @@ -47,6 +48,7 @@ class MysqlConnectionTest extends \PHPUnit\Framework\TestCase self::assertEquals($GLOBALS['CONFIG']['db']['core']['masters']['admin']['host'], $mysql->getHost()); self::assertEquals((int) $GLOBALS['CONFIG']['db']['core']['masters']['admin']['port'], $mysql->getPort()); self::assertInstanceOf('\phpOMS\DataStorage\Database\Query\Grammar\MysqlGrammar', $mysql->getGrammar()); + self::assertEquals(DatabaseType::MYSQL, $mysql->getType()); } /** diff --git a/tests/DataStorage/Database/Connection/NullConnectionTest.php b/tests/DataStorage/Database/Connection/NullConnectionTest.php index 2869d5c72..5396a333a 100644 --- a/tests/DataStorage/Database/Connection/NullConnectionTest.php +++ b/tests/DataStorage/Database/Connection/NullConnectionTest.php @@ -26,7 +26,7 @@ final class NullConnectionTest extends \PHPUnit\Framework\TestCase { /** * @testdox A null connection can be created as placeholder - * @covers phpOMS\DataStorage\Database\Connection\PostgresConnection + * @covers phpOMS\DataStorage\Database\Connection\NullConnection * @group framework */ public function testConnect() : void diff --git a/tests/DataStorage/Database/Connection/PostgresConnectionTest.php b/tests/DataStorage/Database/Connection/PostgresConnectionTest.php index 10273bc4d..32db192ed 100644 --- a/tests/DataStorage/Database/Connection/PostgresConnectionTest.php +++ b/tests/DataStorage/Database/Connection/PostgresConnectionTest.php @@ -15,6 +15,7 @@ namespace phpOMS\tests\DataStorage\Database\Connection; use phpOMS\DataStorage\Database\Connection\PostgresConnection; use phpOMS\DataStorage\Database\DatabaseStatus; +use phpOMS\DataStorage\Database\DatabaseType; /** * @testdox phpOMS\tests\DataStorage\Database\Connection\PostgresConnectionTest: Postgresql connection @@ -34,7 +35,7 @@ class PostgresConnectionTest extends \PHPUnit\Framework\TestCase /** * @testdox Valid postgresql connection data result in a valid database connection - * @covers phpOMS\DataStorage\Database\Connection\PostgresConnection + * @covers phpOMS\DataStorage\Database\Connection\PostgresConnection * @group framework */ public function testConnect() : void @@ -45,6 +46,7 @@ class PostgresConnectionTest extends \PHPUnit\Framework\TestCase self::assertEquals($GLOBALS['CONFIG']['db']['core']['postgresql']['admin']['host'], $psql->getHost()); self::assertEquals((int) $GLOBALS['CONFIG']['db']['core']['postgresql']['admin']['port'], $psql->getPort()); self::assertInstanceOf('\phpOMS\DataStorage\Database\Query\Grammar\PostgresGrammar', $psql->getGrammar()); + self::assertEquals(DatabaseType::PGSQL, $psql->getType()); } /** diff --git a/tests/DataStorage/Database/Connection/SQLiteConnectionTest.php b/tests/DataStorage/Database/Connection/SQLiteConnectionTest.php index e2838e02e..97367d1b9 100644 --- a/tests/DataStorage/Database/Connection/SQLiteConnectionTest.php +++ b/tests/DataStorage/Database/Connection/SQLiteConnectionTest.php @@ -15,6 +15,7 @@ namespace phpOMS\tests\DataStorage\Database\Connection; use phpOMS\DataStorage\Database\Connection\SQLiteConnection; use phpOMS\DataStorage\Database\DatabaseStatus; +use phpOMS\DataStorage\Database\DatabaseType; /** * @testdox phpOMS\tests\DataStorage\Database\Connection\SQLiteConnectionTest: SQLite connection @@ -34,7 +35,7 @@ class SQLiteConnectionTest extends \PHPUnit\Framework\TestCase /** * @testdox Valid sqlite connection data result in a valid database connection - * @covers phpOMS\DataStorage\Database\Connection\SQLiteConnection + * @covers phpOMS\DataStorage\Database\Connection\SQLiteConnection * @group framework */ public function testConnect() : void @@ -43,6 +44,7 @@ class SQLiteConnectionTest extends \PHPUnit\Framework\TestCase self::assertEquals(DatabaseStatus::OK, $sqlite->getStatus()); self::assertEquals($GLOBALS['CONFIG']['db']['core']['sqlite']['admin']['database'], $sqlite->getDatabase()); self::assertInstanceOf('\phpOMS\DataStorage\Database\Query\Grammar\SQLiteGrammar', $sqlite->getGrammar()); + self::assertEquals(DatabaseType::SQLITE, $sqlite->getType()); } /** diff --git a/tests/DataStorage/Database/Connection/SqlServerConnectionTest.php b/tests/DataStorage/Database/Connection/SqlServerConnectionTest.php index e0fd4b92a..282ac3943 100644 --- a/tests/DataStorage/Database/Connection/SqlServerConnectionTest.php +++ b/tests/DataStorage/Database/Connection/SqlServerConnectionTest.php @@ -16,6 +16,7 @@ namespace phpOMS\tests\DataStorage\Database\Connection; use phpOMS\DataStorage\Database\Connection\SqlServerConnection; use phpOMS\DataStorage\Database\DatabaseStatus; +use phpOMS\DataStorage\Database\DatabaseType; /** * @testdox phpOMS\tests\DataStorage\Database\Connection\SqlServerConnectionTest: Sqlserver connection @@ -35,7 +36,7 @@ class SqlServerConnectionTest extends \PHPUnit\Framework\TestCase /** * @testdox Valid sqlserver connection data result in a valid database connection - * @covers phpOMS\DataStorage\Database\Connection\SqlServerConnection + * @covers phpOMS\DataStorage\Database\Connection\SqlServerConnection * @group framework */ public function testConnect() : void @@ -46,6 +47,7 @@ class SqlServerConnectionTest extends \PHPUnit\Framework\TestCase self::assertEquals($GLOBALS['CONFIG']['db']['core']['mssql']['admin']['host'], $ssql->getHost()); self::assertEquals((int) $GLOBALS['CONFIG']['db']['core']['mssql']['admin']['port'], $ssql->getPort()); self::assertInstanceOf('\phpOMS\DataStorage\Database\Query\Grammar\SqlServerGrammar', $ssql->getGrammar()); + self::assertEquals(DatabaseType::SQLSRV, $ssql->getType()); } /** diff --git a/tests/DataStorage/Database/DataMapperAbstractTest.php b/tests/DataStorage/Database/DataMapperAbstractTest.php index 72afd6800..5fc503a7e 100644 --- a/tests/DataStorage/Database/DataMapperAbstractTest.php +++ b/tests/DataStorage/Database/DataMapperAbstractTest.php @@ -15,6 +15,8 @@ namespace phpOMS\tests\DataStorage\Database; use phpOMS\tests\DataStorage\Database\TestModel\BaseModel; use phpOMS\tests\DataStorage\Database\TestModel\BaseModelMapper; +use phpOMS\tests\DataStorage\Database\TestModel\Conditional; +use phpOMS\tests\DataStorage\Database\TestModel\ConditionalMapper; use phpOMS\tests\DataStorage\Database\TestModel\ManyToManyDirectModelMapper; /** @@ -46,6 +48,7 @@ class DataMapperAbstractTest extends \PHPUnit\Framework\TestCase }, 'datetime' => new \DateTime('2005-10-11'), 'datetime_null' => null, + 'conditional' => '', 'ownsOneSelf' => [ 'id' => 0, 'string' => 'OwnsOne', @@ -96,6 +99,16 @@ class DataMapperAbstractTest extends \PHPUnit\Framework\TestCase )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1;' )->execute(); + $GLOBALS['dbpool']->get()->con->prepare( + 'CREATE TABLE `test_conditional` ( + `test_conditional_id` int(11) NOT NULL AUTO_INCREMENT, + `test_conditional_title` varchar(254) NOT NULL, + `test_conditional_base` int(11) NOT NULL, + `test_conditional_language` varchar(254) NOT NULL, + PRIMARY KEY (`test_conditional_id`) + )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1;' + )->execute(); + $GLOBALS['dbpool']->get()->con->prepare( 'CREATE TABLE `test_belongs_to_one` ( `test_belongs_to_one_id` int(11) NOT NULL AUTO_INCREMENT, @@ -141,6 +154,7 @@ class DataMapperAbstractTest extends \PHPUnit\Framework\TestCase protected function tearDown() : void { + $GLOBALS['dbpool']->get()->con->prepare('DROP TABLE test_conditional')->execute(); $GLOBALS['dbpool']->get()->con->prepare('DROP TABLE test_base')->execute(); $GLOBALS['dbpool']->get()->con->prepare('DROP TABLE test_belongs_to_one')->execute(); $GLOBALS['dbpool']->get()->con->prepare('DROP TABLE test_owns_one')->execute(); @@ -227,6 +241,66 @@ class DataMapperAbstractTest extends \PHPUnit\Framework\TestCase self::assertCount(1, BaseModelMapper::getAll()); } + public function testFind() : void + { + $model1 = clone $this->model; + $model2 = clone $this->model; + $model3 = clone $this->model; + + $model1->string = 'abc'; + $model2->string = 'hallo sir'; + $model3->string = 'seasiren'; + + BaseModelMapper::create($model1); + BaseModelMapper::create($model2); + BaseModelMapper::create($model3); + + $found = BaseModelMapper::find('sir'); + self::assertCount(2, $found); + self::assertEquals($model2->string, reset($found)->string); + self::assertEquals($model3->string, end($found)->string); + } + + public function testWithConditional() : void + { + $model1 = clone $this->model; + $model2 = clone $this->model; + $model3 = clone $this->model; + + $model1->string = 'abc'; + $model2->string = 'hallo sir'; + $model3->string = 'seasiren'; + + $id1 = BaseModelMapper::create($model1); + $id2 = BaseModelMapper::create($model2); + $id3 = BaseModelMapper::create($model3); + + $cond1 = new Conditional(); + $cond1->language = 'de'; + $cond1->title = 'cond1_de'; + $cond1->base = $id1; + ConditionalMapper::create($cond1); + + $cond2 = new Conditional(); + $cond2->language = 'en'; + $cond2->title = 'cond1_en'; + $cond2->base = $id1; + ConditionalMapper::create($cond2); + + $cond3 = new Conditional(); + $cond3->language = 'de'; + $cond3->title = 'cond2_de'; + $cond3->base = $id2; + ConditionalMapper::create($cond3); + + $found = BaseModelMapper::withConditional('language', 'de')::getAll(); + self::assertCount(2, $found); + self::assertEquals($model1->string, reset($found)->string); + self::assertEquals($model2->string, end($found)->string); + self::assertEquals('cond1_de', reset($found)->conditional); + self::assertEquals('cond2_de', end($found)->conditional); + } + /** * @testdox The datamapper successfully returns a database entry as array * @covers phpOMS\DataStorage\Database\DataMapperAbstract @@ -307,12 +381,12 @@ class DataMapperAbstractTest extends \PHPUnit\Framework\TestCase $id = BaseModelMapper::createArray($this->modelArray); $modelR = BaseModelMapper::getArray($id); - $modelR['string'] = 'Update'; - $modelR['int'] = '321'; - $modelR['bool'] = true; - $modelR['float'] = 3.15; - $modelR['null'] = null; - $modelR['datetime'] = new \DateTime('now'); + $modelR['string'] = 'Update'; + $modelR['int'] = '321'; + $modelR['bool'] = true; + $modelR['float'] = 3.15; + $modelR['null'] = null; + $modelR['datetime'] = new \DateTime('now'); $modelR['datetime_null'] = null; $id2 = BaseModelMapper::updateArray($modelR); diff --git a/tests/DataStorage/Database/Exception/InvalidMapperExceptionTest.php b/tests/DataStorage/Database/Exception/InvalidMapperExceptionTest.php index 170dd2fe6..e1d1c300f 100644 --- a/tests/DataStorage/Database/Exception/InvalidMapperExceptionTest.php +++ b/tests/DataStorage/Database/Exception/InvalidMapperExceptionTest.php @@ -24,5 +24,8 @@ class InvalidMapperExceptionTest extends \PHPUnit\Framework\TestCase public function testException() : void { self::assertInstanceOf(\RuntimeException::class, new InvalidMapperException('')); + + $e = new InvalidMapperException('TestMapper'); + self::assertStringContainsString('TestMapper', $e->getMessage()); } } diff --git a/tests/DataStorage/Database/Query/BuilderTest.php b/tests/DataStorage/Database/Query/BuilderTest.php index 05d52c3de..c9e6fac8f 100644 --- a/tests/DataStorage/Database/Query/BuilderTest.php +++ b/tests/DataStorage/Database/Query/BuilderTest.php @@ -352,11 +352,21 @@ class BuilderTest extends \PHPUnit\Framework\TestCase self::assertEquals('SELECT test.val FROM test;', $query->raw('SELECT test.val FROM test;')->toSql()); } + /** + * @testdox Read only queries allow selects + * @group framework + */ + public function testReadOnlyRawSelect() : void + { + $query = new Builder($this->con, true); + self::assertInstanceOf(Builder::class, $query->raw('SELECT * from oms;')); + } + /** * @testdox Read only queries don't allow drops * @group framework */ - public function testReadOnlyRaw() : void + public function testReadOnlyRawDrop() : void { self::expectException(\Exception::class); @@ -364,6 +374,42 @@ class BuilderTest extends \PHPUnit\Framework\TestCase $query->raw('DROP DATABASE oms;'); } + /** + * @testdox Read only queries don't allow deletes + * @group framework + */ + public function testReadOnlyRawDelete() : void + { + self::expectException(\Exception::class); + + $query = new Builder($this->con, true); + $query->raw('DELETE oms;'); + } + + /** + * @testdox Read only queries don't allow creates + * @group framework + */ + public function testReadOnlyRawCreate() : void + { + self::expectException(\Exception::class); + + $query = new Builder($this->con, true); + $query->raw('CREATE oms;'); + } + + /** + * @testdox Read only queries don't allow modifications + * @group framework + */ + public function testReadOnlyRawAlter() : void + { + self::expectException(\Exception::class); + + $query = new Builder($this->con, true); + $query->raw('ALTER oms;'); + } + /** * @testdox Read only queries don't allow inserts * @group framework diff --git a/tests/DataStorage/Database/TestModel/BaseModel.php b/tests/DataStorage/Database/TestModel/BaseModel.php index f4bf0df6d..6dc7523d1 100644 --- a/tests/DataStorage/Database/TestModel/BaseModel.php +++ b/tests/DataStorage/Database/TestModel/BaseModel.php @@ -20,6 +20,8 @@ class BaseModel public $string = 'Base'; + public $conditional = ''; + public $int = 11; public $bool = false; diff --git a/tests/DataStorage/Database/TestModel/BaseModelMapper.php b/tests/DataStorage/Database/TestModel/BaseModelMapper.php index 156a6dbad..d025edd21 100644 --- a/tests/DataStorage/Database/TestModel/BaseModelMapper.php +++ b/tests/DataStorage/Database/TestModel/BaseModelMapper.php @@ -25,7 +25,7 @@ class BaseModelMapper extends DataMapperAbstract */ protected static array $columns = [ 'test_base_id' => ['name' => 'test_base_id', 'type' => 'int', 'internal' => 'id'], - 'test_base_string' => ['name' => 'test_base_string', 'type' => 'string', 'internal' => 'string'], + 'test_base_string' => ['name' => 'test_base_string', 'type' => 'string', 'internal' => 'string', 'autocomplete' => true], 'test_base_int' => ['name' => 'test_base_int', 'type' => 'int', 'internal' => 'int'], 'test_base_bool' => ['name' => 'test_base_bool', 'type' => 'bool', 'internal' => 'bool'], 'test_base_null' => ['name' => 'test_base_null', 'type' => 'int', 'internal' => 'null'], @@ -68,14 +68,21 @@ class BaseModelMapper extends DataMapperAbstract 'hasManyDirect' => [ 'mapper' => ManyToManyDirectModelMapper::class, 'table' => 'test_has_many_direct', - 'external' => 'test_has_many_direct_to', - 'self' => null, + 'external' => 'test_has_many_direct_to', + 'self' => null, ], 'hasManyRelations' => [ 'mapper' => ManyToManyRelModelMapper::class, 'table' => 'test_has_many_rel_relations', - 'external' => 'test_has_many_rel_relations_dest', - 'self' => 'test_has_many_rel_relations_src', + 'external' => 'test_has_many_rel_relations_dest', + 'self' => 'test_has_many_rel_relations_src', + ], + 'conditional' => [ + 'mapper' => ConditionalMapper::class, + 'table' => 'test_conditional', + 'external' => 'test_conditional_base', + 'column' => 'title', + 'self' => null, ], ]; diff --git a/tests/DataStorage/Database/TestModel/Conditional.php b/tests/DataStorage/Database/TestModel/Conditional.php new file mode 100644 index 000000000..2aa8c0805 --- /dev/null +++ b/tests/DataStorage/Database/TestModel/Conditional.php @@ -0,0 +1,26 @@ + + * @since 1.0.0 + */ + protected static array $columns = [ + 'test_conditional_id' => ['name' => 'test_conditional_id', 'type' => 'int', 'internal' => 'id'], + 'test_conditional_title' => ['name' => 'test_conditional_title', 'type' => 'string', 'internal' => 'title', 'autocomplete' => true], + 'test_conditional_base' => ['name' => 'test_conditional_base', 'type' => 'int', 'internal' => 'base'], + 'test_conditional_language' => ['name' => 'test_conditional_language', 'type' => 'string', 'internal' => 'language'], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + protected static string $table = 'test_conditional'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + protected static string $primaryField = 'test_conditional_id'; +} diff --git a/tests/Math/Statistic/AverageTest.php b/tests/Math/Statistic/AverageTest.php index 90488d7ba..83177b1d0 100644 --- a/tests/Math/Statistic/AverageTest.php +++ b/tests/Math/Statistic/AverageTest.php @@ -95,9 +95,24 @@ class AverageTest extends \PHPUnit\Framework\TestCase 63.94, 64.13, 64.50, 62.81, 61.88, 62.50, 61.44, 60.13, 61.31, 61.38, ]; - $average = [66.39, 66.03, 65.79, 65.6, 65.24, 64.8, 64.46, 63.94, 63.3, 62.87, 62.4]; + $average = [ + 66.626, 66.302, 66.328, 66.352, 66.19, 66.152, 65.764, 65.264, 64.852, 64.288, 63.452, 63.164, 62.626, 61.752, 61.452, 61.352 + ]; - self::assertEqualsWithDelta($average, Average::totalMovingAverage($data, 10), 0.1); + self::assertEqualsWithDelta($average, Average::totalMovingAverage($data, 5), 0.1); + } + + /** + * @testdox The weighted moving average is correctly calculated + * @group framework + */ + public function testWeightedMovingAverage() : void + { + $data = [67.5, 66.5, 66.44, 66.44, 66.25, 65.88, 66.63]; + $weights = [0.1, 0.2, 0.3, 0.1, 0.2, 0.05, 0.05]; + $average = [39.982, 39.876, 39.826, 23.188, 19.876]; + + self::assertEqualsWithDelta($average, Average::totalMovingAverage($data, 3, $weights), 0.1); } /** diff --git a/tests/Math/Topology/MetricsNDTest.php b/tests/Math/Topology/MetricsNDTest.php index 4eaf779d0..ad5903097 100644 --- a/tests/Math/Topology/MetricsNDTest.php +++ b/tests/Math/Topology/MetricsNDTest.php @@ -133,6 +133,90 @@ class MetricsNDTest extends \PHPUnit\Framework\TestCase ); } + /** + * @testdox Different dimension sizes for the coordinates in the manhattan metric throw a InvalidDimensionException + * @covers phpOMS\Math\Topology\MetricsND + * @group framework + */ + public function testInvalidManhattanDimension() : void + { + self::expectException(\phpOMS\Math\Matrix\Exception\InvalidDimensionException::class); + + MetricsND::manhattan([3, 6, 4], [4, 6, 8, 3]); + } + + /** + * @testdox Different dimension sizes for the coordinates in the euclidean metric throw a InvalidDimensionException + * @covers phpOMS\Math\Topology\MetricsND + * @group framework + */ + public function testInvalidEuclideanDimension() : void + { + self::expectException(\phpOMS\Math\Matrix\Exception\InvalidDimensionException::class); + + MetricsND::euclidean([3, 6, 4], [4, 6, 8, 3]); + } + + /** + * @testdox Different dimension sizes for the coordinates in the chebyshev metric throw a InvalidDimensionException + * @covers phpOMS\Math\Topology\MetricsND + * @group framework + */ + public function testInvalidChebyshevDimension() : void + { + self::expectException(\phpOMS\Math\Matrix\Exception\InvalidDimensionException::class); + + MetricsND::chebyshev([3, 6, 4], [4, 6, 8, 3]); + } + + /** + * @testdox Different dimension sizes for the coordinates in the minkowski metric throw a InvalidDimensionException + * @covers phpOMS\Math\Topology\MetricsND + * @group framework + */ + public function testInvalidMinkowskiDimension() : void + { + self::expectException(\phpOMS\Math\Matrix\Exception\InvalidDimensionException::class); + + MetricsND::minkowski([3, 6, 4], [4, 6, 8, 3], 2); + } + + /** + * @testdox Different dimension sizes for the coordinates in the canberra metric throw a InvalidDimensionException + * @covers phpOMS\Math\Topology\MetricsND + * @group framework + */ + public function testInvalidCanberraDimension() : void + { + self::expectException(\phpOMS\Math\Matrix\Exception\InvalidDimensionException::class); + + MetricsND::canberra([3, 6, 4], [4, 6, 8, 3]); + } + + /** + * @testdox Different dimension sizes for the coordinates in the Bray Curtis metric throw a InvalidDimensionException + * @covers phpOMS\Math\Topology\MetricsND + * @group framework + */ + public function testInvalidBrayCurtisDimension() : void + { + self::expectException(\phpOMS\Math\Matrix\Exception\InvalidDimensionException::class); + + MetricsND::brayCurtis([3, 6, 4], [4, 6, 8, 3]); + } + + /** + * @testdox Different dimension sizes for the coordinates in the angular separation metric throw a InvalidDimensionException + * @covers phpOMS\Math\Topology\MetricsND + * @group framework + */ + public function testInvalidAngularSeparationDimension() : void + { + self::expectException(\phpOMS\Math\Matrix\Exception\InvalidDimensionException::class); + + MetricsND::angularSeparation([3, 6, 4], [4, 6, 8, 3]); + } + /** * @testdox Different dimension sizes for the coordinates in the hamming metric throw a InvalidDimensionException * @covers phpOMS\Math\Topology\MetricsND @@ -142,6 +226,6 @@ class MetricsNDTest extends \PHPUnit\Framework\TestCase { self::expectException(\phpOMS\Math\Matrix\Exception\InvalidDimensionException::class); - Metrics2D::ulam([3, 6, 4], [4, 6, 8, 3]); + MetricsND::hamming([3, 6, 4], [4, 6, 8, 3]); } } diff --git a/tests/Message/Http/HttpRequestTest.php b/tests/Message/Http/HttpRequestTest.php index 02fdf82a8..405817305 100644 --- a/tests/Message/Http/HttpRequestTest.php +++ b/tests/Message/Http/HttpRequestTest.php @@ -25,7 +25,7 @@ use phpOMS\System\MimeType; use phpOMS\Uri\HttpUri; /** - * @testdox phpOMS\tests\Message\Http\RequestTest: HttpRequest wrapper for http requests + * @testdox phpOMS\tests\Message\Http\HttpRequestTest: HttpRequest wrapper for http requests * * @internal */ diff --git a/tests/Module/ModuleAbstractTest.php b/tests/Module/ModuleAbstractTest.php index 6dc6acd45..042a8e35e 100644 --- a/tests/Module/ModuleAbstractTest.php +++ b/tests/Module/ModuleAbstractTest.php @@ -232,6 +232,16 @@ class ModuleAbstractTest extends \PHPUnit\Framework\TestCase )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1;' )->execute(); + $GLOBALS['dbpool']->get()->con->prepare( + 'CREATE TABLE `test_conditional` ( + `test_conditional_id` int(11) NOT NULL AUTO_INCREMENT, + `test_conditional_title` varchar(254) NOT NULL, + `test_conditional_base` int(11) NOT NULL, + `test_conditional_language` varchar(254) NOT NULL, + PRIMARY KEY (`test_conditional_id`) + )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1;' + )->execute(); + $GLOBALS['dbpool']->get()->con->prepare( 'CREATE TABLE `test_belongs_to_one` ( `test_belongs_to_one_id` int(11) NOT NULL AUTO_INCREMENT, @@ -277,6 +287,7 @@ class ModuleAbstractTest extends \PHPUnit\Framework\TestCase private function dbTeardown() : void { + $GLOBALS['dbpool']->get()->con->prepare('DROP TABLE test_conditional')->execute(); $GLOBALS['dbpool']->get()->con->prepare('DROP TABLE test_base')->execute(); $GLOBALS['dbpool']->get()->con->prepare('DROP TABLE test_belongs_to_one')->execute(); $GLOBALS['dbpool']->get()->con->prepare('DROP TABLE test_owns_one')->execute(); diff --git a/tests/Utils/MbStringUtilsTest.php b/tests/Utils/MbStringUtilsTest.php index 0821825b8..273734369 100644 --- a/tests/Utils/MbStringUtilsTest.php +++ b/tests/Utils/MbStringUtilsTest.php @@ -25,6 +25,27 @@ require_once __DIR__ . '/../Autoloader.php'; */ class MbStringUtilsTest extends \PHPUnit\Framework\TestCase { + /** + * @testdox The entropy of a string can be calculated + * @covers phpOMS\Utils\StringUtils + * @group framework + */ + public function testEntropy() : void + { + self::assertEqualsWithDelta(2.75, MbStringUtils::mb_entropy('akj@!©¥j'), 0.1); + } + + /** + * @testdox A string can be checked for multi-byte characters + * @covers phpOMS\Utils\StringUtils + * @group framework + */ + public function testHasMultiBytes() : void + { + self::assertTrue(MbStringUtils::hasMultiBytes('akj@!¥aj')); + self::assertFalse(MbStringUtils::hasMultiBytes('akjc!aj')); + } + /** * @testdox A multi-byte string can be checked if it starts with a defined string * @covers phpOMS\Utils\MbStringUtils