Browse Source
[App Code Check] add check for version and mandatory fields
[App Code Check] add check for version and mandatory fields
* ref #17598 * including unit tests for mandatory fields/versionsremotes/origin/certificate-external-storage-visibility
13 changed files with 338 additions and 2 deletions
-
69core/command/app/checkcode.php
-
3core/register_command.php
-
141lib/private/app/codechecker/infochecker.php
-
9tests/apps/testapp-infoxml-version-different/appinfo/info.xml
-
1tests/apps/testapp-infoxml-version-different/appinfo/version
-
9tests/apps/testapp-infoxml-version/appinfo/info.xml
-
1tests/apps/testapp-infoxml-version/appinfo/version
-
9tests/apps/testapp-infoxml/appinfo/info.xml
-
8tests/apps/testapp-name-missing/appinfo/info.xml
-
8tests/apps/testapp-version-missing/appinfo/info.xml
-
8tests/apps/testapp-version/appinfo/info.xml
-
1tests/apps/testapp-version/appinfo/version
-
73tests/lib/app/codechecker/infocheckertest.php
@ -0,0 +1,141 @@ |
|||
<?php |
|||
/** |
|||
* @author Morris Jobke <hey@morrisjobke.de> |
|||
* |
|||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
|||
* @license AGPL-3.0 |
|||
* |
|||
* This code is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License, version 3, |
|||
* as published by the Free Software Foundation. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License, version 3, |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
|||
* |
|||
*/ |
|||
|
|||
namespace OC\App\CodeChecker; |
|||
|
|||
use OC\App\InfoParser; |
|||
use OC\Hooks\BasicEmitter; |
|||
|
|||
class InfoChecker extends BasicEmitter { |
|||
|
|||
/** @var InfoParser */ |
|||
private $infoParser; |
|||
|
|||
private $mandatoryFields = [ |
|||
'author', |
|||
'description', |
|||
'id', |
|||
'licence', |
|||
'name', |
|||
]; |
|||
private $optionalFields = [ |
|||
'bugs', |
|||
'category', |
|||
'documentation', |
|||
'namespace', |
|||
'ocsid', |
|||
'repository', |
|||
'require', |
|||
'requiremin', |
|||
'types', |
|||
'version', |
|||
'website', |
|||
]; |
|||
private $deprecatedFields = [ |
|||
'default_enable', |
|||
'public', |
|||
'remote', |
|||
'shipped', |
|||
'standalone', |
|||
]; |
|||
|
|||
public function __construct(InfoParser $infoParser) { |
|||
$this->infoParser = $infoParser; |
|||
} |
|||
|
|||
/** |
|||
* @param string $appId |
|||
* @return array |
|||
*/ |
|||
public function analyse($appId) { |
|||
$appPath = \OC_App::getAppPath($appId); |
|||
if ($appPath === false) { |
|||
throw new \RuntimeException("No app with given id <$appId> known."); |
|||
} |
|||
|
|||
$errors = []; |
|||
|
|||
$info = $this->infoParser->parse($appPath . '/appinfo/info.xml'); |
|||
|
|||
foreach ($info as $key => $value) { |
|||
if (in_array($key, $this->mandatoryFields)) { |
|||
$this->emit('InfoChecker', 'mandatoryFieldFound', [$key, $value]); |
|||
continue; |
|||
} |
|||
|
|||
if (in_array($key, $this->optionalFields)) { |
|||
$this->emit('InfoChecker', 'optionalFieldFound', [$key, $value]); |
|||
continue; |
|||
} |
|||
|
|||
if (in_array($key, $this->deprecatedFields)) { |
|||
// skip empty arrays - empty arrays for remote and public are always added
|
|||
if($value === []) { |
|||
continue; |
|||
} |
|||
$this->emit('InfoChecker', 'deprecatedFieldFound', [$key, $value]); |
|||
continue; |
|||
} |
|||
|
|||
$this->emit('InfoChecker', 'unusedFieldFound', [$key, $value]); |
|||
} |
|||
|
|||
foreach ($this->mandatoryFields as $key) { |
|||
if(!isset($info[$key])) { |
|||
$this->emit('InfoChecker', 'mandatoryFieldMissing', [$key]); |
|||
$errors[] = [ |
|||
'type' => 'mandatoryFieldMissing', |
|||
'field' => $key, |
|||
]; |
|||
} |
|||
} |
|||
|
|||
$versionFile = $appPath . '/appinfo/version'; |
|||
if (is_file($versionFile)) { |
|||
$version = trim(file_get_contents($versionFile)); |
|||
if(isset($info['version'])) { |
|||
if($info['version'] !== $version) { |
|||
$this->emit('InfoChecker', 'differentVersions', |
|||
[$version, $info['version']]); |
|||
$errors[] = [ |
|||
'type' => 'differentVersions', |
|||
'message' => 'appinfo/version: ' . $version . |
|||
' - appinfo/info.xml: ' . $info['version'], |
|||
]; |
|||
} else { |
|||
$this->emit('InfoChecker', 'sameVersions', [$versionFile]); |
|||
} |
|||
} else { |
|||
$this->emit('InfoChecker', 'migrateVersion', [$version]); |
|||
} |
|||
} else { |
|||
if(!isset($info['version'])) { |
|||
$this->emit('InfoChecker', 'mandatoryFieldMissing', ['version']); |
|||
$errors[] = [ |
|||
'type' => 'mandatoryFieldMissing', |
|||
'field' => 'version', |
|||
]; |
|||
} |
|||
} |
|||
|
|||
return $errors; |
|||
} |
|||
} |
@ -0,0 +1,9 @@ |
|||
<?xml version="1.0"?> |
|||
<info> |
|||
<id>testapp-infoxml-version</id> |
|||
<version>1.2.3</version> |
|||
<author>Jane</author> |
|||
<description>A b c</description> |
|||
<licence>Abc</licence> |
|||
<name>Test app</name> |
|||
</info> |
@ -0,0 +1 @@ |
|||
1.2.4 |
@ -0,0 +1,9 @@ |
|||
<?xml version="1.0"?> |
|||
<info> |
|||
<id>testapp-infoxml-version</id> |
|||
<version>1.2.3</version> |
|||
<author>Jane</author> |
|||
<description>A b c</description> |
|||
<licence>Abc</licence> |
|||
<name>Test app</name> |
|||
</info> |
@ -0,0 +1 @@ |
|||
1.2.3 |
@ -0,0 +1,9 @@ |
|||
<?xml version="1.0"?> |
|||
<info> |
|||
<id>testapp-infoxml</id> |
|||
<version>1.2.3</version> |
|||
<author>Jane</author> |
|||
<description>A b c</description> |
|||
<licence>Abc</licence> |
|||
<name>Test app</name> |
|||
</info> |
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0"?> |
|||
<info> |
|||
<id>testapp-version</id> |
|||
<version>1.1.1</version> |
|||
<author>Jane</author> |
|||
<description>A b c</description> |
|||
<licence>Abc</licence> |
|||
</info> |
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0"?> |
|||
<info> |
|||
<id>testapp-version</id> |
|||
<author>Jane</author> |
|||
<description>A b c</description> |
|||
<licence>Abc</licence> |
|||
<name>Test app</name> |
|||
</info> |
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0"?> |
|||
<info> |
|||
<id>testapp-version</id> |
|||
<author>Jane</author> |
|||
<description>A b c</description> |
|||
<licence>Abc</licence> |
|||
<name>Test app</name> |
|||
</info> |
@ -0,0 +1 @@ |
|||
1.2.3 |
@ -0,0 +1,73 @@ |
|||
<?php |
|||
/** |
|||
* @author Morris Jobke <hey@morrisjobke.de> |
|||
* |
|||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
|||
* @license AGPL-3.0 |
|||
* |
|||
* This code is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License, version 3, |
|||
* as published by the Free Software Foundation. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License, version 3, |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
|||
* |
|||
*/ |
|||
|
|||
namespace OC\App\CodeChecker; |
|||
|
|||
use OC\App\InfoParser; |
|||
use Test\TestCase; |
|||
|
|||
class InfoCheckerTest extends TestCase { |
|||
/** @var InfoChecker */ |
|||
protected $infoChecker; |
|||
|
|||
public static function setUpBeforeClass() { |
|||
\OC::$APPSROOTS[] = [ |
|||
'path' => \OC::$SERVERROOT . '/tests/apps', |
|||
'url' => '/apps-test', |
|||
'writable' => false, |
|||
]; |
|||
} |
|||
|
|||
public static function tearDownAfterClass() { |
|||
// remove last element
|
|||
array_pop(\OC::$APPSROOTS); |
|||
} |
|||
|
|||
protected function setUp() { |
|||
parent::setUp(); |
|||
$infoParser = new InfoParser(\OC::$server->getHTTPHelper(), \OC::$server->getURLGenerator()); |
|||
|
|||
$this->infoChecker = new InfoChecker($infoParser); |
|||
} |
|||
|
|||
public function appInfoData() { |
|||
return [ |
|||
['testapp-infoxml', []], |
|||
['testapp-version', []], |
|||
['testapp-infoxml-version', []], |
|||
['testapp-infoxml-version-different', [['type' => 'differentVersions', 'message' => 'appinfo/version: 1.2.4 - appinfo/info.xml: 1.2.3']]], |
|||
['testapp-version-missing', [['type' => 'mandatoryFieldMissing', 'field' => 'version']]], |
|||
['testapp-name-missing', [['type' => 'mandatoryFieldMissing', 'field' => 'name']]], |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider appInfoData |
|||
* |
|||
* @param $appId |
|||
* @param $expectedErrors |
|||
*/ |
|||
public function testApps($appId, $expectedErrors) { |
|||
$errors = $this->infoChecker->analyse($appId); |
|||
|
|||
$this->assertEquals($expectedErrors, $errors); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue