mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-17 06:18:44 +02:00
module dependency validation moved in a core folder + cleanup dedicated unit/integration tests
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest;
|
||||
|
||||
class XmlModule {
|
||||
public string $sModuleName;
|
||||
public array $aDependencyModulesNames=[];
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest;
|
||||
|
||||
class XmlModuleMetaInfo {
|
||||
public string $sLastNodeId;
|
||||
public string $sNodeName;
|
||||
@@ -13,18 +13,9 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Integration;
|
||||
|
||||
use ApplicationException;
|
||||
use Combodo\iTop\Test\UnitTest\XmlModule;
|
||||
use Combodo\iTop\Test\UnitTest\XmlModuleMetaInfo;
|
||||
use utils;
|
||||
|
||||
require_once __DIR__ . '/XmlModuleMetaInfo.php';
|
||||
require_once __DIR__ . '/XmlModule.php';
|
||||
|
||||
use ModuleInstallerAPI;
|
||||
|
||||
/**
|
||||
* @group modulesDependencyValidation
|
||||
*/
|
||||
@@ -44,7 +35,6 @@ class iTopModulesDependencyValidationService {
|
||||
{
|
||||
if (!isset(self::$oInstance)) {
|
||||
self::$oInstance = new iTopModulesDependencyValidationService();
|
||||
self::ReadModuleMetaInfo();
|
||||
}
|
||||
|
||||
return self::$oInstance;
|
||||
@@ -54,54 +44,21 @@ class iTopModulesDependencyValidationService {
|
||||
self::$oInstance = $instance;
|
||||
}
|
||||
|
||||
|
||||
public static function ReadModuleMetaInfo(): void
|
||||
{
|
||||
require_once APPROOT."setup/modulediscovery.class.inc.php";
|
||||
require_once(APPROOT.'/setup/moduleinstaller.class.inc.php');
|
||||
|
||||
private static function GetModulesDataByModuleName() : array {
|
||||
if (count(self::$aModulesDataByModuleName)>0){
|
||||
return;
|
||||
return self::$aModulesDataByModuleName;
|
||||
}
|
||||
|
||||
$aDirsToScan = [
|
||||
APPROOT.'datamodels/2.x',
|
||||
APPROOT.'extensions',
|
||||
APPROOT.'extensions/*',
|
||||
APPROOT.'extensions',
|
||||
APPROOT.'data/production-modules',
|
||||
APPROOT.'data/production-modules',
|
||||
APPROOT.'data/production-modules/*',
|
||||
];
|
||||
$aFilesToRemove=[];
|
||||
foreach ($aDirsToScan as $sDir){
|
||||
foreach (glob("$sDir/*/module.*.php") as $sFile) {
|
||||
$sContent = file_get_contents($sFile);
|
||||
$sContent=str_replace('SetupWebPage::AddModule', '$aModuleData=array', $sContent);
|
||||
self::$aModulesDataByModuleName = ModuleDiscovery::GetAvailableModules($aDirsToScan, true);
|
||||
|
||||
$sTempFile = tempnam(sys_get_temp_dir(), 'modulefile_');
|
||||
$aFilesToRemove[]=$sTempFile;
|
||||
file_put_contents($sTempFile, $sContent);
|
||||
|
||||
require_once $sTempFile;
|
||||
|
||||
//replace tmp file by real module path
|
||||
$aModuleData[0]=$sFile;
|
||||
$sModuleId=$aModuleData[1];
|
||||
|
||||
list($sModuleName, $sVersion) = \ModuleDiscovery::GetModuleName($sModuleId);
|
||||
self::$aModulesDataByModuleName[$sModuleName] = $aModuleData;
|
||||
}
|
||||
|
||||
ksort(self::$aModulesDataByModuleName);
|
||||
|
||||
foreach ($aFilesToRemove as $sTmpFile){
|
||||
@unlink($sTmpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function GetModuleMetainfo($sModuleId)
|
||||
{
|
||||
return self::$aModulesDataByModuleName[$sModuleId] ?? [];
|
||||
return self::$aModulesDataByModuleName;
|
||||
}
|
||||
|
||||
public function ListDatamodelFiles() : array
|
||||
@@ -176,10 +133,10 @@ class iTopModulesDependencyValidationService {
|
||||
public function FetchAllDependenciesViaModulesFiles()
|
||||
{
|
||||
$aFullnameClassesByModuleName=[];
|
||||
foreach (self::$aModulesDataByModuleName as $sModuleName => $aModuleData){
|
||||
foreach (self::GetModulesDataByModuleName() as $sModuleName => $aModuleData){
|
||||
//echo "$sModuleName\n";
|
||||
$aFiles = $aModuleData[2]['datamodel'] ?? [];
|
||||
$sDir = dirname($aModuleData[0]);
|
||||
$sDir = dirname($aModuleData['module_file_path']);
|
||||
|
||||
$aDeps=[];
|
||||
foreach ($aFiles as $sFile){
|
||||
@@ -194,12 +151,12 @@ class iTopModulesDependencyValidationService {
|
||||
}
|
||||
|
||||
foreach ($aFullnameClassesByModuleName as $sModuleName => $aFullnameClasses){
|
||||
foreach (self::$aModulesDataByModuleName as $sModuleName2 => $aModuleData){
|
||||
foreach (self::GetModulesDataByModuleName() as $sModuleName2 => $aModuleData){
|
||||
if ($sModuleName2 === $sModuleName){
|
||||
continue;
|
||||
}
|
||||
|
||||
$sDir = dirname($aModuleData[0]);
|
||||
$sDir = dirname($aModuleData['module_file_path']);
|
||||
|
||||
if (count($aFullnameClassesByModuleName)==0){
|
||||
continue;
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
* This file is part of iTop.
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* iTop 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
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Integration;
|
||||
|
||||
use ApplicationException;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use iTopModulesDependencyValidationService;
|
||||
use XmlModule;
|
||||
use XmlModuleMetaInfo;
|
||||
use utils;
|
||||
|
||||
|
||||
use ModuleInstallerAPI;
|
||||
|
||||
/**
|
||||
* @package Combodo\iTop\Test\UnitTest\Setup
|
||||
*/
|
||||
class iTopModulesDependencyValidationServiceTest extends ItopDataTestCase {
|
||||
private iTopModulesDependencyValidationService $oiTopModulesDependencyValidationService;
|
||||
|
||||
private array $aFilesToRemove = [];
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->RequireOnceItopFile('setup/modulediscovery.class.inc.php');
|
||||
$this->RequireOnceItopFile('setup/module/iTopModulesDependencyValidationService.php');
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
parent::tearDown(); // TODO: Change the autogenerated stub
|
||||
foreach ($this->aFilesToRemove as $sTmpFile){
|
||||
@unlink($sTmpFile);
|
||||
}
|
||||
iTopModulesDependencyValidationService::SetInstance(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Module dependency validation: make sure dependencies are correct toward classes/interfaces coming from PHP/Xml datamodel files
|
||||
*/
|
||||
public function testReadModuleFileData()
|
||||
{
|
||||
iTopModulesDependencyValidationService::GetInstance()->FetchAllDependenciesViaModulesFiles();
|
||||
$this->testModulesBasedOnDMFilesOnly();
|
||||
}
|
||||
|
||||
/**
|
||||
* Module dependency validation: make sure dependencies are correct toward classes/interfaces coming from Xml datamodel files
|
||||
*/
|
||||
public function testModulesBasedOnDMFilesOnly()
|
||||
{
|
||||
iTopModulesDependencyValidationService::GetInstance()->FetchAllDependenciesViaDM();
|
||||
|
||||
$aErrors=[];
|
||||
/** @var XmlModule $oXmlModule */
|
||||
foreach (iTopModulesDependencyValidationService::GetInstance()->aModules as $sModuleName => $oXmlModule) {
|
||||
$aCurrentDeps = iTopModulesDependencyValidationService::GetInstance()::$aModulesDataByModuleName[$sModuleName][2]['dependencies'] ?? [];
|
||||
$aModuleErrors=[];
|
||||
foreach ($oXmlModule->aDependencyModulesNames as $sDepModuleName => $oXmlModule2){
|
||||
$sXmlUIDs = implode('|', $oXmlModule->aXMlMetaInfosByModuleNames[$sDepModuleName]);
|
||||
$bResolved=false;
|
||||
foreach ($aCurrentDeps as $sDepString){
|
||||
$oModuleDependency = new \iTopCoreModuleDependency($sDepString);
|
||||
|
||||
if (in_array($sDepModuleName, $oModuleDependency->GetPotentialPrerequisiteModuleNames())) {
|
||||
$bResolved=true;
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($oModuleDependency->GetPotentialPrerequisiteModuleNames() as $sPotentialDepModuleName){
|
||||
/** @var XmlModule $oXmlModule2 */
|
||||
$oXmlModule2 = iTopModulesDependencyValidationService::GetInstance()->aModules[$sPotentialDepModuleName]??null;
|
||||
|
||||
if (! is_null($oXmlModule2) && $oXmlModule2->Depends($sDepModuleName)){
|
||||
$bResolved=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($bResolved) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $bResolved){
|
||||
$aModuleErrors []= "$sModuleName depends on $sDepModuleName but missing in module dependencies: " . implode(' & ', $aCurrentDeps) . ". ($sXmlUIDs)";
|
||||
}
|
||||
}
|
||||
|
||||
if (count($aModuleErrors)){
|
||||
$aErrors[$sModuleName]=$aModuleErrors;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertEquals(0, count($aErrors), var_export($aErrors, true));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,30 +13,23 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Integration;
|
||||
namespace Combodo\iTop\Test\UnitTest\Setup\Module;
|
||||
|
||||
use ApplicationException;
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
use Combodo\iTop\Test\UnitTest\XmlModule;
|
||||
use Combodo\iTop\Test\UnitTest\XmlModuleMetaInfo;
|
||||
use utils;
|
||||
use iTopModulesDependencyValidationService;
|
||||
|
||||
require_once __DIR__ . '/XmlModuleMetaInfo.php';
|
||||
require_once __DIR__ . '/XmlModule.php';
|
||||
require_once __DIR__ . '/iTopModulesDependencyValidationService.php';
|
||||
|
||||
use ModuleInstallerAPI;
|
||||
/**
|
||||
* @package Combodo\iTop\Test\UnitTest\Setup
|
||||
*/
|
||||
class iTopModulesDependencyTest extends ItopTestCase {
|
||||
class iTopModulesDependencyValidationServiceTest extends ItopTestCase {
|
||||
private iTopModulesDependencyValidationService $oiTopModulesDependencyValidationService;
|
||||
|
||||
private array $aFilesToRemove = [];
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp(); // TODO: Change the autogenerated stub
|
||||
parent::setUp();
|
||||
$this->RequireOnceItopFile('setup/module/iTopModulesDependencyValidationService.php');
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
@@ -48,67 +41,6 @@ class iTopModulesDependencyTest extends ItopTestCase {
|
||||
iTopModulesDependencyValidationService::SetInstance(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Module dependency validation: make sure dependencies are correct toward classes/interfaces coming from PHP/Xml datamodel files
|
||||
*/
|
||||
public function testReadModuleFileData()
|
||||
{
|
||||
iTopModulesDependencyValidationService::GetInstance()->FetchAllDependenciesViaModulesFiles();
|
||||
$this->testModulesBasedOnDMFilesOnly();
|
||||
}
|
||||
|
||||
/**
|
||||
* Module dependency validation: make sure dependencies are correct toward classes/interfaces coming from Xml datamodel files
|
||||
*/
|
||||
public function testModulesBasedOnDMFilesOnly()
|
||||
{
|
||||
iTopModulesDependencyValidationService::GetInstance()->FetchAllDependenciesViaDM();
|
||||
|
||||
$aErrors=[];
|
||||
/** @var XmlModule $oXmlModule */
|
||||
foreach (iTopModulesDependencyValidationService::GetInstance()->aModules as $sModuleName => $oXmlModule) {
|
||||
$aCurrentDeps = iTopModulesDependencyValidationService::GetInstance()::$aModulesDataByModuleName[$sModuleName][2]['dependencies'] ?? [];
|
||||
$aModuleErrors=[];
|
||||
foreach ($oXmlModule->aDependencyModulesNames as $sDepModuleName => $oXmlModule2){
|
||||
$sXmlUIDs = implode('|', $oXmlModule->aXMlMetaInfosByModuleNames[$sDepModuleName]);
|
||||
$bResolved=false;
|
||||
foreach ($aCurrentDeps as $sDepString){
|
||||
$oModuleDependency = new \iTopCoreModuleDependency($sDepString);
|
||||
|
||||
if (in_array($sDepModuleName, $oModuleDependency->GetPotentialPrerequisiteModuleNames())) {
|
||||
$bResolved=true;
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($oModuleDependency->GetPotentialPrerequisiteModuleNames() as $sPotentialDepModuleName){
|
||||
/** @var XmlModule $oXmlModule2 */
|
||||
$oXmlModule2 = iTopModulesDependencyValidationService::GetInstance()->aModules[$sPotentialDepModuleName]??null;
|
||||
|
||||
if (! is_null($oXmlModule2) && $oXmlModule2->Depends($sDepModuleName)){
|
||||
$bResolved=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($bResolved) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $bResolved){
|
||||
$aModuleErrors []= "$sModuleName depends on $sDepModuleName but missing in module dependencies: " . implode(' & ', $aCurrentDeps) . ". ($sXmlUIDs)";
|
||||
}
|
||||
}
|
||||
|
||||
if (count($aModuleErrors)){
|
||||
$aErrors[$sModuleName]=$aModuleErrors;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertEquals(0, count($aErrors), var_export($aErrors, true));
|
||||
|
||||
}
|
||||
|
||||
public function testListDeclaredFullnameClassesFromPhpFile()
|
||||
{
|
||||
$aExpected = [
|
||||
@@ -146,31 +78,6 @@ class iTopModulesDependencyTest extends ItopTestCase {
|
||||
$this->assertEquals($aExpected, iTopModulesDependencyValidationService::GetInstance()->ListDeclaredFullnameClassesFromPhpFile(APPROOT . 'datamodels/2.x/itop-oauth-client/vendor/autoload.php'));
|
||||
}
|
||||
|
||||
public function testReadModuleMetaInfo()
|
||||
{
|
||||
$this->markTestSkipped();
|
||||
$aExpected = [
|
||||
'/var/www/html/iTop/datamodels/2.x/itop-portal-base/module.itop-portal-base.php',
|
||||
'itop-portal-base/3.2.1',
|
||||
[
|
||||
'label' => 'Portal Development Library',
|
||||
'category' => 'Portal',
|
||||
'dependencies' => [ 'itop-attachments/3.2.1' ],
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
'datamodel' => [ 'portal/vendor/autoload.php' ],
|
||||
'webservice' => [],
|
||||
'dictionary' => [],
|
||||
'data.struct' => [],
|
||||
'data.sample' => [],
|
||||
'doc.manual_setup' => '',
|
||||
'doc.more_information' => '',
|
||||
'settings' => [],
|
||||
],
|
||||
];
|
||||
$this->assertEquals($aExpected, iTopModulesDependencyValidationService::GetInstance()->GetModuleMetainfo('itop-portal-base'));
|
||||
}
|
||||
|
||||
public function testGetFirstFoundDepsUID() {
|
||||
$sOutput=<<<TXT
|
||||
/var/www/html/Professional-3.2.1-16428/web/datamodels/2.x/authent-token/src/Hook/MyAccountSectionTabContentExtension.php:Combodo\iTop\MyAccount\Hook\iMyAccountTabContentExtension
|
||||
Reference in New Issue
Block a user