]> git.mxchange.org Git - friendica.git/blob - tests/src/Core/Console/AutomaticInstallationConsoleTest.php
remove currently unused testdata
[friendica.git] / tests / src / Core / Console / AutomaticInstallationConsoleTest.php
1 <?php
2
3 namespace Friendica\Test\src\Core\Console;
4
5 use Friendica\Core\Config\Cache\ConfigCache;
6 use Friendica\Core\Console\AutomaticInstallation;
7 use Friendica\Core\Installer;
8 use Friendica\Core\Logger;
9 use Friendica\Test\Util\DBAMockTrait;
10 use Friendica\Test\Util\DBStructureMockTrait;
11 use Friendica\Test\Util\L10nMockTrait;
12 use Friendica\Test\Util\RendererMockTrait;
13 use Friendica\Util\Logger\VoidLogger;
14 use org\bovigo\vfs\vfsStream;
15 use org\bovigo\vfs\vfsStreamFile;
16
17 /**
18  * @runTestsInSeparateProcesses
19  * @preserveGlobalState disabled
20  * @requires PHP 7.0
21  */
22 class AutomaticInstallationConsoleTest extends ConsoleTest
23 {
24         use L10nMockTrait;
25         use DBAMockTrait;
26         use DBStructureMockTrait;
27         use RendererMockTrait;
28
29         /**
30          * @var vfsStreamFile Assert file without DB credentials
31          */
32         private $assertFile;
33         /**
34          * @var vfsStreamFile Assert file with DB credentials
35          */
36         private $assertFileDb;
37
38         /**
39          * @var ConfigCache The configuration cache to check after each test
40          */
41         private $configCache;
42
43         public function setUp()
44         {
45                 parent::setUp();
46
47                 if ($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')) {
48                         $this->root->getChild('config')
49                                 ->removeChild('local.config.php');
50                 }
51
52                 $this->mockL10nT();
53
54                 $this->configCache = new ConfigCache();
55                 $this->configCache->set('system', 'basepath', $this->root->url());
56                 $this->configCache->set('config', 'php_path', trim(shell_exec('which php')));
57
58                 $this->mockApp($this->root, null, true);
59
60                 $this->configMock->shouldReceive('set')->andReturnUsing(function ($cat, $key, $value) {
61                         if ($key !== 'basepath') {
62                                 return $this->configCache->set($cat, $key, $value);
63                         } else {
64                                 return true;
65                         }
66                 });
67
68                 $this->configMock->shouldReceive('has')->andReturn(true);
69                 $this->configMock->shouldReceive('get')->andReturnUsing(function ($cat, $key) {
70                         return $this->configCache->get($cat, $key);
71                 });
72                 $this->configMock->shouldReceive('load')->andReturnUsing(function ($config, $overwrite = false) {
73                         return $this->configCache->load($config, $overwrite);
74                 });
75
76                 $this->mode->shouldReceive('isInstall')->andReturn(true);
77                 Logger::init(new VoidLogger());
78         }
79
80         /**
81          * Returns the dataset for each automatic installation test
82          *
83          * @return array the dataset
84          */
85         public function dataInstaller()
86         {
87                 return [
88                         'empty' => [
89                                 'data' => [
90                                         'database' => [
91                                                 'hostname'    => '',
92                                                 'username'    => '',
93                                                 'password'    => '',
94                                                 'database'    => '',
95                                                 'port'        => '',
96                                         ],
97                                         'config' => [
98                                                 'php_path'    => '',
99                                                 'admin_email' => '',
100                                         ],
101                                         'system' => [
102                                                 'urlpath'     => '',
103                                                 'default_timezone' => '',
104                                                 'language'    => '',
105                                         ],
106                                 ],
107                         ],
108                         'normal' => [
109                                 'data' => [
110                                         'database' => [
111                                                 'hostname'    => 'testhost',
112                                                 'port'        => 3306,
113                                                 'username'    => 'friendica',
114                                                 'password'    => 'a password',
115                                                 'database'    => 'database',
116                                         ],
117                                         'config' => [
118                                                 'php_path'    => '',
119                                                 'admin_email' => 'admin@philipp.info',
120                                         ],
121                                         'system' => [
122                                                 'urlpath'     => 'test/it',
123                                                 'default_timezone' => 'en',
124                                                 'language'    => 'Europe/Berlin',
125                                         ],
126                                 ],
127                         ],
128                         'special' => [
129                                 'data' => [
130                                         'database' => [
131                                                 'hostname'    => 'testhost.new.domain',
132                                                 'port'        => 3341,
133                                                 'username'    => 'fr"ยง%ica',
134                                                 'password'    => '$%\"gse',
135                                                 'database'    => 'db',
136                                         ],
137                                         'config' => [
138                                                 'php_path'    => '',
139                                                 'admin_email' => 'admin@philipp.info',
140                                         ],
141                                         'system' => [
142                                                 'urlpath'     => 'test/it',
143                                                 'default_timezone' => 'en',
144                                                 'language'    => 'Europe/Berlin',
145                                         ],
146                                 ],
147                         ],
148                 ];
149         }
150
151         private function assertFinished($txt, $withconfig = false, $copyfile = false)
152         {
153                 $cfg = '';
154
155                 if ($withconfig) {
156                         $cfg = <<<CFG
157
158
159 Creating config file...
160
161  Complete!
162 CFG;
163                 }
164
165                 if ($copyfile) {
166                         $cfg = <<<CFG
167
168
169 Copying config file...
170
171  Complete!
172 CFG;
173                 }
174
175                 $finished = <<<FIN
176 Initializing setup...
177
178  Complete!
179
180
181 Checking environment...
182
183  NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.
184
185  Complete!
186 {$cfg}
187
188
189 Checking database...
190
191  Complete!
192
193
194 Inserting data into database...
195
196  Complete!
197
198
199 Installing theme
200
201  Complete
202
203
204
205 Installation is finished
206
207
208 FIN;
209                 $this->assertEquals($finished, $txt);
210         }
211
212         private function assertStuckDB($txt)
213         {
214                 $finished = <<<FIN
215 Initializing setup...
216
217  Complete!
218
219
220 Checking environment...
221
222  NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.
223
224  Complete!
225
226
227 Creating config file...
228
229  Complete!
230
231
232 Checking database...
233
234 [Error] --------
235 Could not connect to database.: 
236
237
238 FIN;
239
240                 $this->assertEquals($finished, $txt);
241         }
242
243         /**
244          * Asserts one config entry
245          *
246          * @param string     $cat           The category to test
247          * @param string     $key           The key to test
248          * @param null|array $assertion     The asserted value (null = empty, or array/string)
249          * @param string     $default_value The default value
250          */
251         public function assertConfigEntry($cat, $key, $assertion = null, $default_value = null)
252         {
253                 if (!empty($assertion[$cat][$key])) {
254                         $this->assertEquals($assertion[$cat][$key], $this->configCache->get($cat, $key));
255                 } elseif (!empty($assertion) && !is_array($assertion)) {
256                         $this->assertEquals($assertion, $this->configCache->get($cat, $key));
257                 } elseif (!empty($default_value)) {
258                         $this->assertEquals($default_value, $this->configCache->get($cat, $key));
259                 } else {
260                         $this->assertEmpty($this->configCache->get($cat, $key), $this->configCache->get($cat, $key));
261                 }
262         }
263
264         /**
265          * Asserts all config entries
266          *
267          * @param null|array $assertion    The optional assertion array
268          * @param boolean    $saveDb       True, if the db credentials should get saved to the file
269          * @param boolean    $default      True, if we use the default values
270          * @param boolean    $defaultDb    True, if we use the default value for the DB
271          */
272         public function assertConfig($assertion = null, $saveDb = false, $default = true, $defaultDb = true)
273         {
274                 if (!empty($assertion['database']['hostname'])) {
275                         $assertion['database']['hostname'] .= (!empty($assertion['database']['port']) ? ':' . $assertion['database']['port'] : '');
276                 }
277
278                 $this->assertConfigEntry('database', 'hostname', ($saveDb) ? $assertion : null, (!$saveDb || $defaultDb) ? Installer::DEFAULT_HOST : null);
279                 $this->assertConfigEntry('database', 'username', ($saveDb) ? $assertion : null);
280                 $this->assertConfigEntry('database', 'password', ($saveDb) ? $assertion : null);
281                 $this->assertConfigEntry('database', 'database', ($saveDb) ? $assertion : null);
282
283                 $this->assertConfigEntry('config', 'admin_email', $assertion);
284                 $this->assertConfigEntry('config', 'php_path', trim(shell_exec('which php')));
285
286                 $this->assertConfigEntry('system', 'default_timezone', $assertion, ($default) ? Installer::DEFAULT_TZ : null);
287                 $this->assertConfigEntry('system', 'language', $assertion, ($default) ? Installer::DEFAULT_LANG : null);
288         }
289
290         /**
291          * Test the automatic installation without any parameter/setting
292          */
293         public function testEmpty()
294         {
295                 $this->app->shouldReceive('getURLPath')->andReturn('')->atLeast()->once();
296
297                 $this->mockConnect(true, 1);
298                 $this->mockConnected(true, 1);
299                 $this->mockExistsTable('user', false, 1);
300                 $this->mockUpdate([$this->root->url(), false, true, true], null, 1);
301
302                 $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1);
303                 $this->mockReplaceMacros('testTemplate', \Mockery::any(), '', 1);
304
305                 $console = new AutomaticInstallation($this->consoleArgv);
306
307                 $txt = $this->dumpExecute($console);
308
309                 $this->assertFinished($txt, true, false);
310                 $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php'));
311
312                 $this->assertConfig();
313         }
314
315         /**
316          * Test the automatic installation with a prepared config file
317          * @dataProvider dataInstaller
318          */
319         public function testWithConfig(array $data)
320         {
321                 $this->mockConnect(true, 1);
322                 $this->mockConnected(true, 1);
323                 $this->mockExistsTable('user', false, 1);
324                 $this->mockUpdate([$this->root->url(), false, true, true], null, 1);
325
326                 $conf = function ($cat, $key) use ($data) {
327                         if ($cat == 'database' && $key == 'hostname' && !empty($data['database']['port'])) {
328                                 return $data[$cat][$key] . ':' . $data['database']['port'];
329                         }
330                         return $data[$cat][$key];
331                 };
332
333                 $config = <<<CONF
334 <?php
335
336 // Local configuration
337
338 // If you're unsure about what any of the config keys below do, please check the config/defaults.config.php for detailed
339 // documentation of their data type and behavior.
340
341 return [
342         'database' => [
343                 'hostname' => '{$conf('database', 'hostname')}',
344                 'username' => '{$conf('database', 'username')}',
345                 'password' => '{$conf('database', 'password')}',
346                 'database' => '{$conf('database', 'database')}',
347                 'charset' => 'utf8mb4',
348         ],
349
350         // ****************************************************************
351         // The configuration below will be overruled by the admin panel.
352         // Changes made below will only have an effect if the database does
353         // not contain any configuration for the friendica system.
354         // ****************************************************************
355
356         'config' => [
357                 'admin_email' => '{$conf('config', 'admin_email')}',
358                 'sitename' => 'Friendica Social Network',
359                 'register_policy' => \Friendica\Module\Register::OPEN,
360                 'register_text' => '',
361         ],
362         'system' => [
363                 'urlpath' => '{$conf('system', 'urlpath')}',
364                 'default_timezone' => '{$conf('system', 'default_timezone')}',
365                 'language' => '{$conf('system', 'language')}',
366         ],
367 ];
368 CONF;
369
370                 vfsStream::newFile('prepared.config.php')
371                         ->at($this->root)
372                         ->setContent($config);
373
374                 $console = new AutomaticInstallation($this->consoleArgv);
375                 $console->setOption('f', 'prepared.config.php');
376
377                 $txt = $this->dumpExecute($console);
378
379                 $this->assertFinished($txt, false, true);
380
381                 $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php'));
382                 $this->assertEquals($config, file_get_contents($this->root->getChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')->url()));
383
384                 $this->assertConfig($data, true, false, false);
385         }
386
387         /**
388          * Test the automatic installation with environment variables
389          * Includes saving the DB credentials to the file
390          * @dataProvider dataInstaller
391          */
392         public function testWithEnvironmentAndSave(array $data)
393         {
394                 $this->app->shouldReceive('getURLPath')->andReturn('')->atLeast()->once();
395
396                 $this->mockConnect(true, 1);
397                 $this->mockConnected(true, 1);
398                 $this->mockExistsTable('user', false, 1);
399                 $this->mockUpdate([$this->root->url(), false, true, true], null, 1);
400
401                 $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1);
402                 $this->mockReplaceMacros('testTemplate', \Mockery::any(), '', 1);
403
404                 $this->assertTrue(putenv('MYSQL_HOST='     . $data['database']['hostname']));
405                 $this->assertTrue(putenv('MYSQL_PORT='     . $data['database']['port']));
406                 $this->assertTrue(putenv('MYSQL_DATABASE=' . $data['database']['database']));
407                 $this->assertTrue(putenv('MYSQL_USERNAME=' . $data['database']['username']));
408                 $this->assertTrue(putenv('MYSQL_PASSWORD=' . $data['database']['password']));
409
410                 $this->assertTrue(putenv('FRIENDICA_URL_PATH='   . $data['system']['urlpath']));
411                 $this->assertTrue(putenv('FRIENDICA_PHP_PATH='   . $data['config']['php_path']));
412                 $this->assertTrue(putenv('FRIENDICA_ADMIN_MAIL=' . $data['config']['admin_email']));
413                 $this->assertTrue(putenv('FRIENDICA_TZ='         . $data['system']['default_timezone']));
414                 $this->assertTrue(putenv('FRIENDICA_LANG='       . $data['system']['language']));
415
416                 $console = new AutomaticInstallation($this->consoleArgv);
417                 $console->setOption('savedb', true);
418
419                 $txt = $this->dumpExecute($console);
420
421                 $this->assertFinished($txt, true);
422                 $this->assertConfig($data, true, true, false);
423         }
424
425         /**
426          * Test the automatic installation with environment variables
427          * Don't save the db credentials to the file
428          * @dataProvider dataInstaller
429          */
430         public function testWithEnvironmentWithoutSave(array $data)
431         {
432                 $this->app->shouldReceive('getURLPath')->andReturn('')->atLeast()->once();
433
434                 $this->mockConnect(true, 1);
435                 $this->mockConnected(true, 1);
436                 $this->mockExistsTable('user', false, 1);
437                 $this->mockUpdate([$this->root->url(), false, true, true], null, 1);
438
439                 $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1);
440                 $this->mockReplaceMacros('testTemplate', \Mockery::any(), '', 1);
441
442                 $this->assertTrue(putenv('MYSQL_HOST=' . $data['database']['hostname']));
443                 $this->assertTrue(putenv('MYSQL_PORT=' . $data['database']['port']));
444                 $this->assertTrue(putenv('MYSQL_DATABASE=' . $data['database']['database']));
445                 $this->assertTrue(putenv('MYSQL_USERNAME=' . $data['database']['username']));
446                 $this->assertTrue(putenv('MYSQL_PASSWORD=' . $data['database']['password']));
447
448                 $this->assertTrue(putenv('FRIENDICA_URL_PATH=' . $data['system']['urlpath']));
449                 $this->assertTrue(putenv('FRIENDICA_PHP_PATH=' . $data['config']['php_path']));
450                 $this->assertTrue(putenv('FRIENDICA_ADMIN_MAIL=' . $data['config']['admin_email']));
451                 $this->assertTrue(putenv('FRIENDICA_TZ=' . $data['system']['default_timezone']));
452                 $this->assertTrue(putenv('FRIENDICA_LANG=' . $data['system']['language']));
453
454                 $console = new AutomaticInstallation($this->consoleArgv);
455
456                 $txt = $this->dumpExecute($console);
457
458                 $this->assertFinished($txt, true);
459                 $this->assertConfig($data, false, true);
460         }
461
462         /**
463          * Test the automatic installation with arguments
464          * @dataProvider dataInstaller
465          */
466         public function testWithArguments(array $data)
467         {
468                 $this->app->shouldReceive('getURLPath')->andReturn('')->atLeast()->once();
469
470                 $this->mockConnect(true, 1);
471                 $this->mockConnected(true, 1);
472                 $this->mockExistsTable('user', false, 1);
473                 $this->mockUpdate([$this->root->url(), false, true, true], null, 1);
474
475                 $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1);
476                 $this->mockReplaceMacros('testTemplate', \Mockery::any(), '', 1);
477
478                 $console = new AutomaticInstallation($this->consoleArgv);
479
480                 $option = function($var, $cat, $key) use ($data, $console) {
481                         if (!empty($data[$cat][$key])) {
482                                 $console->setOption($var, $data[$cat][$key]);
483                         }
484                 };
485                 $option('dbhost'   , 'database', 'hostname');
486                 $option('dbport'   , 'database', 'port');
487                 $option('dbuser'   , 'database', 'username');
488                 $option('dbpass'   , 'database', 'password');
489                 $option('dbdata'   , 'database', 'database');
490                 $option('urlpath'  , 'system'  , 'urlpath');
491                 $option('phppath'  , 'config'  , 'php_path');
492                 $option('admin'    , 'config'  , 'admin_email');
493                 $option('tz'       , 'system'  , 'default_timezone');
494                 $option('lang'     , 'system'  , 'language');
495
496                 $txt = $this->dumpExecute($console);
497
498                 $this->assertFinished($txt, true);
499                 $this->assertConfig($data, true, true, true);
500         }
501
502         /**
503          * Test the automatic installation with a wrong database connection
504          */
505         public function testNoDatabaseConnection()
506         {
507                 $this->app->shouldReceive('getURLPath')->andReturn('')->atLeast()->once();
508                 $this->mockConnect(false, 1);
509
510                 $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1);
511                 $this->mockReplaceMacros('testTemplate', \Mockery::any(), '', 1);
512
513                 $console = new AutomaticInstallation($this->consoleArgv);
514
515                 $txt = $this->dumpExecute($console);
516
517                 $this->assertStuckDB($txt);
518                 $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php'));
519
520                 $this->assertConfig(null, false, true, false);
521         }
522
523         public function testGetHelp()
524         {
525                 // Usable to purposely fail if new commands are added without taking tests into account
526                 $theHelp = <<<HELP
527 Installation - Install Friendica automatically
528 Synopsis
529         bin/console autoinstall [-h|--help|-?] [-v] [-a] [-f]
530
531 Description
532     Installs Friendica with data based on the local.config.php file or environment variables
533
534 Notes
535     Not checking .htaccess/URL-Rewrite during CLI installation.
536
537 Options
538     -h|--help|-?            Show help information
539     -v                      Show more debug information.
540     -a                      All setup checks are required (except .htaccess)
541     -f|--file <config>      prepared config file (e.g. "config/local.config.php" itself) which will override every other config option - except the environment variables)
542     -s|--savedb             Save the DB credentials to the file (if environment variables is used)
543     -H|--dbhost <host>      The host of the mysql/mariadb database (env MYSQL_HOST)
544     -p|--dbport <port>      The port of the mysql/mariadb database (env MYSQL_PORT)
545     -d|--dbdata <database>  The name of the mysql/mariadb database (env MYSQL_DATABASE)
546     -U|--dbuser <username>  The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
547     -P|--dbpass <password>  The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
548     -u|--urlpath <url_path> The URL path of Friendica - f.e. '/friendica' (env FRIENDICA_URL_PATH) 
549     -b|--phppath <php_path> The path of the PHP binary (env FRIENDICA_PHP_PATH) 
550     -A|--admin <mail>       The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL)
551     -T|--tz <timezone>      The timezone of Friendica (env FRIENDICA_TZ)
552     -L|--lang <language>    The language of Friendica (env FRIENDICA_LANG)
553  
554 Environment variables
555    MYSQL_HOST                  The host of the mysql/mariadb database (mandatory if mysql and environment is used)
556    MYSQL_PORT                  The port of the mysql/mariadb database
557    MYSQL_USERNAME|MYSQL_USER   The username of the mysql/mariadb database login (MYSQL_USERNAME is for mysql, MYSQL_USER for mariadb)
558    MYSQL_PASSWORD              The password of the mysql/mariadb database login
559    MYSQL_DATABASE              The name of the mysql/mariadb database
560    FRIENDICA_URL_PATH          The URL path of Friendica (f.e. '/friendica')
561    FRIENDICA_PHP_PATH          The path of the PHP binary
562    FRIENDICA_ADMIN_MAIL        The admin email address of Friendica (this email will be used for admin access)
563    FRIENDICA_TZ                The timezone of Friendica
564    FRIENDICA_LANG              The langauge of Friendica
565    
566 Examples
567         bin/console autoinstall -f 'input.config.php
568                 Installs Friendica with the prepared 'input.config.php' file
569
570         bin/console autoinstall --savedb
571                 Installs Friendica with environment variables and saves them to the 'config/local.config.php' file
572
573         bin/console autoinstall -h localhost -p 3365 -U user -P passwort1234 -d friendica
574                 Installs Friendica with a local mysql database with credentials
575
576 HELP;
577
578                 $console = new AutomaticInstallation($this->consoleArgv);
579                 $console->setOption('help', true);
580
581                 $txt = $this->dumpExecute($console);
582
583                 $this->assertEquals($theHelp, $txt);
584         }
585 }