]> git.mxchange.org Git - friendica.git/blob - tests/src/Core/InstallerTest.php
Adding basepath, urlpath, hostname and ssl_policy to installation
[friendica.git] / tests / src / Core / InstallerTest.php
1 <?php
2
3 // this is in the same namespace as Install for mocking 'function_exists'
4 namespace Friendica\Core;
5
6 use Friendica\Core\Config\Cache\IConfigCache;
7 use Friendica\Network\CurlResult;
8 use Friendica\Object\Image;
9 use Friendica\Test\MockedTest;
10 use Friendica\Test\Util\L10nMockTrait;
11 use Friendica\Test\Util\VFSTrait;
12 use Friendica\Util\Network;
13
14 /**
15  * @runTestsInSeparateProcesses
16  * @preserveGlobalState disabled
17  */
18 class InstallerTest extends MockedTest
19 {
20         use VFSTrait;
21         use L10nMockTrait;
22
23         public function setUp()
24         {
25                 parent::setUp();
26
27                 $this->setUpVfsDir();
28         }
29
30         /**
31          * Mocking the L10n::t() calls for the function checks
32          */
33         private function mockFunctionL10TCalls()
34         {
35                 $this->mockL10nT('Apache mod_rewrite module', 1);
36                 $this->mockL10nT('PDO or MySQLi PHP module', 1);
37                 $this->mockL10nT('libCurl PHP module', 1);
38                 $this->mockL10nT('Error: libCURL PHP module required but not installed.', 1);
39                 $this->mockL10nT('XML PHP module', 1);
40                 $this->mockL10nT('GD graphics PHP module', 1);
41                 $this->mockL10nT('Error: GD graphics PHP module with JPEG support required but not installed.', 1);
42                 $this->mockL10nT('OpenSSL PHP module', 1);
43                 $this->mockL10nT('Error: openssl PHP module required but not installed.', 1);
44                 $this->mockL10nT('mb_string PHP module', 1);
45                 $this->mockL10nT('Error: mb_string PHP module required but not installed.', 1);
46                 $this->mockL10nT('iconv PHP module', 1);
47                 $this->mockL10nT('Error: iconv PHP module required but not installed.', 1);
48                 $this->mockL10nT('POSIX PHP module', 1);
49                 $this->mockL10nT('Error: POSIX PHP module required but not installed.', 1);
50                 $this->mockL10nT('JSON PHP module', 1);
51                 $this->mockL10nT('Error: JSON PHP module required but not installed.', 1);
52                 $this->mockL10nT('File Information PHP module', 1);
53                 $this->mockL10nT('Error: File Information PHP module required but not installed.', 1);
54         }
55
56         private function assertCheckExist($position, $title, $help, $status, $required, $assertionArray)
57         {
58                 $this->assertArraySubset([$position => [
59                         'title' => $title,
60                         'status' => $status,
61                         'required' => $required,
62                         'error_msg' => null,
63                         'help' => $help]
64                 ], $assertionArray);
65         }
66
67         /**
68          * Replaces function_exists results with given mocks
69          *
70          * @param array $functions a list from function names and their result
71          */
72         private function setFunctions($functions)
73         {
74                 global $phpMock;
75                 $phpMock['function_exists'] = function($function) use ($functions) {
76                         foreach ($functions as $name => $value) {
77                                 if ($function == $name) {
78                                         return $value;
79                                 }
80                         }
81                         return '__phpunit_continue__';
82                 };
83         }
84
85         /**
86          * Replaces class_exist results with given mocks
87          *
88          * @param array $classes a list from class names and their results
89          */
90         private function setClasses($classes)
91         {
92                 global $phpMock;
93                 $phpMock['class_exists'] = function($class) use ($classes) {
94                         foreach ($classes as $name => $value) {
95                                 if ($class == $name) {
96                                         return $value;
97                                 }
98                         }
99                         return '__phpunit_continue__';
100                 };
101         }
102
103         /**
104          * @small
105          */
106         public function testCheckKeys()
107         {
108                 $this->mockL10nT();
109
110                 $this->setFunctions(['openssl_pkey_new' => false]);
111                 $install = new Installer();
112                 $this->assertFalse($install->checkKeys());
113
114                 $this->setFunctions(['openssl_pkey_new' => true]);
115                 $install = new Installer();
116                 $this->assertTrue($install->checkKeys());
117         }
118
119         /**
120          * @small
121          */
122         public function testCheckFunctions()
123         {
124                 $this->mockFunctionL10TCalls();
125                 $this->setFunctions(['curl_init' => false, 'imagecreatefromjpeg' => true]);
126                 $install = new Installer();
127                 $this->assertFalse($install->checkFunctions());
128                 $this->assertCheckExist(3,
129                         'libCurl PHP module',
130                         'Error: libCURL PHP module required but not installed.',
131                         false,
132                         true,
133                         $install->getChecks());
134
135                 $this->mockFunctionL10TCalls();
136                 $this->setFunctions(['imagecreatefromjpeg' => false]);
137                 $install = new Installer();
138                 $this->assertFalse($install->checkFunctions());
139                 $this->assertCheckExist(4,
140                         'GD graphics PHP module',
141                         'Error: GD graphics PHP module with JPEG support required but not installed.',
142                         false,
143                         true,
144                         $install->getChecks());
145
146                 $this->mockFunctionL10TCalls();
147                 $this->setFunctions(['openssl_public_encrypt' => false]);
148                 $install = new Installer();
149                 $this->assertFalse($install->checkFunctions());
150                 $this->assertCheckExist(5,
151                         'OpenSSL PHP module',
152                         'Error: openssl PHP module required but not installed.',
153                         false,
154                         true,
155                         $install->getChecks());
156
157                 $this->mockFunctionL10TCalls();
158                 $this->setFunctions(['mb_strlen' => false]);
159                 $install = new Installer();
160                 $this->assertFalse($install->checkFunctions());
161                 $this->assertCheckExist(6,
162                         'mb_string PHP module',
163                         'Error: mb_string PHP module required but not installed.',
164                         false,
165                         true,
166                         $install->getChecks());
167
168                 $this->mockFunctionL10TCalls();
169                 $this->setFunctions(['iconv_strlen' => false]);
170                 $install = new Installer();
171                 $this->assertFalse($install->checkFunctions());
172                 $this->assertCheckExist(7,
173                         'iconv PHP module',
174                         'Error: iconv PHP module required but not installed.',
175                         false,
176                         true,
177                         $install->getChecks());
178
179                 $this->mockFunctionL10TCalls();
180                 $this->setFunctions(['posix_kill' => false]);
181                 $install = new Installer();
182                 $this->assertFalse($install->checkFunctions());
183                 $this->assertCheckExist(8,
184                         'POSIX PHP module',
185                         'Error: POSIX PHP module required but not installed.',
186                         false,
187                         true,
188                         $install->getChecks());
189
190                 $this->mockFunctionL10TCalls();
191                 $this->setFunctions(['json_encode' => false]);
192                 $install = new Installer();
193                 $this->assertFalse($install->checkFunctions());
194                 $this->assertCheckExist(9,
195                         'JSON PHP module',
196                         'Error: JSON PHP module required but not installed.',
197                         false,
198                         true,
199                         $install->getChecks());
200
201                 $this->mockFunctionL10TCalls();
202                 $this->setFunctions(['finfo_open' => false]);
203                 $install = new Installer();
204                 $this->assertFalse($install->checkFunctions());
205                 $this->assertCheckExist(10,
206                         'File Information PHP module',
207                         'Error: File Information PHP module required but not installed.',
208                         false,
209                         true,
210                         $install->getChecks());
211
212                 $this->mockFunctionL10TCalls();
213                 $this->setFunctions([
214                         'curl_init' => true,
215                         'imagecreatefromjpeg' => true,
216                         'openssl_public_encrypt' => true,
217                         'mb_strlen' => true,
218                         'iconv_strlen' => true,
219                         'posix_kill' => true,
220                         'json_encode' => true,
221                         'finfo_open' => true,
222                 ]);
223                 $install = new Installer();
224                 $this->assertTrue($install->checkFunctions());
225         }
226
227         /**
228          * @small
229          */
230         public function testCheckLocalIni()
231         {
232                 $this->mockL10nT();
233
234                 $this->assertTrue($this->root->hasChild('config/local.config.php'));
235
236                 $install = new Installer();
237                 $this->assertTrue($install->checkLocalIni());
238
239                 $this->delConfigFile('local.config.php');
240
241                 $this->assertFalse($this->root->hasChild('config/local.config.php'));
242
243                 $install = new Installer();
244                 $this->assertTrue($install->checkLocalIni());
245         }
246
247         /**
248          * @small
249          */
250         public function testCheckHtAccessFail()
251         {
252                 $this->mockL10nT();
253
254                 // Mocking the CURL Response
255                 $curlResult = \Mockery::mock(CurlResult::class);
256                 $curlResult
257                         ->shouldReceive('getReturnCode')
258                         ->andReturn('404');
259                 $curlResult
260                         ->shouldReceive('getRedirectUrl')
261                         ->andReturn('');
262                 $curlResult
263                         ->shouldReceive('getError')
264                         ->andReturn('test Error');
265
266                 // Mocking the CURL Request
267                 $networkMock = \Mockery::mock('alias:' . Network::class);
268                 $networkMock
269                         ->shouldReceive('fetchUrlFull')
270                         ->with('https://test/install/testrewrite')
271                         ->andReturn($curlResult);
272                 $networkMock
273                         ->shouldReceive('fetchUrlFull')
274                         ->with('http://test/install/testrewrite')
275                         ->andReturn($curlResult);
276
277                 // Mocking that we can use CURL
278                 $this->setFunctions(['curl_init' => true]);
279
280                 $install = new Installer();
281
282                 $this->assertFalse($install->checkHtAccess('https://test'));
283                 $this->assertSame('test Error', $install->getChecks()[0]['error_msg']['msg']);
284         }
285
286         /**
287          * @small
288          */
289         public function testCheckHtAccessWork()
290         {
291                 $this->mockL10nT();
292
293                 // Mocking the failed CURL Response
294                 $curlResultF = \Mockery::mock(CurlResult::class);
295                 $curlResultF
296                         ->shouldReceive('getReturnCode')
297                         ->andReturn('404');
298
299                 // Mocking the working CURL Response
300                 $curlResultW = \Mockery::mock(CurlResult::class);
301                 $curlResultW
302                         ->shouldReceive('getReturnCode')
303                         ->andReturn('204');
304
305                 // Mocking the CURL Request
306                 $networkMock = \Mockery::mock('alias:' . Network::class);
307                 $networkMock
308                         ->shouldReceive('fetchUrlFull')
309                         ->with('https://test/install/testrewrite')
310                         ->andReturn($curlResultF);
311                 $networkMock
312                         ->shouldReceive('fetchUrlFull')
313                         ->with('http://test/install/testrewrite')
314                         ->andReturn($curlResultW);
315
316                 // Mocking that we can use CURL
317                 $this->setFunctions(['curl_init' => true]);
318
319                 // needed because of "normalise_link"
320                 require_once __DIR__ . '/../../../include/text.php';
321
322                 $install = new Installer();
323
324                 $this->assertTrue($install->checkHtAccess('https://test'));
325         }
326
327         /**
328          * @small
329          */
330         public function testImagick()
331         {
332                 $this->mockL10nT();
333
334                 $imageMock = \Mockery::mock('alias:'. Image::class);
335                 $imageMock
336                         ->shouldReceive('supportedTypes')
337                         ->andReturn(['image/gif' => 'gif']);
338
339                 $this->setClasses(['Imagick' => true]);
340
341                 $install = new Installer();
342
343                 // even there is no supported type, Imagick should return true (because it is not required)
344                 $this->assertTrue($install->checkImagick());
345
346                 $this->assertCheckExist(1,
347                         L10n::t('ImageMagick supports GIF'),
348                         '',
349                         true,
350                         false,
351                         $install->getChecks());
352         }
353
354         /**
355          * @small
356          */
357         public function testImagickNotFound()
358         {
359                 $this->mockL10nT();
360
361                 $imageMock = \Mockery::mock('alias:' . Image::class);
362                 $imageMock
363                         ->shouldReceive('supportedTypes')
364                         ->andReturn([]);
365
366                 $this->setClasses(['Imagick' => true]);
367
368                 $install = new Installer();
369
370                 // even there is no supported type, Imagick should return true (because it is not required)
371                 $this->assertTrue($install->checkImagick());
372                 $this->assertCheckExist(1,
373                         L10n::t('ImageMagick supports GIF'),
374                         '',
375                         false,
376                         false,
377                         $install->getChecks());
378         }
379
380         public function testImagickNotInstalled()
381         {
382                 $this->setClasses(['Imagick' => false]);
383                 $this->mockL10nT('ImageMagick PHP extension is not installed');
384
385                 $install = new Installer();
386
387                 // even there is no supported type, Imagick should return true (because it is not required)
388                 $this->assertTrue($install->checkImagick());
389                 $this->assertCheckExist(0,
390                         'ImageMagick PHP extension is not installed',
391                         '',
392                         false,
393                         false,
394                         $install->getChecks());
395         }
396
397         /**
398          * Test the setup of the config cache for installation
399          */
400         public function testSetUpCache()
401         {
402                 $this->mockL10nT();
403
404                 $install = new Installer();
405                 $configCache = \Mockery::mock(IConfigCache::class);
406                 $configCache->shouldReceive('set')->with('config', 'php_path', \Mockery::any())->once();
407                 $configCache->shouldReceive('set')->with('system', 'basepath', '/test/')->once();
408
409                 $install->setUpCache($configCache, '/test/');
410         }
411 }
412
413 /**
414  * A workaround to replace the PHP native function_exists with a mocked function
415  *
416  * @param string $function_name the Name of the function
417  *
418  * @return bool true or false
419  */
420 function function_exists($function_name)
421 {
422         global $phpMock;
423         if (isset($phpMock['function_exists'])) {
424                 $result = call_user_func_array($phpMock['function_exists'], func_get_args());
425                 if ($result !== '__phpunit_continue__') {
426                         return $result;
427                 }
428         }
429         return call_user_func_array('\function_exists', func_get_args());
430 }
431
432 function class_exists($class_name)
433 {
434         global $phpMock;
435         if (isset($phpMock['class_exists'])) {
436                 $result = call_user_func_array($phpMock['class_exists'], func_get_args());
437                 if ($result !== '__phpunit_continue__') {
438                         return $result;
439                 }
440         }
441         return call_user_func_array('\class_exists', func_get_args());
442 }