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