3 // this is in the same namespace as Install for mocking 'function_exists'
4 namespace Friendica\Core;
6 use Friendica\Network\CurlResult;
7 use Friendica\Object\Image;
8 use Friendica\Test\MockedTest;
9 use Friendica\Test\Util\L10nMockTrait;
10 use Friendica\Test\Util\VFSTrait;
11 use Friendica\Util\Network;
14 * @runTestsInSeparateProcesses
15 * @preserveGlobalState disabled
17 class InstallerTest extends MockedTest
22 public function setUp()
30 * Mocking the L10n::t() calls for the function checks
32 private function mockFunctionL10TCalls()
34 $this->mockL10nT('Apache mod_rewrite module', 1);
35 $this->mockL10nT('PDO or MySQLi PHP module', 1);
36 $this->mockL10nT('libCurl PHP module', 1);
37 $this->mockL10nT('Error: libCURL PHP module required but not installed.', 1);
38 $this->mockL10nT('XML PHP module', 1);
39 $this->mockL10nT('GD graphics PHP module', 1);
40 $this->mockL10nT('Error: GD graphics PHP module with JPEG support required but not installed.', 1);
41 $this->mockL10nT('OpenSSL PHP module', 1);
42 $this->mockL10nT('Error: openssl PHP module required but not installed.', 1);
43 $this->mockL10nT('mb_string PHP module', 1);
44 $this->mockL10nT('Error: mb_string PHP module required but not installed.', 1);
45 $this->mockL10nT('iconv PHP module', 1);
46 $this->mockL10nT('Error: iconv PHP module required but not installed.', 1);
47 $this->mockL10nT('POSIX PHP module', 1);
48 $this->mockL10nT('Error: POSIX PHP module required but not installed.', 1);
49 $this->mockL10nT('JSON PHP module', 1);
50 $this->mockL10nT('Error: JSON PHP module required but not installed.', 1);
51 $this->mockL10nT('File Information PHP module', 1);
52 $this->mockL10nT('Error: File Information PHP module required but not installed.', 1);
55 private function assertCheckExist($position, $title, $help, $status, $required, $assertionArray)
57 $this->assertArraySubset([$position => [
60 'required' => $required,
67 * Replaces function_exists results with given mocks
69 * @param array $functions a list from function names and their result
71 private function setFunctions($functions)
74 $phpMock['function_exists'] = function($function) use ($functions) {
75 foreach ($functions as $name => $value) {
76 if ($function == $name) {
80 return '__phpunit_continue__';
85 * Replaces class_exist results with given mocks
87 * @param array $classes a list from class names and their results
89 private function setClasses($classes)
92 $phpMock['class_exists'] = function($class) use ($classes) {
93 foreach ($classes as $name => $value) {
94 if ($class == $name) {
98 return '__phpunit_continue__';
105 public function testCheckKeys()
109 $this->setFunctions(['openssl_pkey_new' => false]);
110 $install = new Installer();
111 $this->assertFalse($install->checkKeys());
113 $this->setFunctions(['openssl_pkey_new' => true]);
114 $install = new Installer();
115 $this->assertTrue($install->checkKeys());
121 public function testCheckFunctions()
123 $this->mockFunctionL10TCalls();
124 $this->setFunctions(['curl_init' => false, 'imagecreatefromjpeg' => true]);
125 $install = new Installer();
126 $this->assertFalse($install->checkFunctions());
127 $this->assertCheckExist(3,
128 'libCurl PHP module',
129 'Error: libCURL PHP module required but not installed.',
132 $install->getChecks());
134 $this->mockFunctionL10TCalls();
135 $this->setFunctions(['imagecreatefromjpeg' => false]);
136 $install = new Installer();
137 $this->assertFalse($install->checkFunctions());
138 $this->assertCheckExist(4,
139 'GD graphics PHP module',
140 'Error: GD graphics PHP module with JPEG support required but not installed.',
143 $install->getChecks());
145 $this->mockFunctionL10TCalls();
146 $this->setFunctions(['openssl_public_encrypt' => false]);
147 $install = new Installer();
148 $this->assertFalse($install->checkFunctions());
149 $this->assertCheckExist(5,
150 'OpenSSL PHP module',
151 'Error: openssl PHP module required but not installed.',
154 $install->getChecks());
156 $this->mockFunctionL10TCalls();
157 $this->setFunctions(['mb_strlen' => false]);
158 $install = new Installer();
159 $this->assertFalse($install->checkFunctions());
160 $this->assertCheckExist(6,
161 'mb_string PHP module',
162 'Error: mb_string PHP module required but not installed.',
165 $install->getChecks());
167 $this->mockFunctionL10TCalls();
168 $this->setFunctions(['iconv_strlen' => false]);
169 $install = new Installer();
170 $this->assertFalse($install->checkFunctions());
171 $this->assertCheckExist(7,
173 'Error: iconv PHP module required but not installed.',
176 $install->getChecks());
178 $this->mockFunctionL10TCalls();
179 $this->setFunctions(['posix_kill' => false]);
180 $install = new Installer();
181 $this->assertFalse($install->checkFunctions());
182 $this->assertCheckExist(8,
184 'Error: POSIX PHP module required but not installed.',
187 $install->getChecks());
189 $this->mockFunctionL10TCalls();
190 $this->setFunctions(['json_encode' => false]);
191 $install = new Installer();
192 $this->assertFalse($install->checkFunctions());
193 $this->assertCheckExist(9,
195 'Error: JSON PHP module required but not installed.',
198 $install->getChecks());
200 $this->mockFunctionL10TCalls();
201 $this->setFunctions(['finfo_open' => false]);
202 $install = new Installer();
203 $this->assertFalse($install->checkFunctions());
204 $this->assertCheckExist(10,
205 'File Information PHP module',
206 'Error: File Information PHP module required but not installed.',
209 $install->getChecks());
211 $this->mockFunctionL10TCalls();
212 $this->setFunctions([
214 'imagecreatefromjpeg' => true,
215 'openssl_public_encrypt' => true,
217 'iconv_strlen' => true,
218 'posix_kill' => true,
219 'json_encode' => true,
220 'finfo_open' => true,
222 $install = new Installer();
223 $this->assertTrue($install->checkFunctions());
229 public function testCheckLocalIni()
233 $this->assertTrue($this->root->hasChild('config/local.config.php'));
235 $install = new Installer();
236 $this->assertTrue($install->checkLocalIni());
238 $this->delConfigFile('local.config.php');
240 $this->assertFalse($this->root->hasChild('config/local.config.php'));
242 $install = new Installer();
243 $this->assertTrue($install->checkLocalIni());
249 public function testCheckHtAccessFail()
253 // Mocking the CURL Response
254 $curlResult = \Mockery::mock(CurlResult::class);
256 ->shouldReceive('getReturnCode')
259 ->shouldReceive('getRedirectUrl')
262 ->shouldReceive('getError')
263 ->andReturn('test Error');
265 // Mocking the CURL Request
266 $networkMock = \Mockery::mock('alias:' . Network::class);
268 ->shouldReceive('fetchUrlFull')
269 ->with('https://test/install/testrewrite')
270 ->andReturn($curlResult);
272 ->shouldReceive('fetchUrlFull')
273 ->with('http://test/install/testrewrite')
274 ->andReturn($curlResult);
276 // Mocking that we can use CURL
277 $this->setFunctions(['curl_init' => true]);
279 $install = new Installer();
281 $this->assertFalse($install->checkHtAccess('https://test'));
282 $this->assertSame('test Error', $install->getChecks()[0]['error_msg']['msg']);
288 public function testCheckHtAccessWork()
292 // Mocking the failed CURL Response
293 $curlResultF = \Mockery::mock(CurlResult::class);
295 ->shouldReceive('getReturnCode')
298 // Mocking the working CURL Response
299 $curlResultW = \Mockery::mock(CurlResult::class);
301 ->shouldReceive('getReturnCode')
304 // Mocking the CURL Request
305 $networkMock = \Mockery::mock('alias:' . Network::class);
307 ->shouldReceive('fetchUrlFull')
308 ->with('https://test/install/testrewrite')
309 ->andReturn($curlResultF);
311 ->shouldReceive('fetchUrlFull')
312 ->with('http://test/install/testrewrite')
313 ->andReturn($curlResultW);
315 // Mocking that we can use CURL
316 $this->setFunctions(['curl_init' => true]);
318 // needed because of "normalise_link"
319 require_once __DIR__ . '/../../../include/text.php';
321 $install = new Installer();
323 $this->assertTrue($install->checkHtAccess('https://test'));
329 public function testImagick()
333 $imageMock = \Mockery::mock('alias:'. Image::class);
335 ->shouldReceive('supportedTypes')
336 ->andReturn(['image/gif' => 'gif']);
338 $this->setClasses(['Imagick' => true]);
340 $install = new Installer();
342 // even there is no supported type, Imagick should return true (because it is not required)
343 $this->assertTrue($install->checkImagick());
345 $this->assertCheckExist(1,
346 L10n::t('ImageMagick supports GIF'),
350 $install->getChecks());
356 public function testImagickNotFound()
360 $imageMock = \Mockery::mock('alias:' . Image::class);
362 ->shouldReceive('supportedTypes')
365 $this->setClasses(['Imagick' => true]);
367 $install = new Installer();
369 // even there is no supported type, Imagick should return true (because it is not required)
370 $this->assertTrue($install->checkImagick());
371 $this->assertCheckExist(1,
372 L10n::t('ImageMagick supports GIF'),
376 $install->getChecks());
379 public function testImagickNotInstalled()
381 $this->setClasses(['Imagick' => false]);
382 $this->mockL10nT('ImageMagick PHP extension is not installed');
384 $install = new Installer();
386 // even there is no supported type, Imagick should return true (because it is not required)
387 $this->assertTrue($install->checkImagick());
388 $this->assertCheckExist(0,
389 'ImageMagick PHP extension is not installed',
393 $install->getChecks());
398 * A workaround to replace the PHP native function_exists with a mocked function
400 * @param string $function_name the Name of the function
402 * @return bool true or false
404 function function_exists($function_name)
407 if (isset($phpMock['function_exists'])) {
408 $result = call_user_func_array($phpMock['function_exists'], func_get_args());
409 if ($result !== '__phpunit_continue__') {
413 return call_user_func_array('\function_exists', func_get_args());
416 function class_exists($class_name)
419 if (isset($phpMock['class_exists'])) {
420 $result = call_user_func_array($phpMock['class_exists'], func_get_args());
421 if ($result !== '__phpunit_continue__') {
425 return call_user_func_array('\class_exists', func_get_args());