From 20ce42b24b836f0177a514284624c6950c188fd9 Mon Sep 17 00:00:00 2001 From: odain Date: Tue, 29 Sep 2020 08:57:57 +0200 Subject: [PATCH] =?UTF-8?q?Reintegrate=20validation=20tests=20to=20ease=20?= =?UTF-8?q?iTop=20release=20management=20from=20=20develop=20=20=20=20=20?= =?UTF-8?q?=20-=20N=C2=B03053=20-=20Check=20XML=20conversion=20methods=20?= =?UTF-8?q?=20=20=20=20=20-=20N=C2=B03059=20-=20Automatically=20set=20the?= =?UTF-8?q?=20documentation=20URLs=20=20=20=20=20=20-=20N=C2=B03052=20-=20?= =?UTF-8?q?Check=20community=20modules=20XML=20version=20against=20latest?= =?UTF-8?q?=20version=20=20=20=20=20=20-=20N=C2=B03054=20-=20Check=20commu?= =?UTF-8?q?nity=20modules=20version=20against=20major=20version=20=20=20?= =?UTF-8?q?=20=20=20-=20N=C2=B03062=20-=20setup.css=20file=20integrity=20t?= =?UTF-8?q?est=20=20=20=20=20=20-=20N=C2=B03060=20-=20Check=20consistency?= =?UTF-8?q?=20between=20the=20list=20of=20modules=20and=20installation.xml?= =?UTF-8?q?=20=20=20=20=20=20-=20N=C2=B03061=20-=20Automatically=20check?= =?UTF-8?q?=20the=20installation.xml=20consistency=20=20=20=20=20=20-=20N?= =?UTF-8?q?=C2=B03268=20Add=20test=20to=20check=20dictionary=20files:=20ma?= =?UTF-8?q?ke=20sure=20that=20the=20Dict::Add=20declarations=20match=20the?= =?UTF-8?q?=20file=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup/setuputils.class.inc.php | 2 +- .../DictionariesConsistencyTest.php | 108 ++++++++++++ .../iTopModulesPhpVersionChecklistTest.php | 2 +- .../iTopModulesXmlVersionChecklistTest.php | 43 +++-- ...ml.dist => postbuild_integration.xml.dist} | 4 +- .../SetupCssIntegrityChecklistTest.php | 0 .../iTopDesignFormatChecklistTest.php | 164 ++++++++++++++++++ ...iTopModuleXmlInstallationChecklistTest.php | 0 .../iTopDesignFormatChecklistTest.php | 101 ----------- 9 files changed, 302 insertions(+), 122 deletions(-) create mode 100644 test/integration/DictionariesConsistencyTest.php rename test/{releaseChecklist.xml.dist => postbuild_integration.xml.dist} (95%) rename test/{releaseChecklist => postbuild_integration}/SetupCssIntegrityChecklistTest.php (100%) create mode 100644 test/postbuild_integration/iTopDesignFormatChecklistTest.php rename test/{releaseChecklist => postbuild_integration}/iTopModuleXmlInstallationChecklistTest.php (100%) delete mode 100644 test/releaseChecklist/iTopDesignFormatChecklistTest.php diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index 2b260890c..217c4f77d 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -916,7 +916,7 @@ class SetupUtils $oPage, $bIsItopInstall, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $bTlsEnabled, $sTlsCA, $sNewDBName = '' ) { - $sWikiVersion = '2_7_0'; + $sWikiVersion = utils::GetItopVersionWikiSyntax(); //eg : '2_7_0'; $sMysqlTlsWikiPageUrl = 'https://wiki.openitop.org/doku.php?id='.$sWikiVersion.':install:php_and_mysql_tls'; $oPage->add(''); diff --git a/test/integration/DictionariesConsistencyTest.php b/test/integration/DictionariesConsistencyTest.php new file mode 100644 index 000000000..e11a4c7ea --- /dev/null +++ b/test/integration/DictionariesConsistencyTest.php @@ -0,0 +1,108 @@ + array('CS CZ', 'Czech', 'Čeština'), + 'da' => array('DA DA', 'Danish', 'Dansk'), + 'de' => array('DE DE', 'German', 'Deutsch'), + 'en' => array('EN US', 'English', 'English'), + 'es_cr' => array('ES CR', 'Spanish', 'Español, Castellaño'), + 'fr' => array('FR FR', 'French', 'Français'), + 'hu' => array('HU HU', 'Hungarian', 'Magyar'), + 'it' => array('IT IT', 'Italian', 'Italiano'), + 'ja' => array('JA JP', 'Japanese', '日本語'), + 'nl' => array('NL NL', 'Dutch', 'Nederlands'), + 'pt_br' => array('PT BR', 'Brazilian', 'Brazilian'), + 'ru' => array('RU RU', 'Russian', 'Русский'), + 'sk' => array('SK SK', 'Slovak', 'Slovenčina'), + 'tr' => array('TR TR', 'Turkish', 'Türkçe'), + 'zh_cn' => array('ZH CN', 'Chinese', '简体中文') + ); + + if (!preg_match('/^(.*)\\.dict/', basename($sDictFile), $aMatches)) + { + static::fail("Dictionary file '$sDictFile' not matching the naming convention"); + } + + $sLangPrefix = $aMatches[1]; + if (!array_key_exists($sLangPrefix, $aPrefixToLanguageData)) + { + static::fail("Unknown prefix '$sLangPrefix' for dictionary file '$sDictFile'"); + } + + $sExpectedLanguageCode = $aPrefixToLanguageData[$sLangPrefix][0]; + $sExpectedEnglishLanguageDesc = $aPrefixToLanguageData[$sLangPrefix][1]; + $sExpectedLocalizedLanguageDesc = $aPrefixToLanguageData[$sLangPrefix][2]; + + $sDictPHP = file_get_contents($sDictFile); + if ($iCount = preg_match_all("@Dict::Add\('(.*)'\s*,\s*'(.*)'\s*,\s*'(.*)'@", $sDictPHP, $aMatches) === false) + { + static::fail("Pattern not working"); + } + if ($iCount == 0) + { + // Empty dictionary, that's fine! + static::assertTrue(true); + } + foreach ($aMatches[1] as $sLanguageCode) + { + static::assertSame($sExpectedLanguageCode, $sLanguageCode, + "Unexpected language code for Dict::Add in dictionary $sDictFile"); + } + foreach ($aMatches[2] as $sEnglishLanguageDesc) + { + static::assertSame($sExpectedEnglishLanguageDesc, $sEnglishLanguageDesc, + "Unexpected language description (english) for Dict::Add in dictionary $sDictFile"); + } + foreach ($aMatches[3] as $sLocalizedLanguageDesc) + { + static::assertSame($sExpectedLocalizedLanguageDesc, $sLocalizedLanguageDesc, + "Unexpected language description for Dict::Add in dictionary $sDictFile"); + } + } + + public function DictionaryFileProvider() + { + static::setUp(); + + $aDictFiles = array_merge( + glob(APPROOT.'datamodels/2.x/*/*.dict*.php'), // legacy form in modules + glob(APPROOT.'datamodels/2.x/*/dictionaries/*.dict*.php'), // modern form in modules + glob(APPROOT.'dictionaries/*.dict*.php') // framework + ); + $aTestCases = array(); + foreach ($aDictFiles as $sDictFile) + { + $aTestCases[$sDictFile] = array('sDictFile' => $sDictFile); + } + return $aTestCases; + } +} diff --git a/test/integration/iTopModulesPhpVersionChecklistTest.php b/test/integration/iTopModulesPhpVersionChecklistTest.php index c71316265..c5bfd00f8 100644 --- a/test/integration/iTopModulesPhpVersionChecklistTest.php +++ b/test/integration/iTopModulesPhpVersionChecklistTest.php @@ -57,7 +57,7 @@ class iTopModulesPhpVersionIntegrationTest extends ItopTestCase $matches ); - $this->assertRegExp("#$sExpectedVersion#", $matches[1], "$sPhpFile file refer does not refer to current itop version ($sModuleName/$matches[1] does not match regexp $sModuleName/$sExpectedVersion)"); + $this->assertRegExp("#$sExpectedVersion#", $matches[1], " $sPhpFile:2 file refer does not refer to current itop version ($sModuleName/$matches[1] does not match regexp $sModuleName/$sExpectedVersion)"); } diff --git a/test/integration/iTopModulesXmlVersionChecklistTest.php b/test/integration/iTopModulesXmlVersionChecklistTest.php index 9fde4b779..0ff89f3f0 100644 --- a/test/integration/iTopModulesXmlVersionChecklistTest.php +++ b/test/integration/iTopModulesXmlVersionChecklistTest.php @@ -32,48 +32,57 @@ use iTopDesignFormat; */ class iTopModulesXmlVersionIntegrationTest extends ItopTestCase { + protected function setUp() + { + parent::setUp(); + + require_once APPROOT.'setup/itopdesignformat.class.inc.php'; + } /** - * Verify if the datamodel.*.xml files refer to the current itop version + * Verify if the datamodel.*.xml files refer to the latest version of the design * This is an integration test * * @group skipPostBuild * * @dataProvider DatamodelItopXmlVersionProvider */ - public function testDatamodelItopXmlVersion($sExpectedXmlVersion, $sXmlFile) + public function testDatamodelItopXmlVersion($sXmlFile) { - $sFileContent = file_get_contents($sXmlFile); + $oOriginalXml = new DOMDocument(); + $oOriginalXml->load($sXmlFile); - preg_match( - '//', - $sFileContent, - $matches - ); + $oTransformedXml = new DOMDocument(); + $oTransformedXml->load($sXmlFile); + $oFormat = new iTopDesignFormat($oTransformedXml); - $this->assertSame($sExpectedXmlVersion, $matches[1], "$sXmlFile file refer does not refer to current itop version ($matches[1] instead of expected $sExpectedXmlVersion)"); + if ($oFormat->Convert()) + { + // Compare the original and new format + $sExpectedXmlVersion = ITOP_DESIGN_LATEST_VERSION; + $this->assertSame($oTransformedXml->saveXML(), $oOriginalXml->saveXML(), "Datamodel file $sXmlFile:2 not in the latest format ($sExpectedXmlVersion)"); + } + else + { + $this->fail("Failed to convert $sXmlFile into the latest format"); + } } public function DatamodelItopXmlVersionProvider() { - parent::setUp(); - - require_once APPROOT.'core/config.class.inc.php'; - require_once APPROOT.'application/utils.inc.php'; + static::setUp(); $sPath = APPROOT.'datamodels/2.x/*/datamodel.*.xml'; $aXmlFiles = glob($sPath); - $sItopVersionShort = \utils::GetItopPatchVersion(); - $aItopVersion = explode('.', $sItopVersionShort); - $sExpectedXmlVersion = ($aItopVersion[0] - 1).'.'.($aItopVersion[1]); // eg: 2.7.0-dev become 1.7 + $aXmlFiles[] = APPROOT.'core/datamodel.core.xml'; + $aXmlFiles[] = APPROOT.'application/datamodel.application.xml'; $aTestCases = array(); foreach ($aXmlFiles as $sXmlFile) { $aTestCases[$sXmlFile] = array( - 'sExpectedXmlVersion' => $sExpectedXmlVersion, 'sXmlFile' => $sXmlFile, ); } diff --git a/test/releaseChecklist.xml.dist b/test/postbuild_integration.xml.dist similarity index 95% rename from test/releaseChecklist.xml.dist rename to test/postbuild_integration.xml.dist index 8dea80426..d83d3199f 100644 --- a/test/releaseChecklist.xml.dist +++ b/test/postbuild_integration.xml.dist @@ -41,8 +41,8 @@ verbose="false"> - - releaseChecklist + + postbuild_integration diff --git a/test/releaseChecklist/SetupCssIntegrityChecklistTest.php b/test/postbuild_integration/SetupCssIntegrityChecklistTest.php similarity index 100% rename from test/releaseChecklist/SetupCssIntegrityChecklistTest.php rename to test/postbuild_integration/SetupCssIntegrityChecklistTest.php diff --git a/test/postbuild_integration/iTopDesignFormatChecklistTest.php b/test/postbuild_integration/iTopDesignFormatChecklistTest.php new file mode 100644 index 000000000..0518c84d5 --- /dev/null +++ b/test/postbuild_integration/iTopDesignFormatChecklistTest.php @@ -0,0 +1,164 @@ +GetDataModelFiles(APPROOT.'/datamodels'); + + //retrieve current XML version in datamoldels files + foreach ($aDataModelFiles as $sDataModelFile) + { + if (preg_match('/itop_design .* version="([\d\.]*)"/', file_get_contents($sDataModelFile), $aMatches)) + { + $sVersion = $aMatches[1]; + if (!array_key_exists($sVersion, $aDatamodelCurrentVersions)) + { + if (trim($sVersion) === '') + { + $aErrors[] = "cannot retrieve itop_design datamodel version in $sDataModelFile:1"; + continue; + } + + $aDatamodelCurrentVersions[$sVersion] = $sVersion; + } + } + } + + //make sure there is only one found + $this->assertTrue(is_array($aDatamodelCurrentVersions)); + + $sFirstVersion = array_keys(iTopDesignFormat::$aVersions)[0]; + $sLatestVersion = array_keys(iTopDesignFormat::$aVersions)[count(iTopDesignFormat::$aVersions)-1]; + foreach ($aDatamodelCurrentVersions as $sCurrentVersion) + { + try{ + //check we have migration function from current version to previous + $this->CheckCondition(array_key_exists($sCurrentVersion, iTopDesignFormat::$aVersions), "Missing $sCurrentVersion conversion functions in iTopDesignFormat."); + $aCurrentVersionInfo = iTopDesignFormat::$aVersions[$sCurrentVersion]; + $this->CheckCondition(is_array($aCurrentVersionInfo), "Wrong $sCurrentVersion config in iTopDesignFormat."); + $this->CheckCondition(array_key_exists('previous', $aCurrentVersionInfo), "Missing previous for $sCurrentVersion config in iTopDesignFormat."); + $this->TestDefinedFunction($aCurrentVersionInfo, 'go_to_next', $sCurrentVersion, ($sCurrentVersion=== $sLatestVersion)); + $this->TestDefinedFunction($aCurrentVersionInfo, 'go_to_previous', $sCurrentVersion, ($sCurrentVersion==='1.0')); + + //check we have migration function from N-1 version to current one + if (($sCurrentVersion!=='1.0')) { + $sPreviousVersion = $aCurrentVersionInfo['previous']; + $this->CheckCondition(array_key_exists($sPreviousVersion, iTopDesignFormat::$aVersions), + "$sCurrentVersion: Missing $sPreviousVersion config in iTopDesignFormat."); + $aPreviousVersionInfo = iTopDesignFormat::$aVersions[$sPreviousVersion]; + $this->CheckCondition(is_array($aPreviousVersionInfo), + "$sCurrentVersion: wrong $sPreviousVersion config in iTopDesignFormat."); + $this->CheckCondition(array_key_exists('previous', $aPreviousVersionInfo), + "$sCurrentVersion: Missing previous for $sPreviousVersion config in iTopDesignFormat."); + $this->TestDefinedFunction($aPreviousVersionInfo, 'go_to_previous', $sPreviousVersion, ($sPreviousVersion === '1.0')); + $this->TestDefinedFunction($aPreviousVersionInfo, 'go_to_next', $sPreviousVersion, ($sPreviousVersion === $sLatestVersion)); + } + + //check we have migration function from current version to next one + if (($sCurrentVersion!== $sLatestVersion)) { + $sNextVersion = $aCurrentVersionInfo['next']; + $this->CheckCondition(array_key_exists($sNextVersion, iTopDesignFormat::$aVersions), + "$sCurrentVersion: Missing $sNextVersion config in iTopDesignFormat."); + $aNextVersionInfo = iTopDesignFormat::$aVersions[$sNextVersion]; + $this->CheckCondition(is_array($aNextVersionInfo), + "$sCurrentVersion: wrong $sNextVersion config in iTopDesignFormat."); + $this->CheckCondition(array_key_exists('previous', $aNextVersionInfo), + "$sCurrentVersion: Missing previous for $sNextVersion config in iTopDesignFormat."); + $this->TestDefinedFunction($aNextVersionInfo, 'go_to_previous', $sNextVersion, ($sNextVersion === '1.0')); + $this->TestDefinedFunction($aNextVersionInfo, 'go_to_next', $sNextVersion, ($sNextVersion === $sLatestVersion)); + } + } + catch(Exception $e) + { + $aErrors[] = $e->getMessage(); + } + } + + if (count($aErrors)!=0) + { + $sMsg = "Issue with conversion functions:\n"; + $sMsg .= implode("\n", $aErrors); + $this->fail($sMsg); + } + else + { + $this->assertTrue(true); + } + } + + private function CheckCondition($bCondition, $sMsg) + { + if ($bCondition === false) + { + throw new \Exception($sMsg); + } + } + + private function TestDefinedFunction($aCurrentVersionInfo, $sFunctionKey, $sVersion, $bNullFunction=false) + { + $sInfo = json_encode($aCurrentVersionInfo, true); + $this->CheckCondition(array_key_exists($sFunctionKey, $aCurrentVersionInfo), "Missing $sFunctionKey in $sVersion config in iTopDesignFormat: " . $sInfo); + //echo $aCurrentVersionInfo[$sFunctionKey].'\n'; + if ($bNullFunction === false) + { + $oReflectionClass = new \ReflectionClass(iTopDesignFormat::class); + $this->CheckCondition($oReflectionClass->hasMethod($aCurrentVersionInfo[$sFunctionKey]), "wrong go_to_previous function '".$aCurrentVersionInfo[$sFunctionKey]."'' for $sVersion config in iTopDesignFormat." . $sInfo); + } + else + { + $this->CheckCondition(is_null($aCurrentVersionInfo[$sFunctionKey]), "$sVersion $sFunctionKey function should be null"); + } + } + + public function GetDataModelFiles($sFolder) + { + $aDataModelFiles = array(); + if (is_dir($sFolder)) + { + foreach (glob($sFolder."/*") as $sPath) + { + if (is_dir($sPath)) + { + $aDataModelFiles = array_merge($aDataModelFiles, $this->GetDataModelFiles($sPath)); + } + else if (preg_match("/datamodel\..*\.xml/", basename($sPath))) + { + $aDataModelFiles[] = $sPath; + } + } + } + return $aDataModelFiles; + } +} \ No newline at end of file diff --git a/test/releaseChecklist/iTopModuleXmlInstallationChecklistTest.php b/test/postbuild_integration/iTopModuleXmlInstallationChecklistTest.php similarity index 100% rename from test/releaseChecklist/iTopModuleXmlInstallationChecklistTest.php rename to test/postbuild_integration/iTopModuleXmlInstallationChecklistTest.php diff --git a/test/releaseChecklist/iTopDesignFormatChecklistTest.php b/test/releaseChecklist/iTopDesignFormatChecklistTest.php deleted file mode 100644 index 0cd5a8b6c..000000000 --- a/test/releaseChecklist/iTopDesignFormatChecklistTest.php +++ /dev/null @@ -1,101 +0,0 @@ -GetDataModelFiles(APPROOT.'/datamodels'); - - //retrieve current XML version in datamoldels files - foreach ($aDataModelFiles as $sDataModelFile) - { - if (preg_match('/itop_design .* version="([\d\.]*)"/', file_get_contents($sDataModelFile), $aMatches)) - { - $sVersion = $aMatches[1]; - if (!array_key_exists($sVersion, $aDatamodelCurrentVersions)) - { - $aDatamodelCurrentVersions[$sVersion] = $sVersion; - } - } - } - - //make sure there is only one found - $this->assertTrue(is_array($aDatamodelCurrentVersions)); - $this->assertEquals(1, count($aDatamodelCurrentVersions), "Found too much XML versions: " . json_encode($aDatamodelCurrentVersions)); - - //check we have migration function from new version to previous one - $sCurrentVersion = array_values($aDatamodelCurrentVersions)[0]; - $this->assertTrue(array_key_exists($sCurrentVersion, iTopDesignFormat::$aVersions), "Release checklist: missing $sCurrentVersion config in iTopDesignFormat "); - $aCurrentVersionInfo = iTopDesignFormat::$aVersions[$sCurrentVersion]; - $this->assertTrue(is_array($aCurrentVersionInfo), "Release checklist: wrong $sCurrentVersion config in iTopDesignFormat "); - $this->assertTrue(array_key_exists('previous', $aCurrentVersionInfo), "Release checklist: missing previous for $sCurrentVersion config in iTopDesignFormat "); - $this->TestDefinedFunction($aCurrentVersionInfo, 'go_to_previous', $sCurrentVersion); - - //check we have migration function from N-1 version to new one - $sPreviousVersion = $aCurrentVersionInfo['previous']; - $this->assertTrue(array_key_exists($sPreviousVersion, iTopDesignFormat::$aVersions), "Release checklist: missing $sPreviousVersion config in iTopDesignFormat "); - $aPreviousVersionInfo = iTopDesignFormat::$aVersions[$sPreviousVersion]; - $this->assertTrue(is_array($aPreviousVersionInfo), "Release checklist: wrong $sPreviousVersion config in iTopDesignFormat "); - $this->assertTrue(array_key_exists('previous', $aPreviousVersionInfo), "Release checklist: missing previous for $sPreviousVersion config in iTopDesignFormat "); - $this->TestDefinedFunction($aPreviousVersionInfo, 'go_to_previous', $sPreviousVersion); - $this->TestDefinedFunction($aPreviousVersionInfo, 'go_to_next', $sPreviousVersion); - } - - private function TestDefinedFunction($aCurrentVersionInfo, $sFunctionKey, $sVersion) - { - $sInfo = json_encode($aCurrentVersionInfo, true); - $this->assertTrue(array_key_exists($sFunctionKey, $aCurrentVersionInfo), "Release checklist: missing $sFunctionKey in $sVersion config in iTopDesignFormat: " . $sInfo); - echo $aCurrentVersionInfo[$sFunctionKey].'\n'; - $oReflectionClass = new \ReflectionClass(iTopDesignFormat::class); - $this->assertTrue($oReflectionClass->hasMethod($aCurrentVersionInfo[$sFunctionKey]), "Release checklist: wrong go_to_previous function '".$aCurrentVersionInfo[$sFunctionKey]."'' for $sVersion config in iTopDesignFormat " . $sInfo); - } - - public function GetDataModelFiles($sFolder) - { - $aDataModelFiles = array(); - if (is_dir($sFolder)) - { - foreach (glob($sFolder."/*") as $sPath) - { - if (is_dir($sPath)) - { - $aDataModelFiles = array_merge($aDataModelFiles, $this->GetDataModelFiles($sPath)); - } - else if (preg_match("/datamodel\..*\.xml/", basename($sPath))) - { - $aDataModelFiles[] = $sPath; - } - } - } - return $aDataModelFiles; - } -} \ No newline at end of file