Merge pull request #14526 from Art4/improve-tests

Improve tests
This commit is contained in:
Hypolite Petovan 2024-11-10 15:14:07 -05:00 committed by GitHub
commit a7bc4010b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 517 additions and 287 deletions

View file

@ -148,13 +148,15 @@
] ]
}, },
"require-dev": { "require-dev": {
"mockery/mockery": "^1.3", "dms/phpunit-arraysubset-asserts": "^0.3.1",
"mikey179/vfsstream": "^1.6", "mikey179/vfsstream": "^1.6",
"phpunit/phpunit": "^9", "mockery/mockery": "^1.3",
"dms/phpunit-arraysubset-asserts": "^0.3.1" "php-mock/php-mock-phpunit": "^2.10",
"phpunit/phpunit": "^9"
}, },
"scripts": { "scripts": {
"test": "phpunit", "test": "phpunit",
"test:unit": "phpunit -c tests/phpunit.xml --testsuite unit",
"lint": "find . -name \\*.php -not -path './vendor/*' -not -path './view/asset/*' -print0 | xargs -0 -n1 php -l", "lint": "find . -name \\*.php -not -path './vendor/*' -not -path './view/asset/*' -print0 | xargs -0 -n1 php -l",
"docker:translate": "docker run --rm -v $PWD:/data -w /data friendicaci/transifex bin/run_xgettext.sh", "docker:translate": "docker run --rm -v $PWD:/data -w /data friendicaci/transifex bin/run_xgettext.sh",
"cs:install": "@composer install --working-dir=bin/dev/php-cs-fixer", "cs:install": "@composer install --working-dir=bin/dev/php-cs-fixer",

209
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "4385276f5e7c27e2ceb7b16531dbc33a", "content-hash": "d51158b9593011921144e90af146a86a",
"packages": [ "packages": [
{ {
"name": "asika/simple-console", "name": "asika/simple-console",
@ -4625,6 +4625,213 @@
"description": "Library for handling version information and constraints", "description": "Library for handling version information and constraints",
"time": "2022-02-21T01:04:05+00:00" "time": "2022-02-21T01:04:05+00:00"
}, },
{
"name": "php-mock/php-mock",
"version": "2.5.0",
"source": {
"type": "git",
"url": "https://github.com/php-mock/php-mock.git",
"reference": "fff1a621ebe54100fa3bd852e7be57773a0c0127"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mock/php-mock/zipball/fff1a621ebe54100fa3bd852e7be57773a0c0127",
"reference": "fff1a621ebe54100fa3bd852e7be57773a0c0127",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0 || ^8.0",
"phpunit/php-text-template": "^1 || ^2 || ^3 || ^4"
},
"replace": {
"malkusch/php-mock": "*"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.0 || ^9.0 || ^10.0 || ^11.0",
"squizlabs/php_codesniffer": "^3.8"
},
"suggest": {
"php-mock/php-mock-phpunit": "Allows integration into PHPUnit testcase with the trait PHPMock."
},
"type": "library",
"autoload": {
"files": [
"autoload.php"
],
"psr-4": {
"phpmock\\": [
"classes/",
"tests/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"WTFPL"
],
"authors": [
{
"name": "Markus Malkusch",
"email": "markus@malkusch.de",
"homepage": "http://markus.malkusch.de",
"role": "Developer"
}
],
"description": "PHP-Mock can mock built-in PHP functions (e.g. time()). PHP-Mock relies on PHP's namespace fallback policy. No further extension is needed.",
"homepage": "https://github.com/php-mock/php-mock",
"keywords": [
"BDD",
"TDD",
"function",
"mock",
"stub",
"test",
"test double",
"testing"
],
"support": {
"issues": "https://github.com/php-mock/php-mock/issues",
"source": "https://github.com/php-mock/php-mock/tree/2.5.0"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2024-02-10T21:07:01+00:00"
},
{
"name": "php-mock/php-mock-integration",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/php-mock/php-mock-integration.git",
"reference": "ec6a00a8129d50ed0f07907c91e3274ca4ade877"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mock/php-mock-integration/zipball/ec6a00a8129d50ed0f07907c91e3274ca4ade877",
"reference": "ec6a00a8129d50ed0f07907c91e3274ca4ade877",
"shasum": ""
},
"require": {
"php": ">=5.6",
"php-mock/php-mock": "^2.5",
"phpunit/php-text-template": "^1 || ^2 || ^3 || ^4"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6 || ^7 || ^8 || ^9 || ^10 || ^11"
},
"type": "library",
"autoload": {
"psr-4": {
"phpmock\\integration\\": "classes/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"WTFPL"
],
"authors": [
{
"name": "Markus Malkusch",
"email": "markus@malkusch.de",
"homepage": "http://markus.malkusch.de",
"role": "Developer"
}
],
"description": "Integration package for PHP-Mock",
"homepage": "https://github.com/php-mock/php-mock-integration",
"keywords": [
"BDD",
"TDD",
"function",
"mock",
"stub",
"test",
"test double"
],
"support": {
"issues": "https://github.com/php-mock/php-mock-integration/issues",
"source": "https://github.com/php-mock/php-mock-integration/tree/2.3.0"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2024-02-10T21:37:25+00:00"
},
{
"name": "php-mock/php-mock-phpunit",
"version": "2.10.0",
"source": {
"type": "git",
"url": "https://github.com/php-mock/php-mock-phpunit.git",
"reference": "e1f7e795990b00937376e345883ea68ca3bda7e0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/e1f7e795990b00937376e345883ea68ca3bda7e0",
"reference": "e1f7e795990b00937376e345883ea68ca3bda7e0",
"shasum": ""
},
"require": {
"php": ">=7",
"php-mock/php-mock-integration": "^2.3",
"phpunit/phpunit": "^6 || ^7 || ^8 || ^9 || ^10.0.17 || ^11"
},
"require-dev": {
"mockery/mockery": "^1.3.6"
},
"type": "library",
"autoload": {
"files": [
"autoload.php"
],
"psr-4": {
"phpmock\\phpunit\\": "classes/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"WTFPL"
],
"authors": [
{
"name": "Markus Malkusch",
"email": "markus@malkusch.de",
"homepage": "http://markus.malkusch.de",
"role": "Developer"
}
],
"description": "Mock built-in PHP functions (e.g. time()) with PHPUnit. This package relies on PHP's namespace fallback policy. No further extension is needed.",
"homepage": "https://github.com/php-mock/php-mock-phpunit",
"keywords": [
"BDD",
"TDD",
"function",
"mock",
"phpunit",
"stub",
"test",
"test double",
"testing"
],
"support": {
"issues": "https://github.com/php-mock/php-mock-phpunit/issues",
"source": "https://github.com/php-mock/php-mock-phpunit/tree/2.10.0"
},
"funding": [
{
"url": "https://github.com/michalbundyra",
"type": "github"
}
],
"time": "2024-02-11T07:24:16+00:00"
},
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "9.2.31", "version": "9.2.31",

View file

@ -306,13 +306,6 @@ class Crypto
*/ */
public static function randomDigits($digits) public static function randomDigits($digits)
{ {
$rn = ''; return random_int(0, 10 ** $digits - 1);
// generating cryptographically secure pseudo-random integers
for ($i = 0; $i < $digits; $i++) {
$rn .= random_int(0, 9);
}
return $rn;
} }
} }

View file

@ -0,0 +1,45 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
namespace Friendica\Test\Unit\Util;
use Friendica\Util\Crypto;
use phpmock\phpunit\PHPMock;
use PHPUnit\Framework\TestCase;
class CryptoTest extends TestCase
{
use PHPMock;
public function testRandomDigitsRandomInt()
{
$random_int = $this->getFunctionMock('Friendica\Util', 'random_int');
$random_int->expects($this->any())->willReturnCallback(function ($min, $max) {
return 12345678;
});
self::assertSame(12345678, Crypto::randomDigits(8));
}
public function testDiasporaPubRsaToMe()
{
$key = 'LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tDQpNSUdKQW9HQkFORjVLTmJzN2k3aTByNVFZckNpRExEZ09pU1BWbmgvdlFnMXpnSk9VZVRheWVETk5yZTR6T1RVDQpSVDcyZGlLQ294OGpYOE5paElJTFJtcUtTOWxVYVNzd21QcVNFenVpdE5xeEhnQy8xS2ZuaXM1Qm96NnRwUUxjDQpsZDMwQjJSMWZIVWdFTHZWd0JkV29pRDhSRUt1dFNuRVBGd1RwVmV6aVlWYWtNY25pclRWQWdNQkFBRT0NCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0';
// TODO PHPUnit 10: Replace with assertStringEqualsStringIgnoringLineEndings()
self::assertSame(
str_replace("\n", "\r\n", <<< TXT
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDReSjW7O4u4tK+UGKwogyw4Dok
j1Z4f70INc4CTlHk2sngzTa3uMzk1EU+9nYigqMfI1/DYoSCC0ZqikvZVGkrMJj6
khM7orTasR4Av9Sn54rOQaM+raUC3JXd9AdkdXx1IBC71cAXVqIg/ERCrrUpxDxc
E6VXs4mFWpDHJ4q01QIDAQAB
-----END PUBLIC KEY-----
TXT),
Crypto::rsaToPem(base64_decode($key))
);
}
}

View file

@ -1,6 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDReSjW7O4u4tK+UGKwogyw4Dok
j1Z4f70INc4CTlHk2sngzTa3uMzk1EU+9nYigqMfI1/DYoSCC0ZqikvZVGkrMJj6
khM7orTasR4Av9Sn54rOQaM+raUC3JXd9AdkdXx1IBC71cAXVqIg/ERCrrUpxDxc
E6VXs4mFWpDHJ4q01QIDAQAB
-----END PUBLIC KEY-----

View file

@ -1 +0,0 @@
LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tDQpNSUdKQW9HQkFORjVLTmJzN2k3aTByNVFZckNpRExEZ09pU1BWbmgvdlFnMXpnSk9VZVRheWVETk5yZTR6T1RVDQpSVDcyZGlLQ294OGpYOE5paElJTFJtcUtTOWxVYVNzd21QcVNFenVpdE5xeEhnQy8xS2ZuaXM1Qm96NnRwUUxjDQpsZDMwQjJSMWZIVWdFTHZWd0JkV29pRDhSRUt1dFNuRVBGd1RwVmV6aVlWYWtNY25pclRWQWdNQkFBRT0NCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0

View file

@ -7,10 +7,16 @@
timeoutForMediumTests="900" timeoutForMediumTests="900"
timeoutForLargeTests="900" timeoutForLargeTests="900"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"> xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<testsuite name="friendica"> <testsuites>
<directory suffix=".php">functional/</directory> <testsuite name="friendica">
<directory suffix=".php">src/</directory> <directory suffix=".php">functional/</directory>
</testsuite> <directory suffix=".php">src/</directory>
<directory suffix=".php">Unit/</directory>
</testsuite>
<testsuite name="unit">
<directory suffix=".php">Unit/</directory>
</testsuite>
</testsuites>
<!-- Filters for Code Coverage --> <!-- Filters for Code Coverage -->
<coverage> <coverage>
<include> <include>

View file

@ -5,12 +5,13 @@
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
/// @todo this is in the same namespace as Install for mocking 'function_exists' namespace Friendica\Test\src\Core;
namespace Friendica\Core;
use Dice\Dice; use Dice\Dice;
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
use Friendica\Core\Config\ValueObject\Cache; use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Core\Installer;
use Friendica\Core\L10n;
use Friendica\DI; use Friendica\DI;
use Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses; use Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses;
use Friendica\Network\HTTPClient\Capability\ICanSendHttpRequests; use Friendica\Network\HTTPClient\Capability\ICanSendHttpRequests;
@ -18,18 +19,20 @@ use Friendica\Test\MockedTest;
use Friendica\Test\Util\VFSTrait; use Friendica\Test\Util\VFSTrait;
use Mockery; use Mockery;
use Mockery\MockInterface; use Mockery\MockInterface;
use phpmock\phpunit\PHPMock;
class InstallerTest extends MockedTest class InstallerTest extends MockedTest
{ {
use VFSTrait; use VFSTrait;
use ArraySubsetAsserts; use ArraySubsetAsserts;
use PHPMock;
/** /**
* @var L10n|MockInterface * @var L10n|MockInterface
*/ */
private $l10nMock; private $l10nMock;
/** /**
* @var Dice|MockInterface * @var Dice&MockInterface
*/ */
private $dice; private $dice;
@ -41,7 +44,7 @@ class InstallerTest extends MockedTest
$this->l10nMock = Mockery::mock(L10n::class); $this->l10nMock = Mockery::mock(L10n::class);
/** @var Dice|MockInterface $dice */ /** @var Dice&MockInterface $dice */
$this->dice = Mockery::mock(Dice::class)->makePartial(); $this->dice = Mockery::mock(Dice::class)->makePartial();
$this->dice = $this->dice->addRules(include __DIR__ . '/../../../static/dependencies.config.php'); $this->dice = $this->dice->addRules(include __DIR__ . '/../../../static/dependencies.config.php');
@ -115,65 +118,50 @@ class InstallerTest extends MockedTest
self::assertArraySubset($subSet, $assertionArray, false, "expected subset: " . PHP_EOL . print_r($subSet, true) . PHP_EOL . "current subset: " . print_r($assertionArray, true)); self::assertArraySubset($subSet, $assertionArray, false, "expected subset: " . PHP_EOL . print_r($subSet, true) . PHP_EOL . "current subset: " . print_r($assertionArray, true));
} }
/** public static function getCheckKeysData(): array
* Replaces function_exists results with given mocks
*
* @param array $functions a list from function names and their result
*/
private function setFunctions(array $functions)
{ {
global $phpMock; return [
$phpMock['function_exists'] = function($function) use ($functions) { 'openssl_pkey_new does not exist' => ['openssl_pkey_new', false],
foreach ($functions as $name => $value) { 'openssl_pkey_new does exists' => ['openssl_pkey_new', true],
if ($function == $name) { ];
return $value;
}
}
return '__phpunit_continue__';
};
}
/**
* Replaces class_exist results with given mocks
*
* @param array $classes a list from class names and their results
*/
private function setClasses(array $classes)
{
global $phpMock;
$phpMock['class_exists'] = function($class) use ($classes) {
foreach ($classes as $name => $value) {
if ($class == $name) {
return $value;
}
}
return '__phpunit_continue__';
};
} }
/** /**
* @small * @small
*
* @dataProvider getCheckKeysData
*/ */
public function testCheckKeys() public function testCheckKeys($function, $expected)
{ {
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) use ($function, $expected) {
if ($function_name === $function) {
return $expected;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->l10nMock->shouldReceive('t')->andReturnUsing(function ($args) { return $args; }); $this->l10nMock->shouldReceive('t')->andReturnUsing(function ($args) { return $args; });
$this->setFunctions(['openssl_pkey_new' => false]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkKeys()); self::assertSame($expected, $install->checkKeys());
$this->setFunctions(['openssl_pkey_new' => true]);
$install = new Installer();
self::assertTrue($install->checkKeys());
} }
/** /**
* @small * @small
*/ */
public function testCheckFunctions() public function testCheckFunctionsWithoutIntlChar()
{ {
$class_exists = $this->getFunctionMock('Friendica\Core', 'class_exists');
$class_exists->expects($this->any())->willReturnCallback(function($class_name) {
if ($class_name === 'IntlChar') {
return false;
}
return call_user_func_array('\class_exists', func_get_args());
});
$this->mockFunctionL10TCalls(); $this->mockFunctionL10TCalls();
$this->setClasses(['IntlChar' => false]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(2, self::assertCheckExist(2,
@ -182,9 +170,23 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
}
/**
* @small
*/
public function testCheckFunctionsWithoutCurlInit()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'curl_init') {
return false;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true);
$this->mockFunctionL10TCalls();
$this->setFunctions(['curl_init' => false, 'imagecreatefromjpeg' => true]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(4, self::assertCheckExist(4,
@ -193,9 +195,23 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
}
/**
* @small
*/
public function testCheckFunctionsWithoutImagecreateformjpeg()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'imagecreatefromjpeg') {
return false;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true);
$this->mockFunctionL10TCalls();
$this->setFunctions(['imagecreatefromjpeg' => false]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(5, self::assertCheckExist(5,
@ -204,9 +220,23 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
}
/**
* @small
*/
public function testCheckFunctionsWithoutOpensslpublicencrypt()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'openssl_public_encrypt') {
return false;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true);
$this->mockFunctionL10TCalls();
$this->setFunctions(['openssl_public_encrypt' => false]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(6, self::assertCheckExist(6,
@ -215,9 +245,23 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
}
/**
* @small
*/
public function testCheckFunctionsWithoutMbStrlen()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'mb_strlen') {
return false;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true);
$this->mockFunctionL10TCalls();
$this->setFunctions(['mb_strlen' => false]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(7, self::assertCheckExist(7,
@ -226,9 +270,23 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
}
/**
* @small
*/
public function testCheckFunctionsWithoutIconvStrlen()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'iconv_strlen') {
return false;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true);
$this->mockFunctionL10TCalls();
$this->setFunctions(['iconv_strlen' => false]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(8, self::assertCheckExist(8,
@ -237,9 +295,23 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
}
/**
* @small
*/
public function testCheckFunctionsWithoutPosixkill()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'posix_kill') {
return false;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true);
$this->mockFunctionL10TCalls();
$this->setFunctions(['posix_kill' => false]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(9, self::assertCheckExist(9,
@ -248,9 +320,23 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
}
/**
* @small
*/
public function testCheckFunctionsWithoutProcOpen()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'proc_open') {
return false;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true);
$this->mockFunctionL10TCalls();
$this->setFunctions(['proc_open' => false]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(10, self::assertCheckExist(10,
@ -259,8 +345,23 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
$this->mockFunctionL10TCalls(); }
$this->setFunctions(['json_encode' => false]);
/**
* @small
*/
public function testCheckFunctionsWithoutJsonEncode()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'json_encode') {
return false;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(11, self::assertCheckExist(11,
@ -269,9 +370,23 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
}
/**
* @small
*/
public function testCheckFunctionsWithoutFinfoOpen()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'finfo_open') {
return false;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true);
$this->mockFunctionL10TCalls();
$this->setFunctions(['finfo_open' => false]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(12, self::assertCheckExist(12,
@ -280,9 +395,23 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
}
/**
* @small
*/
public function testCheckFunctionsWithoutGmpStrval()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'gmp_strval') {
return false;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true);
$this->mockFunctionL10TCalls();
$this->setFunctions(['gmp_strval' => false]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkFunctions()); self::assertFalse($install->checkFunctions());
self::assertCheckExist(13, self::assertCheckExist(13,
@ -291,20 +420,36 @@ class InstallerTest extends MockedTest
false, false,
true, true,
$install->getChecks()); $install->getChecks());
}
/**
* @small
*/
public function testCheckFunctions()
{
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if (in_array(
$function_name,
[
'curl_init',
'imagecreatefromjpeg',
'openssl_public_encrypt',
'mb_strlen',
'iconv_strlen',
'posix_kill',
'json_encode',
'finfo_open',
'gmp_strval',
]
)) {
return true;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->mockFunctionL10TCalls(true); $this->mockFunctionL10TCalls(true);
$this->setFunctions([
'curl_init' => true,
'imagecreatefromjpeg' => true,
'openssl_public_encrypt' => true,
'mb_strlen' => true,
'iconv_strlen' => true,
'posix_kill' => true,
'json_encode' => true,
'finfo_open' => true,
'gmp_strval' => true,
]);
$this->setClasses(['IntlChar' => true]);
$install = new Installer(); $install = new Installer();
self::assertTrue($install->checkFunctions()); self::assertTrue($install->checkFunctions());
} }
@ -331,11 +476,18 @@ class InstallerTest extends MockedTest
/** /**
* @small * @small
* @runInSeparateProcess
* @preserveGlobalState disabled
*/ */
public function testCheckHtAccessFail() public function testCheckHtAccessFail()
{ {
// Mocking that we can use CURL
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'curl_init') {
return true;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->l10nMock->shouldReceive('t')->andReturnUsing(function ($args) { return $args; }); $this->l10nMock->shouldReceive('t')->andReturnUsing(function ($args) { return $args; });
// Mocking the CURL Response // Mocking the CURL Response
@ -367,9 +519,6 @@ class InstallerTest extends MockedTest
DI::init($this->dice, true); DI::init($this->dice, true);
// Mocking that we can use CURL
$this->setFunctions(['curl_init' => true]);
$install = new Installer(); $install = new Installer();
self::assertFalse($install->checkHtAccess('https://test')); self::assertFalse($install->checkHtAccess('https://test'));
@ -378,11 +527,18 @@ class InstallerTest extends MockedTest
/** /**
* @small * @small
* @runInSeparateProcess
* @preserveGlobalState disabled
*/ */
public function testCheckHtAccessWork() public function testCheckHtAccessWork()
{ {
// Mocking that we can use CURL
$function_exists = $this->getFunctionMock('Friendica\Core', 'function_exists');
$function_exists->expects($this->any())->willReturnCallback(function($function_name) {
if ($function_name === 'curl_init') {
return true;
}
return call_user_func_array('\function_exists', func_get_args());
});
$this->l10nMock->shouldReceive('t')->andReturnUsing(function ($args) { return $args; }); $this->l10nMock->shouldReceive('t')->andReturnUsing(function ($args) { return $args; });
// Mocking the failed CURL Response // Mocking the failed CURL Response
@ -414,68 +570,20 @@ class InstallerTest extends MockedTest
DI::init($this->dice, true); DI::init($this->dice, true);
// Mocking that we can use CURL
$this->setFunctions(['curl_init' => true]);
$install = new Installer(); $install = new Installer();
self::assertTrue($install->checkHtAccess('https://test')); self::assertTrue($install->checkHtAccess('https://test'));
} }
/**
* @small
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testImagick()
{
static::markTestIncomplete('needs adapted class_exists() mock');
$this->l10nMock->shouldReceive('t')->andReturnUsing(function ($args) { return $args; });
$this->setClasses(['Imagick' => true]);
$install = new Installer();
// even there is no supported type, Imagick should return true (because it is not required)
self::assertTrue($install->checkImagick());
self::assertCheckExist(1,
$this->l10nMock->t('ImageMagick supports GIF'),
'',
true,
false,
$install->getChecks());
}
/**
* @small
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testImagickNotFound()
{
static::markTestIncomplete('Disabled due not working/difficult mocking global functions - needs more care!');
$this->l10nMock->shouldReceive('t')->andReturnUsing(function ($args) { return $args; });
$this->setClasses(['Imagick' => true]);
$install = new Installer();
// even there is no supported type, Imagick should return true (because it is not required)
self::assertTrue($install->checkImagick());
self::assertCheckExist(1,
$this->l10nMock->t('ImageMagick supports GIF'),
'',
false,
false,
$install->getChecks());
}
public function testImagickNotInstalled() public function testImagickNotInstalled()
{ {
$this->setClasses(['Imagick' => false]); $class_exists = $this->getFunctionMock('Friendica\Core', 'class_exists');
$class_exists->expects($this->any())->willReturnCallback(function($class_name) {
if ($class_name === 'Imagick') {
return false;
}
return call_user_func_array('\class_exists', func_get_args());
});
$this->mockL10nT('ImageMagick PHP extension is not installed'); $this->mockL10nT('ImageMagick PHP extension is not installed');
$install = new Installer(); $install = new Installer();
@ -506,34 +614,3 @@ class InstallerTest extends MockedTest
$install->setUpCache($configCache, '/test/'); $install->setUpCache($configCache, '/test/');
} }
} }
/**
* A workaround to replace the PHP native function_exists with a mocked function
*
* @param string $function_name the Name of the function
*
* @return bool true or false
*/
function function_exists(string $function_name)
{
global $phpMock;
if (isset($phpMock['function_exists'])) {
$result = call_user_func_array($phpMock['function_exists'], func_get_args());
if ($result !== '__phpunit_continue__') {
return $result;
}
}
return call_user_func_array('\function_exists', func_get_args());
}
function class_exists($class_name)
{
global $phpMock;
if (isset($phpMock['class_exists'])) {
$result = call_user_func_array($phpMock['class_exists'], func_get_args());
if ($result !== '__phpunit_continue__') {
return $result;
}
}
return call_user_func_array('\class_exists', func_get_args());
}

View file

@ -1,93 +0,0 @@
<?php
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/// @todo Use right namespace - needs alternative way of mocking random_int()
namespace Friendica\Util;
use phpseclib\Crypt\RSA;
use phpseclib\Math\BigInteger;
use PHPUnit\Framework\TestCase;
class CryptoTest extends TestCase
{
public static function tearDownAfterClass(): void
{
// Reset mocking
global $phpMock;
$phpMock = [];
parent::tearDownAfterClass();
}
/**
* Replaces random_int results with given mocks
*
*/
private function assertRandomInt($min, $max)
{
global $phpMock;
$phpMock['random_int'] = function ($mMin, $mMax) use ($min, $max) {
self::assertEquals($min, $mMin);
self::assertEquals($max, $mMax);
return 1;
};
}
public function testRandomDigitsRandomInt()
{
self::assertRandomInt(0, 9);
$test = Crypto::randomDigits(1);
self::assertEquals(1, strlen($test));
self::assertEquals(1, $test);
$test = Crypto::randomDigits(8);
self::assertEquals(8, strlen($test));
self::assertEquals(11111111, $test);
}
public function dataRsa(): array
{
return [
'diaspora' => [
'key' => file_get_contents(__DIR__ . '/../../datasets/crypto/rsa/diaspora-public-rsa-base64'),
'expected' => file_get_contents(__DIR__ . '/../../datasets/crypto/rsa/diaspora-public-pem'),
],
];
}
/**
* @dataProvider dataRsa
*/
public function testPubRsaToMe(string $key, string $expected)
{
self::assertEquals($expected, Crypto::rsaToPem(base64_decode($key)));
}
public function dataPEM()
{
return [
'diaspora' => [
'key' => file_get_contents(__DIR__ . '/../../datasets/crypto/rsa/diaspora-public-pem'),
],
];
}
}
/**
* A workaround to replace the PHP native random_int() (>= 7.0) with a mocked function
*
* @return int
*/
function random_int($min, $max)
{
global $phpMock;
if (isset($phpMock['random_int'])) {
return call_user_func_array($phpMock['random_int'], func_get_args());
}
}