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);
48 $this->mockL10nT('File Information PHP module', 1);
49 $this->mockL10nT('Error: File Information PHP module required but not installed.', 1);
52 private function assertCheckExist($position, $title, $help, $status, $required, $assertionArray)
54 $this->assertArraySubset([$position => [
57 'required' => $required,
64 * Replaces function_exists results with given mocks
66 * @param array $functions a list from function names and their result
68 private function setFunctions($functions)
71 $phpMock['function_exists'] = function($function) use ($functions) {
72 foreach ($functions as $name => $value) {
73 if ($function == $name) {
77 return '__phpunit_continue__';
82 * Replaces class_exist results with given mocks
84 * @param array $classes a list from class names and their results
86 private function setClasses($classes)
89 $phpMock['class_exists'] = function($class) use ($classes) {
90 foreach ($classes as $name => $value) {
91 if ($class == $name) {
95 return '__phpunit_continue__';
102 public function testCheckKeys()
106 $this->setFunctions(['openssl_pkey_new' => false]);
107 $install = new Installer();
108 $this->assertFalse($install->checkKeys());
110 $this->setFunctions(['openssl_pkey_new' => true]);
111 $install = new Installer();
112 $this->assertTrue($install->checkKeys());
118 public function testCheckFunctions()
120 $this->mockFunctionL10TCalls();
121 $this->setFunctions(['curl_init' => false, 'imagecreatefromjpeg' => true]);
122 $install = new Installer();
123 $this->assertFalse($install->checkFunctions());
124 $this->assertCheckExist(3,
125 'libCurl PHP module',
126 'Error: libCURL PHP module required but not installed.',
129 $install->getChecks());
131 $this->mockFunctionL10TCalls();
132 $this->setFunctions(['imagecreatefromjpeg' => false]);
133 $install = new Installer();
134 $this->assertFalse($install->checkFunctions());
135 $this->assertCheckExist(4,
136 'GD graphics PHP module',
137 'Error: GD graphics PHP module with JPEG support required but not installed.',
140 $install->getChecks());
142 $this->mockFunctionL10TCalls();
143 $this->setFunctions(['openssl_public_encrypt' => false]);
144 $install = new Installer();
145 $this->assertFalse($install->checkFunctions());
146 $this->assertCheckExist(5,
147 'OpenSSL PHP module',
148 'Error: openssl PHP module required but not installed.',
151 $install->getChecks());
153 $this->mockFunctionL10TCalls();
154 $this->setFunctions(['mb_strlen' => false]);
155 $install = new Installer();
156 $this->assertFalse($install->checkFunctions());
157 $this->assertCheckExist(6,
158 'mb_string PHP module',
159 'Error: mb_string PHP module required but not installed.',
162 $install->getChecks());
164 $this->mockFunctionL10TCalls();
165 $this->setFunctions(['iconv_strlen' => false]);
166 $install = new Installer();
167 $this->assertFalse($install->checkFunctions());
168 $this->assertCheckExist(7,
170 'Error: iconv PHP module required but not installed.',
173 $install->getChecks());
175 $this->mockFunctionL10TCalls();
176 $this->setFunctions(['posix_kill' => false]);
177 $install = new Installer();
178 $this->assertFalse($install->checkFunctions());
179 $this->assertCheckExist(8,
181 'Error: POSIX PHP module required but not installed.',
184 $install->getChecks());
186 $this->mockFunctionL10TCalls();
187 $this->setFunctions(['json_encode' => false]);
188 $install = new Installer();
189 $this->assertFalse($install->checkFunctions());
190 $this->assertCheckExist(9,
192 'Error: JSON PHP module required but not installed.',
195 $install->getChecks());
197 $this->mockFunctionL10TCalls();
198 $this->setFunctions(['finfo_open' => false]);
199 $install = new Installer();
200 $this->assertFalse($install->checkFunctions());
201 $this->assertCheckExist(10,
202 'File Information PHP module',
203 'Error: File Information PHP module required but not installed.',
206 $install->getChecks());
208 $this->mockFunctionL10TCalls();
209 $this->setFunctions([
211 'imagecreatefromjpeg' => true,
212 'openssl_public_encrypt' => true,
214 'iconv_strlen' => true,
215 'posix_kill' => true,
216 'json_encode' => true,
217 'finfo_open' => true,
219 $install = new Installer();
220 $this->assertTrue($install->checkFunctions());
226 public function testCheckLocalIni()
230 $this->assertTrue($this->root->hasChild('config/local.config.php'));
232 $install = new Installer();
233 $this->assertTrue($install->checkLocalIni());
235 $this->delConfigFile('local.config.php');
237 $this->assertFalse($this->root->hasChild('config/local.config.php'));
239 $install = new Installer();
240 $this->assertTrue($install->checkLocalIni());
246 public function testCheckHtAccessFail()
250 // Mocking the CURL Response
251 $curlResult = \Mockery::mock('Friendica\Network\CurlResult');
253 ->shouldReceive('getReturnCode')
256 ->shouldReceive('getRedirectUrl')
259 ->shouldReceive('getError')
260 ->andReturn('test Error');
262 // Mocking the CURL Request
263 $networkMock = \Mockery::mock('alias:Friendica\Util\Network');
265 ->shouldReceive('fetchUrlFull')
266 ->with('https://test/install/testrewrite')
267 ->andReturn($curlResult);
269 ->shouldReceive('fetchUrlFull')
270 ->with('http://test/install/testrewrite')
271 ->andReturn($curlResult);
273 // Mocking that we can use CURL
274 $this->setFunctions(['curl_init' => true]);
276 $install = new Installer();
278 $this->assertFalse($install->checkHtAccess('https://test'));
279 $this->assertSame('test Error', $install->getChecks()[0]['error_msg']['msg']);
285 public function testCheckHtAccessWork()
289 // Mocking the failed CURL Response
290 $curlResultF = \Mockery::mock('Friendica\Network\CurlResult');
292 ->shouldReceive('getReturnCode')
295 // Mocking the working CURL Response
296 $curlResultW = \Mockery::mock('Friendica\Network\CurlResult');
298 ->shouldReceive('getReturnCode')
301 // Mocking the CURL Request
302 $networkMock = \Mockery::mock('alias:Friendica\Util\Network');
304 ->shouldReceive('fetchUrlFull')
305 ->with('https://test/install/testrewrite')
306 ->andReturn($curlResultF);
308 ->shouldReceive('fetchUrlFull')
309 ->with('http://test/install/testrewrite')
310 ->andReturn($curlResultW);
312 // Mocking that we can use CURL
313 $this->setFunctions(['curl_init' => true]);
315 // needed because of "normalise_link"
316 require_once __DIR__ . '/../../../include/text.php';
318 $install = new Installer();
320 $this->assertTrue($install->checkHtAccess('https://test'));
326 public function testImagick()
330 $imageMock = \Mockery::mock('alias:Friendica\Object\Image');
332 ->shouldReceive('supportedTypes')
333 ->andReturn(['image/gif' => 'gif']);
335 $this->setClasses(['Imagick' => true]);
337 $install = new Installer();
339 // even there is no supported type, Imagick should return true (because it is not required)
340 $this->assertTrue($install->checkImagick());
342 $this->assertCheckExist(1,
343 L10n::t('ImageMagick supports GIF'),
347 $install->getChecks());
353 public function testImagickNotFound()
357 $imageMock = \Mockery::mock('alias:Friendica\Object\Image');
359 ->shouldReceive('supportedTypes')
362 $this->setClasses(['Imagick' => true]);
364 $install = new Installer();
366 // even there is no supported type, Imagick should return true (because it is not required)
367 $this->assertTrue($install->checkImagick());
368 $this->assertCheckExist(1,
369 L10n::t('ImageMagick supports GIF'),
373 $install->getChecks());
376 public function testImagickNotInstalled()
378 $this->setClasses(['Imagick' => false]);
379 $this->mockL10nT('ImageMagick PHP extension is not installed');
381 $install = new Installer();
383 // even there is no supported type, Imagick should return true (because it is not required)
384 $this->assertTrue($install->checkImagick());
385 $this->assertCheckExist(0,
386 'ImageMagick PHP extension is not installed',
390 $install->getChecks());
395 * A workaround to replace the PHP native function_exists with a mocked function
397 * @param string $function_name the Name of the function
399 * @return bool true or false
401 function function_exists($function_name)
404 if (isset($phpMock['function_exists'])) {
405 $result = call_user_func_array($phpMock['function_exists'], func_get_args());
406 if ($result !== '__phpunit_continue__') {
410 return call_user_func_array('\function_exists', func_get_args());
413 function class_exists($class_name)
416 if (isset($phpMock['class_exists'])) {
417 $result = call_user_func_array($phpMock['class_exists'], func_get_args());
418 if ($result !== '__phpunit_continue__') {
422 return call_user_func_array('\class_exists', func_get_args());