From 0e22c18a9da7b1a55e188964af84886bfa7aae32 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 31 Oct 2018 10:16:15 +0100 Subject: [PATCH 1/6] Bugfixing & Enhancement - Added Mocking Engine for App, DBA, Config - Using Mocking Engine for AutomaticInstallationConsoleTest - Using Mocking Engine for ConfigConsoleTest - Removing MultiUserConsole - Workaround --- tests/Util/AppMockTrait.php | 90 ++++++++++ tests/Util/ConfigMockTrait.php | 59 +++++++ tests/Util/DBAMockTrait.php | 35 ++++ tests/Util/DBStructureMockTrait.php | 37 ++++ tests/datasets/ini/assert.ini.php | 56 ++++++ tests/datasets/ini/assert_db.ini.php | 56 ++++++ .../AutomaticInstallationConsoleTest.php | 165 ++++++++++-------- tests/src/Core/Console/ConfigConsoleTest.php | 106 +++++++---- tests/src/Core/Console/ConsoleTest.php | 63 +++---- tests/src/Core/Console/MultiUseConsole.php | 23 --- 10 files changed, 515 insertions(+), 175 deletions(-) create mode 100644 tests/Util/AppMockTrait.php create mode 100644 tests/Util/ConfigMockTrait.php create mode 100644 tests/Util/DBAMockTrait.php create mode 100644 tests/Util/DBStructureMockTrait.php create mode 100644 tests/datasets/ini/assert.ini.php create mode 100644 tests/datasets/ini/assert_db.ini.php delete mode 100644 tests/src/Core/Console/MultiUseConsole.php diff --git a/tests/Util/AppMockTrait.php b/tests/Util/AppMockTrait.php new file mode 100644 index 0000000000..c04b5d7dc5 --- /dev/null +++ b/tests/Util/AppMockTrait.php @@ -0,0 +1,90 @@ +shouldReceive('t') + ->andReturn(''); + + $this->mockConfigGet('system', 'theme', 'testtheme'); + + // Mocking App and most used functions + $this->app = \Mockery::mock('Friendica\App'); + $this->app + ->shouldReceive('getBasePath') + ->andReturn($root->url()); + + $this->app + ->shouldReceive('getConfigValue') + ->with('database', 'hostname') + ->andReturn(getenv('MYSQL_HOST')); + $this->app + ->shouldReceive('getConfigValue') + ->with('database', 'username') + ->andReturn(getenv('MYSQL_USERNAME')); + $this->app + ->shouldReceive('getConfigValue') + ->with('database', 'password') + ->andReturn(getenv('MYSQL_PASSWORD')); + $this->app + ->shouldReceive('getConfigValue') + ->with('database', 'database') + ->andReturn(getenv('MYSQL_DATABASE')); + $this->app + ->shouldReceive('getTemplateEngine') + ->andReturn(new FriendicaSmartyEngine()); + $this->app + ->shouldReceive('getCurrentTheme') + ->andReturn('Smarty3'); + $this->app + ->shouldReceive('getTemplateLeftDelimiter') + ->with('smarty3') + ->andReturn('{{'); + $this->app + ->shouldReceive('getTemplateRightDelimiter') + ->with('smarty3') + ->andReturn('}}'); + $this->app + ->shouldReceive('saveTimestamp') + ->andReturn(true); + $this->app + ->shouldReceive('getBaseUrl') + ->andReturn('http://friendica.local'); + + // Mocking the Theme + // Necessary for macro engine with template files + $themeMock = \Mockery::mock('alias:Friendica\Core\Theme'); + $themeMock + ->shouldReceive('install') + ->with('testtheme') + ->andReturn(true); + + BaseObject::setApp($this->app); + } +} diff --git a/tests/Util/ConfigMockTrait.php b/tests/Util/ConfigMockTrait.php new file mode 100644 index 0000000000..8e285f3922 --- /dev/null +++ b/tests/Util/ConfigMockTrait.php @@ -0,0 +1,59 @@ +configMock)) { + $this->configMock = \Mockery::mock('alias:Friendica\Core\Config'); + } + + $this->configMock + ->shouldReceive('get') + ->times($times) + ->with($family, $key) + ->andReturn($value); + } + + /** + * Mocking setting a new config entry + * + * @param string $family The family of the config double + * @param string $key The key of the config double + * @param mixed $value The value of the config double + * @param null|int $times How often the Config will get used + * @param bool $return Return value of the set (default is true) + */ + public function mockConfigSet($family, $key, $value, $times = null, $return = true) + { + if (!isset($this->configMock)) { + $this->configMock = \Mockery::mock('alias:Friendica\Core\Config'); + } + + $this->mockConfigGet($family, $key, false, 1); + if ($return) { + $this->mockConfigGet($family, $key, $value, 1); + } + + $this->configMock + ->shouldReceive('set') + ->times($times) + ->with($family, $key, $value) + ->andReturn($return); + } +} diff --git a/tests/Util/DBAMockTrait.php b/tests/Util/DBAMockTrait.php new file mode 100644 index 0000000000..77746f7d9e --- /dev/null +++ b/tests/Util/DBAMockTrait.php @@ -0,0 +1,35 @@ +dbaMock)) { + $this->dbaMock = \Mockery::mock('alias:Friendica\Database\DBA'); + } + + $this->dbaMock + ->shouldReceive('connect') + ->times($times) + ->andReturn($return); + } + + public function mockConnected($return = true, $times = null) + { + if (!isset($this->dbaMock)) { + $this->dbaMock = \Mockery::mock('alias:Friendica\Database\DBA'); + } + + $this->dbaMock + ->shouldReceive('connected') + ->times($times) + ->andReturn($return); + } +} diff --git a/tests/Util/DBStructureMockTrait.php b/tests/Util/DBStructureMockTrait.php new file mode 100644 index 0000000000..3298107eb3 --- /dev/null +++ b/tests/Util/DBStructureMockTrait.php @@ -0,0 +1,37 @@ +dbStructure)) { + $this->dbStructure = \Mockery::mock('alias:Friendica\Database\DBStructure'); + } + + $this->dbStructure + ->shouldReceive('update') + ->withArgs($args) + ->times($times) + ->andReturn($return); + } + + public function mockExistsTable($tableName, $return = true, $times = null) + { + if (!isset($this->dbStructure)) { + $this->dbStructure = \Mockery::mock('alias:Friendica\Database\DBStructure'); + } + + $this->dbStructure + ->shouldReceive('existsTable') + ->with($tableName) + ->times($times) + ->andReturn($return); + } +} diff --git a/tests/datasets/ini/assert.ini.php b/tests/datasets/ini/assert.ini.php new file mode 100644 index 0000000000..39828affcb --- /dev/null +++ b/tests/datasets/ini/assert.ini.php @@ -0,0 +1,56 @@ +db_user = getenv('MYSQL_USERNAME') . getenv('MYSQL_USER'); $this->db_pass = getenv('MYSQL_PASSWORD'); - // Mocking 'DBStructure::existsTable()' because with CI, we cannot create an empty database - // therefore we temporary override the existing database - /// @todo Mocking the DB-Calls of ConsoleTest so we don't need this specific mock anymore - $existsMock = \Mockery::mock('alias:Friendica\Database\DBStructure'); - $existsMock->shouldReceive('existsTable') - ->with('user') - ->andReturn(false); - } + $this->mockConfigGet('config', 'php_path', false); - private function assertConfig($family, $key, $value) - { - $config = $this->execute(['config', $family, $key]); - $this->assertEquals($family . "." . $key . " => " . $value . "\n", $config); + $this->assertFile = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'ini' . DIRECTORY_SEPARATOR . + 'assert.ini.php'; + $this->assertFileDb = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'ini' . DIRECTORY_SEPARATOR . + 'assert_db.ini.php'; } private function assertFinished($txt, $withconfig = false, $copyfile = false) @@ -113,14 +121,17 @@ FIN; $finished = <<mockConnect(true, 1); + $this->mockConnected(true, 1); + $this->mockExistsTable('user', false, 1); + $this->mockUpdate([false, true, true], null, 1); + $config = <<at($this->root) ->setContent($config); - $txt = $this->execute(['autoinstall', '-f', 'prepared.ini.php']); + $console = new AutomaticInstallation(); + $console->setOption('f', 'prepared.ini.php'); + + $txt = $this->dumpExecute($console); $this->assertFinished($txt, false, true); @@ -191,23 +210,28 @@ CONF; */ public function testWithEnvironmentAndSave() { + $this->mockConnect(true, 1); + $this->mockConnected(true, 1); + $this->mockExistsTable('user', false, 1); + $this->mockUpdate([false, true, true], null, 1); + $this->assertTrue(putenv('FRIENDICA_ADMIN_MAIL=admin@friendica.local')); $this->assertTrue(putenv('FRIENDICA_TZ=Europe/Berlin')); $this->assertTrue(putenv('FRIENDICA_LANG=de')); + $this->assertTrue(putenv('FRIENDICA_URL_PATH=/friendica')); - $txt = $this->execute(['autoinstall', '--savedb']); + $console = new AutomaticInstallation(); + $console->setOption('savedb', true); + + $txt = $this->dumpExecute($console); $this->assertFinished($txt, true); $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')); - $this->assertConfig('database', 'hostname', $this->db_host . (!empty($this->db_port) ? ':' . $this->db_port : '')); - $this->assertConfig('database', 'username', $this->db_user); - $this->assertConfig('database', 'database', $this->db_data); - $this->assertConfig('config', 'admin_email', 'admin@friendica.local'); - $this->assertConfig('system', 'default_timezone', 'Europe/Berlin'); - // TODO language changes back to en - //$this->assertConfig('system', 'language', 'de'); + $this->assertFileEquals( + $this->assertFileDb, + $this->root->getChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')->url()); } /** @@ -215,25 +239,27 @@ CONF; */ public function testWithEnvironmentWithoutSave() { + $this->mockConnect(true, 1); + $this->mockConnected(true, 1); + $this->mockExistsTable('user', false, 1); + $this->mockUpdate([false, true, true], null, 1); + $this->assertTrue(putenv('FRIENDICA_ADMIN_MAIL=admin@friendica.local')); $this->assertTrue(putenv('FRIENDICA_TZ=Europe/Berlin')); $this->assertTrue(putenv('FRIENDICA_LANG=de')); $this->assertTrue(putenv('FRIENDICA_URL_PATH=/friendica')); - $txt = $this->execute(['autoinstall']); + $console = new AutomaticInstallation(); - $this->assertFinished($txt, true); + $returnStr = $this->dumpExecute($console); + + $this->assertFinished($returnStr, true); $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')); - $this->assertConfig('database', 'hostname', ''); - $this->assertConfig('database', 'username', ''); - $this->assertConfig('database', 'database', ''); - $this->assertConfig('config', 'admin_email', 'admin@friendica.local'); - $this->assertConfig('system', 'default_timezone', 'Europe/Berlin'); - $this->assertConfig('system', 'urlpath', '/friendica'); - // TODO language changes back to en - //$this->assertConfig('system', 'language', 'de'); + $this->assertFileEquals( + $this->assertFile, + $this->root->getChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')->url()); } /** @@ -241,46 +267,38 @@ CONF; */ public function testWithArguments() { - $args = ['autoinstall']; - array_push($args, '--dbhost'); - array_push($args, $this->db_host); - array_push($args, '--dbuser'); - array_push($args, $this->db_user); + $this->mockConnect(true, 1); + $this->mockConnected(true, 1); + $this->mockExistsTable('user', false, 1); + $this->mockUpdate([false, true, true], null, 1); + + $console = new AutomaticInstallation(); + + $console->setOption('dbhost', $this->db_host); + $console->setOption('dbuser', $this->db_user); if (!empty($this->db_pass)) { - array_push($args, '--dbpass'); - array_push($args, $this->db_pass); + $console->setOption('dbpass', $this->db_pass); } if (!empty($this->db_port)) { - array_push($args, '--dbport'); - array_push($args, $this->db_port); + $console->setOption('dbport', $this->db_port); } - array_push($args, '--dbdata'); - array_push($args, $this->db_data); + $console->setOption('dbdata', $this->db_data); - array_push($args, '--admin'); - array_push($args, 'admin@friendica.local'); - array_push($args, '--tz'); - array_push($args, 'Europe/Berlin'); - array_push($args, '--lang'); - array_push($args, 'de'); + $console->setOption('admin', 'admin@friendica.local'); + $console->setOption('tz', 'Europe/Berlin'); + $console->setOption('lang', 'de'); - array_push($args, '--urlpath'); - array_push($args, '/friendica'); + $console->setOption('urlpath', '/friendica'); - $txt = $this->execute($args); + $returnStr = $this->dumpExecute($console); - $this->assertFinished($txt, true); + $this->assertFinished($returnStr, true); $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')); - $this->assertConfig('database', 'hostname', $this->db_host . (!empty($this->db_port) ? ':' . $this->db_port : '')); - $this->assertConfig('database', 'username', $this->db_user); - $this->assertConfig('database', 'database', $this->db_data); - $this->assertConfig('config', 'admin_email', 'admin@friendica.local'); - $this->assertConfig('system', 'default_timezone', 'Europe/Berlin'); - $this->assertConfig('system', 'urlpath', '/friendica'); - // TODO language changes back to en - //$this->assertConfig('system', 'language', 'de'); + $this->assertFileEquals( + $this->assertFileDb, + $this->root->getChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')->url()); } /** @@ -289,17 +307,13 @@ CONF; */ public function testNoDatabaseConnection() { - // TODO DBA mocking for whole console tests make this test work again - $this->markTestSkipped('DBA is already loaded, we have to mock the whole App to make it work'); + $this->mockConnect(false, 1); - $dbaMock = \Mockery::mock('alias:Friendica\Database\DBA'); - $dbaMock - ->shouldReceive('connected') - ->andReturn(false); + $console = new AutomaticInstallation(); - $txt = $this->execute(['autoinstall']); + $returnStr = $this->dumpExecute($console); - $this->assertStuckDB($txt); + $this->assertStuckDB($returnStr); } public function testGetHelp() @@ -357,7 +371,10 @@ Examples HELP; - $txt = $this->execute(['autoinstall', '-h']); + $console = new AutomaticInstallation(); + $console->setOption('help', true); + + $txt = $this->dumpExecute($console); $this->assertEquals($txt, $theHelp); } diff --git a/tests/src/Core/Console/ConfigConsoleTest.php b/tests/src/Core/Console/ConfigConsoleTest.php index c4fd217770..683c7a2e37 100644 --- a/tests/src/Core/Console/ConfigConsoleTest.php +++ b/tests/src/Core/Console/ConfigConsoleTest.php @@ -2,7 +2,8 @@ namespace Friendica\Test\src\Core\Console; -use Friendica\Database\DBA; +use Friendica\Core\Console\Config; +use \Mockery as m; /** * @runTestsInSeparateProcesses @@ -11,76 +12,105 @@ use Friendica\Database\DBA; */ class ConfigConsoleTest extends ConsoleTest { - public function tearDown() + protected function setUp() { - DBA::delete('config', ['k' => 'test']); + parent::setUp(); - parent::tearDown(); - } + m::getConfiguration()->setConstantsMap([ + 'Friendica\App\Mode' => [ + 'DBCONFIGAVAILABLE' => 0 + ] + ]); - private function assertGet($family, $key, $value) { - $config = $this->execute(['config', $family, $key]); - $this->assertEquals($family . "." . $key . " => " . $value . "\n", $config); - } + $mode = m::mock('alias:Friendica\App\Mode'); + $mode + ->shouldReceive('has') + ->andReturn(true); - private function assertSet($family, $key, $value) { - $config = $this->execute(['config', $family, $key, $value]); - $this->assertEquals($family . "." . $key . " <= " . $value . "\n", $config); + $this->app + ->shouldReceive('getMode') + ->andReturn($mode); } function testSetGetKeyValue() { - $this->assertSet( 'config', 'test', 'now'); - $this->assertGet('config', 'test', 'now'); - $this->assertSet('config', 'test', ''); - $this->assertGet('config', 'test', ''); - DBA::delete('config', ['k' => 'test']); - $this->assertGet('config', 'test', null); + $this->mockConfigSet('config', 'test', 'now', 1); + $console = new Config(); + $console->setArgument(0, 'config'); + $console->setArgument(1, 'test'); + $console->setArgument(2, 'now'); + $txt = $this->dumpExecute($console); + $this->assertEquals("config.test <= now\n", $txt); + + $this->mockConfigGet('config', 'test', 'now', 1); + $console = new Config(); + $console->setArgument(0, 'config'); + $console->setArgument(1, 'test'); + $txt = $this->dumpExecute($console); + $this->assertEquals("config.test => now\n", $txt); + + $this->mockConfigGet('config', 'test', null, 1); + $console = new Config(); + $console->setArgument(0, 'config'); + $console->setArgument(1, 'test'); + $txt = $this->dumpExecute($console); + $this->assertEquals("config.test => \n", $txt); } function testSetArrayValue() { $testArray = [1, 2, 3]; - DBA::insert('config', ['cat' => 'config', 'k' => 'test', 'v' => serialize($testArray)]); + $this->mockConfigGet('config', 'test', $testArray, 1); - $txt = $this->execute(['config', 'config', 'test', 'now']); + $console = new Config(); + $console->setArgument(0, 'config'); + $console->setArgument(1, 'test'); + $console->setArgument(2, 'now'); + $txt = $this->dumpExecute($console); $this->assertEquals("[Error] config.test is an array and can't be set using this command.\n", $txt); } function testTooManyArguments() { - $txt = $this->execute(['config', 'config', 'test', 'it', 'now']); + $console = new Config(); + $console->setArgument(0, 'config'); + $console->setArgument(1, 'test'); + $console->setArgument(2, 'it'); + $console->setArgument(3, 'now'); + $txt = $this->dumpExecute($console); $assertion = '[Warning] Too many arguments'; $firstline = substr($txt, 0, strlen($assertion)); - $this->assertEquals($assertion, $firstline); } function testVerbose() { - $this->assertSet('test', 'it', 'now'); - $executable = $this->getExecutablePath(); + $this->mockConfigGet('test', 'it', 'now', 1); + $console = new Config(); + $console->setArgument(0, 'test'); + $console->setArgument(1, 'it'); + $console->setOption('v', 1); $assertion = << 'config', - 1 => 'test', -) -Options: array ( - 'v' => 1, -) -Command: config -Executable: {$executable} +Executable: - Class: Friendica\Core\Console\Config Arguments: array ( 0 => 'test', + 1 => 'it', ) Options: array ( 'v' => 1, ) -[test] -it => now +test.it => now CONF; - $txt = $this->execute(['config', 'test', '-v']); - + $txt = $this->dumpExecute($console); $this->assertEquals($assertion, $txt); } + + function testUnableToSet() { + $this->mockConfigSet('test', 'it', 'now', 1, false); + $console = new Config(); + $console->setArgument(0, 'test'); + $console->setArgument(1, 'it'); + $console->setArgument(2, 'now'); + $txt = $this->dumpExecute($console); + $this->assertSame("Unable to set test.it\n", $txt); + } } diff --git a/tests/src/Core/Console/ConsoleTest.php b/tests/src/Core/Console/ConsoleTest.php index 75f339e8f5..6b58ccced2 100644 --- a/tests/src/Core/Console/ConsoleTest.php +++ b/tests/src/Core/Console/ConsoleTest.php @@ -2,27 +2,16 @@ namespace Friendica\Test\src\Core\Console; -use Friendica\App; -use Friendica\BaseObject; -use Friendica\Database\DBA; +use Asika\SimpleConsole\Console; +use Friendica\Test\Util\AppMockTrait; use Friendica\Test\Util\Intercept; use Friendica\Test\Util\VFSTrait; -use org\bovigo\vfs\vfsStream; -use org\bovigo\vfs\vfsStreamDirectory; use PHPUnit\Framework\TestCase; abstract class ConsoleTest extends TestCase { use VFSTrait; - - /** - * @var MultiUseConsole Extension of the basic Friendica Console for testing purpose - */ - private $console; - /** - * @var App The Friendica App - */ - protected $app; + use AppMockTrait; protected $stdout; @@ -30,43 +19,37 @@ abstract class ConsoleTest extends TestCase { parent::setUp(); - Intercept::setUp(); - if (!getenv('MYSQL_DATABASE')) { $this->markTestSkipped('Please set the MYSQL_* environment variables to your test database credentials.'); } + Intercept::setUp(); + $this->setUpVfsDir(); - - // fake console.php for setting an executable - vfsStream::newFile('console.php') - ->at($this->root->getChild('bin')) - ->setContent('app = new App($this->root->url()); - BaseObject::setApp($this->app); - $this->console = new MultiUseConsole(); + $this->mockApp($this->root); } - public function execute($args) { - $this->app->reload(); + protected function tearDown() + { + \Mockery::close(); - array_unshift($args, $this->getExecutablePath()); - Intercept::reset(); - $this->console->reset(); - $this->console->parseTestArgv($args); - $this->console->execute(); - - $returnStr = Intercept::$cache; - Intercept::reset(); - return $returnStr; + parent::tearDown(); } /** - * @return string returns the path to the console executable during tests + * Dumps the execution of an console output to a string and returns it + * + * @param Console $console The current console instance + * + * @return string the output of the execution */ - protected function getExecutablePath() { - return $this->root->getChild('bin' . DIRECTORY_SEPARATOR . 'console.php')->url(); + protected function dumpExecute($console) + { + Intercept::reset(); + $console->execute(); + $returnStr = Intercept::$cache; + Intercept::reset(); + + return $returnStr; } } diff --git a/tests/src/Core/Console/MultiUseConsole.php b/tests/src/Core/Console/MultiUseConsole.php deleted file mode 100644 index ddcbfebc34..0000000000 --- a/tests/src/Core/Console/MultiUseConsole.php +++ /dev/null @@ -1,23 +0,0 @@ -args = []; - $this->options = []; - } - - public function parseTestArgv($argv) - { - $this->parseArgv($argv); - } -} From 551efde2265434f13e718a34d8bffef0f594836c Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 31 Oct 2018 10:19:33 +0100 Subject: [PATCH 2/6] removed unnecessary use --- tests/src/Core/Console/ConfigConsoleTest.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/src/Core/Console/ConfigConsoleTest.php b/tests/src/Core/Console/ConfigConsoleTest.php index 683c7a2e37..1d5b3a628e 100644 --- a/tests/src/Core/Console/ConfigConsoleTest.php +++ b/tests/src/Core/Console/ConfigConsoleTest.php @@ -3,7 +3,6 @@ namespace Friendica\Test\src\Core\Console; use Friendica\Core\Console\Config; -use \Mockery as m; /** * @runTestsInSeparateProcesses @@ -16,13 +15,13 @@ class ConfigConsoleTest extends ConsoleTest { parent::setUp(); - m::getConfiguration()->setConstantsMap([ + \Mockery::getConfiguration()->setConstantsMap([ 'Friendica\App\Mode' => [ 'DBCONFIGAVAILABLE' => 0 ] ]); - $mode = m::mock('alias:Friendica\App\Mode'); + $mode = \Mockery::mock('alias:Friendica\App\Mode'); $mode ->shouldReceive('has') ->andReturn(true); From 70e240691e56a0b84e069658378b4d6593064632 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 31 Oct 2018 10:24:07 +0100 Subject: [PATCH 3/6] Moved Mocking usage Adding more documentation --- tests/Util/AppMockTrait.php | 6 +++--- tests/Util/ConfigMockTrait.php | 5 +++++ tests/Util/DBAMockTrait.php | 17 +++++++++++++++++ tests/Util/DBStructureMockTrait.php | 19 +++++++++++++++++++ tests/Util/VFSTrait.php | 13 +++++++++++++ .../AutomaticInstallationConsoleTest.php | 14 ++++++++------ 6 files changed, 65 insertions(+), 9 deletions(-) diff --git a/tests/Util/AppMockTrait.php b/tests/Util/AppMockTrait.php index c04b5d7dc5..cdd5aedd5d 100644 --- a/tests/Util/AppMockTrait.php +++ b/tests/Util/AppMockTrait.php @@ -5,6 +5,7 @@ namespace Friendica\Test\Util; use Friendica\App; use Friendica\BaseObject; use Friendica\Render\FriendicaSmartyEngine; +use Mockery\MockInterface; use org\bovigo\vfs\vfsStreamDirectory; /** @@ -13,10 +14,9 @@ use org\bovigo\vfs\vfsStreamDirectory; trait AppMockTrait { use ConfigMockTrait; - use DBAMockTrait; /** - * @var App The Friendica global App Mock + * @var MockInterface|App The mocked Friendica\App */ protected $app; @@ -35,7 +35,7 @@ trait AppMockTrait $this->mockConfigGet('system', 'theme', 'testtheme'); // Mocking App and most used functions - $this->app = \Mockery::mock('Friendica\App'); + $this->app = \Mockery::mock(App::class); $this->app ->shouldReceive('getBasePath') ->andReturn($root->url()); diff --git a/tests/Util/ConfigMockTrait.php b/tests/Util/ConfigMockTrait.php index 8e285f3922..d2867a589e 100644 --- a/tests/Util/ConfigMockTrait.php +++ b/tests/Util/ConfigMockTrait.php @@ -2,11 +2,16 @@ namespace Friendica\Test\Util; +use Mockery\MockInterface; + /** * Trait to Mock Config settings */ trait ConfigMockTrait { + /** + * @var MockInterface The mocking interface of Friendica\Core\Config + */ private $configMock; /** diff --git a/tests/Util/DBAMockTrait.php b/tests/Util/DBAMockTrait.php index 77746f7d9e..a076ac23d0 100644 --- a/tests/Util/DBAMockTrait.php +++ b/tests/Util/DBAMockTrait.php @@ -2,13 +2,24 @@ namespace Friendica\Test\Util; +use Mockery\MockInterface; + /** * Trait to mock the DBA connection status */ trait DBAMockTrait { + /** + * @var MockInterface The mocking interface of Friendica\Database\DBA + */ private $dbaMock; + /** + * Mocking DBA::connect() + * + * @param bool $return True, if the connect was successful, otherwise false + * @param null|int $times How often the method will get used + */ public function mockConnect($return = true, $times = null) { if (!isset($this->dbaMock)) { @@ -21,6 +32,12 @@ trait DBAMockTrait ->andReturn($return); } + /** + * Mocking DBA::connected() + * + * @param bool $return True, if the DB is connected, otherwise false + * @param null|int $times How often the method will get used + */ public function mockConnected($return = true, $times = null) { if (!isset($this->dbaMock)) { diff --git a/tests/Util/DBStructureMockTrait.php b/tests/Util/DBStructureMockTrait.php index 3298107eb3..87c120d3f2 100644 --- a/tests/Util/DBStructureMockTrait.php +++ b/tests/Util/DBStructureMockTrait.php @@ -2,13 +2,25 @@ namespace Friendica\Test\Util; +use Mockery\MockInterface; + /** * Trait to mock the DBStructure connection status */ trait DBStructureMockTrait { + /** + * @var MockInterface The mocking interface of Friendica\Database\DBStructure + */ private $dbStructure; + /** + * Mocking DBStructure::update() + * + * @param array $args The arguments for the update call + * @param bool $return True, if the connect was successful, otherwise false + * @param null|int $times How often the method will get used + */ public function mockUpdate($args = [], $return = true, $times = null) { if (!isset($this->dbStructure)) { @@ -22,6 +34,13 @@ trait DBStructureMockTrait ->andReturn($return); } + /** + * Mocking DBStructure::existsTable() + * + * @param string $tableName The name of the table to check + * @param bool $return True, if the connect was successful, otherwise false + * @param null|int $times How often the method will get used + */ public function mockExistsTable($tableName, $return = true, $times = null) { if (!isset($this->dbStructure)) { diff --git a/tests/Util/VFSTrait.php b/tests/Util/VFSTrait.php index d51ba5b6a5..34763b1385 100644 --- a/tests/Util/VFSTrait.php +++ b/tests/Util/VFSTrait.php @@ -13,6 +13,9 @@ trait VFSTrait */ protected $root; + /** + * Sets up the Virtual File System for Friendica with common files (config, dbstructure) + */ protected function setUpVfsDir() { // the used directories inside the App class $structure = [ @@ -29,6 +32,11 @@ trait VFSTrait $this->setConfigFile('dbstructure.php'); } + /** + * Copying a config file from the file system to the Virtual File System + * + * @param string $filename The filename of the config file + */ protected function setConfigFile($filename) { $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . @@ -43,6 +51,11 @@ trait VFSTrait } } + /** + * Delets a config file from the Virtual File System + * + * @param string $filename The filename of the config file + */ protected function delConfigFile($filename) { if ($this->root->hasChild('config/' . $filename)) { diff --git a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php index 78f4e14e91..1c371f9ba0 100644 --- a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php +++ b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php @@ -3,6 +3,7 @@ namespace Friendica\Test\src\Core\Console; use Friendica\Core\Console\AutomaticInstallation; +use Friendica\Test\Util\DBAMockTrait; use Friendica\Test\Util\DBStructureMockTrait; use org\bovigo\vfs\vfsStream; @@ -13,6 +14,7 @@ use org\bovigo\vfs\vfsStream; */ class AutomaticInstallationConsoleTest extends ConsoleTest { + use DBAMockTrait; use DBStructureMockTrait; private $db_host; @@ -251,9 +253,9 @@ CONF; $console = new AutomaticInstallation(); - $returnStr = $this->dumpExecute($console); + $txt = $this->dumpExecute($console); - $this->assertFinished($returnStr, true); + $this->assertFinished($txt, true); $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')); @@ -290,9 +292,9 @@ CONF; $console->setOption('urlpath', '/friendica'); - $returnStr = $this->dumpExecute($console); + $txt = $this->dumpExecute($console); - $this->assertFinished($returnStr, true); + $this->assertFinished($txt, true); $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')); @@ -311,9 +313,9 @@ CONF; $console = new AutomaticInstallation(); - $returnStr = $this->dumpExecute($console); + $txt = $this->dumpExecute($console); - $this->assertStuckDB($returnStr); + $this->assertStuckDB($txt); } public function testGetHelp() From 92d3d77e76aa21dafca14ee515f664fb81290866 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 31 Oct 2018 11:03:15 +0100 Subject: [PATCH 4/6] Bufixing environment specific assertion problem --- tests/Util/VFSTrait.php | 3 +- tests/datasets/ini/assert_db.ini.php | 56 ------------------- .../AutomaticInstallationConsoleTest.php | 47 ++++++++++++---- 3 files changed, 39 insertions(+), 67 deletions(-) delete mode 100644 tests/datasets/ini/assert_db.ini.php diff --git a/tests/Util/VFSTrait.php b/tests/Util/VFSTrait.php index 34763b1385..972119134a 100644 --- a/tests/Util/VFSTrait.php +++ b/tests/Util/VFSTrait.php @@ -20,7 +20,8 @@ trait VFSTrait // the used directories inside the App class $structure = [ 'config' => [], - 'bin' => [] + 'bin' => [], + 'test' => [] ]; // create a virtual directory and copy all needed files and folders to it diff --git a/tests/datasets/ini/assert_db.ini.php b/tests/datasets/ini/assert_db.ini.php deleted file mode 100644 index f42c9ddba2..0000000000 --- a/tests/datasets/ini/assert_db.ini.php +++ /dev/null @@ -1,56 +0,0 @@ -mockConfigGet('config', 'php_path', false); - $this->assertFile = dirname(__DIR__) . DIRECTORY_SEPARATOR . + $assertFile = dirname(__DIR__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . 'ini' . DIRECTORY_SEPARATOR . 'assert.ini.php'; - $this->assertFileDb = dirname(__DIR__) . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - 'datasets' . DIRECTORY_SEPARATOR . - 'ini' . DIRECTORY_SEPARATOR . - 'assert_db.ini.php'; + $this->assertFile = vfsStream::newFile('assert.ini.php') + ->at($this->root->getChild('test')) + ->setContent($this->replaceEnvironmentSettings($assertFile, false)); + $this->assertFileDb = vfsStream::newFile('assert_db.ini.php') + ->at($this->root->getChild('test')) + ->setContent($this->replaceEnvironmentSettings($assertFile, true)); + } + + /** + * Replacing environment specific variables in the assertion file + * + * @param string $file The file to compare in later tests + * @param bool $withDb If true, db settings are replaced too + * @return string The file content + */ + private function replaceEnvironmentSettings($file, $withDb) + { + $fileContent = file_get_contents($file); + $fileContent = str_replace("/usr/bin/php", trim(shell_exec('which php')), $fileContent); + if ($withDb) { + $fileContent = str_replace("hostname = \"\"", "hostname = \"" . $this->db_host . (!empty($this->db_port) ? ":" . $this->db_port : "") . "\"", $fileContent); + $fileContent = str_replace("username = \"\"", "username = \"" . $this->db_user . "\"", $fileContent); + $fileContent = str_replace("password = \"\"", "password = \"" . $this->db_pass . "\"", $fileContent); + $fileContent = str_replace("database = \"\"", "database = \"" . $this->db_data . "\"", $fileContent); + } + return $fileContent; } private function assertFinished($txt, $withconfig = false, $copyfile = false) @@ -232,7 +259,7 @@ CONF; $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')); $this->assertFileEquals( - $this->assertFileDb, + $this->assertFileDb->url(), $this->root->getChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')->url()); } @@ -260,7 +287,7 @@ CONF; $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')); $this->assertFileEquals( - $this->assertFile, + $this->assertFile->url(), $this->root->getChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')->url()); } @@ -299,7 +326,7 @@ CONF; $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')); $this->assertFileEquals( - $this->assertFileDb, + $this->assertFileDb->url(), $this->root->getChild('config' . DIRECTORY_SEPARATOR . 'local.ini.php')->url()); } From d75cc0cb3454d8299a8b9fa3e2c34406b2129b07 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 31 Oct 2018 11:57:51 +0100 Subject: [PATCH 5/6] Bugfixing executable (Mocking the executable) --- .../AutomaticInstallationConsoleTest.php | 12 ++-- tests/src/Core/Console/ConfigConsoleTest.php | 56 ++++++++++++++++--- tests/src/Core/Console/ConsoleTest.php | 5 +- 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php index 6fc803f842..bed3a578b6 100644 --- a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php +++ b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php @@ -224,7 +224,7 @@ CONF; ->at($this->root) ->setContent($config); - $console = new AutomaticInstallation(); + $console = new AutomaticInstallation($this->consoleArgv); $console->setOption('f', 'prepared.ini.php'); $txt = $this->dumpExecute($console); @@ -249,7 +249,7 @@ CONF; $this->assertTrue(putenv('FRIENDICA_LANG=de')); $this->assertTrue(putenv('FRIENDICA_URL_PATH=/friendica')); - $console = new AutomaticInstallation(); + $console = new AutomaticInstallation($this->consoleArgv); $console->setOption('savedb', true); $txt = $this->dumpExecute($console); @@ -278,7 +278,7 @@ CONF; $this->assertTrue(putenv('FRIENDICA_LANG=de')); $this->assertTrue(putenv('FRIENDICA_URL_PATH=/friendica')); - $console = new AutomaticInstallation(); + $console = new AutomaticInstallation($this->consoleArgv); $txt = $this->dumpExecute($console); @@ -301,7 +301,7 @@ CONF; $this->mockExistsTable('user', false, 1); $this->mockUpdate([false, true, true], null, 1); - $console = new AutomaticInstallation(); + $console = new AutomaticInstallation($this->consoleArgv); $console->setOption('dbhost', $this->db_host); $console->setOption('dbuser', $this->db_user); @@ -338,7 +338,7 @@ CONF; { $this->mockConnect(false, 1); - $console = new AutomaticInstallation(); + $console = new AutomaticInstallation($this->consoleArgv); $txt = $this->dumpExecute($console); @@ -400,7 +400,7 @@ Examples HELP; - $console = new AutomaticInstallation(); + $console = new AutomaticInstallation($this->consoleArgv); $console->setOption('help', true); $txt = $this->dumpExecute($console); diff --git a/tests/src/Core/Console/ConfigConsoleTest.php b/tests/src/Core/Console/ConfigConsoleTest.php index 1d5b3a628e..8f845ae7b0 100644 --- a/tests/src/Core/Console/ConfigConsoleTest.php +++ b/tests/src/Core/Console/ConfigConsoleTest.php @@ -33,7 +33,7 @@ class ConfigConsoleTest extends ConsoleTest function testSetGetKeyValue() { $this->mockConfigSet('config', 'test', 'now', 1); - $console = new Config(); + $console = new Config($this->consoleArgv); $console->setArgument(0, 'config'); $console->setArgument(1, 'test'); $console->setArgument(2, 'now'); @@ -41,14 +41,14 @@ class ConfigConsoleTest extends ConsoleTest $this->assertEquals("config.test <= now\n", $txt); $this->mockConfigGet('config', 'test', 'now', 1); - $console = new Config(); + $console = new Config($this->consoleArgv); $console->setArgument(0, 'config'); $console->setArgument(1, 'test'); $txt = $this->dumpExecute($console); $this->assertEquals("config.test => now\n", $txt); $this->mockConfigGet('config', 'test', null, 1); - $console = new Config(); + $console = new Config($this->consoleArgv); $console->setArgument(0, 'config'); $console->setArgument(1, 'test'); $txt = $this->dumpExecute($console); @@ -59,7 +59,7 @@ class ConfigConsoleTest extends ConsoleTest $testArray = [1, 2, 3]; $this->mockConfigGet('config', 'test', $testArray, 1); - $console = new Config(); + $console = new Config($this->consoleArgv); $console->setArgument(0, 'config'); $console->setArgument(1, 'test'); $console->setArgument(2, 'now'); @@ -69,7 +69,7 @@ class ConfigConsoleTest extends ConsoleTest } function testTooManyArguments() { - $console = new Config(); + $console = new Config($this->consoleArgv); $console->setArgument(0, 'config'); $console->setArgument(1, 'test'); $console->setArgument(2, 'it'); @@ -82,12 +82,13 @@ class ConfigConsoleTest extends ConsoleTest function testVerbose() { $this->mockConfigGet('test', 'it', 'now', 1); - $console = new Config(); + $console = new Config($this->consoleArgv); $console->setArgument(0, 'test'); $console->setArgument(1, 'it'); $console->setOption('v', 1); + $executable = $this->consoleArgv[0]; $assertion = << 'test', @@ -112,4 +113,45 @@ CONF; $txt = $this->dumpExecute($console); $this->assertSame("Unable to set test.it\n", $txt); } + + public function testGetHelp() + { + // Usable to purposely fail if new commands are added without taking tests into account + $theHelp = << [-h|--help|-?] [-v] + bin/console config [-h|--help|-?] [-v] + bin/console config [-h|--help|-?] [-v] + +Description + bin/console config + Lists all config values + + bin/console config + Lists all config values in the provided category + + bin/console config + Shows the value of the provided key in the category + + bin/console config + Sets the value of the provided key in the category + +Notes: + Setting config entries which are manually set in config/local.ini.php may result in + conflict between database settings and the manual startup settings. + +Options + -h|--help|-? Show help information + -v Show more debug information. + +HELP; + $console = new Config($this->consoleArgv); + $console->setOption('help', true); + + $txt = $this->dumpExecute($console); + + $this->assertEquals($txt, $theHelp); + } } diff --git a/tests/src/Core/Console/ConsoleTest.php b/tests/src/Core/Console/ConsoleTest.php index 6b58ccced2..0997269c06 100644 --- a/tests/src/Core/Console/ConsoleTest.php +++ b/tests/src/Core/Console/ConsoleTest.php @@ -13,7 +13,10 @@ abstract class ConsoleTest extends TestCase use VFSTrait; use AppMockTrait; - protected $stdout; + /** + * @var array The default argv for a Console Instance + */ + protected $consoleArgv = [ 'consoleTest.php' ]; protected function setUp() { From 764e1a3cb69931256bbba48bcd68331ef71690e0 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 31 Oct 2018 12:37:01 +0100 Subject: [PATCH 6/6] Fixing issue L10n::t() --- tests/Util/AppMockTrait.php | 4 ++-- tests/src/Core/Console/AutomaticInstallationConsoleTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Util/AppMockTrait.php b/tests/Util/AppMockTrait.php index cdd5aedd5d..72c0dc429b 100644 --- a/tests/Util/AppMockTrait.php +++ b/tests/Util/AppMockTrait.php @@ -27,10 +27,10 @@ trait AppMockTrait */ public function mockApp($root) { - /// @todo This mock is ugly. We return an empty string for each translation - no workaround yet + // simply returning the input when using L10n::t() $l10nMock = \Mockery::mock('alias:Friendica\Core\L10n'); $l10nMock->shouldReceive('t') - ->andReturn(''); + ->andReturnUsing(function ($arg) { return $arg; }); $this->mockConfigGet('system', 'theme', 'testtheme'); diff --git a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php index bed3a578b6..0430e678c5 100644 --- a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php +++ b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php @@ -168,7 +168,7 @@ Creating config file... Checking database... [Error] -------- -: +Could not connect to database.: FIN;