3 // this is in the same namespace as Install for mocking 'function_exists'
4 namespace Friendica\Core;
6 use Friendica\Test\MockedTest;
7 use Friendica\Test\Util\L10nMockTrait;
8 use Friendica\Test\Util\VFSTrait;
11 * @runTestsInSeparateProcesses
12 * @preserveGlobalState disabled
14 class InstallerTest extends MockedTest
19 public function setUp()
27 * Mocking the L10n::t() calls for the function checks
29 private function mockFunctionL10TCalls()
31 $this->mockL10nT('Apache mod_rewrite module', 1);
32 $this->mockL10nT('PDO or MySQLi PHP module', 1);
33 $this->mockL10nT('libCurl PHP module', 1);
34 $this->mockL10nT('Error: libCURL PHP module required but not installed.', 1);
35 $this->mockL10nT('XML PHP module', 1);
36 $this->mockL10nT('GD graphics PHP module', 1);
37 $this->mockL10nT('Error: GD graphics PHP module with JPEG support required but not installed.', 1);
38 $this->mockL10nT('OpenSSL PHP module', 1);
39 $this->mockL10nT('Error: openssl PHP module required but not installed.', 1);
40 $this->mockL10nT('mb_string PHP module', 1);
41 $this->mockL10nT('Error: mb_string PHP module required but not installed.', 1);
42 $this->mockL10nT('iconv PHP module', 1);
43 $this->mockL10nT('Error: iconv PHP module required but not installed.', 1);
44 $this->mockL10nT('POSIX PHP module', 1);
45 $this->mockL10nT('Error: POSIX PHP module required but not installed.', 1);
46 $this->mockL10nT('JSON PHP module', 1);
47 $this->mockL10nT('Error: JSON PHP module required but not installed.', 1);
50 private function assertCheckExist($position, $title, $help, $status, $required, $assertionArray)
52 $this->assertArraySubset([$position => [
55 'required' => $required,
62 * Replaces function_exists results with given mocks
64 * @param array $functions a list from function names and their result
66 private function setFunctions($functions)
69 $phpMock['function_exists'] = function($function) use ($functions) {
70 foreach ($functions as $name => $value) {
71 if ($function == $name) {
75 return '__phpunit_continue__';
80 * Replaces class_exist results with given mocks
82 * @param array $classes a list from class names and their results
84 private function setClasses($classes)
87 $phpMock['class_exists'] = function($class) use ($classes) {
88 foreach ($classes as $name => $value) {
89 if ($class == $name) {
93 return '__phpunit_continue__';
100 public function testCheckKeys()
102 $this->setFunctions(['openssl_pkey_new' => false]);
103 $install = new Installer();
104 $this->assertFalse($install->checkKeys());
106 $this->setFunctions(['openssl_pkey_new' => true]);
107 $install = new Installer();
108 $this->assertTrue($install->checkKeys());
114 public function testCheckFunctions()
116 $this->mockFunctionL10TCalls();
117 $this->setFunctions(['curl_init' => false, 'imagecreatefromjpeg' => true]);
118 $install = new Installer();
119 $this->assertFalse($install->checkFunctions());
120 $this->assertCheckExist(3,
121 'libCurl PHP module',
122 'Error: libCURL PHP module required but not installed.',
125 $install->getChecks());
127 $this->mockFunctionL10TCalls();
128 $this->setFunctions(['imagecreatefromjpeg' => false]);
129 $install = new Installer();
130 $this->assertFalse($install->checkFunctions());
131 $this->assertCheckExist(4,
132 'GD graphics PHP module',
133 'Error: GD graphics PHP module with JPEG support required but not installed.',
136 $install->getChecks());
138 $this->mockFunctionL10TCalls();
139 $this->setFunctions(['openssl_public_encrypt' => false]);
140 $install = new Installer();
141 $this->assertFalse($install->checkFunctions());
142 $this->assertCheckExist(5,
143 'OpenSSL PHP module',
144 'Error: openssl PHP module required but not installed.',
147 $install->getChecks());
149 $this->mockFunctionL10TCalls();
150 $this->setFunctions(['mb_strlen' => false]);
151 $install = new Installer();
152 $this->assertFalse($install->checkFunctions());
153 $this->assertCheckExist(6,
154 'mb_string PHP module',
155 'Error: mb_string PHP module required but not installed.',
158 $install->getChecks());
160 $this->mockFunctionL10TCalls();
161 $this->setFunctions(['iconv_strlen' => false]);
162 $install = new Installer();
163 $this->assertFalse($install->checkFunctions());
164 $this->assertCheckExist(7,
166 'Error: iconv PHP module required but not installed.',
169 $install->getChecks());
171 $this->mockFunctionL10TCalls();
172 $this->setFunctions(['posix_kill' => false]);
173 $install = new Installer();
174 $this->assertFalse($install->checkFunctions());
175 $this->assertCheckExist(8,
177 'Error: POSIX PHP module required but not installed.',
180 $install->getChecks());
182 $this->mockFunctionL10TCalls();
183 $this->setFunctions(['json_encode' => false]);
184 $install = new Installer();
185 $this->assertFalse($install->checkFunctions());
186 $this->assertCheckExist(9,
188 'Error: JSON PHP module required but not installed.',
191 $install->getChecks());
193 $this->mockFunctionL10TCalls();
194 $this->setFunctions([
196 'imagecreatefromjpeg' => true,
197 'openssl_public_encrypt' => true,
199 'iconv_strlen' => true,
200 'posix_kill' => true,
201 'json_encode' => true
203 $install = new Installer();
204 $this->assertTrue($install->checkFunctions());
210 public function testCheckLocalIni()
212 $this->assertTrue($this->root->hasChild('config/local.config.php'));
214 $install = new Installer();
215 $this->assertTrue($install->checkLocalIni());
217 $this->delConfigFile('local.config.php');
219 $this->assertFalse($this->root->hasChild('config/local.config.php'));
221 $install = new Installer();
222 $this->assertTrue($install->checkLocalIni());
228 public function testCheckHtAccessFail()
230 // Mocking the CURL Response
231 $curlResult = \Mockery::mock('Friendica\Network\CurlResult');
233 ->shouldReceive('getReturnCode')
236 ->shouldReceive('getRedirectUrl')
239 ->shouldReceive('getError')
240 ->andReturn('test Error');
242 // Mocking the CURL Request
243 $networkMock = \Mockery::mock('alias:Friendica\Util\Network');
245 ->shouldReceive('fetchUrlFull')
246 ->with('https://test/install/testrewrite')
247 ->andReturn($curlResult);
249 ->shouldReceive('fetchUrlFull')
250 ->with('http://test/install/testrewrite')
251 ->andReturn($curlResult);
253 // Mocking that we can use CURL
254 $this->setFunctions(['curl_init' => true]);
256 $install = new Installer();
258 $this->assertFalse($install->checkHtAccess('https://test'));
259 $this->assertSame('test Error', $install->getChecks()[0]['error_msg']['msg']);
265 public function testCheckHtAccessWork()
267 // Mocking the failed CURL Response
268 $curlResultF = \Mockery::mock('Friendica\Network\CurlResult');
270 ->shouldReceive('getReturnCode')
273 // Mocking the working CURL Response
274 $curlResultW = \Mockery::mock('Friendica\Network\CurlResult');
276 ->shouldReceive('getReturnCode')
279 // Mocking the CURL Request
280 $networkMock = \Mockery::mock('alias:Friendica\Util\Network');
282 ->shouldReceive('fetchUrlFull')
283 ->with('https://test/install/testrewrite')
284 ->andReturn($curlResultF);
286 ->shouldReceive('fetchUrlFull')
287 ->with('http://test/install/testrewrite')
288 ->andReturn($curlResultW);
290 // Mocking that we can use CURL
291 $this->setFunctions(['curl_init' => true]);
293 // needed because of "normalise_link"
294 require_once __DIR__ . '/../../../include/text.php';
296 $install = new Installer();
298 $this->assertTrue($install->checkHtAccess('https://test'));
304 public function testImagick()
306 $imageMock = \Mockery::mock('alias:Friendica\Object\Image');
308 ->shouldReceive('supportedTypes')
309 ->andReturn(['image/gif' => 'gif']);
311 $this->setClasses(['Imagick' => true]);
313 $install = new Installer();
315 // even there is no supported type, Imagick should return true (because it is not required)
316 $this->assertTrue($install->checkImagick());
318 $this->assertCheckExist(1,
319 L10n::t('ImageMagick supports GIF'),
323 $install->getChecks());
329 public function testImagickNotFound()
331 $imageMock = \Mockery::mock('alias:Friendica\Object\Image');
333 ->shouldReceive('supportedTypes')
336 $this->setClasses(['Imagick' => true]);
338 $install = new Installer();
340 // even there is no supported type, Imagick should return true (because it is not required)
341 $this->assertTrue($install->checkImagick());
342 $this->assertCheckExist(1,
343 L10n::t('ImageMagick supports GIF'),
347 $install->getChecks());
350 public function testImagickNotInstalled()
352 $this->setClasses(['Imagick' => false]);
353 $this->mockL10nT('ImageMagick PHP extension is not installed');
355 $install = new Installer();
357 // even there is no supported type, Imagick should return true (because it is not required)
358 $this->assertTrue($install->checkImagick());
359 $this->assertCheckExist(0,
360 'ImageMagick PHP extension is not installed',
364 $install->getChecks());
369 * A workaround to replace the PHP native function_exists with a mocked function
371 * @param string $function_name the Name of the function
373 * @return bool true or false
375 function function_exists($function_name)
378 if (isset($phpMock['function_exists'])) {
379 $result = call_user_func_array($phpMock['function_exists'], func_get_args());
380 if ($result !== '__phpunit_continue__') {
384 return call_user_func_array('\function_exists', func_get_args());
387 function class_exists($class_name)
390 if (isset($phpMock['class_exists'])) {
391 $result = call_user_func_array($phpMock['class_exists'], func_get_args());
392 if ($result !== '__phpunit_continue__') {
396 return call_user_func_array('\class_exists', func_get_args());