3 // this is in the same namespace as Install for mocking 'function_exists'
4 namespace Friendica\Core;
6 use Friendica\Core\Config\Cache\ConfigCache;
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;
15 * @runTestsInSeparateProcesses
16 * @preserveGlobalState disabled
18 class InstallerTest extends MockedTest
23 public function setUp()
31 * Mocking the L10n::t() calls for the function checks
33 private function mockFunctionL10TCalls()
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);
56 private function assertCheckExist($position, $title, $help, $status, $required, $assertionArray)
58 $this->assertArraySubset([$position => [
61 'required' => $required,
68 * Replaces function_exists results with given mocks
70 * @param array $functions a list from function names and their result
72 private function setFunctions($functions)
75 $phpMock['function_exists'] = function($function) use ($functions) {
76 foreach ($functions as $name => $value) {
77 if ($function == $name) {
81 return '__phpunit_continue__';
86 * Replaces class_exist results with given mocks
88 * @param array $classes a list from class names and their results
90 private function setClasses($classes)
93 $phpMock['class_exists'] = function($class) use ($classes) {
94 foreach ($classes as $name => $value) {
95 if ($class == $name) {
99 return '__phpunit_continue__';
106 public function testCheckKeys()
110 $this->setFunctions(['openssl_pkey_new' => false]);
111 $install = new Installer();
112 $this->assertFalse($install->checkKeys());
114 $this->setFunctions(['openssl_pkey_new' => true]);
115 $install = new Installer();
116 $this->assertTrue($install->checkKeys());
122 public function testCheckFunctions()
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.',
133 $install->getChecks());
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.',
144 $install->getChecks());
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.',
155 $install->getChecks());
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.',
166 $install->getChecks());
168 $this->mockFunctionL10TCalls();
169 $this->setFunctions(['iconv_strlen' => false]);
170 $install = new Installer();
171 $this->assertFalse($install->checkFunctions());
172 $this->assertCheckExist(7,
174 'Error: iconv PHP module required but not installed.',
177 $install->getChecks());
179 $this->mockFunctionL10TCalls();
180 $this->setFunctions(['posix_kill' => false]);
181 $install = new Installer();
182 $this->assertFalse($install->checkFunctions());
183 $this->assertCheckExist(8,
185 'Error: POSIX PHP module required but not installed.',
188 $install->getChecks());
190 $this->mockFunctionL10TCalls();
191 $this->setFunctions(['json_encode' => false]);
192 $install = new Installer();
193 $this->assertFalse($install->checkFunctions());
194 $this->assertCheckExist(9,
196 'Error: JSON PHP module required but not installed.',
199 $install->getChecks());
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.',
210 $install->getChecks());
212 $this->mockFunctionL10TCalls();
213 $this->setFunctions([
215 'imagecreatefromjpeg' => true,
216 'openssl_public_encrypt' => true,
218 'iconv_strlen' => true,
219 'posix_kill' => true,
220 'json_encode' => true,
221 'finfo_open' => true,
223 $install = new Installer();
224 $this->assertTrue($install->checkFunctions());
230 public function testCheckLocalIni()
234 $this->assertTrue($this->root->hasChild('config/local.config.php'));
236 $install = new Installer();
237 $this->assertTrue($install->checkLocalIni());
239 $this->delConfigFile('local.config.php');
241 $this->assertFalse($this->root->hasChild('config/local.config.php'));
243 $install = new Installer();
244 $this->assertTrue($install->checkLocalIni());
250 public function testCheckHtAccessFail()
254 // Mocking the CURL Response
255 $curlResult = \Mockery::mock(CurlResult::class);
257 ->shouldReceive('getReturnCode')
260 ->shouldReceive('getRedirectUrl')
263 ->shouldReceive('getError')
264 ->andReturn('test Error');
266 // Mocking the CURL Request
267 $networkMock = \Mockery::mock('alias:' . Network::class);
269 ->shouldReceive('fetchUrlFull')
270 ->with('https://test/install/testrewrite')
271 ->andReturn($curlResult);
273 ->shouldReceive('fetchUrlFull')
274 ->with('http://test/install/testrewrite')
275 ->andReturn($curlResult);
277 // Mocking that we can use CURL
278 $this->setFunctions(['curl_init' => true]);
280 $install = new Installer();
282 $this->assertFalse($install->checkHtAccess('https://test'));
283 $this->assertSame('test Error', $install->getChecks()[0]['error_msg']['msg']);
289 public function testCheckHtAccessWork()
293 // Mocking the failed CURL Response
294 $curlResultF = \Mockery::mock(CurlResult::class);
296 ->shouldReceive('getReturnCode')
299 // Mocking the working CURL Response
300 $curlResultW = \Mockery::mock(CurlResult::class);
302 ->shouldReceive('getReturnCode')
305 // Mocking the CURL Request
306 $networkMock = \Mockery::mock('alias:' . Network::class);
308 ->shouldReceive('fetchUrlFull')
309 ->with('https://test/install/testrewrite')
310 ->andReturn($curlResultF);
312 ->shouldReceive('fetchUrlFull')
313 ->with('http://test/install/testrewrite')
314 ->andReturn($curlResultW);
316 // Mocking that we can use CURL
317 $this->setFunctions(['curl_init' => true]);
319 // needed because of "normalise_link"
320 require_once __DIR__ . '/../../../include/text.php';
322 $install = new Installer();
324 $this->assertTrue($install->checkHtAccess('https://test'));
330 public function testImagick()
334 $imageMock = \Mockery::mock('alias:'. Image::class);
336 ->shouldReceive('supportedTypes')
337 ->andReturn(['image/gif' => 'gif']);
339 $this->setClasses(['Imagick' => true]);
341 $install = new Installer();
343 // even there is no supported type, Imagick should return true (because it is not required)
344 $this->assertTrue($install->checkImagick());
346 $this->assertCheckExist(1,
347 L10n::t('ImageMagick supports GIF'),
351 $install->getChecks());
357 public function testImagickNotFound()
361 $imageMock = \Mockery::mock('alias:' . Image::class);
363 ->shouldReceive('supportedTypes')
366 $this->setClasses(['Imagick' => true]);
368 $install = new Installer();
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'),
377 $install->getChecks());
380 public function testImagickNotInstalled()
382 $this->setClasses(['Imagick' => false]);
383 $this->mockL10nT('ImageMagick PHP extension is not installed');
385 $install = new Installer();
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',
394 $install->getChecks());
398 * Test the setup of the config cache for installation
400 public function testSetUpCache()
404 $install = new Installer();
405 $configCache = \Mockery::mock(ConfigCache::class);
406 $configCache->shouldReceive('set')->with('config', 'php_path', \Mockery::any())->once();
407 $configCache->shouldReceive('set')->with('system', 'basepath', '/test/')->once();
409 $install->setUpCache($configCache, '/test/');
414 * A workaround to replace the PHP native function_exists with a mocked function
416 * @param string $function_name the Name of the function
418 * @return bool true or false
420 function function_exists($function_name)
423 if (isset($phpMock['function_exists'])) {
424 $result = call_user_func_array($phpMock['function_exists'], func_get_args());
425 if ($result !== '__phpunit_continue__') {
429 return call_user_func_array('\function_exists', func_get_args());
432 function class_exists($class_name)
435 if (isset($phpMock['class_exists'])) {
436 $result = call_user_func_array($phpMock['class_exists'], func_get_args());
437 if ($result !== '__phpunit_continue__') {
441 return call_user_func_array('\class_exists', func_get_args());