Merge branch 'support/3.2' into develop

This commit is contained in:
odain
2025-11-07 20:33:14 +01:00
1837 changed files with 33034 additions and 34549 deletions

View File

@@ -56,7 +56,8 @@ $oPage = new iTopWebPage('Render all UI blocks');
$oPageContentLayout = PageContentFactory::MakeStandardEmpty();
$oPage->SetContentLayout($oPageContentLayout);
$oPage->add_style(<<<CSS
$oPage->add_style(
<<<CSS
hr {
background-color: var(--ibo-color-grey-950);
}
@@ -331,7 +332,6 @@ $oPage->AddUiBlock($oCollapsibleSectionSaveState);
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Fieldset/field examples', 2));
$oDashletFieldset1 = new FieldSet('Fieldset 1');
$oDashletField1 = FieldUIBlockFactory::MakeStandard('Field A');
$oDashletInput1 = InputUIBlockFactory::MakeStandard('text', 'input1', 'Input 1');
@@ -360,13 +360,13 @@ $oDashletFieldset2->AddSubBlock($oDashletField6);
// Code
/////////
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Code examples (MakeForCode)', 2 ));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Code examples (MakeForCode)', 2));
$oCode1 = UIContentBlockUIBlockFactory::MakeForCode('function mean(int $a, int $b) {
return ($a + $b)/2
}');
$oPage->AddUiBlock($oCode1);
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Code examples (MakeForPreformatted)', 2 ));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Code examples (MakeForPreformatted)', 2));
$oCode2 = UIContentBlockUIBlockFactory::MakeForPreformatted('function mean(int $a, int $b) {
return ($a + $b)/2
}');
@@ -376,7 +376,7 @@ $oPage->AddUiBlock($oCode2);
// Pill
/////////
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Pill examples', 2 ));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Pill examples', 2));
$oBlock = new UIContentBlockWithJSRefreshCallback(null, ["ibo-dashlet-header-dynamic--container"]);
$oPage->AddUiBlock($oBlock);
@@ -397,95 +397,97 @@ $oBlock->AddSubBlock($oPill6);
// Title
/////////
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title examples', 2 ));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 1', 1 ));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 2', 2 ));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 3', 3 ));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 4', 4 ));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 5', 5 ));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title examples', 2));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 1', 1));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 2', 2));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 3', 3));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 4', 4));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Title example 5', 5));
/////////
// DataTable
/////////
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Datatable examples', 2 ));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Datatable examples', 2));
$oPage->AddUiBlock(DataTableUIBlockFactory::MakeForStaticData('Static datatable',
array(
'a' => array('label' => 'a'),
'b' => array('label' => 'b'),
'c' => array('label' => 'c'),
'd' => array('label' => 'd')
),
array(
array(
'a' => 'A1', 'b' => 'B1', 'c' => 'C1', 'd' => 'D1'
), array(
'a' => 'A2', 'b' => 'B2', 'c' => 'C2', 'd' => 'D2'
), array(
'a' => 'A3', 'b' => 'B3', 'c' => 'C3', 'd' => 'D3'
), array(
$oPage->AddUiBlock(DataTableUIBlockFactory::MakeForStaticData(
'Static datatable',
[
'a' => ['label' => 'a'],
'b' => ['label' => 'b'],
'c' => ['label' => 'c'],
'd' => ['label' => 'd'],
],
[
[
'a' => 'A1', 'b' => 'B1', 'c' => 'C1', 'd' => 'D1',
], [
'a' => 'A2', 'b' => 'B2', 'c' => 'C2', 'd' => 'D2',
], [
'a' => 'A3', 'b' => 'B3', 'c' => 'C3', 'd' => 'D3',
], [
'a' => 'A4',
'b' => 'B4',
'c' => 'C4',
'd' => 'D4',
),
array(
],
[
'@class' => 'ibo-is-red',
'a' => 'A5 (Red highlighting)',
'b' => 'B5',
'c' => 'C5',
'd' => 'D5',
),
array(
],
[
'@class' => 'ibo-is-danger',
'a' => 'A6 (Danger highlighting)',
'b' => 'B6',
'c' => 'C6',
'd' => 'D6',
),
array(
],
[
'@class' => 'ibo-is-orange',
'a' => 'A7 (Orange highlighting)',
'b' => 'B7',
'c' => 'C7',
'd' => 'D7',
),
array(
],
[
'@class' => 'ibo-is-warning',
'a' => 'A8 (Warning highlighting)',
'b' => 'B8',
'c' => 'C8',
'd' => 'D8',
),
array(
],
[
'@class' => 'ibo-is-blue',
'a' => 'A9 (Blue highlighting)',
'b' => 'B9',
'c' => 'C9',
'd' => 'D9',
),
array(
],
[
'@class' => 'ibo-is-info',
'a' => 'A10 (Info highlighting)',
'b' => 'B10',
'c' => 'C10',
'd' => 'D10',
),
array(
],
[
'@class' => 'ibo-is-green',
'a' => 'A11 (Green highlighting)',
'b' => 'B11',
'c' => 'C11',
'd' => 'D11',
),
array(
],
[
'@class' => 'ibo-is-success',
'a' => 'A12 (Success highlighting)',
'b' => 'B12',
'c' => 'C12',
'd' => 'D12',
),
)));
],
]
));
/////////
// Set

View File

@@ -7,7 +7,8 @@ require_once '../../approot.inc.php';
require_once(APPROOT.'/application\utils.inc.php');
$index = 0;
function testSanitize ($sValue, $sType, &$index ){
function testSanitize($sValue, $sType, &$index)
{
$sDefaultVal = '!defaultVal!';
$sValueEscapedJs = str_replace('"', '\"', $sValue);
$sSanitizedValue = utils::Sanitize($sValue, $sDefaultVal, $sType);
@@ -43,7 +44,7 @@ HTML;
$index++;
}
$aValues = array(
$aValues = [
"test",
"t;e-s_t$",
"123test",
@@ -55,9 +56,9 @@ $aValues = array(
"éèç",
"q<div>&egrave;</div>=hcb test",
// "<script>console.debug('((\'&egrave;é&');</script>q<div>&egrave;</div>=hcb test",
);
];
$aTypes = array(
$aTypes = [
utils::ENUM_SANITIZATION_FILTER_CONTEXT_PARAM,
utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER,
utils::ENUM_SANITIZATION_FILTER_FIELD_NAME,
@@ -66,7 +67,7 @@ $aTypes = array(
utils::ENUM_SANITIZATION_FILTER_STRING,
utils::ENUM_SANITIZATION_FILTER_TRANSACTION_ID,
utils::ENUM_SANITIZATION_FILTER_VARIABLE_NAME,
);
];
?>
<!DOCTYPE>

View File

@@ -0,0 +1,25 @@
<?php
$APPROOT = dirname(__DIR__, 2);
echo $APPROOT;
$finder = PhpCsFixer\Finder::create()
->in($APPROOT)
->exclude(['oql', 'data', 'extensions'])
->notPath(['/env-*/', '/cache-*/', 'lib', 'vendor', 'node_modules', 'config-itop', 'php-static-analysis'])
;
$config = new PhpCsFixer\Config();
return $config->setRiskyAllowed(true)
->setRules([
'@PSR12' => true,
'indentation_type' => true,
'no_extra_blank_lines' => true,
'array_syntax' => ['syntax' => 'short'],
'concat_space' => true,
'trailing_comma_in_multiline' => true,
])
->setIndent("\t")
->setLineEnding("\n")
->setFinder($finder)
;

View File

@@ -0,0 +1,17 @@
Code formatting tool used by iTop is PHP-CS-Fixer:
https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/master
to check code style issues (no path provided means whole iTop code base):
```
cd tests/php-code-style/; composer install; cd -
tests/php-code-style/vendor/bin/php-cs-fixer check --config tests/php-code-style/.php-cs-fixer.dist.php [PATH]
```
to respect iTop code standards and re-format (no path provided means whole iTop code base):
```
tests/php-code-style/vendor/bin/php-cs-fixer fix --config tests/php-code-style/.php-cs-fixer.dist.php [PATH]
```

View File

@@ -0,0 +1,7 @@
{
"require-dev": {
"php": "^7.0 || ^8.0",
"friendsofphp/php-cs-fixer": "^3.89",
"phpstan/phpstan": "^2.1"
}
}

2792
tests/php-code-style/composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -13,14 +13,15 @@ namespace Combodo\iTop\Test\UnitTest;
*/
class runClassInSeparateProcessTest extends ItopDataTestCase
{
static public function setUpBeforeClass(): void
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass(); // TODO: Change the autogenerated stub
file_put_contents(
dirname(__FILE__).'/pid.txt',
getmypid().';'.static::class.';'.__METHOD__."\n",
FILE_APPEND);
FILE_APPEND
);
}
protected function LogPid()
@@ -28,16 +29,17 @@ class runClassInSeparateProcessTest extends ItopDataTestCase
file_put_contents(
dirname(__FILE__).'/pid.txt',
getmypid().';'.static::class.';'.$this->getName()."\n",
FILE_APPEND);
FILE_APPEND
);
}
function testA()
public function testA()
{
$this->LogPid();
static::assertTrue(true);
}
function testB()
public function testB()
{
$this->LogPid();
static::assertTrue(true);
@@ -46,13 +48,13 @@ class runClassInSeparateProcessTest extends ItopDataTestCase
/**
* @dataProvider CProvider
*/
function testC($i)
public function testC($i)
{
$this->LogPid();
static::assertTrue(true);
}
function CProvider()
public function CProvider()
{
return [
[1],

View File

@@ -1,6 +1,7 @@
<?php
namespace Combodo\iTop\Test\UnitTest;
use PHPUnit\Framework\TestCase;
/**
@@ -8,7 +9,7 @@ use PHPUnit\Framework\TestCase;
*/
class tearDownAfterFailureTest extends TestCase
{
static $bIsCorrectlyInitialized = true;
public static $bIsCorrectlyInitialized = true;
protected function tearDown(): void
{
@@ -16,7 +17,7 @@ class tearDownAfterFailureTest extends TestCase
static::$bIsCorrectlyInitialized = true;
}
function testIsInitializedAndChangeIt()
public function testIsInitializedAndChangeIt()
{
static::assertTrue(static::$bIsCorrectlyInitialized);
@@ -26,18 +27,18 @@ class tearDownAfterFailureTest extends TestCase
throw new \Exception('hello');
}
function testIsStillInitialized()
public function testIsStillInitialized()
{
static::assertTrue(static::$bIsCorrectlyInitialized);
}
function testFailingDueToUnexpectedException()
public function testFailingDueToUnexpectedException()
{
static::$bIsCorrectlyInitialized = false;
This_Is_Not_A_Function_And_Causes_A_Fatal_Error();
}
function testIsStillInitializedAnyway()
public function testIsStillInitializedAnyway()
{
static::assertTrue(static::$bIsCorrectlyInitialized);
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
* This file is part of iTop.
@@ -17,6 +18,7 @@ namespace Combodo\iTop\Test\UnitTest\Integration;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use Dict;
use const APPROOT;
/**
@@ -44,19 +46,19 @@ class CompiledDictionariesConsistencyTest extends ItopTestCase
'UI:CSVReport-Value-NoMatch-SomeObjectNotVisibleForCurrentUser' => ['arg1'],
];
$sCompiledLanguagesFilePath = APPROOT . 'env-' . \utils::GetCurrentEnvironment() . '/dictionaries/languages.php';
$sCompiledLanguagesFilePath = APPROOT.'env-'.\utils::GetCurrentEnvironment().'/dictionaries/languages.php';
$this->assertFileExists($sCompiledLanguagesFilePath, 'We must have an existing compiled language.php file in the current env !');
require_once($sCompiledLanguagesFilePath);
$this->assertNotEmpty(Dict::GetLanguages(), 'the languages.php file exists but didn\'t load any language');
foreach (glob(APPROOT . 'env-' . \utils::GetCurrentEnvironment() . '/dictionaries/*.dict.php') as $sDictFile) {
foreach (glob(APPROOT.'env-'.\utils::GetCurrentEnvironment().'/dictionaries/*.dict.php') as $sDictFile) {
if (preg_match('/.*\\/(.*).dict.php/', $sDictFile, $aMatches)) {
$sLangCode = $aMatches[1];
$sLanguageCode = strtoupper(str_replace('-', ' ', $sLangCode));
Dict::SetUserLanguage($sLanguageCode);
foreach ($aLabelsToTest as $sLabelKey => $aLabelArgs) {
echo "Testing $sDictFile, label $sLabelKey with " . \var_export($aLabelArgs, true) . "\n";
echo "Testing $sDictFile, label $sLabelKey with ".\var_export($aLabelArgs, true)."\n";
try {
$sLabelValue = Dict::Format($sLabelKey, ...$aLabelArgs);
//$this->debug($sLabelValue);
@@ -71,7 +73,7 @@ class CompiledDictionariesConsistencyTest extends ItopTestCase
]);
}
}
$this->assertEquals([], $aFailedLabels, "$sDictFile : test fail for lang $sLangCode and labels (" . implode(", ", $aFailedLabels) . ')');
$this->assertEquals([], $aFailedLabels, "$sDictFile : test fail for lang $sLangCode and labels (".implode(", ", $aFailedLabels).')');
}
}
}

View File

@@ -35,7 +35,7 @@ class detectStaticPollutionTest extends TestCase
*
* @return void
*/
function testDetectPolluters($sPattern, $sFix)
public function testDetectPolluters($sPattern, $sFix)
{
$sScannedDir = dirname(__FILE__).'/../unitary-tests';
@@ -44,7 +44,7 @@ class detectStaticPollutionTest extends TestCase
$Iterator = new RecursiveIteratorIterator($oDirectory);
foreach (new RegexIterator($Iterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH) as $aMatch) {
$sFile = $aMatch[0];
if(is_file($sFile)) {
if (is_file($sFile)) {
$sFileContents = file_get_contents($sFile);
if (preg_match_all($sPattern, $sFileContents, $keys, PREG_PATTERN_ORDER)) {
$aPolluters = array_merge($aPolluters, $this->FindMatches($sFile, $sFileContents, $sPattern));

View File

@@ -16,7 +16,7 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
"Class:DatacenterDevice/Attribute:redundancy/count",
"Class:DatacenterDevice/Attribute:redundancy/disabled",
"Class:DatacenterDevice/Attribute:redundancy/percent",
"Class:TriggerOnThresholdReached/Attribute:threshold_index+"
"Class:TriggerOnThresholdReached/Attribute:threshold_index+",
];
protected function setUp(): void
@@ -33,7 +33,8 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
$this->SetNonPublicStaticProperty(\Dict::class, 'm_aData', $aDictEntriesByLanguage);
}
public function FormatProvider(){
public function FormatProvider()
{
return [
'key does not exist in dictionnary' => [
'sTemplate' => null,
@@ -55,13 +56,14 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
* @since 2.7.10 N°5491 - Inconsistent dictionary entries regarding arguments to pass to Dict::Format
* @dataProvider FormatProvider
*/
public function testFormatWithOneArgumentAndCustomKey(?string $sTemplate, $sExpectedTranslation){
public function testFormatWithOneArgumentAndCustomKey(?string $sTemplate, $sExpectedTranslation)
{
//tricky way to mock GetLabelAndLangCode behavior via connected user language
$sLangCode = \Dict::GetUserLanguage();
$aDictByLang = $this->GetNonPublicStaticProperty(\Dict::class, 'm_aData');
$sDictKey = 'ITOP::DICT:FORMAT:BROKEN:KEY';
if (! is_null($sTemplate)){
if (! is_null($sTemplate)) {
$aDictByLang[$sLangCode][$sDictKey] = $sTemplate;
}
@@ -72,7 +74,8 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
//test works after setup (no annotation @beforesetup)
//even if it does not extend ItopDataTestCase
private function ReadDictKeys($sLangCode) : array {
private function ReadDictKeys($sLangCode): array
{
\Dict::InitLangIfNeeded($sLangCode);
$aDictEntries = $this->GetNonPublicStaticProperty(\Dict::class, 'm_aData');
@@ -90,28 +93,30 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
*
* @return array
*/
private function GetKeyArgCountMap($aDictEntry) {
private function GetKeyArgCountMap($aDictEntry)
{
$aKeyArgsCount = [];
foreach ($aDictEntry as $sKey => $sValue){
foreach ($aDictEntry as $sKey => $sValue) {
$aKeyArgsCount[$sKey] = $this->countArg($sValue);
}
ksort($aKeyArgsCount);
return $aKeyArgsCount;
}
private function countArg($sLabel) {
private function countArg($sLabel)
{
$iMaxIndex = 0;
if (preg_match_all("/%(\d+)/", $sLabel, $aMatches)){
if (preg_match_all("/%(\d+)/", $sLabel, $aMatches)) {
$aSubMatches = $aMatches[1];
if (is_array($aSubMatches)){
foreach ($aSubMatches as $aCurrentMatch){
if (is_array($aSubMatches)) {
foreach ($aSubMatches as $aCurrentMatch) {
$iIndex = $aCurrentMatch;
$iMaxIndex = ($iMaxIndex < $iIndex) ? $iIndex : $iMaxIndex;
}
}
} else if ((false !== strpos($sLabel, "%s"))
} elseif ((false !== strpos($sLabel, "%s"))
|| (false !== strpos($sLabel, "%d"))
){
) {
$iMaxIndex = 1;
}
@@ -122,7 +127,8 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
* Warning: hardcoded list of languages
* It is hard to have it dynamically via Dict::GetLanguages as for each lang Dict::Init should be called first
**/
public function LangCodeProvider(){
public function LangCodeProvider()
{
return [
'cs' => [ 'CS CZ' ],
'da' => [ 'DA DA' ],
@@ -154,7 +160,6 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
$aDictEntry = $this->ReadDictKeys($sLanguageCodeToTest);
$aKeyArgsCountMap = [];
$aKeyArgsCountMap[$sReferenceLangCode] = $this->GetKeyArgCountMap($aReferenceLangDictEntry);
//$aKeyArgsCountMap[$sCode] = $this->GetKeyArgCountMap($aDictEntry);
@@ -164,30 +169,30 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
$aMismatchedKeys = [];
foreach ($aKeyArgsCountMap[$sReferenceLangCode] as $sKey => $iExpectedNbOfArgs){
if (0 === $iExpectedNbOfArgs){
//no arg needed in EN.
foreach ($aKeyArgsCountMap[$sReferenceLangCode] as $sKey => $iExpectedNbOfArgs) {
if (0 === $iExpectedNbOfArgs) {
//no arg needed in EN.
//let s assume job has been done correctly in EN to simplify
continue;
}
if (in_array($sKey, self::$aLabelCodeNotToCheck)){
if (in_array($sKey, self::$aLabelCodeNotToCheck)) {
//false positive: do not test
continue;
}
if (array_key_exists($sKey, $aDictEntry)){
if (array_key_exists($sKey, $aDictEntry)) {
$aPlaceHolders = [];
for ($i=0; $i<$iExpectedNbOfArgs; $i++){
$aPlaceHolders[]=$i;
for ($i = 0; $i < $iExpectedNbOfArgs; $i++) {
$aPlaceHolders[] = $i;
}
$sLabelTemplate = $aDictEntry[$sKey];
try{
try {
vsprintf($sLabelTemplate, $aPlaceHolders);
} catch(\Throwable $e){
} catch (\Throwable $e) {
$sError = $e->getMessage();
if (array_key_exists($sError, $aMismatchedKeys)){
if (array_key_exists($sError, $aMismatchedKeys)) {
$aMismatchedKeys[$sError][$sKey] = $iExpectedNbOfArgs;
} else {
$aMismatchedKeys[$sError] = [$sKey => $iExpectedNbOfArgs];
@@ -197,7 +202,7 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
}
$iCount = 0;
foreach ($aMismatchedKeys as $sError => $aKeys){
foreach ($aMismatchedKeys as $sError => $aKeys) {
var_dump($sError);
foreach ($aKeys as $sKey => $iExpectedNbOfArgs) {
$iCount++;
@@ -222,7 +227,8 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
$this->assertEquals([], $aMismatchedKeys, $sErrorMsg);
}
public function testEveryEnglishEntryShouldHaveItsFrenchCounterpart() {
public function testEveryEnglishEntryShouldHaveItsFrenchCounterpart()
{
$sReferenceLangCode = 'EN US';
$aReferenceLangDictEntries = $this->ReadDictKeys($sReferenceLangCode);
@@ -233,13 +239,14 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
$this->assertCount(0, $aMissingEntries, "The following entries are missing in french dictionaries : \n - ".implode("\n - ", $aMissingEntries));
}
public function testEveryFrenchEntryShouldBeTranslated() {
public function testEveryFrenchEntryShouldBeTranslated()
{
$sFrenchLangCode = 'FR FR';
$aFrenchDictEntries = $this->ReadDictKeys($sFrenchLangCode);
$aUntranslatedEntries = [];
foreach ($aFrenchDictEntries as $sKey => $sValue){
if(mb_substr($sValue,-2) === '~~'){
foreach ($aFrenchDictEntries as $sKey => $sValue) {
if (mb_substr($sValue, -2) === '~~') {
$aUntranslatedEntries[] = $sKey.' => '.var_export($sValue, true);
}
}
@@ -247,7 +254,8 @@ class DictionariesConsistencyAfterSetupTest extends ItopTestCase
$this->assertCount(0, $aUntranslatedEntries, "The following french entries require translation : \n - ".implode("\n - ", $aUntranslatedEntries));
}
public function VsprintfProvider(){
public function VsprintfProvider()
{
return [
'not enough args' => [
"sLabelTemplate" => "$1%s",

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
* This file is part of iTop.
@@ -21,10 +22,10 @@ use Exception;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use RegexIterator;
use const ARRAY_FILTER_USE_BOTH;
use const DIRECTORY_SEPARATOR;
/**
* Wrapper to load dictionary files without altering the main dictionary
* Eval will be called within the current namespace (this is done by adding a "namespace" statement)
@@ -49,7 +50,8 @@ class Dict
public static $sLastAddedLanguageCode = null;
public static function EnableLoadEntries(bool $bSaveKeyDuplicates = false) :void {
public static function EnableLoadEntries(bool $bSaveKeyDuplicates = false): void
{
self::$sLastAddedLanguageCode = null;
self::$m_aData = [];
self::$aKeysDuplicate = [];
@@ -84,8 +86,6 @@ class Dict
}
}
/**
* For tests on compiled dict files, see {@see CompiledDictionariesConsistencyTest}
* @group beforeSetup
@@ -126,20 +126,28 @@ class DictionariesConsistencyTest extends ItopTestCase
static::assertTrue(true);
}
foreach ($aMatches[1] as $sLanguageCode) {
static::assertSame($sExpectedLanguageCode, $sLanguageCode,
"Unexpected language code for Dict::Add in dictionary $sDictFile");
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");
static::assertSame(
$sExpectedEnglishLanguageDesc,
$sEnglishLanguageDesc,
"Unexpected language description (english) for Dict::Add in dictionary $sDictFile"
);
}
foreach ($aMatches[3] as $sLocalizedLanguageDesc)
{
foreach ($aMatches[3] as $sLocalizedLanguageDesc) {
if (false === is_array($aExpectedLocalizedLanguageDesc)) {
$aExpectedLocalizedLanguageDesc = array($aExpectedLocalizedLanguageDesc);
$aExpectedLocalizedLanguageDesc = [$aExpectedLocalizedLanguageDesc];
}
static::assertContains($sLocalizedLanguageDesc,$aExpectedLocalizedLanguageDesc,
"Unexpected language description for Dict::Add in dictionary $sDictFile");
static::assertContains(
$sLocalizedLanguageDesc,
$aExpectedLocalizedLanguageDesc,
"Unexpected language description for Dict::Add in dictionary $sDictFile"
);
}
}
@@ -148,18 +156,16 @@ class DictionariesConsistencyTest extends ItopTestCase
$this->setUp();
$sAppRoot = static::GetAppRoot();
$aDictFilesCore = [];
$sCoreDictionariesPath = realpath($sAppRoot.'dictionaries');
$sDictFilePattern = '/^.+\.dict.*\.php$/i';
$oDirIterator = new RecursiveDirectoryIterator($sCoreDictionariesPath, RecursiveDirectoryIterator::SKIP_DOTS);
$oIterator = new RecursiveIteratorIterator($oDirIterator, RecursiveIteratorIterator::SELF_FIRST);
$oRegexIterator = new RegexIterator($oIterator, $sDictFilePattern, RegexIterator::GET_MATCH);
foreach($oRegexIterator as $file) {
foreach ($oRegexIterator as $file) {
$aDictFilesCore[] = $file[0];
}
$aDictFilesModules = array_merge(
glob($sAppRoot.'datamodels/2.x/*/*.dict*.php'), // legacy form in modules
glob($sAppRoot.'datamodels/2.x/*/dictionaries/*.dict*.php'), // modern form in modules
@@ -170,15 +176,14 @@ class DictionariesConsistencyTest extends ItopTestCase
);
$this->RemoveModulesWithout7246Fixes($aDictFilesModules);
$aDictFiles = array_merge($aDictFilesCore, $aDictFilesModules);
$aTestCases = array();
$aTestCases = [];
foreach ($aDictFiles as $sDictFile) {
preg_match('/^(.*)\\.dict/', basename($sDictFile), $aMatches);
$sDictFileLangPrefix = $aMatches[1];
$aTestCases[$sDictFile] = array('sDictFile' => $sDictFile, 'sLanguagePrefix' => $sDictFileLangPrefix);
$aTestCases[$sDictFile] = ['sDictFile' => $sDictFile, 'sLanguagePrefix' => $sDictFileLangPrefix];
}
return $aTestCases;
@@ -189,11 +194,11 @@ class DictionariesConsistencyTest extends ItopTestCase
*
* @since 3.0.5 3.1.2 3.2.0 N°7246
*/
private function RemoveModulesWithout7246Fixes(array &$aDictFilesModules):void
private function RemoveModulesWithout7246Fixes(array &$aDictFilesModules): void
{
require_once static::GetAppRoot() . 'approot.inc.php'; // mandatory for tearDownAfterClass to work, of not present will thow `Undefined constant "LINKSET_TRACKING_LIST"`
require_once static::GetAppRoot().'approot.inc.php'; // mandatory for tearDownAfterClass to work, of not present will thow `Undefined constant "LINKSET_TRACKING_LIST"`
$this->RequireOnceItopFile('core/config.class.inc.php'); // source of the ITOP_VERSION constant
if (version_compare(ITOP_VERSION, '3.2.0', '>=')) {
if (version_compare(ITOP_VERSION, '3.2.0', '>=')) {
return;
}
@@ -246,7 +251,8 @@ class DictionariesConsistencyTest extends ItopTestCase
$this->CheckDictionarySyntax(__DIR__.'/dictionaries-test/fr.dictionary.itop.core.OK.php', true);
}
private function GetPhpCodeFromDictFile(string $sDictFile) : string {
private function GetPhpCodeFromDictFile(string $sDictFile): string
{
$sPHP = file_get_contents($sDictFile);
// Strip php tag to allow "eval"
$sPHP = substr(trim($sPHP), strlen('<?php'));
@@ -281,14 +287,12 @@ class DictionariesConsistencyTest extends ItopTestCase
if (!$bIsSyntaxValid) {
$this->fail("Failed to detect syntax error in dictionary `{$sDictFile}` (which is known as being INCORRECT)");
}
}
catch (Error $e) {
} catch (Error $e) {
if ($bIsSyntaxValid) {
$iLine = $e->getLine() - $iLineShift;
$this->fail("Invalid dictionary: {$e->getMessage()} in {$sDictFile}:{$iLine}");
}
}
catch (Exception $e) {
} catch (Exception $e) {
if ($bIsSyntaxValid) {
$iLine = $e->getLine() - $iLineShift;
$sExceptionClass = get_class($e);
@@ -303,7 +307,8 @@ class DictionariesConsistencyTest extends ItopTestCase
*
* @since 3.0.5 3.1.2 3.2.0 N°7143
*/
public function testNoDictFileInDatamodelsModuleRootDirectory():void {
public function testNoDictFileInDatamodelsModuleRootDirectory(): void
{
$sAppRoot = static::GetAppRoot();
$aDictFilesInDatamodelsModuleRootDir = glob($sAppRoot.'datamodels/2.x/*/*.dict*.php');
$this->assertNotFalse($aDictFilesInDatamodelsModuleRootDir, 'Searching for files returned an error');
@@ -311,7 +316,7 @@ class DictionariesConsistencyTest extends ItopTestCase
$aExcludedModulesList = $this->GetLtsCompatibleModulesList();
$aDictFilesInDatamodelsModuleRootDir = array_filter(
$aDictFilesInDatamodelsModuleRootDir,
function($sDictFileFullPath) use ($aExcludedModulesList) {
function ($sDictFileFullPath) use ($aExcludedModulesList) {
$sModuleFullPath = dirname($sDictFileFullPath);
$sModuleDirectory = basename($sModuleFullPath);
return !in_array($sModuleDirectory, $aExcludedModulesList);
@@ -319,7 +324,9 @@ class DictionariesConsistencyTest extends ItopTestCase
);
$sDictFilesInDatamodelsModuleRootDirList = var_export($aDictFilesInDatamodelsModuleRootDir, true);
$this->assertCount(0, $aDictFilesInDatamodelsModuleRootDir,
$this->assertCount(
0,
$aDictFilesInDatamodelsModuleRootDir,
<<<EOF
There are some files in datamodels module root dirs ! You must either:
- add the module in the GetLtsCompatibleModulesList method (if the module needs to keep compatibility with iTop 2.7)
@@ -336,7 +343,8 @@ EOF
* Indeed multiple targets will add modules that must remain compatible with iTop 2.7 LTS, though with dict files in their root dir
* The dictionaries directory in modules was added in 3.0.0 with N°2969
*/
private function GetLtsCompatibleModulesList(): array {
private function GetLtsCompatibleModulesList(): array
{
return [
'approval-base',
'authent-token',
@@ -385,7 +393,8 @@ EOF
/**
* @dataProvider DictionaryFileProvider
*/
public function testDictKeyDefinedOncePerFile(string $sDictFileToTestFullPath): void {
public function testDictKeyDefinedOncePerFile(string $sDictFileToTestFullPath): void
{
Dict::EnableLoadEntries(true);
$sDictFileToTestPhp = $this->GetPhpCodeFromDictFile($sDictFileToTestFullPath);
@@ -406,17 +415,18 @@ EOF
*
* @return void
*/
public function testDictKeyDefinedOnceForWholeProject(string $sLang): void {
public function testDictKeyDefinedOnceForWholeProject(string $sLang): void
{
$this->markTestSkipped("Skip because duplicates exists in modules, while once is installed at setup. Possible solution : centralize common string in another dictionnary, and then enable this test.");
Dict::EnableLoadEntries(true);
$aDictKeysDefinedMultipleTimes = [];
foreach ($this->DictionaryFileProvider() as $aDictFile) {
if($aDictFile['sLanguagePrefix'] !== $sLang) continue;
if ($aDictFile['sLanguagePrefix'] !== $sLang) {
continue;
}
Dict::ResetFileDuplicate();
$sDictFileToTestFullPath = $aDictFile['sDictFile'];
@@ -426,21 +436,20 @@ EOF
foreach (Dict::$aKeysDuplicate as $sDictKey => $iNumberOfDuplicates) {
if (array_key_exists($sDictKey, $aDictKeysDefinedMultipleTimes)) {
$aDictKeysDefinedMultipleTimes[$sDictKey]+= $iNumberOfDuplicates;
$aDictKeysDefinedMultipleTimes[$sDictKey] += $iNumberOfDuplicates;
} else {
$aDictKeysDefinedMultipleTimes[$sDictKey] = $iNumberOfDuplicates;
}
}
}
$aDictKeysDefinedMoreThanOnce = array_filter($aDictKeysDefinedMultipleTimes, static function($iNumberOfDuplicates) {
$aDictKeysDefinedMoreThanOnce = array_filter($aDictKeysDefinedMultipleTimes, static function ($iNumberOfDuplicates) {
return $iNumberOfDuplicates > 0;
});
$this->assertEmpty($aDictKeysDefinedMoreThanOnce, "Some keys (". sizeof($aDictKeysDefinedMoreThanOnce).") are defined multiple times in the whole projectin lang $sLang: ".var_export($aDictKeysDefinedMoreThanOnce, true));
$this->assertEmpty($aDictKeysDefinedMoreThanOnce, "Some keys (".sizeof($aDictKeysDefinedMoreThanOnce).") are defined multiple times in the whole projectin lang $sLang: ".var_export($aDictKeysDefinedMoreThanOnce, true));
}
/**
/**
* @dataProvider DictionaryFileProvider
*/
public function testNoRemainingTildesInTranslatedKeys(string $sDictFileToTestFullPath): void
@@ -449,7 +458,6 @@ EOF
$sReferenceLangCode = 'EN US';
$sReferenceDictName = 'en';
$sDictFileToTestPhp = $this->GetPhpCodeFromDictFile($sDictFileToTestFullPath);
eval($sDictFileToTestPhp);
@@ -482,7 +490,6 @@ EOF
$aLangToTestDictEntries = Dict::$m_aData[$sLanguageCodeToTest];
$aReferenceLangDictEntries = Dict::$m_aData[$sReferenceLangCode];
$this->assertGreaterThan(0, count($aLangToTestDictEntries), 'There should be at least one entry in the dictionary file to test');
$aLangToTestDictEntriesNotEmptyValues = array_filter(
$aLangToTestDictEntries,
@@ -493,7 +500,6 @@ EOF
);
$this->assertNotEmpty($aLangToTestDictEntriesNotEmptyValues);
$aTranslatedKeysWithTildes = [];
foreach ($aReferenceLangDictEntries as $sDictKey => $sReferenceLangLabel) {
if (false === array_key_exists($sDictKey, $aLangToTestDictEntries)) {
@@ -522,13 +528,13 @@ EOF
$sLanguageCodeToTest.'_file_location' => $this->MakeFilePathClickable($sDictFileToTestFullPath, $sDictKeyLineNumberInDictFileToTest),
$sLanguageCodeToTest => $sTranslatedLabel,
$sReferenceLangCode.'_file_location' => $this->MakeFilePathClickable($sDictFileReferenceFullPath, $sDictKeyLineNumberInDictFileReference),
$sReferenceLangCode => $sReferenceLangLabel
$sReferenceLangCode => $sReferenceLangLabel,
];
}
$sPathRoot = static::GetAppRoot();
$sDictFileToTestRelativePath = str_replace($sPathRoot, '', $sDictFileToTestFullPath);
$this->assertEmpty($aTranslatedKeysWithTildes, "In {$sDictFileToTestRelativePath} \n following keys are different from their '{$sReferenceDictName}' counterpart (translated ?) but have tildes at the end:\n" . var_export($aTranslatedKeysWithTildes, true));
$this->assertEmpty($aTranslatedKeysWithTildes, "In {$sDictFileToTestRelativePath} \n following keys are different from their '{$sReferenceDictName}' counterpart (translated ?) but have tildes at the end:\n".var_export($aTranslatedKeysWithTildes, true));
}
/**
@@ -538,18 +544,19 @@ EOF
* @return string a path that is clickable in PHPStorm 🤩
* For this to happen we need full path with correct dir sep + line number
* If it is not, check in File | Settings | Tools | Terminal the hyperlink option is checked
*/
private function MakeFilePathClickable(string $sFullPath, int $iLineNumber):string {
return str_replace(array('//', '/'), array('/', DIRECTORY_SEPARATOR), $sFullPath).':'.$iLineNumber;
*/
private function MakeFilePathClickable(string $sFullPath, int $iLineNumber): string
{
return str_replace(['//', '/'], ['/', DIRECTORY_SEPARATOR], $sFullPath).':'.$iLineNumber;
}
private function FindDictKeyLineNumberInContent(string $sFileContent, string $sDictKey): int
{
$aContentLines = explode("\n", $sFileContent);
$aContentLines = explode("\n", $sFileContent);
$sDictKeyToFind = "'{$sDictKey}'"; // adding string delimiters to match exact dict key (eg if not we would match 'Core:AttributeDateTime?SmartSearch' for 'Core:AttributeDateTime')
foreach($aContentLines as $iLineNumber => $line) {
if(strpos($line, $sDictKeyToFind) !== false){
foreach ($aContentLines as $iLineNumber => $line) {
if (strpos($line, $sDictKeyToFind) !== false) {
return $iLineNumber;
}
}
@@ -576,7 +583,7 @@ EOF
[
'Español, Castellaño', // old value
'Español, Castellano', // new value since N°3635
]
],
],
'fr' => ['FR FR', 'French', 'Français'],
'hu' => ['HU HU', 'Hungarian', 'Magyar'],

View File

@@ -4,8 +4,8 @@
* @used-by \Combodo\iTop\Test\UnitTest\Integration\DictionariesConsistencyTest::testPlaygroundDictionariesPhpSyntax
*/
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'MyDictKey1' => 'l\'échappement : bon exemple 1'.ITOP_APPLICATION,
'MyDictKey2' => 'l\'échappement : bon exemple 2',
'MyDictKey3' => 'l\'échappement : bon exemple 3',
));
]);

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
* This file is part of iTop.
@@ -19,18 +20,19 @@ use ApplicationException;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use utils;
/**
* @package Combodo\iTop\Test\UnitTest\Setup
* @group beforeSetup
*/
class iTopModulesPhpVersionIntegrationTest extends ItopTestCase {
class iTopModulesPhpVersionIntegrationTest extends ItopTestCase
{
/**
* @param string $sPhpFile iTop module file
*
* @return string module version
*/
private function GetItopModuleVersion(string $sPhpFile): ?string {
private function GetItopModuleVersion(string $sPhpFile): ?string
{
$sModulePath = realpath($sPhpFile);
$sModuleFileName = basename($sModulePath);
$sModuleName = preg_replace('/[^.]+\.([^.]+)\.php/', '$1', $sModuleFileName);
@@ -60,7 +62,8 @@ class iTopModulesPhpVersionIntegrationTest extends ItopTestCase {
* @since 2.7.7 3.0.1 3.1.0 N°4714 uses new {@link ITOP_CORE_VERSION} constant
* @since 3.0.3 3.1.0 move itop-community group in this method
*/
public function testITopModulesPhpVersion(): void {
public function testITopModulesPhpVersion(): void
{
if (is_dir(APPROOT.'datamodels/2.x')) {
$DatamodelsPath = APPROOT.'datamodels/2.x';
} elseif (is_dir(APPROOT.'datamodels/1.x')) {
@@ -79,8 +82,11 @@ class iTopModulesPhpVersionIntegrationTest extends ItopTestCase {
foreach ($aPhpFiles as $sPhpFile) {
$sActualVersion = $this->GetItopModuleVersion($sPhpFile);
$this->assertSame($sExpectedVersion, $sActualVersion,
'Module desc file does not contain the same version as the core: '.$sPhpFile);
$this->assertSame(
$sExpectedVersion,
$sActualVersion,
'Module desc file does not contain the same version as the core: '.$sPhpFile
);
}
self::assertEquals([], $aModuleWithError, 'Some modules have wrong versions ! They should match '.$sExpectedVersion);
@@ -90,11 +96,11 @@ class iTopModulesPhpVersionIntegrationTest extends ItopTestCase {
* @dataProvider ItopWikiVersionProvider
* @since 2.7.7 3.0.1 3.1.1 N°4714 new ITOP_CORE_VERSION constant
*/
public function testItopWikiVersion($sItopVersion, $sExpectedWikiVersion) {
public function testItopWikiVersion($sItopVersion, $sExpectedWikiVersion)
{
try {
$sActualWikiVersion = utils::GetItopVersionWikiSyntax($sItopVersion);
}
catch (ApplicationException $e) {
} catch (ApplicationException $e) {
self::fail('Cannot get wiki version : '.$e->getMessage());
}
self::assertSame($sExpectedWikiVersion, $sActualWikiVersion, 'Computed wiki version is wrong !');

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
* This file is part of iTop.
@@ -19,7 +20,6 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase;
use DOMDocument;
use iTopDesignFormat;
/**
* @covers iTopDesignFormat
*
@@ -35,7 +35,6 @@ class iTopModulesXmlVersionIntegrationTest extends ItopTestCase
$this->RequireOnceItopFile('setup/itopdesignformat.class.inc.php');
}
/**
* Verify if the `datamodels/2.x/datamodel.*.xml` files refer to the latest version of the design
* This is an integration test
@@ -61,8 +60,11 @@ class iTopModulesXmlVersionIntegrationTest extends ItopTestCase
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)");
$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");
}
@@ -80,11 +82,11 @@ class iTopModulesXmlVersionIntegrationTest extends ItopTestCase
$aXmlFiles[] = $sAppRoot.'core/datamodel.core.xml';
$aXmlFiles[] = $sAppRoot.'application/datamodel.application.xml';
$aTestCases = array();
$aTestCases = [];
foreach ($aXmlFiles as $sXmlFile) {
$aTestCases[$sXmlFile] = array(
$aTestCases[$sXmlFile] = [
'sXmlFile' => $sXmlFile,
);
];
}
return $aTestCases;

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
* This file is part of iTop.
@@ -17,7 +18,6 @@ namespace Combodo\iTop\Test\UnitTest\Integration;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
/**
* @package Combodo\iTop\Test\UnitTest\Setup
* @group beforeSetup
@@ -32,7 +32,6 @@ class iTopXmlVersionIntegrationTest extends ItopTestCase
$this->RequireOnceItopFile('setup/itopdesignformat.class.inc.php');
}
/**
* Verify if the latest version of the XML datamodel is aligned with the app. core version
* This is an integration test

View File

@@ -1,14 +1,16 @@
<?php
namespace Combodo\iTop\Test\UnitTest\HubConnector;
use Combodo\iTop\Application\Helper\Session;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use PHPUnit\Framework\SkippedTestCase;
class AjaxPageTest extends ItopDataTestCase {
const USE_TRANSACTION = false;
const AUTHENTICATION_TOKEN = '14b5da9d092f84044187421419a0347e7317bc8cd2b486fdda631be06b959269';
const AUTHENTICATION_PASSWORD = "tagada-Secret,007";
class AjaxPageTest extends ItopDataTestCase
{
public const USE_TRANSACTION = false;
public const AUTHENTICATION_TOKEN = '14b5da9d092f84044187421419a0347e7317bc8cd2b486fdda631be06b959269';
public const AUTHENTICATION_PASSWORD = "tagada-Secret,007";
protected function setUp(): void
{
@@ -38,12 +40,12 @@ class AjaxPageTest extends ItopDataTestCase {
// Then
$aRes = json_decode($sOutput, true);
$this->assertNotNull($aRes, "Response should be a valid json, found instead:" . PHP_EOL . $sOutput);
$this->assertNotNull($aRes, "Response should be a valid json, found instead:".PHP_EOL.$sOutput);
$this->assertEquals(
[
'code' => 0,
'message' => 'Ok',
'fields' => []
'message' => 'Ok',
'fields' => [],
],
$aRes
);
@@ -73,4 +75,4 @@ class AjaxPageTest extends ItopDataTestCase {
return $sOutput;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -19,25 +20,20 @@
use Combodo\iTop\Application\WebPage\iTopWebPage;
require_once ('../../../approot.inc.php');
require_once('../../../approot.inc.php');
require_once(APPROOT.'application/application.inc.php');
require_once(APPROOT.'application/startup.inc.php');
require_once(APPROOT.'application/loginwebpage.class.inc.php');
/////////////////////////////////////////////////////////////////////
// Main program
//
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed
$sSubmit = utils::ReadParam('submit', '', false, 'raw_data');
if ($sSubmit != 'Reset')
{
if ($sSubmit != 'Reset') {
$sOQL = utils::ReadParam('OQL_Request', '', false, 'raw_data');
}
else
{
} else {
$sOQL = '';
}
$bError = false;
@@ -46,20 +42,15 @@ $oP->set_base(utils::GetAbsoluteUrlAppRoot().'tests/');
$oP->set_title('Grouping with functions');
$oP->add('<div style="padding: 15px;"><h2>Grouping with functions</h2>');
$oP->add('<div style="padding: 15px; background: #ddd;">');
try
{
if (!empty($sOQL))
{
try {
if (!empty($sOQL)) {
// Getting class attributes
$oSearch = DBSearch::FromOQL($sOQL);
$aSearches = $oSearch->GetSearches();
if ($oSearch instanceof DBUnionSearch)
{
if ($oSearch instanceof DBUnionSearch) {
$sClass = $aSearches[0]->GetClassAlias();
$sRealClass = $aSearches[0]->GetClass();
}
else
{
} else {
$sClass = $oSearch->GetClassAlias();
$sRealClass = $oSearch->GetClass();
}
@@ -74,22 +65,17 @@ try
$sAttributesOptions3 = '';
$sAttributesOptions4 = '';
foreach(array('_itop_sum_', '_itop_avg_', '_itop_min_', '_itop_max_', '_itop_count_', 'group1', 'group2') as $sAttCode)
{
foreach (['_itop_sum_', '_itop_avg_', '_itop_min_', '_itop_max_', '_itop_count_', 'group1', 'group2'] as $sAttCode) {
$sAttributesOptions3 .= '<option value="'.$sAttCode.'" '.($sOrderBy1 == $sAttCode ? 'selected' : '').'>'.$sAttCode.'</option>';
$sAttributesOptions4 .= '<option value="'.$sAttCode.'" '.($sOrderBy2 == $sAttCode ? 'selected' : '').'>'.$sAttCode.'</option>';
}
foreach(MetaModel::ListAttributeDefs($sRealClass) as $sAttCode => $oAttDef)
{
foreach (MetaModel::ListAttributeDefs($sRealClass) as $sAttCode => $oAttDef) {
// Skip this attribute if not defined in this table
if ($oSearch instanceof DBUnionSearch)
{
foreach($aSearches as $oSubQuery)
{
if ($oSearch instanceof DBUnionSearch) {
foreach ($aSearches as $oSubQuery) {
$sSubClass = $oSubQuery->GetClass();
if (!MetaModel::IsValidAttCode($sSubClass, $sAttCode))
{
if (!MetaModel::IsValidAttCode($sSubClass, $sAttCode)) {
continue 2;
}
}
@@ -109,22 +95,17 @@ try
$sFuncField = utils::ReadParam('funcfield', '');
$sFuncFieldOption = '';
foreach(MetaModel::ListAttributeDefs($sRealClass) as $sAttCode => $oAttDef)
{
foreach (MetaModel::ListAttributeDefs($sRealClass) as $sAttCode => $oAttDef) {
// Skip this attribute if not defined in this table
if ($oSearch instanceof DBUnionSearch)
{
foreach($aSearches as $oSubQuery)
{
if ($oSearch instanceof DBUnionSearch) {
foreach ($aSearches as $oSubQuery) {
$sSubClass = $oSubQuery->GetClass();
if (!MetaModel::IsValidAttCode($sSubClass, $sAttCode))
{
if (!MetaModel::IsValidAttCode($sSubClass, $sAttCode)) {
continue 2;
}
}
}
switch (get_class($oAttDef))
{
switch (get_class($oAttDef)) {
case 'Integer':
case 'AttributeDecimal':
case 'AttributeDuration':
@@ -135,9 +116,7 @@ try
}
}
}
}
catch (Exception $e)
{
} catch (Exception $e) {
$oP->p('<div class="header_message message_error">'.$e->getMessage().'</div>');
$bError = true;
}
@@ -158,8 +137,7 @@ $oP->add(
EOF
);
if (!empty($sOQL) && !$bError)
{
if (!empty($sOQL) && !$bError) {
$oP->add(
<<<EOF
<div>
@@ -210,55 +188,46 @@ $oP->add("</form>");
$sSQL = '';
if (empty($sOQL) || empty($sGroupBy1))
{
if (empty($sOQL) || empty($sGroupBy1)) {
$oP->output();
return;
}
try
{
try {
$iLimitStart = 0;
$aOrderBy = array();
if (!empty($sOrderBy1))
{
$aOrderBy = [];
if (!empty($sOrderBy1)) {
$aOrderBy[$sOrderBy1] = ($sInvOrder1 != 'on');
}
if (!empty($sOrderBy2))
{
if (!empty($sOrderBy2)) {
$aOrderBy[$sOrderBy2] = ($sInvOrder2 != 'on');
}
$aGroupBy = array();
$aGroupBy = [];
$oExpr1 = Expression::FromOQL($sClass.'.'.$sGroupBy1);
$aGroupBy["group1"] = $oExpr1;
if (!empty($sGroupBy2))
{
if (!empty($sGroupBy2)) {
$oExpr2 = Expression::FromOQL($sClass.'.'.$sGroupBy2);
$aGroupBy["group2"] = $oExpr2;
}
$aArgs = array();
$aArgs = [];
if (empty($sFuncField))
{
$aFunctions = array();
}
else
{
if (empty($sFuncField)) {
$aFunctions = [];
} else {
$oTimeExpr = Expression::FromOQL($sClass.'.'.$sFuncField);
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
$oSumExpr = new FunctionExpression('SUM', [$oTimeExpr]);
$oAvgExpr = new FunctionExpression('AVG', [$oTimeExpr]);
$oMinExpr = new FunctionExpression('MIN', [$oTimeExpr]);
$oMaxExpr = new FunctionExpression('MAX', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => $oSumExpr,
'_itop_avg_' => $oAvgExpr,
'_itop_min_' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
];
}
$sSQL = $oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy, $iLimit, $iLimitStart);
@@ -266,28 +235,23 @@ try
$aRes = CMDBSource::QueryToArray($sSQL);
// Display results
if (!empty($aRes))
{
if (!empty($aRes)) {
$oP->add('<div>');
$oP->add('<table class="listResults">');
$aLine = $aRes[0];
$aCols = array();
$aCols = [];
$oP->add('<tr>');
foreach(array_keys($aLine) as $item)
{
if (!is_numeric($item))
{
foreach (array_keys($aLine) as $item) {
if (!is_numeric($item)) {
$aCols[] = $item;
$oP->add("<th>$item</th>");
}
}
$oP->add('</tr>');
foreach($aRes as $aLine)
{
foreach ($aRes as $aLine) {
$oP->add('<tr>');
foreach($aCols as $sCol)
{
foreach ($aCols as $sCol) {
$oP->add("<td>".$aLine[$sCol]."</td>");
}
$oP->add('</tr>');
@@ -295,14 +259,10 @@ try
$oP->add('</table>');
$oP->add('</div>');
}
else
{
} else {
$oP->add("<p>No Result</p>\n");
}
}
catch (Exception $e)
{
} catch (Exception $e) {
$oP->p('<div class="header_message message_error">'.$e->getMessage().'</div>');
$bError = true;
}
@@ -341,4 +301,4 @@ foreach($aClassSelection as $sClass)
}
}
}
*/
*/

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -29,17 +30,17 @@ require_once(APPROOT.'/setup/setuppage.class.inc.php');
class BenchmarkDataCreation
{
var $m_iIfByServer;
var $m_iIfByNWDevice;
var $m_aRequested;
var $m_aPlanned;
var $m_aCreatedByClass = array();
var $m_aCreatedByDesc = array();
public $m_iIfByServer;
public $m_iIfByNWDevice;
public $m_aRequested;
public $m_aPlanned;
public $m_aCreatedByClass = [];
public $m_aCreatedByDesc = [];
var $m_aStatsByClass = array();
public $m_aStatsByClass = [];
/** @var \CMDBChange $m_oChange */
var $m_oChange;
public $m_oChange;
public function __construct()
{
CMDBObject::SetTrackInfo('Benchmark setup');
@@ -47,22 +48,22 @@ class BenchmarkDataCreation
public function PlanStructure($iPlannedContacts, $iPlannedContracts)
{
$this->m_aRequested = array(
$this->m_aRequested = [
'plannedcontacts' => $iPlannedContacts,
'plannedcontracts' => $iPlannedContracts,
);
$this->m_aPlanned = array(
];
$this->m_aPlanned = [
'Contacts' => $iPlannedContacts,
'Contracts' => $iPlannedContracts,
'Documents' => $iPlannedContracts * 2,
);
];
}
public function PlanCis($iPlannedCIs)
{
$this->m_aRequested = array(
$this->m_aRequested = [
'plannedcis' => $iPlannedCIs,
);
];
$this->m_iIfByServer = 2;
$this->m_iIfByNWDevice = 10;
@@ -74,7 +75,7 @@ class BenchmarkDataCreation
$iSolutions = ceil($iApplications / 2);
$iProcesses = ceil($iSolutions / 2);
$this->m_aPlanned = array(
$this->m_aPlanned = [
'Network devices' => $iNWDevices,
'Servers' => $iServers,
'Interfaces' => $iInterfaces,
@@ -82,45 +83,43 @@ class BenchmarkDataCreation
'Applications' => $iApplications,
'Solutions' => $iSolutions,
'Processes' => $iProcesses,
);
];
}
public function PlanTickets($iPlannedTickets, $iBigTicketCis)
{
$this->m_aRequested = array(
$this->m_aRequested = [
'plannedtickets' => $iPlannedTickets,
'plannedbigticketcis' => $iBigTicketCis,
);
];
$this->m_aPlanned = array(
$this->m_aPlanned = [
'Incidents' => ceil($iPlannedTickets / 2),
'Changes' => ceil($iPlannedTickets / 2),
'Big ticket: CIs' => $iBigTicketCis,
);
];
}
public function ShowPlans($oP)
{
$oP->add("<h2>Planned creations</h2>\n");
$aPlanned = $this->m_aPlanned;
$aForm = array();
foreach ($aPlanned as $sKey => $iCount)
{
$aForm[] = array(
$aForm = [];
foreach ($aPlanned as $sKey => $iCount) {
$aForm[] = [
'label' => $sKey,
'input' => $iCount,
);
];
}
$oP->form($aForm);
}
public function ShowForm($oP, $sNextOperation)
{
$aRequested = $this->m_aRequested;
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Loading data...', 10)\">\n");
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"$sNextOperation\">\n");
foreach($this->m_aRequested as $sName => $sValue)
{
foreach ($this->m_aRequested as $sName => $sValue) {
$oP->add("<input type=\"hidden\" name=\"$sName\" value=\"$sValue\">\n");
}
$oP->add("<button type=\"submit\">Next >></button>\n");
@@ -132,10 +131,8 @@ class BenchmarkDataCreation
$mu_t1 = MyHelpers::getmicrotime();
$oMyObject = MetaModel::NewObject($sClass);
foreach($aData as $sProp => $value)
{
if (is_array($value))
{
foreach ($aData as $sProp => $value) {
if (is_array($value)) {
// transform into a link set
$sCSVSpec = implode('|', $value);
$oAttDef = MetaModel::GetAttributeDef($sClass, $sProp);
@@ -152,21 +149,19 @@ class BenchmarkDataCreation
$mu_t2 = MyHelpers::getmicrotime();
$this->m_aStatsByClass[$sClass][] = $mu_t2 - $mu_t1;
return $iId;
}
static $m_aClassIdCache = array();
public static $m_aClassIdCache = [];
protected function GetClassIds($sClass)
{
if (!isset(self::$m_aClassIdCache[$sClass]))
{
if (!isset(self::$m_aClassIdCache[$sClass])) {
// Load the cache now
self::$m_aClassIdCache[$sClass] = array();
self::$m_aClassIdCache[$sClass] = [];
$oSet = new DBObjectSet(new DBObjectSearch($sClass));
while($oObj = $oSet->Fetch())
{
while ($oObj = $oSet->Fetch()) {
self::$m_aClassIdCache[$sClass][] = $oObj->GetKey();
}
}
@@ -176,20 +171,18 @@ class BenchmarkDataCreation
protected function RandomId($sClass, $sClassDesc = '')
{
$sClassId = "$sClass ($sClassDesc)";
if (isset($this->m_aCreatedByDesc[$sClassId]))
{
if (isset($this->m_aCreatedByDesc[$sClassId])) {
return $this->m_aCreatedByDesc[$sClassId][array_rand($this->m_aCreatedByDesc[$sClassId])];
}
$aIds = self::GetClassIds($sClass);
return $aIds[array_rand($aIds)];
}
static protected function FindId($sClass)
protected static function FindId($sClass)
{
$oSet = new DBObjectSet(new DBObjectSearch($sClass));
if ($oSet->Count() < 1)
{
if ($oSet->Count() < 1) {
return null;
}
@@ -197,11 +190,10 @@ class BenchmarkDataCreation
return $oObj->GetKey();
}
static protected function FindIdFromOQL($sOQL)
protected static function FindIdFromOQL($sOQL)
{
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL));
if ($oSet->Count() < 1)
{
if ($oSet->Count() < 1) {
return null;
}
@@ -211,22 +203,15 @@ class BenchmarkDataCreation
protected function my_array_rand($aData, $iCount)
{
if ($iCount == 0)
{
return array();
}
elseif ($iCount == 1)
{
if ($iCount == 0) {
return [];
} elseif ($iCount == 1) {
// array_rand() for one item returns only the key
$key = array_rand($aData);
$aSample = array($key);
}
elseif ($iCount <= count($aData))
{
$aSample = [$key];
} elseif ($iCount <= count($aData)) {
$aSample = array_rand($aData, $iCount);
}
else
{
} else {
$aSample = array_merge(array_keys($aData), self::my_array_rand($aData, $iCount - count($aData)));
}
return $aSample;
@@ -240,12 +225,11 @@ class BenchmarkDataCreation
$aTargets = self::GetClassIds($sToClass);
$aSample = self::my_array_rand($aTargets, $iCount);
foreach($aSample as $key)
{
$aData = array(
foreach ($aSample as $key) {
$aData = [
$sAttCodeFrom => $iFrom,
$sAttCodeTo => $aTargets[$key],
);
];
$this->CreateObject($sLinkClass, $aData);
}
}
@@ -253,158 +237,153 @@ class BenchmarkDataCreation
public function CreateStructure($oP)
{
$aClasses = MetaModel::GetClasses();
$aActions = array('Read', 'Bulk Read', 'Delete', 'Bulk Delete', 'Modify', 'Bulk Modify');
$aStdProfiles = array(2, 3, 4, 5, 6, 7, 8, 9);
$aActions = ['Read', 'Bulk Read', 'Delete', 'Bulk Delete', 'Modify', 'Bulk Modify'];
$aStdProfiles = [2, 3, 4, 5, 6, 7, 8, 9];
////////////////////////////////////////
// New specific profile, giving access to everything
//
$aData = array(
$aData = [
'name' => 'Data guru',
'description' => 'Could do anything, because everything is granted',
);
];
$iGuruProfile = $this->CreateObject('URP_Profiles', $aData);
foreach($aClasses as $sClass)
{
foreach($aActions as $sAction)
{
$aData = array(
foreach ($aClasses as $sClass) {
foreach ($aActions as $sAction) {
$aData = [
'profileid' => $iGuruProfile,
'class' => $sClass,
'permission' => 'yes',
'action' => $sAction,
);
];
$this->CreateObject('URP_ActionGrant', $aData);
}
}
// User login with super access rights
//
$aData = array(
$aData = [
'org_id' => self::FindId('Organization'),
'location_id' => self::FindId('Location'),
'first_name' => 'Jesus',
'name' => 'Deus',
'email' => 'guru@combodo.com',
);
];
$iPerson = $this->CreateObject('Person', $aData);
$aData = array(
$aData = [
'contactid' => $iPerson,
'login' => 'guru',
'password' => 'guru',
'language' => 'EN US',
'profile_list' => array("profileid:$iGuruProfile;reason:he is the one"),
);
'profile_list' => ["profileid:$iGuruProfile;reason:he is the one"],
];
$iLogin = $this->CreateObject('UserLocal', $aData);
////////////////////////////////////////
// User login having all std profiles
//
$aData = array(
$aData = [
'org_id' => self::FindId('Organization'),
'location_id' => self::FindId('Location'),
'first_name' => 'Little ze',
'name' => 'Foo',
'email' => 'foo@combodo.com',
);
];
$iPerson = $this->CreateObject('Person', $aData);
$aProfileSet = array();
foreach($aStdProfiles as $iProfileId)
{
$aProfileSet = [];
foreach ($aStdProfiles as $iProfileId) {
$aProfileSet[] = "profileid:$iProfileId;reason:xxx";
}
$aData = array(
$aData = [
'contactid' => $iPerson,
'login' => 'foo',
'password' => 'foo',
'language' => 'EN US',
'profile_list' => $aProfileSet,
);
];
$iLogin = $this->CreateObject('UserLocal', $aData);
/////////////////////////
//
// Organizations
//
$aData = array(
$aData = [
'name' => 'Benchmark',
);
];
$iOrg = $this->CreateObject('Organization', $aData);
/////////////////////////
//
// Locations
//
$aData = array(
$aData = [
'org_id' => $iOrg,
'name' => 'Rio de Janeiro',
);
];
$iLoc = $this->CreateObject('Location', $aData);
/////////////////////////
//
// Teams
//
$aData = array(
$aData = [
'org_id' => $iOrg,
'location_id' => $iLoc,
'name' => 'Fluminense',
'email' => 'fluminense@combodo.com',
);
];
$iTeam = $this->CreateObject('Team', $aData);
/////////////////////////
//
// Persons
//
for($i = 0 ; $i < $this->m_aPlanned['Contacts'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Contacts'] ; $i++) {
$aData = [
'org_id' => $iOrg,
'location_id' => $iLoc,
'first_name' => 'Joaõ',
'name' => 'Ningem #'.$i,
'email' => 'foo'.$i.'@nowhere.fr',
);
];
$iPerson = $this->CreateObject('Person', $aData);
// Contract/Infra
//
$aData = array(
$aData = [
'contact_id' => $iPerson,
'team_id' => $this->RandomId('Team'),
);
];
$this->CreateObject('lnkTeamToContact', $aData);
}
/////////////////////////
//
// Services
//
$aData = array(
$aData = [
'org_id' => $iOrg,
'name' => 'My Service',
);
];
$iService = $this->CreateObject('Service', $aData);
/////////////////////////
//
// Service subcategories
//
$aData = array(
$aData = [
'name' => 'My subcategory',
'service_id' => $iService,
);
];
$iOrg = $this->CreateObject('ServiceSubcategory', $aData);
/////////////////////////
//
// Contracts
//
for($i = 0 ; $i < $this->m_aPlanned['Contracts'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Contracts'] ; $i++) {
$aData = [
'name' => "Contract #$i",
'description' => 'Created for benchmarking purposes',
'org_id' => $this->RandomId('Organization'),
@@ -412,19 +391,18 @@ class BenchmarkDataCreation
'start_date' => '2009-12-25',
'end_date' => '2019-08-01',
'support_team_id' => $this->RandomId('Team'),
);
];
$iContract = $this->CreateObject('CustomerContract', $aData);
// Contract/Contact (10% of contacts)
//
$iContactCount = ceil($this->m_aPlanned['Contracts'] / 10);
for($iLinked = 0 ; $iLinked < $iContactCount ; $iLinked++)
{
$aData = array(
for ($iLinked = 0 ; $iLinked < $iContactCount ; $iLinked++) {
$aData = [
'contact_id' => $this->RandomId('Person'),
'contract_id' => $iContract,
'role' => 'role '.$iLinked,
);
];
$this->CreateObject('lnkContractToContact', $aData);
}
}
@@ -434,20 +412,18 @@ class BenchmarkDataCreation
// Documents
//
$sMyDoc = '';
for($i = 0 ; $i < 1000 ; $i++)
{
for ($i = 0 ; $i < 1000 ; $i++) {
// 100 chars
$sMyDoc .= "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\n";
}
$oRefDoc = new ormDocument($sMyDoc, 'text/plain');
for($i = 0 ; $i < $this->m_aPlanned['Documents'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Documents'] ; $i++) {
$aData = [
'org_id' => $iOrg,
'name' => "document$i",
'contents' => $oRefDoc,
);
];
$this->CreateObject('FileDoc', $aData);
}
}
@@ -461,29 +437,27 @@ class BenchmarkDataCreation
//
// Servers
//
for($i = 0 ; $i < $this->m_aPlanned['Servers'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Servers'] ; $i++) {
$aData = [
'org_id' => $iOrg,
'location_id' => $iLoc,
'name' => 'server'.$i,
'status' => 'production',
);
];
$iServer = $this->CreateObject('Server', $aData);
// Contract/Infra
$this->CreateLinks($iServer, 1, 'lnkContractToCI', 'ci_id', 'contract_id');
// Interfaces
for($iLinked = 0 ; $iLinked < $this->m_iIfByServer ; $iLinked++)
{
$aData = array(
for ($iLinked = 0 ; $iLinked < $this->m_iIfByServer ; $iLinked++) {
$aData = [
'name' => "eth$iLinked",
'status' => 'implementation',
'org_id' => $iOrg,
'device_id' => $iServer,
'status' => 'production',
);
];
$this->CreateObject('NetworkInterface', $aData, 'server if');
}
}
@@ -492,14 +466,13 @@ class BenchmarkDataCreation
//
// Network devices
//
for($i = 0 ; $i < $this->m_aPlanned['Network devices'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Network devices'] ; $i++) {
$aData = [
'org_id' => $iOrg,
'location_id' => $iLoc,
'name' => 'equipment #'.$i,
'status' => 'production',
);
];
$iNWDevice = $this->CreateObject('NetworkDevice', $aData);
// Contract/Infra
@@ -507,16 +480,15 @@ class BenchmarkDataCreation
// Interfaces
//
for($iLinked = 0 ; $iLinked < $this->m_iIfByNWDevice ; $iLinked++)
{
$aData = array(
for ($iLinked = 0 ; $iLinked < $this->m_iIfByNWDevice ; $iLinked++) {
$aData = [
'name' => "eth$iLinked",
'status' => 'implementation',
'org_id' => $iOrg,
'device_id' => $iNWDevice,
'connected_if' => $this->RandomId('NetworkInterface', 'server if'),
'status' => 'production',
);
];
$this->CreateObject('NetworkInterface', $aData, 'equipment if');
}
}
@@ -525,11 +497,10 @@ class BenchmarkDataCreation
//
// Application Software
//
for($i = 0 ; $i < $this->m_aPlanned['Application SW'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Application SW'] ; $i++) {
$aData = [
'name' => 'Software #'.$i,
);
];
$iNWDevice = $this->CreateObject('Application', $aData);
}
@@ -537,15 +508,14 @@ class BenchmarkDataCreation
//
// Applications
//
for($i = 0 ; $i < $this->m_aPlanned['Applications'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Applications'] ; $i++) {
$aData = [
'org_id' => $iOrg,
'device_id' => $this->RandomId('Server'),
'software_id' => $this->RandomId('Application'),
'name' => 'Application #'.$i,
'status' => 'production',
);
];
$iAppInstance = $this->CreateObject('ApplicationInstance', $aData);
// Contract/Infra
@@ -556,13 +526,12 @@ class BenchmarkDataCreation
//
// Application Solution
//
for($i = 0 ; $i < $this->m_aPlanned['Solutions'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Solutions'] ; $i++) {
$aData = [
'org_id' => $iOrg,
'name' => 'Solution #'.$i,
'status' => 'production',
);
];
$iAppSolution = $this->CreateObject('ApplicationSolution', $aData);
// Contract/Infra
@@ -573,13 +542,12 @@ class BenchmarkDataCreation
//
// Business Process
//
for($i = 0 ; $i < $this->m_aPlanned['Processes'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Processes'] ; $i++) {
$aData = [
'org_id' => $iOrg,
'name' => 'Process #'.$i,
'status' => 'production',
);
];
$iProcess = $this->CreateObject('BusinessProcess', $aData);
// Contract/Infra
@@ -596,9 +564,8 @@ class BenchmarkDataCreation
//
// Incident Tickets
//
for($i = 0 ; $i < $this->m_aPlanned['Incidents'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Incidents'] ; $i++) {
$aData = [
'org_id' => $iOrg,
'caller_id' => $this->RandomId('Person'),
'workgroup_id' => $this->RandomId('Team'),
@@ -608,7 +575,7 @@ class BenchmarkDataCreation
'title' => 'Incident #'.$i,
'description' => 'O que aconteceu?',
'ticket_log' => 'Testing...',
);
];
$iTicket = $this->CreateObject('Incident', $aData);
// Incident/Infra
@@ -624,7 +591,7 @@ class BenchmarkDataCreation
//
// Big Ticket
//
$aData = array(
$aData = [
'org_id' => $iOrg,
'caller_id' => $this->RandomId('Person'),
'workgroup_id' => $this->RandomId('Team'),
@@ -634,7 +601,7 @@ class BenchmarkDataCreation
'title' => 'Big ticket',
'description' => 'O que aconteceu?',
'ticket_log' => 'Testing...',
);
];
$iTicket = $this->CreateObject('Incident', $aData);
// Incident/Infra
@@ -649,9 +616,8 @@ class BenchmarkDataCreation
//
// Change Tickets
//
for($i = 0 ; $i < $this->m_aPlanned['Changes'] ; $i++)
{
$aData = array(
for ($i = 0 ; $i < $this->m_aPlanned['Changes'] ; $i++) {
$aData = [
'org_id' => $iOrg,
'requestor_id' => $this->RandomId('Person'),
'workgroup_id' => $this->RandomId('Team'),
@@ -662,13 +628,13 @@ class BenchmarkDataCreation
'manager_id' => $this->RandomId('Person'),
'title' => 'change #'.$i,
'description' => "Let's do something there",
);
];
$iTicket = $this->CreateObject('NormalChange', $aData);
// Incident/Infra
$iInfraCount = rand(1, 6);
$this->CreateLinks($iTicket, $iInfraCount, 'lnkTicketToCI', 'ticket_id', 'ci_id');
// Incident/Infra
$iContactCount = rand(1, 6);
$this->CreateLinks($iTicket, $iContactCount, 'lnkTicketToContact', 'ticket_id', 'contact_id');
@@ -677,16 +643,15 @@ class BenchmarkDataCreation
public function MakeFeedback($oP)
{
foreach($this->m_aCreatedByClass as $sClass => $aClassIds)
{
foreach ($this->m_aCreatedByClass as $sClass => $aClassIds) {
$iSample = reset($aClassIds);
$sSample = "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=details&class=$sClass&id=$iSample\">sample</a>";
$iDuration = number_format(array_sum($this->m_aStatsByClass[$sClass]), 3);
$fDurationMin = number_format(min($this->m_aStatsByClass[$sClass]), 3);
$fDurationMax = number_format(max($this->m_aStatsByClass[$sClass]), 3);
$fDurationAverage = number_format(array_sum($this->m_aStatsByClass[$sClass]) / count($this->m_aStatsByClass[$sClass]), 3);
$oP->add("<ul>");
$oP->add("<li>");
$oP->add("$sClass: ".count($this->m_aStatsByClass[$sClass])." - $sSample<br/>");
@@ -699,7 +664,7 @@ class BenchmarkDataCreation
/**
* Ask the user what are the settings for the data load
*/
*/
function DisplayStep1(SetupPage $oP)
{
$sNextOperation = 'step2';
@@ -707,17 +672,17 @@ function DisplayStep1(SetupPage $oP)
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Evaluating real plans...', 10)\">\n");
$oP->add("<fieldset><legend>Data load configuration</legend>\n");
$aForm = array();
$aForm[] = array(
$aForm = [];
$aForm[] = [
'label' => "Contacts:",
'input' => "<input id=\"from\" type=\"text\" name=\"plannedcontacts\" value=\"100\">",
'help' => '',
);
$aForm[] = array(
];
$aForm[] = [
'label' => "Contracts:",
'input' => "<input id=\"from\" type=\"text\" name=\"plannedcontracts\" value=\"10\">",
'help' => '',
);
];
$oP->form($aForm);
$oP->add("</fieldset>\n");
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"create_structure\">\n");
@@ -726,12 +691,12 @@ function DisplayStep1(SetupPage $oP)
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Evaluating real plans...', 10)\">\n");
$oP->add("<fieldset><legend>Data load configuration</legend>\n");
$aForm = array();
$aForm[] = array(
$aForm = [];
$aForm[] = [
'label' => "Main CIs:",
'input' => "<input id=\"to\" type=\"text\" name=\"plannedcis\" value=\"70\">",
'help' => ' exclude interfaces, subnets or any other type of secondary CI',
);
];
$oP->form($aForm);
$oP->add("</fieldset>\n");
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"create_cis\">\n");
@@ -740,17 +705,17 @@ function DisplayStep1(SetupPage $oP)
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Evaluating real plans...', 10)\">\n");
$oP->add("<fieldset><legend>Data load configuration</legend>\n");
$aForm = array();
$aForm[] = array(
$aForm = [];
$aForm[] = [
'label' => "Tickets:",
'input' => "<input id=\"to\" type=\"text\" name=\"plannedtickets\" value=\"200\">",
'help' => ' 50% incidents, 50% changes',
);
$aForm[] = array(
];
$aForm[] = [
'label' => "CIs for the big ticket:",
'input' => "<input id=\"to\" type=\"text\" name=\"plannedbigticketcis\" value=\"200\">",
'help' => 'Number of CI for the single big ticket',
);
];
$oP->form($aForm);
$oP->add("</fieldset>\n");
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"create_tickets\">\n");
@@ -758,7 +723,6 @@ function DisplayStep1(SetupPage $oP)
$oP->add("</form>\n");
}
/**
* Main program
*/
@@ -771,13 +735,11 @@ $oP = new SetupPage('iTop benchmark utility');
ExecutionKPI::EnableDuration();
$oKPI = new ExecutionKPI();
try
{
switch($sOperation)
{
try {
switch ($sOperation) {
case 'step1':
DisplayStep1($oP);
break;
DisplayStep1($oP);
break;
case 'create_structure':
$oP->no_cache();
@@ -792,71 +754,66 @@ try
break;
case 'create_structure_go':
$oP->no_cache();
$iPlannedContacts = Utils::ReadParam('plannedcontacts');
$iPlannedContracts = Utils::ReadParam('plannedcontracts');
$oP->no_cache();
$iPlannedContacts = Utils::ReadParam('plannedcontacts');
$iPlannedContracts = Utils::ReadParam('plannedcontracts');
$oDataCreation = new BenchmarkDataCreation();
$oDataCreation->PlanStructure($iPlannedContacts, $iPlannedContracts);
$oDataCreation->CreateStructure($oP);
$oDataCreation->MakeFeedback($oP);
break;
$oDataCreation = new BenchmarkDataCreation();
$oDataCreation->PlanStructure($iPlannedContacts, $iPlannedContracts);
$oDataCreation->CreateStructure($oP);
$oDataCreation->MakeFeedback($oP);
break;
case 'create_cis':
$oP->no_cache();
$iPlannedCIs = Utils::ReadParam('plannedcis');
$oP->no_cache();
$iPlannedCIs = Utils::ReadParam('plannedcis');
$oDataCreation = new BenchmarkDataCreation();
$oDataCreation->PlanCis($iPlannedCIs);
$oDataCreation->ShowPlans($oP);
$oDataCreation->ShowForm($oP, 'create_cis_go');
break;
$oDataCreation = new BenchmarkDataCreation();
$oDataCreation->PlanCis($iPlannedCIs);
$oDataCreation->ShowPlans($oP);
$oDataCreation->ShowForm($oP, 'create_cis_go');
break;
case 'create_cis_go':
$oP->no_cache();
$iPlannedCIs = Utils::ReadParam('plannedcis');
$oP->no_cache();
$iPlannedCIs = Utils::ReadParam('plannedcis');
$oDataCreation = new BenchmarkDataCreation();
$oDataCreation->PlanCis($iPlannedCIs);
$oDataCreation->CreateCis($oP);
$oDataCreation->MakeFeedback($oP);
break;
$oDataCreation = new BenchmarkDataCreation();
$oDataCreation->PlanCis($iPlannedCIs);
$oDataCreation->CreateCis($oP);
$oDataCreation->MakeFeedback($oP);
break;
case 'create_tickets':
$oP->no_cache();
$iPlannedTickets = Utils::ReadParam('plannedtickets');
$iBigTicketCis = Utils::ReadParam('plannedbigticketcis');
$oP->no_cache();
$iPlannedTickets = Utils::ReadParam('plannedtickets');
$iBigTicketCis = Utils::ReadParam('plannedbigticketcis');
$oDataCreation = new BenchmarkDataCreation();
$oDataCreation->PlanTickets($iPlannedTickets, $iBigTicketCis);
$oDataCreation->ShowPlans($oP);
$oDataCreation->ShowForm($oP, 'create_tickets_go');
break;
$oDataCreation = new BenchmarkDataCreation();
$oDataCreation->PlanTickets($iPlannedTickets, $iBigTicketCis);
$oDataCreation->ShowPlans($oP);
$oDataCreation->ShowForm($oP, 'create_tickets_go');
break;
case 'create_tickets_go':
$oP->no_cache();
$iPlannedTickets = Utils::ReadParam('plannedtickets');
$iBigTicketCis = Utils::ReadParam('plannedbigticketcis');
$oP->no_cache();
$iPlannedTickets = Utils::ReadParam('plannedtickets');
$iBigTicketCis = Utils::ReadParam('plannedbigticketcis');
$oDataCreation = new BenchmarkDataCreation();
$oDataCreation->PlanTickets($iPlannedTickets, $iBigTicketCis);
$oDataCreation->CreateTickets($oP);
$oDataCreation->MakeFeedback($oP);
break;
$oDataCreation = new BenchmarkDataCreation();
$oDataCreation->PlanTickets($iPlannedTickets, $iBigTicketCis);
$oDataCreation->CreateTickets($oP);
$oDataCreation->MakeFeedback($oP);
break;
default:
$oP->error("Error: unsupported operation '$sOperation'");
$oP->error("Error: unsupported operation '$sOperation'");
}
}
catch(ZZException $e)
{
$oP->error("Error: '".$e->getMessage()."'");
}
catch(ZZCoreException $e)
{
$oP->error("Error: '".$e->getHtmlDesc()."'");
} catch (ZZException $e) {
$oP->error("Error: '".$e->getMessage()."'");
} catch (ZZCoreException $e) {
$oP->error("Error: '".$e->getHtmlDesc()."'");
}
$oKPI->ComputeAndReport('Total execution');
//DBSearch::RecordQueryTrace();
$oP->output();
?>

View File

@@ -1,4 +1,5 @@
<?php
// Copyright (c) 2010-2024 Combodo SAS
//
// This file is part of iTop.
@@ -21,7 +22,6 @@
* Date: 06/10/2017
*/
require_once('../../../approot.inc.php');
require_once(APPROOT.'application/startup.inc.php');
@@ -34,7 +34,7 @@ $oTestHandle = @fopen($sTestFile, "w");
@fwrite($oTestHandle, "<?php\n\n");
$aFoundOQLs = array();
$aFoundOQLs = [];
$iCount = 0;
$iRead = 0;
@@ -47,7 +47,9 @@ if ($oOQLHandle) {
$sOQL = $aRecord['oql'];
$sChecksum = md5($sBuffer);
if (isset($aFoundOQLs[$sChecksum])) { continue; }
if (isset($aFoundOQLs[$sChecksum])) {
continue;
}
$aFoundOQLs[$sChecksum] = true;
$iCount++;
@@ -72,10 +74,8 @@ if ($oOQLHandle) {
echo "File '$sTestFile' generated with $iCount entries (from $iRead captured OQL).\n";
/// Group by
$sOQLFile = APPROOT.'log/oql_group_by_records.txt';
$sTestFile = APPROOT.'tests/core/oql_group_by_records.php';
@@ -83,7 +83,7 @@ $oTestHandle = @fopen($sTestFile, "w");
@fwrite($oTestHandle, "<?php\n\n");
$aFoundOQLs = array();
$aFoundOQLs = [];
$iCount = 1000;
$iRead = 0;
@@ -96,19 +96,18 @@ if ($oOQLHandle) {
$sOQL = $aRecord['oql'];
$sChecksum = md5($sBuffer);
if (isset($aFoundOQLs[$sChecksum])) { continue; }
if (isset($aFoundOQLs[$sChecksum])) {
continue;
}
$aFoundOQLs[$sChecksum] = true;
$iCount++;
$sOrderBy = ConvertArray($aRecord['order_by']);
$sGroupByExpr = ConvertArray($aRecord['group_by_expr']);
$sSelectExpr = ConvertArray($aRecord['select_expr']);
if ($aRecord['exclude_null_values'])
{
if ($aRecord['exclude_null_values']) {
$bExcludeNullValues = 'true';
}
else
{
} else {
$bExcludeNullValues = 'false';
}
$iLimitCount = $aRecord['limit_count'];
@@ -128,19 +127,17 @@ if ($oOQLHandle) {
@fclose($oTestHandle);
echo "<br>File '$sTestFile' generated with ".($iCount-1000)." entries (from $iRead captured OQL).\n";
echo "<br>File '$sTestFile' generated with ".($iCount - 1000)." entries (from $iRead captured OQL).\n";
function ConvertArray($aArray)
{
if (is_null($aArray))
{
if (is_null($aArray)) {
return 'null';
}
if (empty($aArray))
{
if (empty($aArray)) {
return 'array()';
}
return 'unserialize(\''.str_replace("'", "\\'",serialize($aArray)).'\')';
return 'unserialize(\''.str_replace("'", "\\'", serialize($aArray)).'\')';
}

View File

@@ -8,31 +8,29 @@
// The file is used in MetaModel::LoadConfig() which does all the necessary initialization job
//
$MySettings = array(
$MySettings = [
'db_host' => 'localhost',
'db_user' => 'root',
'db_pwd' => '',
'db_name' => 'TestFarm',
'db_subname' => '', // use it to differentiate two applications instances running on the same DB
);
];
// Modules: file names should be specified as a absolute paths
$MyModules = array(
'application' => array (
$MyModules = [
'application' => [
// '../core/event.class.inc.php',
// '../core/action.class.inc.php',
// '../core/trigger.class.inc.php',
// to be continued...
),
'business' => array (
],
'business' => [
'../business/test_farm.class.inc.php',
// to be continued...
),
'addons' => array (
],
'addons' => [
//'user rights' => '/addons/userrights/userrightsnull.class.inc.php', // or userrightsmatrix.class.inc.php
// other modules to come later
)
);
?>
],
];

View File

@@ -1,9 +1,10 @@
<?php
// Copyright (C) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// 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.
@@ -23,7 +24,6 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/core/attributedef.class.inc.php');
require_once(APPROOT.'/core/stimulus.class.inc.php');
require_once(APPROOT.'/core/MyHelpers.class.inc.php');
@@ -47,11 +47,10 @@ require_once(APPROOT.'/core/userrights.class.inc.php');
require_once(APPROOT.'/webservices/webservices.class.inc.php');
// Just to differentiate programmatically triggered exceptions and other kind of errors (usefull?)
class UnitTestException extends Exception
{}
{
}
/**
* Improved display of the backtrace
@@ -68,7 +67,6 @@ class ExceptionFromError extends Exception
}
}
/**
* Test handler API and basic helpers
*
@@ -83,21 +81,33 @@ abstract class TestHandler
public function __construct()
{
$this->m_aSuccesses = array();
$this->m_aWarnings = array();
$this->m_aErrors = array();
$this->m_aSuccesses = [];
$this->m_aWarnings = [];
$this->m_aErrors = [];
}
static public function GetName() {return "fooname";}
static public function GetDescription(){return "foodesc";}
public static function GetName()
{
return "fooname";
}
public static function GetDescription()
{
return "foodesc";
}
protected function DoPrepare() {return true;}
protected function DoPrepare()
{
return true;
}
abstract protected function DoExecute();
protected function DoCleanup() {return true;}
protected function DoCleanup()
{
return true;
}
protected static function DumpVariable($var)
{
echo "<pre class=\"vardump\">\n";
echo "<pre class=\"vardump\">\n";
print_r($var);
echo "</pre>\n";
}
@@ -141,24 +151,25 @@ abstract class TestHandler
{
// Note: return false to call the default handler (stop the program if an error)
if ($errstr == 'assert()') $errno = E_USER_ERROR;
if ($errstr == 'assert()') {
$errno = E_USER_ERROR;
}
switch ($errno)
{
case E_USER_ERROR:
case E_WARNING: //(assertion failed)
$this->ReportError("$errfile@$errline - $errstr");
break;
case E_USER_WARNING:
$this->ReportWarning("$errfile@$errline - $errstr");
break;
case E_USER_NOTICE:
$this->ReportWarning("$errfile@$errline - $errstr");
break;
default:
$this->ReportWarning("$errfile@$errline - Unknown error type: [$errno] $errstr");
echo "Unknown error type: [$errno] $errstr in $errfile at $errline<br />\n";
break;
switch ($errno) {
case E_USER_ERROR:
case E_WARNING: //(assertion failed)
$this->ReportError("$errfile@$errline - $errstr");
break;
case E_USER_WARNING:
$this->ReportWarning("$errfile@$errline - $errstr");
break;
case E_USER_NOTICE:
$this->ReportWarning("$errfile@$errline - $errstr");
break;
default:
$this->ReportWarning("$errfile@$errline - Unknown error type: [$errno] $errstr");
echo "Unknown error type: [$errno] $errstr in $errfile at $errline<br />\n";
break;
}
return true; // do not call the default handler
}
@@ -166,24 +177,17 @@ abstract class TestHandler
public function Execute()
{
ob_start();
set_error_handler(array($this, 'error_handler'));
try
{
set_error_handler([$this, 'error_handler']);
try {
$this->DoPrepare();
$this->DoExecute();
}
catch (ExceptionFromError $e)
{
} catch (ExceptionFromError $e) {
$this->ReportError($e->getMessage().' - '.$e->getTraceAsHtml());
}
catch (CoreException $e)
{
} catch (CoreException $e) {
//$this->ReportError($e->getMessage());
//$this->ReportError($e->__tostring());
$this->ReportError($e->getMessage().' - '.$e->getTraceAsHtml());
}
catch (Exception $e)
{
} catch (Exception $e) {
//$this->ReportError($e->getMessage());
//$this->ReportError($e->__tostring());
$this->ReportError('class '.get_class($e).' --- '.$e->getMessage().' - '.$e->getTraceAsString());
@@ -193,10 +197,10 @@ abstract class TestHandler
return (count($this->GetErrors()) == 0);
}
static protected function DoPostRequestAuth($sRelativeUrl, $aData, $sLogin = 'admin', $sPassword = 'admin', $sOptionnalHeaders = null)
protected static function DoPostRequestAuth($sRelativeUrl, $aData, $sLogin = 'admin', $sPassword = 'admin', $sOptionnalHeaders = null)
{
$aDataAndAuth = $aData;
// To be changed to use basic authentication
// To be changed to use basic authentication
$aDataAndAuth['operation'] = 'login';
$aDataAndAuth['auth_user'] = $sLogin;
$aDataAndAuth['auth_pwd'] = $sPassword;
@@ -211,50 +215,41 @@ abstract class TestHandler
// Source: http://netevil.org/blog/2006/nov/http-post-from-php-without-curl
// originaly named after do_post_request
// Partially adapted to our coding conventions
static protected function DoPostRequest($sUrl, $aData, $sOptionnalHeaders = null)
protected static function DoPostRequest($sUrl, $aData, $sOptionnalHeaders = null)
{
// $sOptionnalHeaders is a string containing additional HTTP headers that you would like to send in your request.
$sData = http_build_query($aData);
$aParams = array('http' => array(
$aParams = ['http' => [
'method' => 'POST',
'content' => $sData,
'header'=> "Content-type: application/x-www-form-urlencoded\r\nContent-Length: ".strlen($sData)."\r\n",
));
if ($sOptionnalHeaders !== null)
{
'header' => "Content-type: application/x-www-form-urlencoded\r\nContent-Length: ".strlen($sData)."\r\n",
]];
if ($sOptionnalHeaders !== null) {
$aParams['http']['header'] .= $sOptionnalHeaders;
}
$ctx = stream_context_create($aParams);
$fp = @fopen($sUrl, 'rb', false, $ctx);
if (!$fp)
{
if (!$fp) {
global $php_errormsg;
if (isset($php_errormsg))
{
if (isset($php_errormsg)) {
throw new Exception("Problem with $sUrl, $php_errormsg");
}
else
{
} else {
throw new Exception("Problem with $sUrl");
}
}
$response = @stream_get_contents($fp);
if ($response === false)
{
if ($response === false) {
throw new Exception("Problem reading data from $sUrl, $php_errormsg");
}
return $response;
}
}
/**
* Test to execute a piece of code (checks if an error occurs)
* Test to execute a piece of code (checks if an error occurs)
*
* @package iTopORM
*/
@@ -263,9 +258,8 @@ abstract class TestFunction extends TestHandler
// simply overload DoExecute (temporary)
}
/**
* Test to execute a piece of code (checks if an error occurs)
* Test to execute a piece of code (checks if an error occurs)
*
* @package iTopORM
*/
@@ -274,7 +268,7 @@ abstract class TestWebServices extends TestHandler
}
/**
* Test to execute a piece of code (checks if an error occurs)
* Test to execute a piece of code (checks if an error occurs)
*
* @package iTopORM
*/
@@ -282,60 +276,52 @@ abstract class TestSoapWebService extends TestHandler
{
// simply overload DoExecute (temporary)
function __construct()
public function __construct()
{
parent::__construct();
}
}
/**
* Test to check that a function outputs some values depending on its input
* Test to check that a function outputs some values depending on its input
*
* @package iTopORM
*/
abstract class TestFunctionInOut extends TestFunction
{
// abstract static public function GetCallSpec(); // parameters to call_user_func
// abstract static public function GetInOut(); // array of input => output
// abstract static public function GetCallSpec(); // parameters to call_user_func
// abstract static public function GetInOut(); // array of input => output
protected function DoExecute()
{
$aTests = $this->GetInOut();
if (is_array($aTests))
{
foreach ($aTests as $iTestId => $aTest)
{
if (is_array($aTests)) {
foreach ($aTests as $iTestId => $aTest) {
$ret = call_user_func_array($this->GetCallSpec(), $aTest['args']);
if ($ret != $aTest['output'])
{
if ($ret != $aTest['output']) {
// Note: to be improved to cope with non string parameters
$this->ReportError("Found '$ret' while expecting '".$aTest['output']."'", $iTestId);
}
else
{
} else {
$this->ReportSuccess("Found the expected output '$ret'", $iTestId);
}
}
}
else
{
} else {
$ret = call_user_func($this->GetCallSpec());
$this->ReportSuccess('Finished successfully');
}
}
}
/**
* Test to check an URL (Searches for Error/Warning/Etc keywords)
* Test to check an URL (Searches for Error/Warning/Etc keywords)
*
* @package iTopORM
*/
abstract class TestUrl extends TestHandler
{
// abstract static public function GetUrl();
// abstract static public function GetErrorKeywords();
// abstract static public function GetWarningKeywords();
// abstract static public function GetUrl();
// abstract static public function GetErrorKeywords();
// abstract static public function GetWarningKeywords();
protected function DoExecute()
{
@@ -343,9 +329,8 @@ abstract class TestUrl extends TestHandler
}
}
/**
* Test to check a user management module
* Test to check a user management module
*
* @package iTopORM
*/
@@ -357,7 +342,6 @@ abstract class TestUserRights extends TestHandler
}
}
/**
* Test to execute a scenario on a given DB
*
@@ -365,10 +349,10 @@ abstract class TestUserRights extends TestHandler
*/
abstract class TestScenarioOnDB extends TestHandler
{
// abstract static public function GetDBHost();
// abstract static public function GetDBUser();
// abstract static public function GetDBPwd();
// abstract static public function GetDBName();
// abstract static public function GetDBHost();
// abstract static public function GetDBUser();
// abstract static public function GetDBPwd();
// abstract static public function GetDBName();
protected function DoPrepare()
{
@@ -379,8 +363,7 @@ abstract class TestScenarioOnDB extends TestHandler
CMDBSource::Init($sDBHost, $sDBUser, $sDBPwd);
CMDBSource::SetCharacterSet();
if (CMDBSource::IsDB($sDBName))
{
if (CMDBSource::IsDB($sDBName)) {
CMDBSource::DropDB($sDBName);
}
CMDBSource::CreateDB($sDBName);
@@ -392,26 +375,28 @@ abstract class TestScenarioOnDB extends TestHandler
}
}
/**
* Test to use a business model on a given DB
* Test to use a business model on a given DB
*
* @package iTopORM
*/
abstract class TestBizModel extends TestHandler
{
// abstract static public function GetDBSubName();
// abstract static public function GetBusinessModelFile();
// abstract static public function GetConfigFile();
// abstract static public function GetDBSubName();
// abstract static public function GetBusinessModelFile();
// abstract static public function GetConfigFile();
static public function GetConfigFile() {return 'conf/production/config-itop.php';}
public static function GetConfigFile()
{
return 'conf/production/config-itop.php';
}
protected function DoPrepare()
{
$sConfigFile = APPROOT.$this->GetConfigFile();
MetaModel::Startup($sConfigFile);
// #@# Temporary disabled by Romain
// MetaModel::CheckDefinitions();
// #@# Temporary disabled by Romain
// MetaModel::CheckDefinitions();
// something here to create records... but that's another story
}
@@ -419,52 +404,45 @@ abstract class TestBizModel extends TestHandler
protected $m_oChange;
protected function GetCurrentChange()
{
if (!isset($this->m_oChange))
{
new CMDBChange();
if (!isset($this->m_oChange)) {
new CMDBChange();
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Someone doing some tests");
$iChangeId = $oMyChange->DBInsertNoReload();
$this->m_oChange = $oMyChange;
$this->m_oChange = $oMyChange;
}
return $this->m_oChange;
}
protected function ObjectToDB($oNew, $bReload = false)
{
if ($bReload)
{
if ($bReload) {
$iId = $oNew->DBInsert();
}
else
{
} else {
$iId = $oNew->DBInsertNoReload();
}
return $iId;
}
protected function UpdateObjectInDB($oObject)
protected function UpdateObjectInDB($oObject)
{
$oObject->DBUpdate();
}
protected function ResetDB()
{
if (MetaModel::DBExists(false))
{
if (MetaModel::DBExists(false)) {
MetaModel::DBDrop();
}
MetaModel::DBCreate();
}
static protected function show_list($oObjectSet)
protected static function show_list($oObjectSet)
{
$oObjectSet->Rewind();
$aData = array();
while ($oItem = $oObjectSet->Fetch())
{
$aValues = array();
foreach(MetaModel::GetAttributesList(get_class($oItem)) as $sAttCode)
{
$aData = [];
while ($oItem = $oObjectSet->Fetch()) {
$aValues = [];
foreach (MetaModel::GetAttributesList(get_class($oItem)) as $sAttCode) {
$aValues[$sAttCode] = $oItem->GetAsHTML($sAttCode);
}
//echo $oItem->GetKey()." => ".implode(", ", $aValues)."</br>\n";
@@ -473,22 +451,21 @@ abstract class TestBizModel extends TestHandler
echo MyHelpers::make_table_from_assoc_array($aData);
}
static protected function search_and_show_list(DBSearch $oMyFilter)
protected static function search_and_show_list(DBSearch $oMyFilter)
{
$oObjSet = new CMDBObjectSet($oMyFilter);
echo $oMyFilter->ToOQL()."' - Found ".$oObjSet->Count()." items.</br>\n";
self::show_list($oObjSet);
}
static protected function search_and_show_list_from_oql($sOQL)
protected static function search_and_show_list_from_oql($sOQL)
{
echo $sOQL."...<br/>\n";
echo $sOQL."...<br/>\n";
$oNewFilter = DBObjectSearch::FromOQL($sOQL);
self::search_and_show_list($oNewFilter);
}
}
/**
* Test to execute a scenario common to any business model (tries to build all the possible queries, etc.)
*
@@ -496,12 +473,12 @@ abstract class TestBizModel extends TestHandler
*/
abstract class TestBizModelGeneric extends TestBizModel
{
static public function GetName()
public static function GetName()
{
return 'Full test on a given business model';
}
static public function GetDescription()
public static function GetDescription()
{
return 'Systematic tests: gets each and every existing class and tries every attribute, search filters, etc.';
}
@@ -510,8 +487,7 @@ abstract class TestBizModelGeneric extends TestBizModel
{
parent::DoPrepare();
if (!MetaModel::DBExists(false))
{
if (!MetaModel::DBExists(false)) {
MetaModel::DBCreate();
}
// something here to create records... but that's another story
@@ -519,12 +495,13 @@ abstract class TestBizModelGeneric extends TestBizModel
protected function DoExecute()
{
foreach(MetaModel::GetClasses() as $sClassName)
{
if (MetaModel::HasTable($sClassName)) continue;
foreach (MetaModel::GetClasses() as $sClassName) {
if (MetaModel::HasTable($sClassName)) {
continue;
}
$oNobody = MetaModel::GetObject($sClassName, 123);
$oBaby = new $sClassName;
$oBaby = new $sClassName();
$oFilter = new DBObjectSearch($sClassName);
// Challenge reversibility of OQL / filter object
@@ -532,8 +509,7 @@ abstract class TestBizModelGeneric extends TestBizModel
$sExpr1 = $oFilter->ToOQL();
$oNewFilter = DBObjectSearch::FromOQL($sExpr1);
$sExpr2 = $oNewFilter->ToOQL();
if ($sExpr1 != $sExpr2)
{
if ($sExpr1 != $sExpr2) {
$this->ReportError("Found two different OQL expression out of the (same?) filter: <em>$sExpr1</em> != <em>$sExpr2</em>");
}
@@ -545,6 +521,3 @@ abstract class TestBizModelGeneric extends TestBizModel
return true;
}
}
?>

View File

@@ -33,8 +33,7 @@ line-height:100%;
function ReadMandatoryParam($sName)
{
$value = utils::ReadParam($sName, null);
if (is_null($value))
{
if (is_null($value)) {
echo "<p>Missing mandatory argument <b>$sName</b></p>";
exit;
}
@@ -45,12 +44,16 @@ function IsAValidTestClass($sClassName)
{
// Must be a child of TestHandler
//
if (!is_subclass_of($sClassName, 'TestHandler')) return false;
if (!is_subclass_of($sClassName, 'TestHandler')) {
return false;
}
// Must not be abstract
//
$oReflectionClass = new ReflectionClass($sClassName);
if (!$oReflectionClass->isInstantiable()) return false;
if (!$oReflectionClass->isInstantiable()) {
return false;
}
return true;
}
@@ -64,17 +67,13 @@ function GetTestClassLine($sClassName)
function DisplayEvents($aEvents, $sTitle)
{
echo "<h4>$sTitle</h4>\n";
if (count($aEvents) > 0)
{
if (count($aEvents) > 0) {
echo "<ul>\n";
foreach ($aEvents as $sEvent)
{
foreach ($aEvents as $sEvent) {
echo "<li>$sEvent</li>\n";
}
echo "</ul>\n";
}
else
{
} else {
echo "<p>none</p>\n";
}
}
@@ -92,36 +91,30 @@ require_once('./testlist.inc.php');
require_once(APPROOT.'/core/cmdbobject.class.inc.php');
$sTodo = utils::ReadParam("todo", "");
if ($sTodo == '')
{
if ($sTodo == '') {
// Show the list of tests
//
echo "<h3>Existing tests</h3>\n";
echo "<ul>\n";
foreach (get_declared_classes() as $sClassName)
{
if (!IsAValidTestClass($sClassName)) continue;
$sName = call_user_func(array($sClassName, 'GetName'));
$sDescription = call_user_func(array($sClassName, 'GetDescription'));
foreach (get_declared_classes() as $sClassName) {
if (!IsAValidTestClass($sClassName)) {
continue;
}
$sName = call_user_func([$sClassName, 'GetName']);
$sDescription = call_user_func([$sClassName, 'GetDescription']);
echo "<li><a href=\"?todo=exec&testid=$sClassName\">$sName</a> ($sDescription)</li>\n";
}
echo "</ul>\n";
}
else if ($sTodo == 'exec')
{
} elseif ($sTodo == 'exec') {
// Execute a test
//
$sTestClass = ReadMandatoryParam("testid");
if (!IsAValidTestClass($sTestClass))
{
if (!IsAValidTestClass($sTestClass)) {
echo "<p>Wrong value for testid, expecting a valid class name</p>\n";
}
else
{
} else {
$oTest = new $sTestClass();
$iStartLine = GetTestClassLine($sTestClass);
echo "<h3>Testing: ".$oTest->GetName()."</h3>\n";
@@ -129,19 +122,16 @@ else if ($sTodo == 'exec')
$bRes = $oTest->Execute();
}
/*
MyHelpers::var_dump_html($oTest->GetResults());
MyHelpers::var_dump_html($oTest->GetWarnings());
MyHelpers::var_dump_html($oTest->GetErrors());
*/
/*
MyHelpers::var_dump_html($oTest->GetResults());
MyHelpers::var_dump_html($oTest->GetWarnings());
MyHelpers::var_dump_html($oTest->GetErrors());
*/
if ($bRes)
{
if ($bRes) {
echo "<p>Success :-)</p>\n";
DisplayEvents($oTest->GetResults(), 'Results');
}
else
{
} else {
echo "<p>Failure :-(</p>\n";
}
DisplayEvents($oTest->GetErrors(), 'Errors');
@@ -153,10 +143,7 @@ MyHelpers::var_dump_html($oTest->GetErrors());
echo "<div style=\"border: dashed; background-color:light-grey;\">\n";
echo $oTest->GetOutput();
echo "</div>\n";
} else {
}
else
{
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2010-2024 Combodo SAS
*
@@ -25,7 +26,6 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase;
use iTopDesignFormat;
use utils;
/**
* Class SetupCssIntegrityChecklistTest
*/
@@ -35,19 +35,19 @@ class SetupCssIntegrityChecklistTest extends ItopTestCase
{
$sCssFileAbsPath = APPROOT."css/setup.css";
// First check if the compiled file exists
$this->assertTrue(file_exists($sCssFileAbsPath));
// First check if the compiled file exists
$this->assertTrue(file_exists($sCssFileAbsPath));
// Then check that it is not empty
$sVersionedCssFileContent = file_get_contents($sCssFileAbsPath);
$this->assertGreaterThan(0, strlen($sVersionedCssFileContent), "Compiled setup.css file seems empty");
// Then check that it is not empty
$sVersionedCssFileContent = file_get_contents($sCssFileAbsPath);
$this->assertGreaterThan(0, strlen($sVersionedCssFileContent), "Compiled setup.css file seems empty");
// Then check that the compiled file is up-to-date
// Then check that the compiled file is up-to-date
$sScssFileRelPath = "css/setup.scss";
$sScssFileAbsPath = APPROOT . $sScssFileRelPath;
touch($sScssFileAbsPath);
utils::GetCSSFromSASS($sScssFileRelPath);
$sCompiledCssFileContent = file_get_contents($sCssFileAbsPath);
$this->assertSame($sCompiledCssFileContent, $sVersionedCssFileContent, "Compiled setup.css file does not seem up to date as the one compiled just now is different");
$sScssFileAbsPath = APPROOT.$sScssFileRelPath;
touch($sScssFileAbsPath);
utils::GetCSSFromSASS($sScssFileRelPath);
$sCompiledCssFileContent = file_get_contents($sCssFileAbsPath);
$this->assertSame($sCompiledCssFileContent, $sVersionedCssFileContent, "Compiled setup.css file does not seem up to date as the one compiled just now is different");
}
}

View File

@@ -6,7 +6,6 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase;
use iTopDesignFormat;
use PHPUnit\Exception;
/**
* Class iTopDesignFormatChecklistTest
* Ticket 3053 - Check XML conversion methods
@@ -31,19 +30,15 @@ class iTopDesignFormatChecklistTest extends ItopTestCase
public function testCurrentVersion_DataModelConversionFunctions()
{
$aErrors = [];
$aDatamodelCurrentVersions = array();
$aDatamodelCurrentVersions = [];
$aDataModelFiles = $this->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))
{
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) === '')
{
if (!array_key_exists($sVersion, $aDatamodelCurrentVersions)) {
if (trim($sVersion) === '') {
$aErrors[] = "cannot retrieve itop_design datamodel version in $sDataModelFile:1";
continue;
}
@@ -57,102 +52,99 @@ class iTopDesignFormatChecklistTest extends ItopTestCase
$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{
$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'));
$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')) {
if (($sCurrentVersion !== '1.0')) {
$sPreviousVersion = $aCurrentVersionInfo['previous'];
$this->CheckCondition(array_key_exists($sPreviousVersion, iTopDesignFormat::$aVersions),
"$sCurrentVersion: Missing $sPreviousVersion config in iTopDesignFormat.");
$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->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)) {
if (($sCurrentVersion !== $sLatestVersion)) {
$sNextVersion = $aCurrentVersionInfo['next'];
$this->CheckCondition(array_key_exists($sNextVersion, iTopDesignFormat::$aVersions),
"$sCurrentVersion: Missing $sNextVersion config in iTopDesignFormat.");
$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->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)
{
} catch (Exception $e) {
$aErrors[] = $e->getMessage();
}
}
if (count($aErrors)!=0)
{
if (count($aErrors) != 0) {
$sMsg = "Issue with conversion functions:\n";
$sMsg .= implode("\n", $aErrors);
$this->fail($sMsg);
}
else
{
} else {
$this->assertTrue(true);
}
}
private function CheckCondition($bCondition, $sMsg)
{
if ($bCondition === false)
{
if ($bCondition === false) {
throw new \Exception($sMsg);
}
}
private function TestDefinedFunction($aCurrentVersionInfo, $sFunctionKey, $sVersion, $bNullFunction=false)
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);
$this->CheckCondition(array_key_exists($sFunctionKey, $aCurrentVersionInfo), "Missing $sFunctionKey in $sVersion config in iTopDesignFormat: ".$sInfo);
//echo $aCurrentVersionInfo[$sFunctionKey].'\n';
if ($bNullFunction === false)
{
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($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 = [];
if (is_dir($sFolder)) {
foreach (glob($sFolder."/*") as $sPath) {
if (is_dir($sPath)) {
/** @noinspection SlowArrayOperationsInLoopInspection */
$aDataModelFiles = array_merge($aDataModelFiles, $this->GetDataModelFiles($sPath));
}
else if (preg_match("/datamodel\..*\.xml/", basename($sPath)))
{
} elseif (preg_match("/datamodel\..*\.xml/", basename($sPath))) {
$aDataModelFiles[] = $sPath;
}
}

View File

@@ -4,7 +4,6 @@ namespace Combodo\iTop\Test\UnitTest\ReleaseChecklist;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
/**
* @since 2.7.2 N°3060 / N°3061 Automatically check the installation.xml consistency
*
@@ -17,16 +16,14 @@ class iTopModuleXmlInstallationChecklistTest extends ItopTestCase
*/
public function testInstallationXmlFormat()
{
$sInstallationXmlPath = APPROOT . 'datamodels/2.x/installation.xml';
$sInstallationXmlPath = APPROOT.'datamodels/2.x/installation.xml';
$this->assertTrue(is_file($sInstallationXmlPath), "$sInstallationXmlPath does not exist");
$doc = new \DOMDocument();
try{
try {
$doc->loadxml(file_get_contents($sInstallationXmlPath));
}
catch(\Exception $e)
{
$this->assertFalse(true, "$sInstallationXmlPath is not a valid XML content: " . $e->getMessage());
} catch (\Exception $e) {
$this->assertFalse(true, "$sInstallationXmlPath is not a valid XML content: ".$e->getMessage());
}
}
@@ -75,32 +72,24 @@ class iTopModuleXmlInstallationChecklistTest extends ItopTestCase
public function GetModulesNotAutoSelected($sFolder)
{
$aExcludedModules = ['authent-external', 'authent-ldap'];
$aModules = array();
if (is_dir($sFolder))
{
foreach (glob($sFolder."/*") as $sPath)
{
if (is_dir($sPath))
{
$aModules = [];
if (is_dir($sFolder)) {
foreach (glob($sFolder."/*") as $sPath) {
if (is_dir($sPath)) {
/** @noinspection SlowArrayOperationsInLoopInspection */
$aModules = array_merge($aModules, $this->GetModulesNotAutoSelected($sPath));
}
else if (preg_match("/module\..*\.php/", basename($sPath)))
{
} elseif (preg_match("/module\..*\.php/", basename($sPath))) {
$sModulePhpContent = file_get_contents($sPath);
if (strpos($sModulePhpContent, "SetupWebPage::AddModule")!==false
&& strpos($sModulePhpContent, "'mandatory' => true")===false)
{
if (strpos($sModulePhpContent, "SetupWebPage::AddModule") !== false
&& strpos($sModulePhpContent, "'mandatory' => true") === false) {
//filter modules autoselected due to below condition
if (strpos($sModulePhpContent, "'mandatory' => false")!==false
&& strpos($sModulePhpContent, "'visible' => false")!==false)
{
if (strpos($sModulePhpContent, "'mandatory' => false") !== false
&& strpos($sModulePhpContent, "'visible' => false") !== false) {
continue;
}
$sModule = basename(dirname($sPath));
if (in_array($sModule, $aExcludedModules))// || $sModule === 'authent-ldap')
{
if (in_array($sModule, $aExcludedModules)) {// || $sModule === 'authent-ldap')
//hardcode this condition to make sure test is OK (CI context) + added a ticket to work/investigate why it is failed for these 2 cases (itop dev context)
continue;
}
@@ -115,21 +104,15 @@ class iTopModuleXmlInstallationChecklistTest extends ItopTestCase
public function GetAllModules($sFolder)
{
$aModules = array();
if (is_dir($sFolder))
{
foreach (glob($sFolder."/*") as $sPath)
{
if (is_dir($sPath))
{
$aModules = [];
if (is_dir($sFolder)) {
foreach (glob($sFolder."/*") as $sPath) {
if (is_dir($sPath)) {
/** @noinspection SlowArrayOperationsInLoopInspection */
$aModules = array_merge($aModules, $this->GetAllModules($sPath));
}
else if (preg_match("/module\..*\.php/", basename($sPath)))
{
} elseif (preg_match("/module\..*\.php/", basename($sPath))) {
$sModulePhpContent = file_get_contents($sPath);
if (strpos($sModulePhpContent, "SetupWebPage::AddModule")!==false)
{
if (strpos($sModulePhpContent, "SetupWebPage::AddModule") !== false) {
$sModule = basename(dirname($sPath));
$aModules[$sModule] = $sModule;
}
@@ -138,4 +121,4 @@ class iTopModuleXmlInstallationChecklistTest extends ItopTestCase
}
return $aModules;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -14,7 +15,6 @@ use MetaModel;
use SetupUtils;
use utils;
/**
* Class ItopCustomDatamodelTestCase
*
@@ -30,7 +30,7 @@ abstract class ItopCustomDatamodelTestCase extends ItopDataTestCase
{
/**
* @var UnitTestRunTimeEnvironment
*/
*/
protected $oEnvironment = null;
/**
@@ -49,15 +49,15 @@ abstract class ItopCustomDatamodelTestCase extends ItopDataTestCase
$this->setRunClassInSeparateProcess(true);
}
/**
/**
* @return string Abs path to the XML delta to use for the tests of that class
*/
abstract public function GetDatamodelDeltaAbsPath(): string;
protected function setUp(): void
{
static::LoadRequiredItopFiles();
$this->oEnvironment = new UnitTestRunTimeEnvironment('production', $this->GetTestEnvironment());
static::LoadRequiredItopFiles();
$this->oEnvironment = new UnitTestRunTimeEnvironment('production', $this->GetTestEnvironment());
parent::setUp();
}
@@ -107,8 +107,8 @@ abstract class ItopCustomDatamodelTestCase extends ItopDataTestCase
if (false === file_exists($this->GetTestEnvironmentFolderAbsPath())) {
return false;
}
return $this->oEnvironment->IsUpToDate();
}
return $this->oEnvironment->IsUpToDate();
}
/**
* @inheritDoc
@@ -124,10 +124,10 @@ abstract class ItopCustomDatamodelTestCase extends ItopDataTestCase
// This requires XML deltas to be compatible, but it is a known and accepted trade-off. See PR #457
if (false === $this->IsEnvironmentReady()) {
$this->debug("Preparing custom environment '$sTestEnv' with the following datamodel files:");
foreach ($this->oEnvironment->GetCustomDatamodelFiles() as $sCustomDatamodelFile) {
$this->debug(" - $sCustomDatamodelFile");
}
$this->debug("Preparing custom environment '$sTestEnv' with the following datamodel files:");
foreach ($this->oEnvironment->GetCustomDatamodelFiles() as $sCustomDatamodelFile) {
$this->debug(" - $sCustomDatamodelFile");
}
//----------------------------------------------------
// Clear any previous "$sTestEnv" environment
@@ -169,7 +169,7 @@ abstract class ItopCustomDatamodelTestCase extends ItopDataTestCase
}
CMDBSource::CreateDB($oTestConfig->Get('db_name'));
MetaModel::Startup($sConfFile, false /* $bModelOnly */, true /* $bAllowCache */, false /* $bTraceSourceFiles */, $sTestEnv);
// N°7446 For some reason we need to create the DB schema before starting the MM, then only we can create the tables.
// N°7446 For some reason we need to create the DB schema before starting the MM, then only we can create the tables.
MetaModel::DBCreate();
$this->debug("Custom environment '$sTestEnv' is ready!");

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -14,6 +15,7 @@ use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use ReflectionMethod;
use SetupUtils;
use Symfony\Component\HttpKernel\KernelInterface;
use const DEBUG_BACKTRACE_IGNORE_ARGS;
/**
@@ -97,7 +99,6 @@ abstract class ItopTestCase extends KernelTestCase
}
}
/**
* @param array $args
* @param string $sExportFileName relative to log folder
@@ -141,15 +142,16 @@ abstract class ItopTestCase extends KernelTestCase
}
$var_export = var_export($paramValues, true);
file_put_contents(APPROOT.'/log/' .$sExportFileName, $var_export);
file_put_contents(APPROOT.'/log/'.$sExportFileName, $var_export);
return $var_export;
}
protected function setUp(): void {
protected function setUp(): void
{
parent::setUp();
// Hack - Required the first time the Portal kernel is booted on a newly installed iTop
$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'] = __DIR__ . '/../../../../../env-production/itop-portal-base/portal/public/';
$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'] = __DIR__.'/../../../../../env-production/itop-portal-base/portal/public/';
$this->LoadRequiredItopFiles();
$this->LoadRequiredTestFiles();
@@ -188,22 +190,22 @@ abstract class ItopTestCase extends KernelTestCase
$sAppRootPath = static::GetFirstDirUpContainingFile(__DIR__, 'approot.inc.php');
return $sAppRootPath . '/';
return $sAppRootPath.'/';
}
private static function GetFirstDirUpContainingFile(string $sSearchPath, string $sFileToFindGlobPattern): ?string
{
for ($iDepth = 0; $iDepth < 8; $iDepth++) {
$aGlobFiles = glob($sSearchPath . '/' . $sFileToFindGlobPattern);
$aGlobFiles = glob($sSearchPath.'/'.$sFileToFindGlobPattern);
if (is_array($aGlobFiles) && (count($aGlobFiles) > 0)) {
return $sSearchPath . '/';
return $sSearchPath.'/';
}
$iOffsetSep = strrpos($sSearchPath, '/');
if ($iOffsetSep === false) {
$iOffsetSep = strrpos($sSearchPath, '\\');
if ($iOffsetSep === false) {
// Do not throw an exception here as PHPUnit will not show it clearly when determing the list of test to perform
return 'Could not find the approot file in ' . $sSearchPath;
return 'Could not find the approot file in '.$sSearchPath;
}
}
$sSearchPath = substr($sSearchPath, 0, $iOffsetSep);
@@ -211,7 +213,6 @@ abstract class ItopTestCase extends KernelTestCase
return null;
}
/**
* Overload this method to require necessary files through {@see \Combodo\iTop\Test\UnitTest\ItopTestCase::RequireOnceItopFile()}
*
@@ -222,7 +223,7 @@ abstract class ItopTestCase extends KernelTestCase
{
// At least make sure that the autoloader will be loaded, and that the APPROOT constant is defined
require_once __DIR__.'/../../../../approot.inc.php';
}
}
/**
* Overload this method to require necessary files through {@see \Combodo\iTop\Test\UnitTest\ItopTestCase::RequireOnceUnitTestFile()}
@@ -246,7 +247,7 @@ abstract class ItopTestCase extends KernelTestCase
*/
protected function RequireOnceItopFile(string $sFileRelPath): void
{
require_once $this->GetAppRoot() . $sFileRelPath;
require_once $this->GetAppRoot().$sFileRelPath;
}
/**
@@ -263,7 +264,7 @@ abstract class ItopTestCase extends KernelTestCase
$aStack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$sCallerDirAbsPath = dirname($aStack[0]['file']);
require_once $sCallerDirAbsPath . DIRECTORY_SEPARATOR . $sFileRelPath;
require_once $sCallerDirAbsPath.DIRECTORY_SEPARATOR.$sFileRelPath;
}
protected function debug($sMsg)
@@ -272,11 +273,11 @@ abstract class ItopTestCase extends KernelTestCase
if (is_string($sMsg)) {
echo "$sMsg\n";
} else {
/** @noinspection ForgottenDebugOutputInspection */
print_r($sMsg);
}
}
}
/** @noinspection ForgottenDebugOutputInspection */
print_r($sMsg);
}
}
}
public function GetMicroTime()
{
@@ -287,8 +288,7 @@ abstract class ItopTestCase extends KernelTestCase
public function WriteToCsvHeader($sFilename, $aHeader)
{
$sResultFile = APPROOT.'log/'.$sFilename;
if (is_file($sResultFile))
{
if (is_file($sResultFile)) {
@unlink($sResultFile);
}
SetupUtils::builddir(dirname($sResultFile));
@@ -379,7 +379,9 @@ abstract class ItopTestCase extends KernelTestCase
{
$class = new \ReflectionClass($sClass);
foreach ($class->getProperties() as $property) {
if (!$property->isStatic()) continue;
if (!$property->isStatic()) {
continue;
}
$property->setAccessible(true);
static::$aBackupStaticProperties[$sClass][$property->getName()] = $property->getValue();
}
@@ -397,7 +399,9 @@ abstract class ItopTestCase extends KernelTestCase
{
$class = new \ReflectionClass($sClass);
foreach ($class->getProperties() as $property) {
if (!$property->isStatic()) continue;
if (!$property->isStatic()) {
continue;
}
$property->setAccessible(true);
$property->setValue(null, static::$aBackupStaticProperties[$sClass][$property->getName()]);
}
@@ -415,7 +419,6 @@ abstract class ItopTestCase extends KernelTestCase
return $oProperty;
}
/**
* @param object $oObject
* @param string $sProperty
@@ -455,38 +458,38 @@ abstract class ItopTestCase extends KernelTestCase
}
}
public static function CreateTmpdir() {
$sTmpDir=tempnam(sys_get_temp_dir(),'');
if (file_exists($sTmpDir))
{
public static function CreateTmpdir()
{
$sTmpDir = tempnam(sys_get_temp_dir(), '');
if (file_exists($sTmpDir)) {
unlink($sTmpDir);
}
mkdir($sTmpDir);
if (is_dir($sTmpDir))
{
if (is_dir($sTmpDir)) {
return $sTmpDir;
}
return sys_get_temp_dir();
}
public static function RecurseMkdir($sDir){
if (strpos($sDir, DIRECTORY_SEPARATOR) === 0){
public static function RecurseMkdir($sDir)
{
if (strpos($sDir, DIRECTORY_SEPARATOR) === 0) {
$sPath = DIRECTORY_SEPARATOR;
} else {
$sPath = "";
}
foreach (explode(DIRECTORY_SEPARATOR, $sDir) as $sSubDir){
foreach (explode(DIRECTORY_SEPARATOR, $sDir) as $sSubDir) {
if (($sSubDir === '..')) {
break;
}
if (( trim($sSubDir) === '' ) || ( $sSubDir === '.' )) {
if ((trim($sSubDir) === '') || ($sSubDir === '.')) {
continue;
}
$sPath .= $sSubDir . DIRECTORY_SEPARATOR;
$sPath .= $sSubDir.DIRECTORY_SEPARATOR;
if (!is_dir($sPath)) {
var_dump($sPath);
@mkdir($sPath);
@@ -495,16 +498,16 @@ abstract class ItopTestCase extends KernelTestCase
}
public static function RecurseCopy($src,$dst) {
public static function RecurseCopy($src, $dst)
{
$dir = opendir($src);
@mkdir($dst);
while(false !== ( $file = readdir($dir)) ) {
if (( $file != '.' ) && ( $file != '..' )) {
if ( is_dir($src . '/' . $file) ) {
static::RecurseCopy($src . DIRECTORY_SEPARATOR . $file,$dst . DIRECTORY_SEPARATOR . $file);
}
else {
copy($src . DIRECTORY_SEPARATOR . $file,$dst . DIRECTORY_SEPARATOR . $file);
while (false !== ($file = readdir($dir))) {
if (($file != '.') && ($file != '..')) {
if (is_dir($src.'/'.$file)) {
static::RecurseCopy($src.DIRECTORY_SEPARATOR.$file, $dst.DIRECTORY_SEPARATOR.$file);
} else {
copy($src.DIRECTORY_SEPARATOR.$file, $dst.DIRECTORY_SEPARATOR.$file);
}
}
}
@@ -553,7 +556,7 @@ abstract class ItopTestCase extends KernelTestCase
/**
* @since 3.2.1
*/
static protected function AssertDateEqualsNow($sActualDate, $sMessage = ''): void
protected static function AssertDateEqualsNow($sActualDate, $sMessage = ''): void
{
$oActualDate = \DateTime::createFromFormat(\AttributeDate::GetInternalFormat(), $sActualDate);
$oNow = new \DateTime();
@@ -563,7 +566,7 @@ abstract class ItopTestCase extends KernelTestCase
/**
* @since 3.2.1
*/
static protected function AssertDateTimeEqualsNow($sActualDate, $sMessage = ''): void
protected static function AssertDateTimeEqualsNow($sActualDate, $sMessage = ''): void
{
$oActualDateTime = \DateTime::createFromFormat(\AttributeDateTime::GetInternalFormat(), $sActualDate);
$oNow = new \DateTime();
@@ -576,17 +579,17 @@ abstract class ItopTestCase extends KernelTestCase
*
* @see static::bootKernel(), static::getContainer()
* @see \Combodo\iTop\Kernel, \Combodo\iTop\Portal\Kernel
*
*
* @param string $sKernelClass
*
* @since 3.2.1
*/
static protected function SetKernelClass(string $sKernelClass): void
protected static function SetKernelClass(string $sKernelClass): void
{
$_SERVER['KERNEL_CLASS'] = $sKernelClass;
}
static protected function bootKernel(array $options = []): KernelInterface
protected static function bootKernel(array $options = []): KernelInterface
{
if (!array_key_exists('KERNEL_CLASS', $_SERVER)) {
throw new \LogicException('static::SetKernelClass() must be called before booting the kernel.');
@@ -599,31 +602,33 @@ abstract class ItopTestCase extends KernelTestCase
*
* @since 3.2.1
*/
static protected function ReadTail($sFilename, $iLines = 1)
protected static function ReadTail($sFilename, $iLines = 1)
{
$handle = fopen($sFilename, "r");
$iLineCounter = $iLines;
$iPos = -2;
$bBeginning = false;
$aLines = array();
$aLines = [];
while ($iLineCounter > 0) {
$sChar = " ";
while ($sChar != "\n") {
if(fseek($handle, $iPos, SEEK_END) == -1) {
if (fseek($handle, $iPos, SEEK_END) == -1) {
$bBeginning = true;
break;
}
$sChar = fgetc($handle);
$iPos --;
$iPos--;
}
$iLineCounter --;
$iLineCounter--;
if ($bBeginning) {
rewind($handle);
}
$aLines[$iLines - $iLineCounter - 1] = fgets($handle);
if ($bBeginning) break;
if ($bBeginning) {
break;
}
}
fclose ($handle);
fclose($handle);
return array_reverse($aLines);
}
}

View File

@@ -16,7 +16,6 @@ use RunTimeEnvironment;
use SetupUtils;
use utils;
/**
* Class UnitTestRunTimeEnvironment
*
@@ -32,18 +31,18 @@ class UnitTestRunTimeEnvironment extends RunTimeEnvironment
*/
protected $aCustomDatamodelFiles = null;
/**
* @var string
*/
protected $sSourceEnv;
/**
* @var string
*/
protected $sSourceEnv;
public function __construct($sSourceEnv, $sTargetEnv)
{
parent::__construct($sTargetEnv);
$this->sSourceEnv = $sSourceEnv;
}
public function __construct($sSourceEnv, $sTargetEnv)
{
parent::__construct($sTargetEnv);
$this->sSourceEnv = $sSourceEnv;
}
public function GetEnvironment(): string
public function GetEnvironment(): string
{
return $this->sFinalEnv;
}
@@ -60,19 +59,19 @@ class UnitTestRunTimeEnvironment extends RunTimeEnvironment
parent::CompileFrom($sSourceEnv, $bUseSymLinks);
}
public function IsUpToDate()
{
clearstatcache();
$fLastCompilationTime = filemtime(APPROOT.'env-'.$this->sFinalEnv);
$aModifiedFiles = [];
$this->FindFilesModifiedAfter($fLastCompilationTime, APPROOT.'datamodels/2.x', $aModifiedFiles);
$this->FindFilesModifiedAfter($fLastCompilationTime, APPROOT.'extensions', $aModifiedFiles);
$this->FindFilesModifiedAfter($fLastCompilationTime, APPROOT.'data/production-modules', $aModifiedFiles);
foreach ($this->GetCustomDatamodelFiles() as $sCustomDatamodelFile) {
if (filemtime($sCustomDatamodelFile) > $fLastCompilationTime) {
$aModifiedFiles[] = $sCustomDatamodelFile;
}
}
public function IsUpToDate()
{
clearstatcache();
$fLastCompilationTime = filemtime(APPROOT.'env-'.$this->sFinalEnv);
$aModifiedFiles = [];
$this->FindFilesModifiedAfter($fLastCompilationTime, APPROOT.'datamodels/2.x', $aModifiedFiles);
$this->FindFilesModifiedAfter($fLastCompilationTime, APPROOT.'extensions', $aModifiedFiles);
$this->FindFilesModifiedAfter($fLastCompilationTime, APPROOT.'data/production-modules', $aModifiedFiles);
foreach ($this->GetCustomDatamodelFiles() as $sCustomDatamodelFile) {
if (filemtime($sCustomDatamodelFile) > $fLastCompilationTime) {
$aModifiedFiles[] = $sCustomDatamodelFile;
}
}
// Keep only xml files
$aFilesToCompile = [];
foreach ($aModifiedFiles as $sModifiedFile) {
@@ -80,17 +79,17 @@ class UnitTestRunTimeEnvironment extends RunTimeEnvironment
$aFilesToCompile[] = $sModifiedFile;
}
}
$aModifiedFiles = $aFilesToCompile;
if (count($aModifiedFiles) > 0) {
echo "The following files have been modified after the last compilation:\n";
foreach ($aModifiedFiles as $sFile) {
echo " - $sFile\n";
}
}
return (count($aModifiedFiles) === 0);
$aModifiedFiles = $aFilesToCompile;
if (count($aModifiedFiles) > 0) {
echo "The following files have been modified after the last compilation:\n";
foreach ($aModifiedFiles as $sFile) {
echo " - $sFile\n";
}
}
return (count($aModifiedFiles) === 0);
}
/**
/**
* @inheritDoc
*/
protected function GetMFModulesToCompile($sSourceEnv, $sSourceDir)
@@ -99,8 +98,8 @@ class UnitTestRunTimeEnvironment extends RunTimeEnvironment
foreach ($this->GetCustomDatamodelFiles() as $sDeltaFile) {
$sDeltaId = preg_replace('/[^\d\w]/', '', $sDeltaFile);
$sDeltaName = basename($sDeltaFile);
$sDeltaDir = dirname($sDeltaFile);
$sDeltaName = basename($sDeltaFile);
$sDeltaDir = dirname($sDeltaFile);
$oDelta = new MFCoreModule($sDeltaName, "$sDeltaDir/$sDeltaName", $sDeltaFile);
$aRet[$sDeltaId] = $oDelta;
}
@@ -119,16 +118,16 @@ class UnitTestRunTimeEnvironment extends RunTimeEnvironment
// APPROOT, APPROOT/extensions/*, APPROOT/data/production-modules/*, APPROOT/data/production-modules/*/*
$aTestDirs = [];
foreach(['', 'extensions/*/', 'data/production-modules/*/', 'data/production-modules/*/*/'] as $sRoot) {
foreach (['', 'extensions/*/', 'data/production-modules/*/', 'data/production-modules/*/*/'] as $sRoot) {
$aTestDirs = array_merge($aTestDirs, glob(APPROOT.$sRoot.'tests', GLOB_ONLYDIR));
}
$aLoadedTestClasses = [];
foreach($aTestDirs as $sTestDir) {
foreach ($aTestDirs as $sTestDir) {
// Iterate on all PHP files in subdirectories
// Note: grep is not available on Windows, so we will use the PHP Reflection API
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($sTestDir)) as $oFile) {
if ($oFile->isDir()){
if ($oFile->isDir()) {
continue;
}
if (! utils::EndsWith($oFile->getFilename(), 'Test.php')) {
@@ -154,16 +153,16 @@ class UnitTestRunTimeEnvironment extends RunTimeEnvironment
if (in_array($sClass, $aLoadedTestClasses)) {
continue;
}
$aLoadedTestClasses[]=$sClass;
require_once $sFile;
$aLoadedTestClasses[] = $sClass;
require_once $sFile;
$oReflectionClass = new ReflectionClass($sClass);
if ($oReflectionClass->isAbstract()) {
continue;
}
// Check if the class extends ItopCustomDatamodelTestCase
if (!$oReflectionClass->isSubclassOf(ItopCustomDatamodelTestCase::class)) {
continue;
}
// Check if the class extends ItopCustomDatamodelTestCase
if (!$oReflectionClass->isSubclassOf(ItopCustomDatamodelTestCase::class)) {
continue;
}
/** @var \Combodo\iTop\Test\UnitTest\ItopCustomDatamodelTestCase $oTestClassInstance */
$oTestClassInstance = new $sClass();
if ($oTestClassInstance->GetTestEnvironment() !== $this->sFinalEnv) {
@@ -182,18 +181,18 @@ class UnitTestRunTimeEnvironment extends RunTimeEnvironment
return $this->aCustomDatamodelFiles;
}
private function FindFilesModifiedAfter(float $fReferenceTimestamp, string $sPathToScan, array &$aModifiedFiles)
{
if (!is_dir($sPathToScan)) {
return;
}
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($sPathToScan)) as $oFile) {
if ($oFile->isDir()) {
continue;
}
if (filemtime($oFile->getPathname()) > $fReferenceTimestamp) {
$aModifiedFiles[] = $oFile->getPathname();
}
}
}
}
private function FindFilesModifiedAfter(float $fReferenceTimestamp, string $sPathToScan, array &$aModifiedFiles)
{
if (!is_dir($sPathToScan)) {
return;
}
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($sPathToScan)) as $oFile) {
if ($oFile->isDir()) {
continue;
}
if (filemtime($oFile->getPathname()) > $fReferenceTimestamp) {
$aModifiedFiles[] = $oFile->getPathname();
}
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Usage: php run_class_by_class.php
*
@@ -43,8 +44,7 @@ function RunTests($sFilterRegExp, $sUnitaryTestsDir = '', $bPassthru = false)
///echo "executing <<<$sCommand>>>\n";
if ($bPassthru) {
passthru($sCommand, $iResultCode);
}
else {
} else {
exec($sCommand, $aTrashedOutput, $iResultCode);
}
$bTestSuccess = ($iResultCode == 0); // or 1 in case of a failing test
@@ -61,4 +61,4 @@ foreach ($aTestClasses as $sTestClass) {
$bSuccess = RunTests($sTestClass);
$sDuration = round(microtime(true) - $fStarted, 3);
echo "$sTestClass: ".($bSuccess ? 'Ok' : "FAILURE")." [$sDuration s]\n";
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -31,20 +32,20 @@ class DashboardLayoutTest extends ItopTestCase
*/
public function GetDashletCoordinatesProvider()
{
return array(
'OneColLayout-Cell0' => array('DashboardLayoutOneCol', 0, array(0, 0)),
'OneColLayout-Cell1' => array('DashboardLayoutOneCol', 1, array(0, 1)),
'TwoColsLayout-Cell0' => array('DashboardLayoutTwoCols', 0, array(0, 0)),
'TwoColsLayout-Cell1' => array('DashboardLayoutTwoCols', 1, array(1, 0)),
'TwoColsLayout-Cell2' => array('DashboardLayoutTwoCols', 2, array(0, 1)),
'TwoColsLayout-Cell3' => array('DashboardLayoutTwoCols', 3, array(1, 1)),
'ThreeColsLayout-Cell0' => array('DashboardLayoutThreeCols', 0, array(0, 0)),
'ThreeColsLayout-Cell1' => array('DashboardLayoutThreeCols', 1, array(1, 0)),
'ThreeColsLayout-Cell2' => array('DashboardLayoutThreeCols', 2, array(2, 0)),
'ThreeColsLayout-Cell3' => array('DashboardLayoutThreeCols', 3, array(0, 1)),
'ThreeColsLayout-Cell4' => array('DashboardLayoutThreeCols', 4, array(1, 1)),
'ThreeColsLayout-Cell5' => array('DashboardLayoutThreeCols', 5, array(2, 1)),
);
return [
'OneColLayout-Cell0' => ['DashboardLayoutOneCol', 0, [0, 0]],
'OneColLayout-Cell1' => ['DashboardLayoutOneCol', 1, [0, 1]],
'TwoColsLayout-Cell0' => ['DashboardLayoutTwoCols', 0, [0, 0]],
'TwoColsLayout-Cell1' => ['DashboardLayoutTwoCols', 1, [1, 0]],
'TwoColsLayout-Cell2' => ['DashboardLayoutTwoCols', 2, [0, 1]],
'TwoColsLayout-Cell3' => ['DashboardLayoutTwoCols', 3, [1, 1]],
'ThreeColsLayout-Cell0' => ['DashboardLayoutThreeCols', 0, [0, 0]],
'ThreeColsLayout-Cell1' => ['DashboardLayoutThreeCols', 1, [1, 0]],
'ThreeColsLayout-Cell2' => ['DashboardLayoutThreeCols', 2, [2, 0]],
'ThreeColsLayout-Cell3' => ['DashboardLayoutThreeCols', 3, [0, 1]],
'ThreeColsLayout-Cell4' => ['DashboardLayoutThreeCols', 4, [1, 1]],
'ThreeColsLayout-Cell5' => ['DashboardLayoutThreeCols', 5, [2, 1]],
];
}
/**
@@ -59,6 +60,6 @@ class DashboardLayoutTest extends ItopTestCase
$oDashboardLayout = new $sDashboardLayoutClass();
$aDashletCoordinates = $oDashboardLayout->GetDashletCoordinates($iCellIdx);
$this->assertEquals($aExpectedCoordinates,$aDashletCoordinates);
$this->assertEquals($aExpectedCoordinates, $aDashletCoordinates);
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2018 Dennis Lassiter
*

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -15,10 +16,10 @@ use UserRequest;
class DisplayBlockTest extends ItopCustomDatamodelTestCase
{
const CREATE_TEST_ORG = true;
public const CREATE_TEST_ORG = true;
public function GetDatamodelDeltaAbsPath(): string
{
return __DIR__ . '/Delta/add-enum-value-with-quote.xml';
return __DIR__.'/Delta/add-enum-value-with-quote.xml';
}
public function renderChartAjaxProvider(): array
@@ -94,4 +95,4 @@ class DisplayBlockTest extends ItopCustomDatamodelTestCase
$this->assertFalse(in_array($sNonExpected, $aJSNames));
$this->assertTrue(in_array($sExpected, $aJSNames));
}
}
}

View File

@@ -1,15 +1,18 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Application;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use MetaModel;
class LoginTest extends ItopDataTestCase {
class LoginTest extends ItopDataTestCase
{
protected $sConfigTmpBackupFile;
protected $sConfigPath;
protected $sLoginMode;
protected function setUp(): void {
protected function setUp(): void
{
parent::setUp();
clearstatcache();
@@ -29,8 +32,9 @@ class LoginTest extends ItopDataTestCase {
@chmod($this->sConfigPath, 0444);
}
protected function tearDown(): void {
if (! is_null($this->sConfigTmpBackupFile) && is_file($this->sConfigTmpBackupFile)){
protected function tearDown(): void
{
if (! is_null($this->sConfigTmpBackupFile) && is_file($this->sConfigTmpBackupFile)) {
//put config back
@chmod($this->sConfigPath, 0770);
file_put_contents($this->sConfigPath, file_get_contents($this->sConfigTmpBackupFile));
@@ -40,18 +44,19 @@ class LoginTest extends ItopDataTestCase {
parent::tearDown();
}
protected function CallItopUrlByCurl($sUri, ?array $aPostFields=[]){
protected function CallItopUrlByCurl($sUri, ?array $aPostFields = [])
{
$ch = curl_init();
$sUrl = MetaModel::GetConfig()->Get('app_root_url') . "/$sUri";
$sUrl = MetaModel::GetConfig()->Get('app_root_url')."/$sUri";
curl_setopt($ch, CURLOPT_URL, $sUrl);
if (0 !== sizeof($aPostFields)){
if (0 !== sizeof($aPostFields)) {
curl_setopt($ch, CURLOPT_POST, 1);// set post data to true
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPostFields);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$sOutput = curl_exec($ch);
curl_close ($ch);
curl_close($ch);
return $sOutput;
}

View File

@@ -5,10 +5,12 @@ namespace Combodo\iTop\Test\UnitTest\Application;
use Combodo\iTop\Application\WebPage\WebPage;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
class MenuNodeTest extends ItopDataTestCase {
class MenuNodeTest extends ItopDataTestCase
{
private \UserRequest $oUR;
protected function setUp(): void {
protected function setUp(): void
{
parent::setUp();
clearstatcache();
@@ -20,7 +22,6 @@ class MenuNodeTest extends ItopDataTestCase {
$this->oUR = $this->CreateUserRequest(666, $aUserRequestCustomParams);
}
public function RenderOQLSearchProvider()
{
$aUseCases = [];
@@ -66,16 +67,16 @@ OQL;
SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (DATE_FORMAT(`UserRequest`.`ttr_escalation_deadline`, '%Y%v') != DATE_FORMAT(NOW(), '%Y%v'))
OQL;
try{
try {
$sContent = $this->CallRenderOQLSearch(true, true, true, $sOql);
$this->assertTrue(false !== strpos($sContent, $this->oUR->Get('title')), $sContent);
} catch(\Exception $e){
} catch (\Exception $e) {
echo($e->getMessage());
$this->fail('Without N°7750 fix Exception raised => TypeError : date(): Argument #2 ($timestamp) must be of type ?int, string given');
}
}
public function CallRenderOQLSearch(bool $bSearchPane, bool $bSearchOpen, bool $bAutoreload, string $sOql) : string
public function CallRenderOQLSearch(bool $bSearchPane, bool $bSearchOpen, bool $bAutoreload, string $sOql): string
{
$sTitle = 'title';
$oPage = new WebPage($sTitle);
@@ -94,4 +95,3 @@ OQL;
return $oResponse->getContent();
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -11,7 +12,6 @@ use utils;
class SCSSCompilationTest extends ItopTestCase
{
/**
* @dataProvider CompileDefaultThemesProvider
* @doesNotPerformAssertions

View File

@@ -85,7 +85,6 @@ class SessionTest extends ItopTestCase
$this->assertEquals('OK', Session::Get('test'));
}
public function testIsSet()
{
$this->assertFalse(Session::IsSet('test'));

View File

@@ -11,19 +11,18 @@ use ThemeHandler;
*/
class ThemeHandlerTest extends ItopTestCase
{
const PATTERN = '|\\\/var[^"]+testimages|';
public const PATTERN = '|\\\/var[^"]+testimages|';
private $oCompileCSSServiceMock;
private $sCompiledThemesDirAbsPath;
private $sCssAbsPath;
private $sDmCssAbsPath;
private $sJsonThemeParamFile;
static private $sTmpDir = null;
static private $aDirsToCleanup = [];
static private $sAbsoluteImagePath;
private static $sTmpDir = null;
private static $aDirsToCleanup = [];
private static $sAbsoluteImagePath;
static function setUpBeforeClass(): void
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
@@ -39,10 +38,9 @@ class ThemeHandlerTest extends ItopTestCase
static::$aDirsToCleanup[] = dirname(static::$sAbsoluteImagePath);
}
static function tearDownAfterClass(): void
public static function tearDownAfterClass(): void
{
foreach (static::$aDirsToCleanup as $sDir)
{
foreach (static::$aDirsToCleanup as $sDir) {
static::RecurseRmdir($sDir);
}
@@ -73,35 +71,36 @@ class ThemeHandlerTest extends ItopTestCase
parent::tearDown();
}
function KeepSignatureDiff($sSignature1, $sSignature2) : string {
public function KeepSignatureDiff($sSignature1, $sSignature2): string
{
$aSignature1 = json_decode($sSignature1, true);
$aSignature2 = json_decode($sSignature2, true);
$aDiffOuput = [];
foreach ($aSignature1 as $sKey => $oVal1){
if (is_array($oVal1) && ! empty($oVal1)){
foreach ($aSignature1 as $sKey => $oVal1) {
if (is_array($oVal1) && ! empty($oVal1)) {
$aCurrentDiffVal = [];
$oVal2 = $aSignature2[$sKey];
if (0 != sizeof($oVal1)){
foreach ($oVal1 as $sKey1 => $sVal1){
if (! array_key_exists($sKey1, $oVal2)){
if (0 != sizeof($oVal1)) {
foreach ($oVal1 as $sKey1 => $sVal1) {
if (! array_key_exists($sKey1, $oVal2)) {
$aCurrentDiffVal[$sKey1] = "Missing";
} else if ($sVal1 !== $oVal2[$sKey1]) {
$aCurrentDiffVal[$sKey1] = "expected:$sVal1 | actual:" . $oVal2[$sKey1];
} elseif ($sVal1 !== $oVal2[$sKey1]) {
$aCurrentDiffVal[$sKey1] = "expected:$sVal1 | actual:".$oVal2[$sKey1];
}
}
}
if (! empty($oVal2)){
foreach ($oVal2 as $sKey2 => $sVal2){
if (! array_key_exists($sKey2, $oVal1)){
if (! empty($oVal2)) {
foreach ($oVal2 as $sKey2 => $sVal2) {
if (! array_key_exists($sKey2, $oVal1)) {
$aCurrentDiffVal[$sKey1] = "Missing";
}
}
}
if (! empty($aCurrentDiffVal)){
if (! empty($aCurrentDiffVal)) {
$aDiffOuput[$sKey] = $aCurrentDiffVal;
}
} else if ($oVal1 !== $aSignature2[$sKey]){
} elseif ($oVal1 !== $aSignature2[$sKey]) {
$aDiffOuput[$sKey] = "expected:$oVal1 | actual:$aSignature2[$sKey]";
}
}
@@ -111,14 +110,12 @@ class ThemeHandlerTest extends ItopTestCase
public static function RecurseMkdir($dir)
{
if (is_dir($dir))
{
if (is_dir($dir)) {
return true;
}
$sParentDir = dirname($dir);
if (!static::RecurseMkdir($sParentDir))
{
if (!static::RecurseMkdir($sParentDir)) {
return false;
}
@@ -128,28 +125,28 @@ class ThemeHandlerTest extends ItopTestCase
public function testGetSignatureWithFileWithoutSignature()
{
$sTmpFile = tempnam(sys_get_temp_dir(), "sig");
file_put_contents($sTmpFile,"ffff");
$this->assertEquals("", ThemeHandler::GetSignature($sTmpFile));
file_put_contents($sTmpFile, "ffff");
$this->assertEquals("", ThemeHandler::GetSignature($sTmpFile));
}
public function testGetSignature()
{
$sSig = ThemeHandler::GetSignature(APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main.css');
$sExpectedSig=<<<JSON
$sExpectedSig = <<<JSON
{"variables":"37c31105548fce44fecca5cb34e455c9","stylesheets":{"jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"52d8a7c5530ceb3a4d777364fa4e1eea"},"variable_imports":{"css-variables":"3c3f5adf98b9dbf893658314436c4b93"},"images":{"css\/ui-lightness\/images\/ui-icons_222222_256x240.png":"3a3c5468f484f07ac4a320d9e22acb8c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_20_666666_40x40.png":"4429d568c67d8dfeb9040273ea0fb8c4","css\/ui-lightness\/images\/ui-icons_E87C1E_256x240.png":"7003dd36cb2aa032c8ec871ce4d4e03d","css\/ui-lightness\/images\/ui-icons_1c94c4_256x240.png":"dbd693dc8e0ef04e90a2f7ac7b390086","css\/ui-lightness\/images\/ui-icons_F26522_256x240.png":"16278ec0c07270be571f4c2e97fcc10c","css\/ui-lightness\/images\/ui-bg_diagonals-thick_18_b81900_40x40.png":"e460a66d4b3e093fc651e62a236267cb","css\/ui-lightness\/images\/ui-icons_ffffff_256x240.png":"41612b0f4a034424f8321c9f824a94da","css\/ui-lightness\/images\/ui-icons_ffd27a_256x240.png":"dda1b6f694b0d196aefc66a1d6d758f6","images\/actions_right.png":"31c8906bd25d27b83a0a2466bf903462","images\/ac-background.gif":"76135f3697b41a15aed787cfd77776c7","images\/green-square.gif":"16ea9a497d72f5e66e4e8ea9ae08024e","images\/tv-item.gif":"719fe2d4566108e73162fb8868d3778c","images\/tv-collapsable.gif":"63a3351ea0d580797c9b8c386aa4f48b","images\/tv-expandable.gif":"a2d1af4128e4a798a7f3390b12a28574","images\/tv-item-last.gif":"2ae7e1d9972ce71e5caa65a086bc5b7e","images\/tv-collapsable-last.gif":"71acaa9d7c2616e9e8b7131a75ca65da","images\/tv-expandable-last.gif":"9d51036b3a8102742709da66789fd0f7","images\/red-header.gif":"c73b8765f0c8c3c183cb6a0c2bb0ec69","images\/green-header.gif":"0e22a09bb8051b2a274b3427ede62e82","images\/orange-header.gif":"ce1f93f0af64431771b4cbd6c99c567b","images\/calendar.png":"ab56e59af3c96ca661821257d376465e","images\/truncated.png":"c6f91108afe8159d417b4dc556cd3b2a","images\/plus.gif":"f00e1e6e1161f48608bb2bbc79b9948c","images\/minus.gif":"6d77c0c0c2f86b6995d1cdf78274eaab","images\/full-screen.png":"b541fadd3f1563856a4b44aeebd9d563","images\/indicator.gif":"03ce3dcc84af110e9da8699a841e5200","images\/delete.png":"93c047549c31a270a037840277cf59d3","images\/info-mini.png":"445c090ed777c5e6a08ac390fa896193","images\/ok.png":"f6973773335fd83d8d2875f9a3c925af","images\/error.png":"1af8a1041016f67669c5fd22dc88c82e","images\/eye-open-555.png":"9940f4e5b1248042c238e1924359fd5e","images\/eye-closed-555.png":"6ad3b0bae791bf61addc9d8ca80a642d","images\/eye-open-fff.png":"b7db2402d4d5c72314c25790a66150d4","images\/eye-closed-fff.png":"f9be7454dbb47b0e0bca3aa370ae7db5"},"utility_imports":[]}
JSON;
$this->assertEquals($sExpectedSig, $sSig);
$this->assertEquals($sExpectedSig, $sSig);
}
public function testGetVarSignature()
{
$sSignature=<<<JSON
$sSignature = <<<JSON
{"variables":"37c31105548fce44fecca5cb34e455c9","stylesheets":{"css-variables":"934888ebb4991d4c76555be6b6d1d5cc","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"52d8a7c5530ceb3a4d777364fa4e1eea"},"variable_imports":[],"utility_imports":[]}
JSON;
$var_sig = ThemeHandler::GetVarSignature($sSignature);
$this->assertEquals("37c31105548fce44fecca5cb34e455c9",$var_sig);
$this->assertEquals("37c31105548fce44fecca5cb34e455c9", $var_sig);
}
/**
@@ -158,19 +155,17 @@ JSON;
* @throws \CoreException
* @dataProvider CompileThemesProviderWithoutCss
*/
public function testCompileThemeWithoutCssFile_FocusOnParamAttribute($readFromParamAttributeFromJson=false)
public function testCompileThemeWithoutCssFile_FocusOnParamAttribute($readFromParamAttributeFromJson = false)
{
static::InitCSSDirectory();
$sExpectJsonFilePath = APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/theme-parameters.json';
$sExpectedThemeParamJson = file_get_contents($sExpectJsonFilePath);
$aThemeParameters = json_decode($sExpectedThemeParamJson, true);
if (is_file($this->sJsonThemeParamFile))
{
if (is_file($this->sJsonThemeParamFile)) {
unlink($this->sJsonThemeParamFile);
}
if (is_file($this->sCssAbsPath))
{
if (is_file($this->sCssAbsPath)) {
unlink($this->sCssAbsPath);
}
@@ -178,25 +173,22 @@ JSON;
->method("CompileCSSFromSASS")
->willReturn("====CSSCOMPILEDCONTENT====");
if($readFromParamAttributeFromJson)
{
if ($readFromParamAttributeFromJson) {
copy($sExpectJsonFilePath, $this->sJsonThemeParamFile);
$this->assertTrue(ThemeHandler::CompileTheme('basque-red', true, "COMPILATIONTIMESTAMP", null, [static::$sTmpDir.'/branding/themes/'], static::$sTmpDir));
}
else
{
} else {
$this->assertTrue(ThemeHandler::CompileTheme('basque-red', true, "COMPILATIONTIMESTAMP", $aThemeParameters, [static::$sTmpDir.'/branding/themes/'], static::$sTmpDir));
}
$this->assertTrue(is_file($this->sCssAbsPath));
$this->assertEquals($sExpectedThemeParamJson, file_get_contents($this->sJsonThemeParamFile));
$this->assertEquals(file_get_contents(APPROOT . 'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main.css'), file_get_contents($this->sCssAbsPath));
$this->assertEquals(file_get_contents(APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main.css'), file_get_contents($this->sCssAbsPath));
}
public function CompileThemesProviderWithoutCss()
{
return [
"pass ParamAttributes and Save them in Json" => [false],
"use them from saved json" => [true]
"use them from saved json" => [true],
];
}
@@ -208,23 +200,23 @@ JSON;
* @throws \CoreException
* @dataProvider CompileThemesProviderEmptyArray
*/
public function testCompileThemesEmptyArray($ThemeParametersJson, $CompileCount=0)
public function testCompileThemesEmptyArray($ThemeParametersJson, $CompileCount = 0)
{
$sCssPath = static::$sTmpDir . '/branding/themes/basque-red/main.css';
copy(APPROOT . 'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main.css', $sCssPath);
$sCssPath = static::$sTmpDir.'/branding/themes/basque-red/main.css';
copy(APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main.css', $sCssPath);
$this->oCompileCSSServiceMock->expects($this->exactly($CompileCount))
->method("CompileCSSFromSASS")
->willReturn("====CSSCOMPILEDCONTENT====");
$this->assertEquals($CompileCount!=0,ThemeHandler::CompileTheme('basque-red', true, "COMPILATIONTIMESTAMP", json_decode($ThemeParametersJson, true), [static::$sTmpDir.'/branding/themes/'], static::$sTmpDir));
$this->assertEquals($CompileCount != 0, ThemeHandler::CompileTheme('basque-red', true, "COMPILATIONTIMESTAMP", json_decode($ThemeParametersJson, true), [static::$sTmpDir.'/branding/themes/'], static::$sTmpDir));
}
public function CompileThemesProviderEmptyArray()
{
$aEmptyImports = '{"variables":{"brand-primary":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"utility_imports":[],"variable_imports":[],"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/DO_NOT_CHANGE.jqueryui.scss","main":"..\/css\/DO_NOT_CHANGE.light-grey.scss"}}';
$aEmptyStyleSheets='{"variables":{"brand-primary":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"utility_imports":{"css-variables":"..\/css\/DO_NOT_CHANGE.css-variables.scss"},"variable_imports":[],"stylesheets":[]}';
$aEmptyVars='{"variables":[],"utility_imports":{"css-variables":"..\/css\/DO_NOT_CHANGE.css-variables.scss"},"variable_imports":[],"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/DO_NOT_CHANGE.jqueryui.scss","main":"..\/css\/DO_NOT_CHANGE.light-grey.scss"}}';
$aEmptyStyleSheets = '{"variables":{"brand-primary":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"utility_imports":{"css-variables":"..\/css\/DO_NOT_CHANGE.css-variables.scss"},"variable_imports":[],"stylesheets":[]}';
$aEmptyVars = '{"variables":[],"utility_imports":{"css-variables":"..\/css\/DO_NOT_CHANGE.css-variables.scss"},"variable_imports":[],"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/DO_NOT_CHANGE.jqueryui.scss","main":"..\/css\/DO_NOT_CHANGE.light-grey.scss"}}';
return [
"empty imports" => [$aEmptyImports],
"empty styles" => [$aEmptyStyleSheets],
@@ -245,13 +237,13 @@ JSON;
*/
public function CompileThemesProvider()
{
$sModifiedVariableThemeParameterJson='{"variables":{"brand-primary1":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"variable_imports":{"css-variables":"..\/css\/DO_NOT_CHANGE.css-variables.scss"},"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/DO_NOT_CHANGE.jqueryui.scss","main":"..\/css\/DO_NOT_CHANGE.light-grey.scss"},"utility_imports":[]}';
$sInitialThemeParamJson='{"variables":{"brand-primary":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"variable_imports":{"css-variables":"..\/css\/DO_NOT_CHANGE.css-variables.scss"},"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/DO_NOT_CHANGE.jqueryui.scss","main":"..\/css\/DO_NOT_CHANGE.light-grey.scss"},"utility_imports":[]}';
$sModifiedVariableThemeParameterJson = '{"variables":{"brand-primary1":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"variable_imports":{"css-variables":"..\/css\/DO_NOT_CHANGE.css-variables.scss"},"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/DO_NOT_CHANGE.jqueryui.scss","main":"..\/css\/DO_NOT_CHANGE.light-grey.scss"},"utility_imports":[]}';
$sInitialThemeParamJson = '{"variables":{"brand-primary":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"variable_imports":{"css-variables":"..\/css\/DO_NOT_CHANGE.css-variables.scss"},"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/DO_NOT_CHANGE.jqueryui.scss","main":"..\/css\/DO_NOT_CHANGE.light-grey.scss"},"utility_imports":[]}';
$sImportFilePath = '/branding/css/DO_NOT_CHANGE.css-variables.scss';
$sVarChangedMainCssPath="tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_varchanged.css";
$sStylesheetMainCssPath="tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_stylesheet.css";
$sImageMainCssPath="tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_imagemodified.css";
$sImportModifiedMainCssPath="tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_importmodified.css";
$sVarChangedMainCssPath = "tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_varchanged.css";
$sStylesheetMainCssPath = "tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_stylesheet.css";
$sImageMainCssPath = "tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_imagemodified.css";
$sImportModifiedMainCssPath = "tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_importmodified.css";
$sStylesheetFilePath = '/branding/css/DO_NOT_CHANGE.light-grey.scss';
$sImageFilePath = 'tests/php-unit-tests/unitary-tests/application/theme-handler/copied/testimages/images/green-header.gif';
return [
@@ -273,7 +265,6 @@ JSON;
];
}
/**
* @param $ThemeParametersJson
* @param int $iCompileCSSFromSASSCount
@@ -287,13 +278,12 @@ JSON;
* @throws \CoreException
* @dataProvider CompileThemesProvider
*/
public function testCompileThemes($ThemeParametersJson, $iCompileCSSFromSASSCount, $bMissingFile=false, $bFilesTouchedRecently=false, $bFileMd5sumModified=false, $sFileToTest=null, $sExpectedMainCssPath=null, $bSetup=true)
public function testCompileThemes($ThemeParametersJson, $iCompileCSSFromSASSCount, $bMissingFile = false, $bFilesTouchedRecently = false, $bFileMd5sumModified = false, $sFileToTest = null, $sExpectedMainCssPath = null, $bSetup = true)
{
static::InitCSSDirectory();
$sAfterReplacementCssVariableMd5sum='';
if (is_file(static::$sTmpDir.'/'.$sFileToTest))
{
$sAfterReplacementCssVariableMd5sum = '';
if (is_file(static::$sTmpDir.'/'.$sFileToTest)) {
$sFileToTest = static::$sTmpDir.'/'.$sFileToTest;
} else {
$sFileToTest = APPROOT.'/'.$sFileToTest;
@@ -309,14 +299,12 @@ JSON;
$sLine = '$approot-relative: "'.static::$sAbsoluteImagePath.'" !default;';
$sCssVariableContent = preg_replace("/\\\$approot-relative: \"(.*)\"/", $sLine, $sCssVariableContent);
file_put_contents($sCssVarPath, $sCssVariableContent);
if ($bMissingFile)
{
if ($bMissingFile) {
$sAfterReplacementCssVariableMd5sum = $sBeforeReplacementCssVariableMd5sum;
unlink($sFileToTest);
}
if (is_file($sCssVarPath))
{
if (is_file($sCssVarPath)) {
$sAfterReplacementCssVariableMd5sum = md5_file($sCssVarPath);
}
@@ -324,26 +312,23 @@ JSON;
$sMainCssContent = file_get_contents(APPROOT."tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_testcompilethemes.css");
$sMainCssContent = preg_replace('/MD5SUM/', $sAfterReplacementCssVariableMd5sum, $sMainCssContent);
$sReplacement = rtrim(static::$sAbsoluteImagePath, '/');
$sReplacement=preg_replace('|\/|', '\/', $sReplacement);
$sMainCssContent = preg_replace(static::PATTERN, $sReplacement, $sMainCssContent);
$cssPath = static::$sTmpDir . '/branding/themes/basque-red/main.css';
$sReplacement = preg_replace('|\/|', '\/', $sReplacement);
$sMainCssContent = preg_replace(static::PATTERN, $sReplacement, $sMainCssContent);
$cssPath = static::$sTmpDir.'/branding/themes/basque-red/main.css';
file_put_contents($cssPath, $sMainCssContent);
//should be after main.css modification to make sure precompilation check will be performed
if ($bFilesTouchedRecently)
{
if ($bFilesTouchedRecently) {
touch($sFileToTest, time() + 2, time() + 2);
}
//same: it should be after main.css modification
if ($bFileMd5sumModified)
{
if ($bFileMd5sumModified) {
file_put_contents($sFileToTest, "###\n".file_get_contents($sFileToTest));
touch($sFileToTest, time() + 2, time() + 2);
}
if (is_file($sCssVarPath))
{
if (is_file($sCssVarPath)) {
$sAfterReplacementCssVariableMd5sum = md5_file($sCssVarPath);
}
@@ -352,10 +337,9 @@ JSON;
->willReturn("====CSSCOMPILEDCONTENT====");
$aThemeParameters = json_decode($ThemeParametersJson, true);
$this->assertEquals($iCompileCSSFromSASSCount!=0, ThemeHandler::CompileTheme('basque-red', $bSetup, "COMPILATIONTIMESTAMP", $aThemeParameters, [static::$sTmpDir.'/branding/themes/'], static::$sTmpDir));
$this->assertEquals($iCompileCSSFromSASSCount != 0, ThemeHandler::CompileTheme('basque-red', $bSetup, "COMPILATIONTIMESTAMP", $aThemeParameters, [static::$sTmpDir.'/branding/themes/'], static::$sTmpDir));
if ($iCompileCSSFromSASSCount==1)
{
if ($iCompileCSSFromSASSCount == 1) {
$sExpectedMainCssFile = APPROOT.$sExpectedMainCssPath;
if (!is_file($sExpectedMainCssFile)) {
$this->assertTrue(false, "Cannot find expected main css file $sExpectedMainCssFile");
@@ -379,19 +363,18 @@ JSON;
$sActualContent = file_get_contents($sActualCssFile);
//replace absolute path to fix it in any envt
$sExpectedContent = preg_replace($aPatterns, $aReplacements, file_get_contents($sExpectedCssFile));
$sExpectedContent = preg_replace($aPatterns, $aReplacements, file_get_contents($sExpectedCssFile));
//echo($sExpectedContent);
if ($sExpectedContent != $sActualContent)
{
if ($sExpectedContent != $sActualContent) {
//try to have inner json diff failure
/** @var array $aExpectedJson */
//replace absolute path to fix it in any envt
$sExpectedJson = preg_replace($aPatterns, $aReplacements, ThemeHandler::GetSignature($sExpectedCssFile));
$sExpectedJson = preg_replace($aPatterns, $aReplacements, ThemeHandler::GetSignature($sExpectedCssFile));
$aExpectedJson = json_decode($sExpectedJson, true);
/** @var array $aActualJson */
$aActualJson = json_decode(ThemeHandler::GetSignature($sActualCssFile), true);
echo (ThemeHandler::GetSignature($sActualCssFile));
echo(ThemeHandler::GetSignature($sActualCssFile));
$this->assertEquals($aExpectedJson, $aActualJson, "CSS file dont match ($sExpectedCssFile / $sActualCssFile)");
}
@@ -405,14 +388,16 @@ JSON;
*/
public function testGetAllUrlFromScss($sScssFile)
{
$aIncludedUrls = ThemeHandler::GetAllUrlFromScss(['attr' => "123"],APPROOT.$sScssFile);
$aIncludedUrls = ThemeHandler::GetAllUrlFromScss(['attr' => "123"], APPROOT.$sScssFile);
$this->assertEquals(['approot-relative', 'version', 'version1'], array_values($aIncludedUrls['aMissingVariables']));
$this->assertEquals(["attr"=>"123"],
$aIncludedUrls['aFoundVariables']);
$this->assertEquals(
["attr" => "123"],
$aIncludedUrls['aFoundVariables']
);
$aExpectedCompletedUrls = [
'css/ui-lightness/images/tutu.jpg',
"css/ui-lightness/images/tata.jpeg",
"css/ui-lightness/images/tete.jpeg?g=123"
"css/ui-lightness/images/tete.jpeg?g=123",
];
$aExpectedToCompleteUrls = [
'\'abc/\'+ $approot-relative + "css/ui-lightness/images/toutou.png?v=" + $version',
@@ -467,7 +452,8 @@ SCSS;
$this->assertEquals(['gray-darker', 'brand-primary', 'brand-primary-lightest'], $aMissingVariables);
}
public function testGetVariablesFromFile(){
public function testGetVariablesFromFile()
{
$sContent = <<< 'SCSS'
$approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css
$approot-relative2: "../../" !default; // relative to env-***/branding/themes/***/main.css
@@ -482,7 +468,7 @@ $icons-filter: hue-rotate(0deg) !default;
$toto : titi;
SCSS;
file_put_contents(static::$sTmpDir . DIRECTORY_SEPARATOR . 'css-variable.scss', $sContent);
file_put_contents(static::$sTmpDir.DIRECTORY_SEPARATOR.'css-variable.scss', $sContent);
$aVariables = ThemeHandler::GetVariablesFromFile(
[ 'css-variable.scss' ],
[ static::$sTmpDir ]
@@ -504,7 +490,8 @@ SCSS;
$this->assertEquals(
$aExpectedVariables,
$aVariables);
$aVariables
);
}
/**
@@ -522,13 +509,13 @@ SCSS;
public function ResolveUrlProvider()
{
return [
'XXX + $key1 UNresolved' => ["abc/'+ \$key1", ['key'=>'123'], false],
'$key1 + XXX UNresolved' => ["\$key1 + abs", ['key'=>'123'], false],
'XXX + $key UNresolved' => ["abc/'+ \$unknownkey", ['key'=>'123'], false],
'XXX + $key resolved' => ["abc/'+ \$key", ['key'=>'123'], "abc/123"],
'XXX + $key1 resolved' => ["abc/'+ \$key1", ['key1'=>'123'], "abc/123"],
'$key + XXX resolved' => ["\$key + \"/abc", ['key'=>'123'], "123/abc"],
'XXX + $key + YYY resolved' => ["abc/'+ \$key + '/def", ['key'=>'123'], "abc/123/def"],
'XXX + $key1 UNresolved' => ["abc/'+ \$key1", ['key' => '123'], false],
'$key1 + XXX UNresolved' => ["\$key1 + abs", ['key' => '123'], false],
'XXX + $key UNresolved' => ["abc/'+ \$unknownkey", ['key' => '123'], false],
'XXX + $key resolved' => ["abc/'+ \$key", ['key' => '123'], "abc/123"],
'XXX + $key1 resolved' => ["abc/'+ \$key1", ['key1' => '123'], "abc/123"],
'$key + XXX resolved' => ["\$key + \"/abc", ['key' => '123'], "123/abc"],
'XXX + $key + YYY resolved' => ["abc/'+ \$key + '/def", ['key' => '123'], "abc/123/def"],
];
}
@@ -536,8 +523,8 @@ SCSS;
{
static::InitCSSDirectory();
$aStylesheetFile=glob(static::$sTmpDir."/branding/css/*.scss");
$aStylesheetFile[]=static::$sTmpDir."/branding/css/ui-lightness/DO_NOT_CHANGE.jqueryui.scss";
$aStylesheetFile = glob(static::$sTmpDir."/branding/css/*.scss");
$aStylesheetFile[] = static::$sTmpDir."/branding/css/ui-lightness/DO_NOT_CHANGE.jqueryui.scss";
$expectJsonFilePath = APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/theme-parameters.json';
$expectedThemeParamJson = file_get_contents($expectJsonFilePath);
$aThemeParametersVariables = json_decode($expectedThemeParamJson, true);
@@ -549,8 +536,7 @@ SCSS;
$aExpectedUris = json_decode(file_get_contents(APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/getimages/expected-getimages.json'), true);
$aExpectedImages = [];
foreach ($aExpectedUris as $sExpectedUri)
{
foreach ($aExpectedUris as $sExpectedUri) {
$aExpectedImages[] = ThemeHandler::GetAppRootWithSlashes().$sExpectedUri;
}
@@ -561,7 +547,8 @@ SCSS;
* @dataProvider FindStylesheetFileProvider
* @throws \Exception
*/
public function testFindStylesheetFile(string $sFileToFind, array $aAllImports){
public function testFindStylesheetFile(string $sFileToFind, array $aAllImports)
{
$sImportsPath = static::$sTmpDir.'branding/';
// Windows compat O:)
@@ -575,7 +562,6 @@ SCSS;
}
}
$oFindStylesheetObject = new FindStylesheetObject();
ThemeHandler::FindStylesheetFile($sFileToFind, [$sImportsPath], $oFindStylesheetObject);
@@ -607,15 +593,15 @@ SCSS;
],
"scss with multi @imports" => [
"sFileToFind" => $sFileToFind3,
"aAllImports" => [$sFileToFind4, $sFileToFind5]
"aAllImports" => [$sFileToFind4, $sFileToFind5],
],
"scss with simple @imports in another folder" => [
"sFileToFind" => "css/simple_import2.scss",
"aAllImports" => [$sFileToFind5]
"aAllImports" => [$sFileToFind5],
],
"scss with @imports shortcut included_file3 => _included_file3.scss" => [
"sFileToFind" => "css/shortcut.scss",
"aAllImports" => ["css/_included_file3.scss", "css/included_scss/included_file4.scss"]
"aAllImports" => ["css/_included_file3.scss", "css/included_scss/included_file4.scss"],
],
"scss with @imports shortcut same file and folder names => feature1/_feature1.scss" => [
"sFileToFind" => "css/shortcut2.scss",
@@ -656,7 +642,7 @@ SCSS;
return [
[ '/var/www/html/iTop/images/itop-logo-2.png', '/var/www/html/iTop/env-production/branding/themes/light-grey/../../../../images/itop-logo-2.png' ],
[ '/var/www/html/iTop/env-production/branding/themes/light-grey/images/', '/var/www/html/iTop/env-production/branding/themes/light-grey/images/' ],
[ '/var/www/html/iTop/css/ui-lightness/images/ui-icons_222222_256x240.png', '/var/www/html/iTop/env-production//branding/themes/light-grey//../../../../css/ui-lightness/images/ui-icons_222222_256x240.png' ]
[ '/var/www/html/iTop/css/ui-lightness/images/ui-icons_222222_256x240.png', '/var/www/html/iTop/env-production//branding/themes/light-grey//../../../../css/ui-lightness/images/ui-icons_222222_256x240.png' ],
];
}
}
}

View File

@@ -14,8 +14,10 @@ use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
*
* @package UI\Base\Layout
*/
class NavigationMenuTest extends ItopDataTestCase {
public function IsAllowedProvider(){
class NavigationMenuTest extends ItopDataTestCase
{
public function IsAllowedProvider()
{
return [
'show menu' => [ true ],
'hide menu' => [ false ],
@@ -26,17 +28,20 @@ class NavigationMenuTest extends ItopDataTestCase {
* @dataProvider IsAllowedProvider
* test used to make sure backward compatibility is ensured
*/
public function testIsAllowed($bExpectedIsAllowed=true){
public function testIsAllowed($bExpectedIsAllowed = true)
{
\MetaModel::GetConfig()->Set('navigation_menu.show_organization_filter', $bExpectedIsAllowed);
$oNavigationMenu = new NavigationMenu(
$this->createMock(ApplicationContext::class),
$this->createMock(PopoverMenu::class));
$this->createMock(PopoverMenu::class)
);
$isAllowed = $oNavigationMenu->IsSiloSelectionEnabled();
$this->assertEquals($bExpectedIsAllowed, $isAllowed);
}
public function testIsAllowed_BackwardCompatibility_NoVariableInConfFile(){
public function testIsAllowed_BackwardCompatibility_NoVariableInConfFile()
{
\MetaModel::GetConfig()->Set('navigation_menu.show_organization_filter', false);
$sTmpFilePath = tempnam(sys_get_temp_dir(), 'test_');
@@ -46,7 +51,7 @@ class NavigationMenuTest extends ItopDataTestCase {
//remove variable for the test
$aLines = file($sTmpFilePath);
$aRows = array();
$aRows = [];
foreach ($aLines as $key => $sLine) {
if (!preg_match('/navigation_menu.show_organization_filter/', $sLine)) {

View File

@@ -21,12 +21,12 @@ class WelcomePopupTest extends ItopDataTestCase
$bResult = usort($aProvidersMessagesData, [WelcomePopupService::class, 'SortOnImportance']);
$this->assertTrue($bResult);
$aMessageIdsSorted = array_map(function($aItem) {
$aMessageIdsSorted = array_map(function ($aItem) {
return $aItem['message']->GetId();
}, $aProvidersMessagesData);
$this->assertEquals($aExpected, $aMessageIdsSorted);
}
/**
* Data provider for testSortOnImportance
* @return array[][]|string[][][][]|number[][][][]
@@ -76,10 +76,10 @@ class WelcomePopupTest extends ItopDataTestCase
{
$oService = WelcomePopupService::GetInstance();
$this->InvokeNonPublicMethod(WelcomePopupService::class, 'SetAcknowledgedMessagesCache', $oService, [$aCache]);
$this->assertEquals($bExpected, $this->InvokeNonPublicMethod(WelcomePopupService::class, 'IsMessageAcknowledged', $oService, [$sMessageId]));
}
public function isMessageAcknowledgedDataProvider()
{
return [
@@ -94,7 +94,7 @@ class WelcomePopupTest extends ItopDataTestCase
],
];
}
public function testProcessMessages()
{
// Mock a WelcomePopup message provider, with a fixed class name
@@ -103,7 +103,7 @@ class WelcomePopupTest extends ItopDataTestCase
new Message('123', 'foo', '<p>Hello Foo</p>', null, [], 0),
new Message('456', 'bar', '<p>Hello Bar</p>', null, [], 1), // Already acknowledged will be skipped
]);
// Mock another WelcomePopup message provider, with a different class name
$oProvider2 = $this->getMockBuilder(iWelcomePopupExtension::class)->setMockClassName('Provider2')->getMock();
$oProvider2->expects($this->once())->method('GetMessages')->willReturn([
@@ -113,7 +113,7 @@ class WelcomePopupTest extends ItopDataTestCase
$oService = WelcomePopupService::GetInstance();
$this->InvokeNonPublicMethod(WelcomePopupService::class, 'SetAcknowledgedMessagesCache', $oService, [[get_class($oProvider1).'::456']]);
$this->InvokeNonPublicMethod(WelcomePopupService::class, 'SetMessagesProviders', $oService, [[$oProvider1, $oProvider2]]);
$aProvidersMessagesData = $this->InvokeNonPublicMethod(WelcomePopupService::class, 'ProcessMessages', $oService, []);
$this->assertEquals(
[
@@ -141,11 +141,11 @@ class WelcomePopupTest extends ItopDataTestCase
{
self::CreateUser('admin-testAcknowledgeMessage', 1, '-Passw0rd!Complex-');
UserRights::Login('admin-testAcknowledgeMessage');
// Mock a WelcomePopup message provider, with a fixed class name
$oProvider1 = $this->getMockBuilder(iWelcomePopupExtension::class)->setMockClassName('Provider1')->getMock();
$oProvider1->expects($this->exactly(2))->method('AcknowledgeMessage');
// Mock another WelcomePopup message provider, with a different class name
$oProvider2 = $this->getMockBuilder(iWelcomePopupExtension::class)->setMockClassName('Provider2')->getMock();
$oProvider2->expects($this->exactly(1))->method('AcknowledgeMessage');
@@ -154,24 +154,24 @@ class WelcomePopupTest extends ItopDataTestCase
$sMessageUUID2 = get_class($oProvider1).'::456789';
$sMessageUUID3 = get_class($oProvider2).'::456789'; // Same message id but different provider / UUID
$oService = WelcomePopupService::GetInstance();
$this->InvokeNonPublicMethod(WelcomePopupService::class, 'SetMessagesProviders', $oService, [[$oProvider1, $oProvider2]]);
$oService->AcknowledgeMessage($sMessageUUID1);
$this->assertTrue($this->InvokeNonPublicMethod(WelcomePopupService::class, 'IsMessageAcknowledged', $oService, [$sMessageUUID1]));
$this->assertFalse($this->InvokeNonPublicMethod(WelcomePopupService::class, 'IsMessageAcknowledged', $oService, ['-This-Message-Id-Is-Not-Ack0ledg3dged!']));
$this->assertFalse($this->InvokeNonPublicMethod(WelcomePopupService::class, 'IsMessageAcknowledged', $oService, [$sMessageUUID3]));
$oService->AcknowledgeMessage($sMessageUUID2);
$this->assertTrue($this->InvokeNonPublicMethod(WelcomePopupService::class, 'IsMessageAcknowledged', $oService, [$sMessageUUID1]));
$this->assertTrue($this->InvokeNonPublicMethod(WelcomePopupService::class, 'IsMessageAcknowledged', $oService, [$sMessageUUID2]));
$this->assertFalse($this->InvokeNonPublicMethod(WelcomePopupService::class, 'IsMessageAcknowledged', $oService, ['-This-Message-Id-Is-Not-Ack0ledg3dged!']));
$this->assertFalse($this->InvokeNonPublicMethod(WelcomePopupService::class, 'IsMessageAcknowledged', $oService, [$sMessageUUID3]));
$oService->AcknowledgeMessage($sMessageUUID3);
$this->assertTrue($this->InvokeNonPublicMethod(WelcomePopupService::class, 'IsMessageAcknowledged', $oService, [$sMessageUUID3]));
}
/**
* @dataProvider makeStringFitInProvider
*/
@@ -182,7 +182,7 @@ class WelcomePopupTest extends ItopDataTestCase
$this->assertTrue(mb_strlen($sFitted) <= $iLimit);
$this->assertEquals($sExpected, $sFitted);
}
public function makeStringFitInProvider()
{
return [
@@ -193,4 +193,3 @@ class WelcomePopupTest extends ItopDataTestCase
}
}

View File

@@ -23,4 +23,4 @@ class ApplicationContextTest extends \Combodo\iTop\Test\UnitTest\ItopTestCase
$this->assertEquals($sExpected, $sActual, 'Query parameters string should not start with & when $bIncludeAmpersand is false');
}
}
}

View File

@@ -4,11 +4,10 @@ namespace applicationContext;
class MockApplicationContext extends \ApplicationContext
{
public function __construct(array $applicationContextConfig)
{
parent::__construct();
$this->aValues = $applicationContextConfig;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -24,7 +25,7 @@ class ApplicationExtensionTest extends ItopCustomDatamodelTestCase
*/
public function GetDatamodelDeltaAbsPath(): string
{
return __DIR__ . '/Delta/application-extension-usages-in-snippets.xml';
return __DIR__.'/Delta/application-extension-usages-in-snippets.xml';
}
/**

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -32,9 +33,9 @@ use UserRights;
class privUITransactionFileTest extends ItopDataTestCase
{
/** @var int ID of the "support agent" pofile in the sample data */
const SAMPLE_DATA_SUPPORT_PROFILE_ID = 5;
const USER1_TEST_LOGIN = 'user1_support_test_privUITransaction';
const USER2_TEST_LOGIN = 'user2_support_test_privUITransaction';
public const SAMPLE_DATA_SUPPORT_PROFILE_ID = 5;
public const USER1_TEST_LOGIN = 'user1_support_test_privUITransaction';
public const USER2_TEST_LOGIN = 'user2_support_test_privUITransaction';
/**
* @dataProvider cleanupOldTransactionsProvider
@@ -43,7 +44,7 @@ class privUITransactionFileTest extends ItopDataTestCase
{
MetaModel::GetConfig()->Set('transactions_gc_threshold', 100);
$iBaseLimit = time() - 24*3600; //24h
$iBaseLimit = time() - 24 * 3600; //24h
$sBaseDir = sys_get_temp_dir();
$sDir = "$sBaseDir/privUITransactionFileTest/cleanupOldTransactions";
@@ -53,10 +54,10 @@ class privUITransactionFileTest extends ItopDataTestCase
mkdir("$sDir", 0777, true);
for ($i = 0; $i < $iCleanableCreated; $i++) {
touch("$sDir/{$sCleanablePrefix}$i", $iBaseLimit - 10*60);
touch("$sDir/{$sCleanablePrefix}$i", $iBaseLimit - 10 * 60);
}
for ($i = 0; $i < $iPreservableCreated; $i++) {
touch("$sDir/{$sPreservablePrefix}$i", $iBaseLimit + 10*60);
touch("$sDir/{$sPreservablePrefix}$i", $iBaseLimit + 10 * 60);
}
$iCleanableCount = count(glob("$sDir/{$sCleanablePrefix}*"));
@@ -123,7 +124,8 @@ class privUITransactionFileTest extends ItopDataTestCase
];
}
public function rm($sDir) {
public function rm($sDir)
{
$aFiles = array_diff(scandir($sDir), ['.','..']);
foreach ($aFiles as $sFile) {
if ((is_dir("$sDir/$sFile"))) {
@@ -135,7 +137,7 @@ class privUITransactionFileTest extends ItopDataTestCase
return rmdir($sDir);
}
const USER_TEST_LOGIN = 'support_test_privUITransaction';
public const USER_TEST_LOGIN = 'support_test_privUITransaction';
/**
* @throws \SecurityException

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2018 Dennis Lassiter
*
@@ -38,11 +39,11 @@ use utils;
class QueryTest extends ItopDataTestCase
{
// disable transaction to avoid data inconsistency between test and call to export (outside test scope)
const USE_TRANSACTION = false;
public const USE_TRANSACTION = false;
// user for exportation process
const USER = 'dani2';
const PASSWORD = '1TopCombodo+';
public const USER = 'dani2';
public const PASSWORD = '1TopCombodo+';
private $oUser;
/** @inheritDoc */
@@ -60,7 +61,7 @@ class QueryTest extends ItopDataTestCase
*/
private function CreateExportUser()
{
$oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => 'Administrator'), true);
$oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => 'Administrator'], true);
$this->oUser = $this->CreateUser(self::USER, $oAdminProfile->GetKey(), self::PASSWORD);
}
@@ -72,14 +73,14 @@ class QueryTest extends ItopDataTestCase
* @param string $sOql query oql phrase
* @param string|null $sFields fields to export
*/
private function CreateQueryOQL(string $sName, string $sDescription, string $sOql, string $sFields = null) : QueryOQL
private function CreateQueryOQL(string $sName, string $sDescription, string $sOql, string $sFields = null): QueryOQL
{
$oQuery = new QueryOQL();
$oQuery->Set('name', $sName);
$oQuery->Set('description', $sDescription);
$oQuery->Set('oql', $sOql);
if($sFields != null){
if ($sFields != null) {
$oQuery->Set('fields', $sFields);
}
@@ -125,10 +126,10 @@ class QueryTest extends ItopDataTestCase
*/
public function getQueryProvider()
{
return array(
'Export #1' => array('query without params', 'SELECT Person'),
'Export #2' => array('query with params', "SELECT Person WHERE first_name LIKE 'B%'")
);
return [
'Export #1' => ['query without params', 'SELECT Person'],
'Export #2' => ['query with params', "SELECT Person WHERE first_name LIKE 'B%'"],
];
}
/**
@@ -148,7 +149,7 @@ class QueryTest extends ItopDataTestCase
// curl options
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_USERPWD, self::USER . ':' . self::PASSWORD);
curl_setopt($curl, CURLOPT_USERPWD, self::USER.':'.self::PASSWORD);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// Force disable of certificate check as most of dev / test env have a self-signed certificate

View File

@@ -1,10 +1,12 @@
<?php
namespace Combodo\iTop\Application\TwigBase\Controller;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use MetaModel;
class ControllerTest extends ItopDataTestCase {
class ControllerTest extends ItopDataTestCase
{
protected function setUp(): void
{
parent::setUp();
@@ -12,7 +14,8 @@ class ControllerTest extends ItopDataTestCase {
$this->RequireOnceUnitTestFile('FakeController.php');
}
public function CheckAccessProvider() {
public function CheckAccessProvider()
{
return [
'simple token access OK' => [
'access_token' => 'toto123',
@@ -42,7 +45,8 @@ class ControllerTest extends ItopDataTestCase {
* Fix N°7147
* @dataProvider CheckAccessProvider
*/
public function testCheckAccess($sConfiguredAccessToken, $sHttpAccessToken, $bSuccess, $bPost=false){
public function testCheckAccess($sConfiguredAccessToken, $sHttpAccessToken, $bSuccess, $bPost = false)
{
$sModuleName = "MyModule";
$sTokenParamName = "access_token_conf_param";
@@ -51,7 +55,7 @@ class ControllerTest extends ItopDataTestCase {
$_REQUEST = [];
$_REQUEST['exec_module'] = $sModuleName;
if ($bPost){
if ($bPost) {
$_POST[$sTokenParamName] = $sHttpAccessToken;
} else {
$_REQUEST[$sTokenParamName] = $sHttpAccessToken;
@@ -62,13 +66,13 @@ class ControllerTest extends ItopDataTestCase {
MetaModel::GetConfig()->SetModuleSetting($sModuleName, $sTokenParamName, $sConfiguredAccessToken);
if (! $bSuccess){
if (! $bSuccess) {
$this->expectExceptionMessage("Invalid token");
}
$this->InvokeNonPublicMethod(FakeController::class, "CheckAccess", $oController);
if ($bSuccess){
if ($bSuccess) {
$this->assertTrue(true, "no issue encountered");
}
}

View File

@@ -1,5 +1,7 @@
<?php
namespace Combodo\iTop\Application\TwigBase\Controller;
class FakeController extends Controller {
class FakeController extends Controller
{
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2018 Dennis Lassiter
*
@@ -42,7 +43,6 @@ class utilsTest extends ItopTestCase
parent::tearDown();
}
public function testEndsWith()
{
$this->assertFalse(utils::EndsWith('a', 'bbbb'));
@@ -87,8 +87,7 @@ class utilsTest extends ItopTestCase
$sSep = DIRECTORY_SEPARATOR;
$sItopRootRealPath = realpath($sAppRoot).$sSep;
$sLicenseFileName = 'license.txt';
if (!is_file($sAppRoot.$sLicenseFileName))
{
if (!is_file($sAppRoot.$sLicenseFileName)) {
$sLicenseFileName = 'LICENSE';
}
@@ -96,7 +95,7 @@ class utilsTest extends ItopTestCase
$sLicenseFileName => [$sAppRoot.$sLicenseFileName, $sAppRoot, $sItopRootRealPath.$sLicenseFileName],
'unexisting file' => [$sAppRoot.'license_DOES_NOT_EXIST.txt', $sAppRoot, false],
'/'.$sLicenseFileName => [$sAppRoot.$sSep.$sLicenseFileName, $sAppRoot, $sItopRootRealPath.$sLicenseFileName],
'%2f'.$sLicenseFileName => [$sAppRoot.'%2f'. $sLicenseFileName, $sAppRoot, false],
'%2f'.$sLicenseFileName => [$sAppRoot.'%2f'.$sLicenseFileName, $sAppRoot, false],
'../'.$sLicenseFileName => [$sAppRoot.'..'.$sSep.$sLicenseFileName, $sAppRoot, false],
'%2e%2e%2f'.$sLicenseFileName => [$sAppRoot.'%2e%2e%2f'.$sLicenseFileName, $sAppRoot, false],
'application/utils.inc.php with basepath=APPROOT' => [
@@ -132,32 +131,32 @@ class utilsTest extends ItopTestCase
public function LocalPathProvider()
{
$sAppRoot = static::GetAppRoot();
return array(
'index.php' => array(
return [
'index.php' => [
'sAbsolutePath' => $sAppRoot.'index.php',
'expected' => 'index.php',
),
'non existing' => array(
],
'non existing' => [
'sAbsolutePath' => $sAppRoot.'nonexisting/nonexisting',
'expected' => false,
),
'outside' => array(
],
'outside' => [
'sAbsolutePath' => '/tmp',
'expected' => false,
),
'application/cmdbabstract.class.inc.php' => array(
],
'application/cmdbabstract.class.inc.php' => [
'sAbsolutePath' => $sAppRoot.'application/cmdbabstract.class.inc.php',
'expected' => 'application/cmdbabstract.class.inc.php',
),
'dir' => array(
],
'dir' => [
'sAbsolutePath' => $sAppRoot.'application/.',
'expected' => 'application',
),
'root' => array(
],
'root' => [
'sAbsolutePath' => $sAppRoot.'.',
'expected' => '',
),
);
],
];
}
/**
@@ -171,14 +170,15 @@ class utilsTest extends ItopTestCase
public function appRootUrlProvider()
{
return array(
'Setup index (windows antislash)' => array('http://localhost/', 'C:\Dev\wamp64\www\itop-dev\setup\index.php', 'C:\Dev\wamp64\www\itop-dev', 'http://localhost/setup/'),
'Setup index (windows slash)' => array('http://127.0.0.1/', 'C:/web/setup/index.php', 'C:/web', 'http://127.0.0.1/setup/'),
'Setup index (windows slash, drive letter case difference)' => array('http://127.0.0.1/', 'c:/web/setup/index.php', 'C:/web', 'http://127.0.0.1/setup/'),
);
return [
'Setup index (windows antislash)' => ['http://localhost/', 'C:\Dev\wamp64\www\itop-dev\setup\index.php', 'C:\Dev\wamp64\www\itop-dev', 'http://localhost/setup/'],
'Setup index (windows slash)' => ['http://127.0.0.1/', 'C:/web/setup/index.php', 'C:/web', 'http://127.0.0.1/setup/'],
'Setup index (windows slash, drive letter case difference)' => ['http://127.0.0.1/', 'c:/web/setup/index.php', 'C:/web', 'http://127.0.0.1/setup/'],
];
}
public function GetAbsoluteUrlAppRootPersistency() {
public function GetAbsoluteUrlAppRootPersistency()
{
$this->setUp();
return [
@@ -260,7 +260,7 @@ class utilsTest extends ItopTestCase
/**
* @dataProvider GetAbsoluteUrlAppRootPersistency
*/
public function testGetAbsoluteUrlAppRootPersistency($bBehindReverseProxy,$bForceTrustProxy1 ,$sExpectedAppRootUrl1,$bForceTrustProxy2 , $sExpectedAppRootUrl2,$bForceTrustProxy3 , $sExpectedAppRootUrl3)
public function testGetAbsoluteUrlAppRootPersistency($bBehindReverseProxy, $bForceTrustProxy1, $sExpectedAppRootUrl1, $bForceTrustProxy2, $sExpectedAppRootUrl2, $bForceTrustProxy3, $sExpectedAppRootUrl3)
{
// resetting static property for each test pass
$this->SetNonPublicStaticProperty(utils::class, 'sAbsoluteUrlAppRootCache', null);
@@ -291,7 +291,6 @@ class utilsTest extends ItopTestCase
$this->assertEquals($sExpectedAppRootUrl3, utils::GetAbsoluteUrlAppRoot($bForceTrustProxy3));
}
/**
* @dataProvider GetDefaultUrlAppRootProvider
*/
@@ -863,78 +862,78 @@ class utilsTest extends ItopTestCase
'Basic positional with enough args' => [
'Format: %1$s, %2$d, %3$s',
['Hello', 42, 'World'],
'Format: Hello, 42, World'
'Format: Hello, 42, World',
],
'Basic positional with args in different order' => [
'Format: %2$s, %1$d, %3$s',
[42, 'Hello', 'World'],
'Format: Hello, 42, World'
'Format: Hello, 42, World',
],
'Positional with reused specifiers' => [
'Format: %1$s, %2$d, %1$s again',
['Hello', 42],
'Format: Hello, 42, Hello again'
'Format: Hello, 42, Hello again',
],
// Missing arguments tests
'Missing one positional arg' => [
'Format: %1$s, %2$d, %3$s',
['Hello', 42],
'Format: Hello, 42, %3$s'
'Format: Hello, 42, %3$s',
],
'Missing multiple positional args' => [
'Format: %1$s, %2$s, %3$s, %4$s',
['Hello'],
'Format: Hello, %2$s, %3$s, %4$s'
'Format: Hello, %2$s, %3$s, %4$s',
],
'Missing first positional arg' => [
'Format: %1$s, %2$s, %3$s',
[],
'Format: %1$s, %2$s, %3$s'
'Format: %1$s, %2$s, %3$s',
],
// Edge cases
'Positional with larger numbers' => [
'Format: %2$s, %1$d, %3$s, %2$s again',
[123456, 'Hello', 'World'],
'Format: Hello, 123456, World, Hello again'
'Format: Hello, 123456, World, Hello again',
],
'Positional specifiers with non-sequential indexes' => [
'Format: %3$s then %1$s and %5$d',
['first', 'second', 'third', 'fourth', 42],
'Format: third then first and 42'
'Format: third then first and 42',
],
// More complex format specifiers
'Positional with format modifiers' => [
'Format: %1$\'*10s, %2$04d',
['Hello', 42],
'Format: *****Hello, 0042'
'Format: *****Hello, 0042',
],
'Positional with various types' => [
'Format: String: %1$s, Integer: %2$d, Char: %3$c',
['Hello', 42, 65],
'Format: String: Hello, Integer: 42, Char: A'
'Format: String: Hello, Integer: 42, Char: A',
],
// Testing with non-Latin characters
'Positional with UTF-8 characters' => [
'Format: %1$s %2$s %3$s',
['こんにちは', 'Здравствуйте', '你好'],
'Format: こんにちは Здравствуйте 你好'
'Format: こんにちは Здравствуйте 你好',
],
// Mixed formats
'Mixed positional with complex specifiers' => [
'Format: %1$-10s | %2$+d',
['Hello', 42],
'Format: Hello | +42'
'Format: Hello | +42',
],
'Reused positional indexes with some missing' => [
'Format: %1$s %2$d %1$s %3$s %2$d',
['Hello', 42],
'Format: Hello 42 Hello %3$s 42'
]
'Format: Hello 42 Hello %3$s 42',
],
];
}
}

View File

@@ -17,18 +17,18 @@ class ActionEmailTest extends ItopDataTestCase
/**
* @inheritDoc
*/
const CREATE_TEST_ORG = true;
public const CREATE_TEST_ORG = true;
/** @var \ActionEmail|null Temp ActionEmail created for tests */
protected static $oActionEmail = null;
/** @var \ormDocument|null Temp ormDocument for tests */
protected static $oDocument = null;
/** @var \UserRequest|null Temp ormDocument for tests */
protected static $oUserRequest = null;
/** @var string[] Dict formatted message, because the Dict class is not available in providers */
/** @var string[] Dict formatted message, because the Dict class is not available in providers */
protected static $aWarningMessages;
protected function setUp(): void
@@ -57,11 +57,11 @@ HTML
static::$oDocument = new \ormDocument($sHtml, 'text/html', 'sample.html');
static::$oUserRequest = MetaModel::NewObject('UserRequest', [
'title' => 'Test UserRequest',
'description' => '<p>Multi-line<br/>description</p>'
'description' => '<p>Multi-line<br/>description</p>',
]);
static::$aWarningMessages = [
'warning-missing-content' => Dict::Format('ActionEmail:content_placeholder_missing', '$content$', Dict::S('Class:ActionEmail/Attribute:body'))
'warning-missing-content' => Dict::Format('ActionEmail:content_placeholder_missing', '$content$', Dict::S('Class:ActionEmail/Attribute:body')),
];
}
@@ -129,7 +129,7 @@ HTML
'subject' => 'Test subject',
'body' => 'Test body',
]);
foreach($aActionFields as $sCode => $value) {
foreach ($aActionFields as $sCode => $value) {
if ($sCode === 'html_template') {
// special case since the data provider cannot create ormDocument objects
$oActionEmail->Set($sCode, static::$oDocument);
@@ -139,9 +139,9 @@ HTML
}
$oActionEmail->DBInsert();
$oOrg = $this->CreateOrganization('testPrepareMessageContent');
$oContact1 = MetaModel::NewObject('Person', [
'name' => 'Person 1',
'first_name' => 'PrepareMessageContent',
@@ -150,8 +150,7 @@ HTML
'notify' => 'yes',
]);
$oContact1->DBInsert();
$oContact2 = MetaModel::NewObject('Person', [
'name' => 'Person 2',
'first_name' => 'PrepareMessageContent',
@@ -160,19 +159,19 @@ HTML
'notify' => 'no',
]);
$oContact2->DBInsert();
$oLog = null;
$aEmailContent = $this->InvokeNonPublicMethod('\ActionEmail', 'PrepareMessageContent', $oActionEmail, [$aContext, &$oLog]);
// Normalize the content of the body to simplify the comparison, useful when status == test
$aEmailContent['body'] = preg_replace('/title="[^"]+"/', 'title="****"', $aEmailContent['body']);
$aEmailContent['body'] = preg_replace('/class="object-ref-link" href="[^"]+"/', 'class="object-ref-link" href="****"', $aEmailContent['body']);
$aEmailContent['body'] = preg_replace('/References: <[^>]+>/', 'References: ****', $aEmailContent['body']);
foreach($aFieldsToCheck as $sCode => $expectedValue) {
foreach ($aFieldsToCheck as $sCode => $expectedValue) {
$this->assertEquals($expectedValue, $aEmailContent[$sCode]);
}
}
public function prepareMessageContentProvider()
{
return [
@@ -226,7 +225,7 @@ HTML
'simple-body-with-placeholder-TEST-mode' => [
'EN US',
['body' => '<p>Ticket "$this->title$" created.</p>', 'status' => 'test'],
['body' =>
['body' =>
<<<HTML
<div class="email-is-html-content">
<p>Ticket "Test UserRequest" created.</p>
@@ -259,7 +258,7 @@ HTML
'simple-body-with-placeholder_and_template' => [
'EN US',
['body' => '<p>Ticket "$this->title$" created.</p>', 'html_template' => true],
['body' =>
['body' =>
<<<HTML
<body>
<table data-something-that-would-be-removed-by-the-sanitizer-through-ckeditor-but-that-will-stay-with-the-template="bar">
@@ -298,9 +297,9 @@ HTML
$this->assertEquals($aWarnings, $expectedWarnings);
} else {
// The warning messages are localized, but the provider functions does not
// have access to the Dict class, so let's replace the value given by the
// have access to the Dict class, so let's replace the value given by the
// provider by a statically precomputed and localized message
foreach($expectedWarnings as $index => $sMessageKey) {
foreach ($expectedWarnings as $index => $sMessageKey) {
$expectedWarnings[$index] = static::$aWarningMessages[$sMessageKey];
}
$this->assertEquals($aWarnings, $expectedWarnings);
@@ -313,14 +312,14 @@ HTML
'no warnings' => [
'<p>Some text here</p>',
'<div>$content$</div>',
null
],
null,
],
'$content$ missing' => [
'<p>Some text here</p>',
'<div>no placeholder</div>',
[ 'warning-missing-content' ]
[ 'warning-missing-content' ],
],
];
];
}
/**
@@ -330,9 +329,9 @@ HTML
{
$oConfig = utils::GetConfig();
$sCurrentEmailAsync = $oConfig->Get('email_asynchronous');
$oConfig->Set('email_asynchronous', $sConfigAsyncValue);
$oActionEmail = MetaModel::NewObject('ActionEmail', [
'name' => 'Test action',
'status' => 'disabled',
@@ -341,46 +340,45 @@ HTML
'body' => 'Test body',
'asynchronous' => $sActionAsyncValue,
]);
self::assertEquals($sExpectedValue, $oActionEmail->IsAsynchronous());
$oConfig->Set('email_asynchronous', $sCurrentEmailAsync);
}
public function asynchronousValuesContentProvider()
{
return [
'ActionEmail is asynchronous' => [
'yes',
false,
true
true,
],
'ActionEmail is not asynchronous' => [
'no',
true,
false
false,
],
'ActionEmail is asynchronous and config is asynchronous' => [
'yes',
true,
true
true,
],
'ActionEmail is not asynchronous and config is not asynchronous' => [
'no',
false,
false
false,
],
'ActionEmail follows global settings, config is not asynchronous' => [
'use_global_setting',
false,
false
false,
],
'ActionEmail follows global settings, config is asynchronous' => [
'use_global_setting',
true,
true
true,
],
];
}
}
}

View File

@@ -9,23 +9,28 @@ use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use MetaModel;
use UserRequest;
class AttributeDefinitionTest extends ItopDataTestCase {
const CREATE_TEST_ORG = true;
class AttributeDefinitionTest extends ItopDataTestCase
{
public const CREATE_TEST_ORG = true;
protected function setUp(): void {
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'core/attributedef.class.inc.php');
}
public function testGetImportColumns(){
public function testGetImportColumns()
{
$oAttributeDefinition = MetaModel::GetAttributeDef("ApplicationSolution", "status");
$aImportColumns = $oAttributeDefinition->GetImportColumns();
var_dump($aImportColumns);
$this->assertTrue(is_array($aImportColumns), var_export($aImportColumns, true));
$this->assertEquals(["status" => "ENUM('active','inactive') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"],
$aImportColumns);
$this->assertEquals(
["status" => "ENUM('active','inactive') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"],
$aImportColumns
);
}
/**
@@ -279,7 +284,6 @@ PHP
self::assertNull($defaultValue, 'Invalid default value for Date attribute should give null default value');
}
public function testDateInvalidDefaultReturnsNullAsDefaultValue_Case2()
{
$oDateAttribute = $this->GivenAttribute(\WorkOrder::class, 'start_date', AttributeDate::class, '"27/01/2025"', false);
@@ -337,10 +341,10 @@ PHP
'default_value' => $defaultValue,
'allowed_values' => null,
'depends_on' => [],
'always_load_in_tables' => false
'always_load_in_tables' => false,
]);
$oAttribute->SetHostClass($sHostClass);
return $oAttribute;
}
}
}

View File

@@ -36,7 +36,8 @@ class AttributeImageTest extends ItopDataTestCase
/**
* Note that we need to reset manually the cache in \utils::GetAbsoluteUrlAppRoot, which is called from \AttributeImage::Get
*/
private function SetNewAppRootUrl(Config $oConfig, string $sAppRootUrl):void {
private function SetNewAppRootUrl(Config $oConfig, string $sAppRootUrl): void
{
$oConfig->Set('app_root_url', $sAppRootUrl);
$this->SetNonPublicStaticProperty(utils::class, 'sAbsoluteUrlAppRootCache', null);
}

View File

@@ -4,7 +4,8 @@
* @since 3.0.0 N°4515
* @used-by \Combodo\iTop\Test\UnitTest\Core\AttributeURLTest
*/
class AttributeURLDefaultPattern extends AttributeURL {
class AttributeURLDefaultPattern extends AttributeURL
{
public function GetValidationPattern()
{
/** @noinspection OneTimeUseVariablesInspection */

View File

@@ -5,7 +5,8 @@ namespace Combodo\iTop\Test\UnitTest\Core;
use AttributeURLDefaultPattern;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
class AttributeURLTest extends ItopTestCase {
class AttributeURLTest extends ItopTestCase
{
public function setUp(): void
{
parent::setUp();
@@ -19,7 +20,7 @@ class AttributeURLTest extends ItopTestCase {
*/
public function testCheckFormat(string $sUrlValue, int $iExpectedResult): void
{
$oAttDefUrl = new AttributeURLDefaultPattern('myCode', ["target"=>'_blank', "allowed_values"=>null, "sql"=>'url', "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array(), "always_load_in_tables"=>false]);
$oAttDefUrl = new AttributeURLDefaultPattern('myCode', ["target" => '_blank', "allowed_values" => null, "sql" => 'url', "default_value" => '', "is_null_allowed" => true, "depends_on" => [], "always_load_in_tables" => false]);
$bResult = $oAttDefUrl->CheckFormat($sUrlValue);
$this->assertSame($iExpectedResult, $bResult);

View File

@@ -5,18 +5,15 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Test\UnitTest\Core;
use BulkExport;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use DBObjectSearch;
class BulkExportTest extends ItopDataTestCase
{
const CREATE_TEST_ORG = true;
public const CREATE_TEST_ORG = true;
public function OrganizationsForExportProvider()
{
@@ -45,7 +42,7 @@ EOF;
EOF;
return [
'Page1'=>[
'Page1' => [
'list_org' => [
['org1', true],
['org2', true],
@@ -63,9 +60,9 @@ EOF;
],
'export_org' => $sExportResultPage1,
'nb_pages' => 1,
'expected_status' =>'run'
'expected_status' => 'run',
],
'Page2'=>[
'Page2' => [
'list_org' => [
['org1', true],
['org2', true],
@@ -83,8 +80,8 @@ EOF;
],
'export_org' => $sExportResultPage2,
'nb_pages' => 2,
'expected_status' =>'done'
]
'expected_status' => 'done',
],
];
}
@@ -99,9 +96,12 @@ EOF;
* @throws \OQLException
* @throws \ReflectionException
*/
public function testExportWithShowObsoleteParam($aListOrg,
$sExpectedValue, $iNbPage, $sExpectedStatus)
{
public function testExportWithShowObsoleteParam(
$aListOrg,
$sExpectedValue,
$iNbPage,
$sExpectedStatus
) {
// Create tests organizations to have enough data (some obsolete)
$iFirstOrg = 0;
foreach ($aListOrg as $aOrg) {
@@ -110,18 +110,18 @@ EOF;
$oObj->Set('status', 'inactive');
$oObj->DBUpdate();
}
if($iFirstOrg === 0){
if ($iFirstOrg === 0) {
$iFirstOrg = $oObj->GetKey();
}
}
$aResult = [
// Fallback error, just in case
'code' => 'error',
'percentage' => 100,
'message' => "Export not found for token",
];
// Prepare status info and for obsolete data to `false` in order to check that we have less organizations
// in the export result than we have in DB
$aStatusInfo = [
@@ -132,15 +132,15 @@ EOF;
"sClass" => "Organization",
"sAttCode" => "name",
"sLabel" => "Name",
"sColLabel" => "Name"
]
"sColLabel" => "Name",
],
],
"text_qualifier" => "\"",
"charset" => "ISO-8859-1",
"separator" => ",",
"date_format" => "Y-m-d H:i:s",
"formatted_text" => false,
"show_obsolete_data" => false
"text_qualifier" => "\"",
"charset" => "ISO-8859-1",
"separator" => ",",
"date_format" => "Y-m-d H:i:s",
"formatted_text" => false,
"show_obsolete_data" => false,
];
$oSearch = DBObjectSearch::FromOQL('SELECT Organization WHERE id >= '.$iFirstOrg);
@@ -154,7 +154,7 @@ EOF;
for ($i = 0; $i < $iNbPage; $i++) {
$data .= $oExporter->GetNextChunk($aResult);
}
$this->assertEquals($sExpectedStatus,$aResult['code']);
$this->assertEquals($sExpectedStatus, $aResult['code']);
$this->assertEquals($sExpectedValue, $data);
}

View File

@@ -1,6 +1,5 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Core;
use CMDBSource;
@@ -48,79 +47,79 @@ class CMDBSourceTest extends ItopTestCase
public function compareFieldTypesProvider()
{
return array(
'same datetime types' => array(true, 'DATETIME', 'DATETIME'),
'different types' => array(false, 'VARCHAR(255)', 'INT(11)'),
'different types, same type options' => array(false, 'VARCHAR(11)', 'INT(11)'),
'same int declaration, same case' => array(true, 'INT(11)', 'INT(11)'),
'same int declaration, different case on data type' => array(true, 'INT(11)', 'int(11)'),
'same enum declaration, same case' => array(
return [
'same datetime types' => [true, 'DATETIME', 'DATETIME'],
'different types' => [false, 'VARCHAR(255)', 'INT(11)'],
'different types, same type options' => [false, 'VARCHAR(11)', 'INT(11)'],
'same int declaration, same case' => [true, 'INT(11)', 'INT(11)'],
'same int declaration, different case on data type' => [true, 'INT(11)', 'int(11)'],
'same enum declaration, same case' => [
true,
"ENUM('error','idle','planned','running')",
"ENUM('error','idle','planned','running')",
),
'same enum declaration, different case on data type' => array(
],
'same enum declaration, different case on data type' => [
true,
"ENUM('error','idle','planned','running')",
"enum('error','idle','planned','running')",
),
'same enum declaration, different case on type options' => array(
],
'same enum declaration, different case on type options' => [
false,
"ENUM('ERROR','IDLE','planned','running')",
"ENUM('error','idle','planned','running')",
),
'same enum declaration, different case on both data type and type options' => array(
],
'same enum declaration, different case on both data type and type options' => [
false,
"ENUM('ERROR','IDLE','planned','running')",
"enum('error','idle','planned','running')",
),
'MariaDB 10.2 nullable datetime' => array(
],
'MariaDB 10.2 nullable datetime' => [
true,
'DATETIME',
"datetime DEFAULT 'NULL'",
),
'MariaDB 10.2 nullable text' => array(
],
'MariaDB 10.2 nullable text' => [
true,
'TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci',
"text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 'NULL'",
),
'MariaDB 10.2 nullable unsigned int' => array(
],
'MariaDB 10.2 nullable unsigned int' => [
true,
'INT(11) UNSIGNED',
"int(11) unsigned DEFAULT 'NULL'",
),
'MariaDB 10.2 varchar with default value' => array(
],
'MariaDB 10.2 varchar with default value' => [
true,
'VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 0',
"varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '0'",
),
'varchar with default value not at the end' => array(
],
'varchar with default value not at the end' => [
true,
"VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 0 COMMENT 'my comment'",
"varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '0' COMMENT 'my comment'",
),
'MariaDB 10.2 Enum with string default value' => array(
],
'MariaDB 10.2 Enum with string default value' => [
true,
"ENUM('error','idle','planned','running') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 'planned'",
"enum('error','idle','planned','running') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 'planned'",
),
'MariaDB 10.2 Enum with numeric default value' => array(
],
'MariaDB 10.2 Enum with numeric default value' => [
true,
"ENUM('1','2','3') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '1'",
"enum('1','2','3') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '1'",
),
'ENUM with values containing parenthesis' => array(
],
'ENUM with values containing parenthesis' => [
true, // see N°3065 : if having distinct values having parenthesis in enum values will cause comparison to be inexact
"ENUM('CSP A','CSP M','NA','OEM(ROC)','OPEN(VL)','RETAIL (Boite)') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
"enum('CSP A','CSP M','NA','OEM(ROC)','OPEN(VL)','RETAIL (Boite)') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
),
],
// N°3065 before the fix this returned true :(
'ENUM with different values, containing parenthesis' => array(
'ENUM with different values, containing parenthesis' => [
false,
"ENUM('value 1 (with parenthesis)','value 2') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
"enum('value 1 (with parenthesis)','value 3') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
),
);
],
];
}
/**
@@ -204,7 +203,7 @@ class CMDBSourceTest extends ItopTestCase
});
DbConnectionWrapper::SetDbConnectionMockForQuery($oMockMysqli);
$sTestErrorLogPath = APPROOT . 'log/error.phpunit.log';
$sTestErrorLogPath = APPROOT.'log/error.phpunit.log';
IssueLog::Enable($sTestErrorLogPath);
try {
$this->InvokeNonPublicStaticMethod(CMDBSource::class, 'LogDeadLock', [$oDeadlockException, true, false]);

View File

@@ -1,13 +1,12 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Test\UnitTest\Core;
use CMDBSource;
use Exception;
use IssueLog;
@@ -41,7 +40,6 @@ class DeadLockInjection
$this->bShowRequest = $bShowRequest;
}
public function query($sSQL)
{
if (utils::StartsWith($sSQL, "SELECT")) {
@@ -60,4 +58,4 @@ class DeadLockInjection
}
}
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -89,8 +90,7 @@ class TransactionsTest extends ItopTestCase
$this->debug("---> DBInsert()");
try {
$oTicket->DBWrite();
}
catch (Exception $e) {
} catch (Exception $e) {
// If an exception occurs must be a deadlock
$this->assertTrue(CMDBSource::IsDeadlockException($e), $e->getMessage());
}
@@ -161,7 +161,7 @@ class TransactionsTest extends ItopTestCase
}
/**
* Test DBUpdate database transaction by provoking deadlock exceptions
* Test DBUpdate database transaction by provoking deadlock exceptions
*
* @dataProvider DBUpdateProvider
* @param $iFailAt
@@ -210,8 +210,7 @@ class TransactionsTest extends ItopTestCase
$this->debug("---> DBUpdate()");
try {
$oTicket->DBWrite();
}
catch (Exception $e) {
} catch (Exception $e) {
// If an exception occurs must be a deadlock
$this->assertTrue(CMDBSource::IsDeadlockException($e));
}
@@ -281,11 +280,10 @@ class TransactionsTest extends ItopTestCase
try {
DbConnectionWrapper::SetDbConnectionMockForQuery();
parent::tearDown();
}
catch (MySQLTransactionNotClosedException $e) {
} catch (MySQLTransactionNotClosedException $e) {
if ($this->getName() === 'testTransactionOpenedNotClosed') {
$this->debug('Executing the testTransactionOpenNoClose method throws a '.MySQLTransactionNotClosedException::class.' exception in tearDown');
}
}
}
}
}

View File

@@ -5,7 +5,6 @@ namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use CSVParser;
class CSVParserTest extends ItopTestCase
{
protected function setUp(): void
@@ -36,32 +35,29 @@ a2?;?b?;?c?
?a?;?b?;?ouf !?
spaces trimmed out ; 1234; mac@enroe.com ';
$aExpectedResult = array(
array('line 0, col 0', 'line 0, col 1', 'line 0, col 2'),
array('a', 'b', 'c'),
array('a', 'b', null),
array(' a ', ' b ', ' c '),
array('a', 'b', 'c'),
array('', '', ''),
array('', '', ''),
array('a"', 'b', 'c'),
array("a1\na2", 'b', 'c'),
array('a1,a2', 'b', 'c'),
array('a', 'b', "c1,\",c2\n,c3"),
array('a', 'b', 'ouf !'),
array('spaces trimmed out', '1234', 'mac@enroe.com'),
);
$aExpectedResult = [
['line 0, col 0', 'line 0, col 1', 'line 0, col 2'],
['a', 'b', 'c'],
['a', 'b', null],
[' a ', ' b ', ' c '],
['a', 'b', 'c'],
['', '', ''],
['', '', ''],
['a"', 'b', 'c'],
["a1\na2", 'b', 'c'],
['a1,a2', 'b', 'c'],
['a', 'b', "c1,\",c2\n,c3"],
['a', 'b', 'ouf !'],
['spaces trimmed out', '1234', 'mac@enroe.com'],
];
$oCSVParser = new CSVParser($sDataFile, $sSeparator, $sDelimiter);
$aData = $oCSVParser->ToArray(1, null, 0);
foreach ($aData as $iRow => $aRow)
{
foreach ($aRow as $iCol => $cellValue)
{
foreach ($aData as $iRow => $aRow) {
foreach ($aRow as $iCol => $cellValue) {
$this->assertSame($aExpectedResult[$iRow][$iCol], $cellValue, "Line $iRow, Column $iCol");
}
}
}
}

View File

@@ -2,21 +2,18 @@
namespace Combodo\iTop\Test\UnitTest\Core;
use CMDBObject;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use CoreException;
use Exception;
use MetaModel;
/**
* @since 2.7.7 3.0.2 3.1.0 N°3717 tests history objects creation
*
* @package Combodo\iTop\Test\UnitTest\Core
*/
class CMDBObjectTest extends ItopDataTestCase
{
private $sAdminLogin;
@@ -51,8 +48,11 @@ class CMDBObjectTest extends ItopDataTestCase
$oTestObject->Set('url', 'https://www.combodo.com');
$oTestObject->DBWrite();
self::assertFalse(CMDBObject::GetCurrentChange()->IsNew(), 'TrackInfo : Current change persisted');
self::assertEquals($sTrackInfo, CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : current change created with expected trackinfo');
self::assertEquals(
$sTrackInfo,
CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : current change created with expected trackinfo'
);
//-- new object with non persisted current change
$sTrackInfo2 = $sTrackInfo.'_2';
@@ -64,8 +64,11 @@ class CMDBObjectTest extends ItopDataTestCase
$oTestObject->Set('url', 'https://fr.wikipedia.org');
$oTestObject->DBUpdate();
self::assertFalse(CMDBObject::GetCurrentChange()->IsNew(), 'SetCurrentChange : Current change persisted');
self::assertEquals($sTrackInfo2, CMDBObject::GetCurrentChange()->Get('userinfo'),
'SetCurrentChange : current change created with expected trackinfo');
self::assertEquals(
$sTrackInfo2,
CMDBObject::GetCurrentChange()->Get('userinfo'),
'SetCurrentChange : current change created with expected trackinfo'
);
//-- new object with current change init using helper method
$sTrackInfo3 = $sTrackInfo.'_3';
@@ -73,8 +76,11 @@ class CMDBObjectTest extends ItopDataTestCase
$oTestObject->Set('url', 'https://en.wikipedia.org');
$oTestObject->DBUpdate();
self::assertFalse(CMDBObject::GetCurrentChange()->IsNew(), 'SetCurrentChangeFromParams : Current change persisted');
self::assertEquals($sTrackInfo3, CMDBObject::GetCurrentChange()->Get('userinfo'),
'SetCurrentChangeFromParams : current change created with expected trackinfo');
self::assertEquals(
$sTrackInfo3,
CMDBObject::GetCurrentChange()->Get('userinfo'),
'SetCurrentChangeFromParams : current change created with expected trackinfo'
);
// restore initial conditions
$oTestObject->DBDelete();
@@ -82,7 +88,8 @@ class CMDBObjectTest extends ItopDataTestCase
CMDBObject::SetTrackInfo($sInitialTrackInfo);
}
public function CurrentChangeUnderImpersonationProvider(){
public function CurrentChangeUnderImpersonationProvider()
{
return [
'no track info' => [ 'sTrackInfo' => null ],
'track info from approvalbase' => [
@@ -99,7 +106,8 @@ class CMDBObjectTest extends ItopDataTestCase
* @runInSeparateProcess
* @dataProvider CurrentChangeUnderImpersonationProvider
*/
public function testCurrentChangeUnderImpersonation($sTrackInfo=null, $sExpectedChangeLogWhenImpersonation=null) {
public function testCurrentChangeUnderImpersonation($sTrackInfo = null, $sExpectedChangeLogWhenImpersonation = null)
{
$this->CreateTestOrganization();
$sUid = date('dmYHis');
@@ -119,7 +127,7 @@ class CMDBObjectTest extends ItopDataTestCase
// reset current change
CMDBObject::SetCurrentChange(null);
if (is_null($sTrackInfo)){
if (is_null($sTrackInfo)) {
CMDBObject::SetTrackInfo(null);
} else {
$sTrackInfo = $this->ReplaceByFriendlyNames($sTrackInfo, $oAdminUser, $oImpersonatedUser);
@@ -127,43 +135,70 @@ class CMDBObjectTest extends ItopDataTestCase
}
$this->CreateSimpleObject();
if (is_null($sTrackInfo)){
self::assertEquals($oAdminUser->GetFriendlyName(), CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : no impersonation');
if (is_null($sTrackInfo)) {
self::assertEquals(
$oAdminUser->GetFriendlyName(),
CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : no impersonation'
);
} else {
self::assertEquals($sTrackInfo, CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : no impersonation');
self::assertEquals(
$sTrackInfo,
CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : no impersonation'
);
}
self::assertEquals($oAdminUser->GetKey(), CMDBObject::GetCurrentChange()->Get('user_id'),
'TrackInfo : admin userid');
self::assertEquals(
$oAdminUser->GetKey(),
CMDBObject::GetCurrentChange()->Get('user_id'),
'TrackInfo : admin userid'
);
\UserRights::Impersonate($sImpersonatedLogin);
$this->CreateSimpleObject();
if (is_null($sExpectedChangeLogWhenImpersonation)){
if (is_null($sExpectedChangeLogWhenImpersonation)) {
$sExpectedMsg = $this->ReplaceByFriendlyNames("AdminSurName AdminName on behalf of ImpersonatedSurName ImpersonatedName", $oAdminUser, $oImpersonatedUser);
self::assertEquals($sExpectedMsg, CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : impersonation');
self::assertEquals(
$sExpectedMsg,
CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : impersonation'
);
} else {
$sExpectedMsg = $this->ReplaceByFriendlyNames($sExpectedChangeLogWhenImpersonation, $oAdminUser, $oImpersonatedUser);
self::assertEquals($sExpectedMsg, CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : impersonation');
self::assertEquals(
$sExpectedMsg,
CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : impersonation'
);
}
self::assertEquals(null, CMDBObject::GetCurrentChange()->Get('user_id'),
'TrackInfo : no userid to force userinfo being displayed on UI caselog side');
self::assertEquals(
null,
CMDBObject::GetCurrentChange()->Get('user_id'),
'TrackInfo : no userid to force userinfo being displayed on UI caselog side'
);
\UserRights::Deimpersonate();
$this->CreateSimpleObject();
if (is_null($sTrackInfo)){
self::assertEquals($oAdminUser->GetFriendlyName(), CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : no impersonation');
if (is_null($sTrackInfo)) {
self::assertEquals(
$oAdminUser->GetFriendlyName(),
CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : no impersonation'
);
} else {
self::assertEquals($sTrackInfo, CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : no impersonation');
self::assertEquals(
$sTrackInfo,
CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : no impersonation'
);
}
self::assertEquals($oAdminUser->GetKey(), CMDBObject::GetCurrentChange()->Get('user_id'),
'TrackInfo : admin userid');
self::assertEquals(
$oAdminUser->GetKey(),
CMDBObject::GetCurrentChange()->Get('user_id'),
'TrackInfo : admin userid'
);
// restore initial conditions
CMDBObject::SetCurrentChange($oInitialCurrentChange);
@@ -196,7 +231,7 @@ class CMDBObjectTest extends ItopDataTestCase
* @dataProvider RecordObjDeletionProvider
*
*/
public function testRecordObjDeletion( string $sFirstName, string $sName)
public function testRecordObjDeletion(string $sFirstName, string $sName)
{
$oPerson = MetaModel::NewObject('Person', [
'first_name' => $sFirstName,
@@ -208,39 +243,40 @@ class CMDBObjectTest extends ItopDataTestCase
$bDeletionOK = true;
try {
$oDeletionPlan = $this->InvokeNonPublicMethod(CMDBObject::class, 'RecordObjDeletion', $oPerson, [$oPerson->GetKey()]);
}
catch (CoreException $e) {
} catch (CoreException $e) {
$bDeletionOK = false;
}
// We don't need to test the result (truncated string), it's already done in \DBObject::SetTrim() with N°3448
$this->assertTrue($bDeletionOK);
}
private function ReplaceByFriendlyNames($sMessage, $oAdminUser, $oImpersonatedUser) : string {
private function ReplaceByFriendlyNames($sMessage, $oAdminUser, $oImpersonatedUser): string
{
$sNewMessage = str_replace('AdminSurName AdminName', $oAdminUser->GetFriendlyName(), $sMessage);
$sNewMessage = str_replace('ImpersonatedSurName ImpersonatedName', $oImpersonatedUser->GetFriendlyName(), $sNewMessage);
return $sNewMessage;
}
private function CreateSimpleObject(){
private function CreateSimpleObject()
{
/** @var \DocumentWeb $oTestObject */
$oTestObject = MetaModel::NewObject('DocumentWeb');
$oTestObject->Set('name', 'PHPUnit test');
$oTestObject->Set('org_id', $this->getTestOrgId() );
$oTestObject->Set('org_id', $this->getTestOrgId());
$oTestObject->Set('url', 'https://www.combodo.com');
$oTestObject->DBWrite();
}
private function CreateUserForImpersonation($sLogin, $sProfileName, $sName, $sSurname): \UserLocal {
private function CreateUserForImpersonation($sLogin, $sProfileName, $sName, $sSurname): \UserLocal
{
/** @var \Person $oPerson */
$oPerson = $this->createObject('Person', array(
$oPerson = $this->createObject('Person', [
'name' => $sName,
'first_name' => $sSurname,
'org_id' => $this->getTestOrgId(),
));
]);
$oProfile = \MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => $sProfileName), true);
$oProfile = \MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => $sProfileName], true);
/** @var \UserLocal $oUser */
$oUser = $this->CreateUser($sLogin, $oProfile->GetKey(), "1234567Azert@", $oPerson->GetKey());

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -23,6 +24,7 @@ use Server;
use Team;
use UserRequest;
use utils;
use const EVENT_DB_ABOUT_TO_DELETE;
use const EVENT_DB_AFTER_DELETE;
use const EVENT_DB_AFTER_WRITE;
@@ -35,11 +37,10 @@ use const EVENT_ENUM_TRANSITIONS;
class CRUDEventTest extends ItopDataTestCase
{
const USE_TRANSACTION = true;
const CREATE_TEST_ORG = true;
use DBObject\Utils\EventTest;
use DBObject\Utils\ClassesWithDebug;
public const USE_TRANSACTION = true;
public const CREATE_TEST_ORG = true;
private static string $sLogFile = 'log/test_error_CRUDEventTest.log';
@@ -447,10 +448,10 @@ class CRUDEventTest extends ItopDataTestCase
$oUserRequest->DBInsert();
// 1 insert for UserRequest, 3 insert for lnkFunctionalCIToTicket
$this->AssertEventCountEquals(4,EVENT_DB_COMPUTE_VALUES);
$this->AssertEventCountEquals(4,EVENT_DB_CHECK_TO_WRITE);
$this->AssertEventCountEquals(4,EVENT_DB_BEFORE_WRITE);
$this->AssertEventCountEquals(4,EVENT_DB_AFTER_WRITE);
$this->AssertEventCountEquals(4, EVENT_DB_COMPUTE_VALUES);
$this->AssertEventCountEquals(4, EVENT_DB_CHECK_TO_WRITE);
$this->AssertEventCountEquals(4, EVENT_DB_BEFORE_WRITE);
$this->AssertEventCountEquals(4, EVENT_DB_AFTER_WRITE);
$this->AssertEventNotReceived(EVENT_DB_LINKS_CHANGED, 'Event must not be fired if host object is created with links');
$this->AssertTotalEventCountEquals(16);
@@ -724,4 +725,4 @@ class CRUDEventTest extends ItopDataTestCase
$this->assertArrayNotHasKey('ev_assign', $aTransitions, 'Assign transition should have been removed by EVENT_ENUM_TRANSITIONS handler');
$this->assertEquals(1, count($aRefTransitions) - count($aTransitions), 'Only one transition should have been removed');
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -14,20 +15,20 @@ use IssueLog;
use LogChannels;
use MetaModel;
use utils;
use const EVENT_DB_LINKS_CHANGED;
class CRUDEventWithModifiedDataModelTest extends ItopCustomDatamodelTestCase
{
use EventTest;
use ClassesWithDebug;
public function GetDatamodelDeltaAbsPath(): string
{
return __DIR__.'/Delta/dbobjecttest.xml';
}
const USE_TRANSACTION = true;
const CREATE_TEST_ORG = false;
use EventTest;
use ClassesWithDebug;
public const USE_TRANSACTION = true;
public const CREATE_TEST_ORG = false;
private static string $sLogFile = 'log/test_error_CRUDEventTest.log';
@@ -79,4 +80,3 @@ class CRUDEventWithModifiedDataModelTest extends ItopCustomDatamodelTestCase
$this->AssertEventCountEquals(0, EVENT_DB_LINKS_CHANGED, 'Event EVENT_DB_LINKS_CHANGED should not have been thrown on deleted objects');
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0

View File

@@ -1,4 +1,5 @@
<?php
// Copyright (c) 2010-2024 Combodo SAS
//
// This file is part of iTop.
@@ -40,19 +41,17 @@ use UserRequest;
use UserRights;
use utils;
/**
* @group specificOrgInSampleData
*/
class DBObjectTest extends ItopDataTestCase
{
const CREATE_TEST_ORG = true;
const INVALID_OBJECT_KEY = 123456789;
public const CREATE_TEST_ORG = true;
public const INVALID_OBJECT_KEY = 123456789;
// Counts
public $aReloadCount = [];
protected function setUp(): void
{
parent::setUp();
@@ -83,18 +82,18 @@ class DBObjectTest extends ItopDataTestCase
public function keyProviderOK()
{
return array(
array(1, true),
array('255', true),
array(-24576, true),
array(0123, true),
array(0xCAFE, true),
array(PHP_INT_MIN, true),
array(PHP_INT_MAX, true),
array('test', false),
array('', false),
array('a255', false),
array('PHP_INT_MIN', false));
return [
[1, true],
['255', true],
[-24576, true],
[0123, true],
[0xCAFE, true],
[PHP_INT_MIN, true],
[PHP_INT_MAX, true],
['test', false],
['', false],
['a255', false],
['PHP_INT_MIN', false]];
}
/**
@@ -152,7 +151,7 @@ class DBObjectTest extends ItopDataTestCase
*/
public function testAttributeRefresh_FriendlyNameWithoutCascade()
{
$oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2));
$oObject = \MetaModel::NewObject('Person', ['name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2]);
static::assertEquals('John Foo', $oObject->Get('friendlyname'));
$oObject->Set('name', 'Who');
@@ -181,7 +180,7 @@ class DBObjectTest extends ItopDataTestCase
*/
public function testAttributeRefresh_FriendlyNameFromDB()
{
$oObject = \MetaModel::NewObject('Person', array('name' => 'Gary', 'first_name' => 'Romain', 'org_id' => 3, 'location_id' => 2));
$oObject = \MetaModel::NewObject('Person', ['name' => 'Gary', 'first_name' => 'Romain', 'org_id' => 3, 'location_id' => 2]);
$oObject->DBInsert();
$iObjKey = $oObject->GetKey();
@@ -198,7 +197,7 @@ class DBObjectTest extends ItopDataTestCase
*/
public function testPartialAttributeEvaluation()
{
$oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'org_id' => 3, 'location_id' => 2));
$oObject = \MetaModel::NewObject('Person', ['name' => 'Foo', 'org_id' => 3, 'location_id' => 2]);
static::assertEquals(' Foo', $oObject->Get('friendlyname'));
}
@@ -208,7 +207,7 @@ class DBObjectTest extends ItopDataTestCase
*/
public function testEmptyAttributeEvaluation()
{
$oObject = \MetaModel::NewObject('Person', array('org_id' => 3, 'location_id' => 2));
$oObject = \MetaModel::NewObject('Person', ['org_id' => 3, 'location_id' => 2]);
static::assertEquals(' ', $oObject->Get('friendlyname'));
}
@@ -232,7 +231,7 @@ class DBObjectTest extends ItopDataTestCase
*/
public function testAttributeRefresh_ObsolescenceFlagWithoutCascade()
{
$oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2));
$oObject = \MetaModel::NewObject('Person', ['name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2]);
static::assertEquals(false, (bool)$oObject->Get('obsolescence_flag'));
$oObject->Set('status', 'inactive');
@@ -264,26 +263,26 @@ class DBObjectTest extends ItopDataTestCase
*/
public function testAttributeRefresh_ExternalKeysAndFields()
{
$this->assertDBQueryCount(0, function() use (&$oObject){
$oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2));
$this->assertDBQueryCount(0, function () use (&$oObject) {
$oObject = \MetaModel::NewObject('Person', ['name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2]);
});
$this->assertDBQueryCount(2, function() use (&$oObject){
$this->assertDBQueryCount(2, function () use (&$oObject) {
static::assertEquals('Demo', $oObject->Get('org_id_friendlyname'));
static::assertEquals('Grenoble', $oObject->Get('location_id_friendlyname'));
});
// External key given as an id
$this->assertDBQueryCount(1, function() use (&$oObject){
$this->assertDBQueryCount(1, function () use (&$oObject) {
$oObject->Set('org_id', 2);
static::assertEquals('IT Department', $oObject->Get('org_id_friendlyname'));
});
// External key given as an object
$this->assertDBQueryCount(1, function() use (&$oBordeaux){
$this->assertDBQueryCount(1, function () use (&$oBordeaux) {
$oBordeaux = \MetaModel::GetObject('Location', 1);
});
$this->assertDBQueryCount(0, function() use (&$oBordeaux, &$oObject){
$this->assertDBQueryCount(0, function () use (&$oBordeaux, &$oObject) {
/** @var DBObject $oObject */
$oObject->Set('location_id', $oBordeaux);
static::assertEquals('IT Department', $oObject->Get('org_id_friendlyname'));
@@ -292,7 +291,7 @@ class DBObjectTest extends ItopDataTestCase
});
static::assertEquals('Bordeaux', $oObject->Get('location_id_friendlyname'));
// static::assertEquals('toto', $oObject->EvaluateExpression(\Expression::FromOQL("CONCAT(org_name, '-', location_id_friendlyname)")));
// static::assertEquals('toto', $oObject->EvaluateExpression(\Expression::FromOQL("CONCAT(org_name, '-', location_id_friendlyname)")));
}
/**
@@ -304,7 +303,7 @@ class DBObjectTest extends ItopDataTestCase
{
$this->ResetReloadCount();
$this->assertDBQueryCount(0, function() use (&$oObject){
$this->assertDBQueryCount(0, function () use (&$oObject) {
$oObject = \MetaModel::NewObject('Person', ['name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2]);
});
// The number of queries depends on the installed modules so it varies on CI
@@ -314,14 +313,14 @@ class DBObjectTest extends ItopDataTestCase
$this->debug("Created $sClass::$sKey");
$this->DebugReloadCount("Person::DBInsertNoReload()");
$this->assertDBQueryCount(0, function() use (&$oObject){
$this->assertDBQueryCount(0, function () use (&$oObject) {
static::assertEquals('Demo', $oObject->Get('org_id_friendlyname'));
static::assertEquals('Grenoble', $oObject->Get('location_id_friendlyname'));
});
$this->DebugReloadCount("Get('org_id_friendlyname') and Get('location_id_friendlyname')");
// External key given as an id
$this->assertDBQueryCount(1, function() use (&$oObject){
$this->assertDBQueryCount(1, function () use (&$oObject) {
$oObject->Set('org_id', 2);
static::assertEquals('IT Department', $oObject->Get('org_id_friendlyname'));
});
@@ -329,12 +328,12 @@ class DBObjectTest extends ItopDataTestCase
$this->DebugReloadCount("Set('org_id', 2) and Get('org_id_friendlyname')");
// External key given as an object
$this->assertDBQueryCount(1, function() use (&$oBordeaux){
$this->assertDBQueryCount(1, function () use (&$oBordeaux) {
$oBordeaux = MetaModel::GetObject('Location', 1);
});
$this->DebugReloadCount("GetObject('Location', 1)");
$this->assertDBQueryCount(0, function() use (&$oBordeaux, &$oObject){
$this->assertDBQueryCount(0, function () use (&$oBordeaux, &$oObject) {
$oObject->Set('location_id', $oBordeaux);
static::assertEquals('IT Department', $oObject->Get('org_id_friendlyname'));
static::assertEquals('IT Department', $oObject->Get('org_name'));
@@ -343,7 +342,6 @@ class DBObjectTest extends ItopDataTestCase
$this->DebugReloadCount("Set('location_id',...) Get('org_id_friendlyname') Get('org_name') Get('location_id_friendlyname')");
}
/**
* @covers DBObject::NewObject
* @covers DBObject::Get
@@ -353,7 +351,7 @@ class DBObjectTest extends ItopDataTestCase
{
$this->ResetReloadCount();
$this->assertDBQueryCount(0, function() use (&$oPerson){
$this->assertDBQueryCount(0, function () use (&$oPerson) {
$oPerson = MetaModel::NewObject('Person', ['name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2]);
});
// The number of queries depends on the installed modules so it varies on CI
@@ -363,7 +361,7 @@ class DBObjectTest extends ItopDataTestCase
$this->debug("Created $sPersonClass::$sPersonKey");
$this->DebugReloadCount("Person::DBInsertNoReload()");
$this->assertDBQueryCount(1, function() use (&$oTeam, &$oPerson){
$this->assertDBQueryCount(1, function () use (&$oTeam, &$oPerson) {
$oTeam = MetaModel::NewObject('Team', ['name' => 'Team Foo', 'org_id' => 3]);
// Add person to team
$oNewLink = new lnkPersonToTeam();
@@ -389,7 +387,7 @@ class DBObjectTest extends ItopDataTestCase
$this->assertCount(0, $oTeam->ListChanges());
// External key given as an id
$this->assertDBQueryCount(1, function() use (&$oTeam){
$this->assertDBQueryCount(1, function () use (&$oTeam) {
$oTeam->Set('org_id', 2);
static::assertEquals('IT Department', $oTeam->Get('org_id_friendlyname'));
});
@@ -397,10 +395,9 @@ class DBObjectTest extends ItopDataTestCase
$this->assertCount(1, $oTeam->ListChanges());
}
public function testSetExtKeyUnsetDependentAttribute()
{
$oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2));
$oObject = \MetaModel::NewObject('Person', ['name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2]);
$oOrg = \MetaModel::GetObject('Organization', 2);
$oObject->Set('org_id', $oOrg);
@@ -408,13 +405,13 @@ class DBObjectTest extends ItopDataTestCase
static::assertEquals(2, $oObject->Get('location_id'));
// Dependent external field is updated because the Set('org_id') is done with an object
$this->assertDBQueryCount(0, function() use (&$oObject){
$this->assertDBQueryCount(0, function () use (&$oObject) {
static::assertNotEmpty($oObject->Get('org_name'));
});
// Dependent external field is reset and reloaded from DB
$oObject->Set('org_id', 3);
$this->assertDBQueryCount(1, function() use (&$oObject){
$this->assertDBQueryCount(1, function () use (&$oObject) {
static::assertNotEmpty($oObject->Get('org_name'));
});
}
@@ -471,17 +468,16 @@ class DBObjectTest extends ItopDataTestCase
*/
public function testModelExpressions()
{
foreach (\MetaModel::GetClasses() as $sClass)
{
if (\MetaModel::IsAbstract($sClass)) continue;
foreach (\MetaModel::GetClasses() as $sClass) {
if (\MetaModel::IsAbstract($sClass)) {
continue;
}
$oObject = \MetaModel::NewObject($sClass);
foreach (\MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
if ($oAttDef->IsBasedOnOQLExpression())
{
foreach (\MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
if ($oAttDef->IsBasedOnOQLExpression()) {
$this->debug("$sClass::$sAttCode");
$this->assertDBQueryCount(0, function() use (&$oObject, &$oAttDef){
$this->assertDBQueryCount(0, function () use (&$oObject, &$oAttDef) {
$oObject->EvaluateExpression($oAttDef->GetOQLExpression());
});
}
@@ -604,7 +600,7 @@ class DBObjectTest extends ItopDataTestCase
$oTeam = MetaModel::NewObject(Team::class, [
'name' => 'The A Team',
'org_id' => $oDemoOrg->GetKey()
'org_id' => $oDemoOrg->GetKey(),
]);
// Part 1 - Test with an invalid id (non-existing object)
@@ -666,8 +662,7 @@ class DBObjectTest extends ItopDataTestCase
try {
$oTeam->CheckChangedExtKeysValues();
$this->fail('An unauthorized object should be detected as invalid');
}
catch (InvalidExternalKeyValueException $e) {
} catch (InvalidExternalKeyValueException $e) {
// Ok, the exception was expected
}
@@ -680,8 +675,7 @@ class DBObjectTest extends ItopDataTestCase
$oTeam->DBInsert(); // persisting invalid value and resets the object changed values
try {
$oTeam->CheckChangedExtKeysValues();
}
catch (InvalidExternalKeyValueException $e) {
} catch (InvalidExternalKeyValueException $e) {
$this->fail('An unauthorized value should be ignored when it is not being modified');
}
}
@@ -745,7 +739,7 @@ class DBObjectTest extends ItopDataTestCase
$oQueryOQL = \MetaModel::NewObject('QueryOQL', [
'name' => 'Test Query',
'description' => 'Test Query',
'oql' => 'SELECT Person'
'oql' => 'SELECT Person',
]);
$oQueryOQL->DBInsert();
@@ -768,12 +762,12 @@ class DBObjectTest extends ItopDataTestCase
*/
public function getAttributeIntegerDBIncrementProvider()
{
return array(
'Incrementation #1' => array('export_count', [5], 5),
'Incrementation #2' => array('export_count', [5, 10], 15),
'Incrementation #3' => array('export_count', [50, 20, 10, 100], 180),
'Incrementation #4' => array('export_count', [50, 20, -10, 1000], 1060)
);
return [
'Incrementation #1' => ['export_count', [5], 5],
'Incrementation #2' => ['export_count', [5, 10], 15],
'Incrementation #3' => ['export_count', [50, 20, 10, 100], 180],
'Incrementation #4' => ['export_count', [50, 20, -10, 1000], 1060],
];
}
/**
@@ -788,7 +782,7 @@ class DBObjectTest extends ItopDataTestCase
$oQueryOQL = \MetaModel::NewObject('QueryOQL', [
'name' => 'Test Query',
'description' => 'Test Query',
'oql' => 'SELECT Person'
'oql' => 'SELECT Person',
]);
$oQueryOQL->DBInsert();
@@ -811,7 +805,7 @@ class DBObjectTest extends ItopDataTestCase
$oQueryOQL = \MetaModel::NewObject('QueryOQL', [
'name' => 'Test Query',
'description' => 'Test Query',
'oql' => 'SELECT Person'
'oql' => 'SELECT Person',
]);
$oQueryOQL->DBInsert();
@@ -837,12 +831,12 @@ class DBObjectTest extends ItopDataTestCase
$oQueryOQL = \MetaModel::NewObject('QueryOQL', [
'name' => 'Test Query',
'description' => 'Test Query',
'oql' => 'SELECT Person'
'oql' => 'SELECT Person',
]);
$oQueryOQL->DBInsert();
// assert query count
$this->assertDBQueryCount(2, function() use (&$oQueryOQL) {
$this->assertDBQueryCount(2, function () use (&$oQueryOQL) {
$oQueryOQL->DBIncrement('export_count', 1);
});
}
@@ -978,8 +972,7 @@ class DBObjectTest extends ItopDataTestCase
try {
$oPerson->Set('email', 'test1@combodo.com');
$this->assertTrue(false, 'Set() should have raised a CoreException');
}
catch (\CoreException $e) {
} catch (\CoreException $e) {
$this->assertEquals($sMessage, $e->getMessage());
}
@@ -1045,9 +1038,9 @@ class DBObjectTest extends ItopDataTestCase
'xml',
[
'ev_assign',
'ev_timeout',
'ev_wait_for_approval',
'ev_autoresolve',
'ev_timeout',
'ev_wait_for_approval',
'ev_autoresolve',
],
],
'UserRequest - XML sort when in specific state' => [
@@ -1057,10 +1050,10 @@ class DBObjectTest extends ItopDataTestCase
'xml',
[
'ev_pending',
'ev_resolve',
'ev_reassign',
'ev_timeout',
'ev_autoresolve',
'ev_resolve',
'ev_reassign',
'ev_timeout',
'ev_autoresolve',
],
],
'UserRequest - Alphabetical (labels not codes) sort' => [
@@ -1070,9 +1063,9 @@ class DBObjectTest extends ItopDataTestCase
'alphabetical',
[
'ev_assign',
'ev_autoresolve',
'ev_timeout',
'ev_wait_for_approval',
'ev_autoresolve',
'ev_timeout',
'ev_wait_for_approval',
],
],
'UserRequest - Alphabetical (labels not codes) sort when in specific state' => [
@@ -1081,11 +1074,11 @@ class DBObjectTest extends ItopDataTestCase
'assigned',
'alphabetical',
[
'ev_autoresolve',
'ev_autoresolve',
'ev_resolve',
'ev_pending',
'ev_reassign',
'ev_timeout',
'ev_pending',
'ev_reassign',
'ev_timeout',
],
],
'UserRequest - Fixed sort' => [
@@ -1094,10 +1087,10 @@ class DBObjectTest extends ItopDataTestCase
null,
'fixed',
[
'ev_wait_for_approval',
'ev_wait_for_approval',
'ev_assign',
'ev_timeout',
'ev_autoresolve',
'ev_timeout',
'ev_autoresolve',
],
],
'UserRequest - Fixed sort when in specific state' => [
@@ -1117,10 +1110,10 @@ class DBObjectTest extends ItopDataTestCase
null,
'relative',
[
'ev_wait_for_approval',
'ev_wait_for_approval',
'ev_assign',
'ev_timeout',
'ev_autoresolve',
'ev_timeout',
'ev_autoresolve',
],
],
'UserRequest - Relative sort when in specific state' => [
@@ -1212,8 +1205,7 @@ class DBObjectTest extends ItopDataTestCase
$bDeletionOK = true;
try {
$oDeletionPlan = $oPerson->DBDelete();
}
catch (CoreException $e) {
} catch (CoreException $e) {
$bDeletionOK = false;
}
$this->assertTrue($bDeletionOK);
@@ -1265,7 +1257,7 @@ class DBObjectTest extends ItopDataTestCase
/**
* @since 3.1.0-3 3.1.1 3.2.0 N°6716 test creation
*/
public function testConstructorMemoryFootprint():void
public function testConstructorMemoryFootprint(): void
{
$idx = 0;
$fStart = microtime(true);
@@ -1287,7 +1279,7 @@ class DBObjectTest extends ItopDataTestCase
$sCurrPeak = \utils::BytesToFriendlyFormat($iMemoryPeakUsage, 4);
echo "$idx ".sprintf('%.1f ms', $fDuration * 1000)." - Peak Memory Usage: $sCurrPeak\n";
$this->assertTrue(($iMemoryPeakUsage - $iInitialPeak) <= $iMaxAllowedMemoryIncrease , "Peak memory changed from $sInitialPeak to $sCurrPeak after $i loops");
$this->assertTrue(($iMemoryPeakUsage - $iInitialPeak) <= $iMaxAllowedMemoryIncrease, "Peak memory changed from $sInitialPeak to $sCurrPeak after $i loops");
$fStartLoop = microtime(true);
}
@@ -1337,7 +1329,7 @@ class DBObjectTest extends ItopDataTestCase
$sPrefix = 'a'; // just a small prefix so that the emoji bytes won't have a power of 2 (we want a non even value)
$sEmojiToRepeat = '😎'; // this emoji is 4 bytes long
$sEmojiRepeats = str_repeat($sEmojiToRepeat, $iValueLength - mb_strlen($sPrefix));
$sValueToSet = $sPrefix . $sEmojiRepeats;
$sValueToSet = $sPrefix.$sEmojiRepeats;
$oTicket = MetaModel::NewObject('UserRequest', [
'ref' => 'Test Ticket',
@@ -1356,14 +1348,14 @@ class DBObjectTest extends ItopDataTestCase
$bIsValueToSetBelowAttrMaxSize = ($iValueLength <= $iAttrMaxSize);
/** @noinspection PhpUnusedLocalVariableInspection */
[$bCheckStatus, $aCheckIssues, $bSecurityIssue] = $oTicket->CheckToWrite();
$this->assertEquals($bIsValueToSetBelowAttrMaxSize, $bCheckStatus, "CheckResult result:" . var_export($aCheckIssues, true));
$this->assertEquals($bIsValueToSetBelowAttrMaxSize, $bCheckStatus, "CheckResult result:".var_export($aCheckIssues, true));
$oTicket->SetTrim($sAttrCode, $sValueToSet);
$sValueInObject = $oTicket->Get($sAttrCode);
if ($bIsValueToSetBelowAttrMaxSize) {
$this->assertEquals($sValueToSet, $sValueInObject,'Should not alter string that is already shorter than attribute max length');
$this->assertEquals($sValueToSet, $sValueInObject, 'Should not alter string that is already shorter than attribute max length');
} else {
$this->assertEquals($iAttrMaxSize, mb_strlen($sValueInObject),'Should truncate at the same length than attribute max length');
$this->assertEquals($iAttrMaxSize, mb_strlen($sValueInObject), 'Should truncate at the same length than attribute max length');
$sLastCharsOfValueInObject = mb_substr($sValueInObject, -30);
$this->assertStringContainsString(' -truncated', $sLastCharsOfValueInObject, 'Should end with "truncated" comment');
}
@@ -1373,13 +1365,13 @@ class DBObjectTest extends ItopDataTestCase
{
return [
'short string should not be truncated' => ['name','name'],
'simple ascii string longer than 255 characters truncated' => [
str_repeat('e',300),
str_repeat('e',232) . ' -truncated (300 chars)'
],
'simple ascii string longer than 255 characters truncated' => [
str_repeat('e', 300),
str_repeat('e', 232).' -truncated (300 chars)',
],
'smiley string longer than 255 characters truncated' => [
str_repeat('😃',300),
str_repeat('😃',232) . ' -truncated (300 chars)'
str_repeat('😃', 300),
str_repeat('😃', 232).' -truncated (300 chars)',
],
];
@@ -1389,7 +1381,8 @@ class DBObjectTest extends ItopDataTestCase
* @dataProvider SetTrimProvider
* @return void
*/
public function testSetTrim($sName, $sResult){
public function testSetTrim($sName, $sResult)
{
$oOrganisation = MetaModel::NewObject(Organization::class);
$oOrganisation->SetTrim('name', $sName);
$this->assertEquals($sResult, $oOrganisation->Get('name'), 'SetTrim must limit string to 255 characters');
@@ -1399,21 +1392,23 @@ class DBObjectTest extends ItopDataTestCase
* @covers DBObject::SetComputedDate
* @return void
*/
public function testSetComputedDateOnAttributeDate(){
$oObject = MetaModel::NewObject(\CustomerContract::class, ['name'=>'Test contract','org_id'=>'3','provider_id'=>'2']);
$oObject->Set('start_date',time());
public function testSetComputedDateOnAttributeDate()
{
$oObject = MetaModel::NewObject(\CustomerContract::class, ['name' => 'Test contract','org_id' => '3','provider_id' => '2']);
$oObject->Set('start_date', time());
$oObject->SetComputedDate('end_date', "+2 weeks", 'start_date');
$this->assertTrue(true,'No fatal error on computing date');
$this->assertTrue(true, 'No fatal error on computing date');
}
/**
* @covers DBObject::SetComputedDate
* @return void
*/
public function testSetComputedDateOnAttributeDateTime(){
$oObject = MetaModel::NewObject(\WorkOrder::class, ['name'=>'Test workorder','description'=>'Toto']);
$oObject->Set('start_date','2024-01-01 09:45:00');
public function testSetComputedDateOnAttributeDateTime()
{
$oObject = MetaModel::NewObject(\WorkOrder::class, ['name' => 'Test workorder','description' => 'Toto']);
$oObject->Set('start_date', '2024-01-01 09:45:00');
$oObject->SetComputedDate('end_date', "+2 weeks", 'start_date');
$this->assertTrue(true,'No fatal error on computing date');
$this->assertTrue(true, 'No fatal error on computing date');
$this->assertEquals("2024-01-15 09:45:00", $oObject->Get('end_date'), 'SetComputedDate +2 weeks on a WorkOrder DateTimeAttribute');
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -11,6 +12,7 @@ use IssueLog;
use LogChannels;
use MetaModel;
use utils;
use const EVENT_DB_LINKS_CHANGED;
class DBObjectWithModifiedDataModelTest extends ItopCustomDatamodelTestCase
@@ -20,9 +22,8 @@ class DBObjectWithModifiedDataModelTest extends ItopCustomDatamodelTestCase
return __DIR__.'/Delta/dbobjecttest.xml';
}
const USE_TRANSACTION = true;
const CREATE_TEST_ORG = false;
public const USE_TRANSACTION = true;
public const CREATE_TEST_ORG = false;
private static string $sLogFile = 'log/test_error_CRUDEventTest.log';
@@ -81,4 +82,3 @@ class DBObjectWithModifiedDataModelTest extends ItopCustomDatamodelTestCase
$this->assertEquals('resolved', $oParent->Get('status'), 'The status should have been modified to resolved (the final state after a nested stimulus)');
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -10,7 +11,6 @@ use Combodo\iTop\Service\Events\EventData;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use MetaModel;
/**
* Test support class used to count events received
* And allow callbacks on events
@@ -51,7 +51,6 @@ class CRUDEventReceiver
$this->bDBUpdateCalledSuccessfullyDuringEvent = false;
}
/**
* Event callbacks => this function counts the received events by event name and source class
* If AddCallback() method has been called a specific callback is called, else only the count is done

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -6,11 +7,10 @@
namespace DBObject\Utils;
/**
* Add debug feature to test support class
*/
Trait ClassesWithDebug
trait ClassesWithDebug
{
public static function DebugStatic($sMsg)
{
@@ -22,4 +22,4 @@ Trait ClassesWithDebug
}
}
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -42,4 +43,4 @@ trait EventTest
{
$this->assertArrayNotHasKey($sEvent, self::$aEventCallsCount, $sMessage);
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -11,7 +12,6 @@ use DBSearch;
class DBSearchAddConditionPointingToTest extends ItopTestCase
{
protected function setUp(): void
{
parent::setUp();
@@ -67,4 +67,4 @@ class DBSearchAddConditionPointingToTest extends ItopTestCase
],
];
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Created by PhpStorm.
* User: Eric
@@ -21,7 +22,7 @@ use DBSearch;
class DBSearchCommitTest extends ItopDataTestCase
{
// Need database COMMIT in order to create the FULLTEXT INDEX of MySQL
const USE_TRANSACTION = false;
public const USE_TRANSACTION = false;
/**
* @group itopFaqLight
@@ -47,7 +48,6 @@ class DBSearchCommitTest extends ItopDataTestCase
$oSet = new DBObjectSet($oSearch);
static::assertEquals(1, $oSet->Count());
$oObjWithTagSet->Set(TAG_ATTCODE, 'tag1 tag2');
$oObjWithTagSet->DBWrite();
@@ -80,7 +80,6 @@ class DBSearchCommitTest extends ItopDataTestCase
$oSet = new \DBObjectSet($oSearch);
static::assertEquals(1, $oSet->Count());
$oObjWithTagSet->Set(TAG_ATTCODE, 'tag1 tag2');
$oObjWithTagSet->DBWrite();

View File

@@ -14,7 +14,6 @@ use DBSearch;
*/
class DBSearchIntersectTest extends ItopTestCase
{
protected function setUp(): void
{
parent::setUp();
@@ -46,104 +45,101 @@ class DBSearchIntersectTest extends ItopTestCase
public function FilterProvider()
{
$aTests = array();
$aTests = [];
$aTests['Union filtered by parent class'] = array(
$aTests['Union filtered by parent class'] = [
'left' => "SELECT ApplicationSolution UNION SELECT BusinessProcess",
'right' => "SELECT FunctionalCI WHERE org_id = 3",
'alias' => "ApplicationSolution",
'result' => "SELECT `ApplicationSolution` FROM ApplicationSolution AS `ApplicationSolution` WHERE (`ApplicationSolution`.`org_id` = 3) UNION SELECT `BusinessProcess` FROM BusinessProcess AS `BusinessProcess` WHERE (`BusinessProcess`.`org_id` = 3)");
'result' => "SELECT `ApplicationSolution` FROM ApplicationSolution AS `ApplicationSolution` WHERE (`ApplicationSolution`.`org_id` = 3) UNION SELECT `BusinessProcess` FROM BusinessProcess AS `BusinessProcess` WHERE (`BusinessProcess`.`org_id` = 3)"];
$aTests['Test union #2902'] = array(
$aTests['Test union #2902'] = [
'left' => "SELECT `L-1` FROM ServiceFamily AS `L-1` WHERE 1",
'right' => "SELECT `sf` FROM ServiceFamily AS `sf` JOIN Service AS `s` ON `s`.servicefamily_id = `sf`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id WHERE (`cc`.`org_id` = 3) UNION SELECT `sf` FROM ServiceFamily AS `sf` JOIN Service AS `s` ON `s`.servicefamily_id = `sf`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id JOIN Organization AS `child` ON `cc`.org_id = `child`.id JOIN Organization AS `root` ON `child`.parent_id BELOW `root`.id WHERE (`root`.`id` = 3)",
'alias' => "L-1",
'result' => "SELECT `L-1` FROM ServiceFamily AS `L-1` JOIN Service AS `s` ON `s`.servicefamily_id = `L-1`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id WHERE (`cc`.`org_id` = 3) UNION SELECT `L-1` FROM ServiceFamily AS `L-1` JOIN Service AS `s` ON `s`.servicefamily_id = `L-1`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id JOIN Organization AS `child` ON `cc`.org_id = `child`.id JOIN Organization AS `root` ON `child`.parent_id BELOW `root`.id WHERE (`root`.`id` = 3)");
'result' => "SELECT `L-1` FROM ServiceFamily AS `L-1` JOIN Service AS `s` ON `s`.servicefamily_id = `L-1`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id WHERE (`cc`.`org_id` = 3) UNION SELECT `L-1` FROM ServiceFamily AS `L-1` JOIN Service AS `s` ON `s`.servicefamily_id = `L-1`.id JOIN lnkCustomerContractToService AS `l1` ON `l1`.service_id = `s`.id JOIN CustomerContract AS `cc` ON `l1`.customercontract_id = `cc`.id JOIN Organization AS `child` ON `cc`.org_id = `child`.id JOIN Organization AS `root` ON `child`.parent_id BELOW `root`.id WHERE (`root`.`id` = 3)"];
$aTests['Multiple selected classes inverted'] = array(
$aTests['Multiple selected classes inverted'] = [
'left' => "SELECT `L`, `P` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE 1",
'right' => "SELECT Person WHERE org_id = 3",
'alias' => "P",
'result' => "SELECT `L`, `P` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE (`P`.`org_id` = 3)");
'result' => "SELECT `L`, `P` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE (`P`.`org_id` = 3)"];
$aTests['Multiple selected classes inverted 1'] = array(
$aTests['Multiple selected classes inverted 1'] = [
'left' => "SELECT `L`, `P`, `D` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id JOIN Server AS D ON D.location_id = L.id JOIN Person AS P2 ON P.manager_id = P2.id WHERE 1",
'right' => "SELECT Location WHERE org_id = 3",
'alias' => "L",
'result' => "SELECT `L`, `P`, `D` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id JOIN Server AS `D` ON `D`.location_id = `L`.id JOIN Person AS `P2` ON `P`.manager_id = `P2`.id WHERE (`L`.`org_id` = 3)");
'result' => "SELECT `L`, `P`, `D` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id JOIN Server AS `D` ON `D`.location_id = `L`.id JOIN Person AS `P2` ON `P`.manager_id = `P2`.id WHERE (`L`.`org_id` = 3)"];
$aTests['Multiple selected classes inverted 2'] = array(
$aTests['Multiple selected classes inverted 2'] = [
'left' => "SELECT `L`, `P`, `D` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id JOIN Server AS D ON D.location_id = L.id JOIN Person AS P2 ON P.manager_id = P2.id WHERE (`L`.`org_id` = 3)",
'right' => "SELECT Person WHERE org_id = 3",
'alias' => "P",
'result' => "SELECT `L`, `P`, `D` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id JOIN Server AS `D` ON `D`.location_id = `L`.id JOIN Person AS `P2` ON `P`.manager_id = `P2`.id WHERE ((`L`.`org_id` = 3) AND (`P`.`org_id` = 3))");
'result' => "SELECT `L`, `P`, `D` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id JOIN Server AS `D` ON `D`.location_id = `L`.id JOIN Person AS `P2` ON `P`.manager_id = `P2`.id WHERE ((`L`.`org_id` = 3) AND (`P`.`org_id` = 3))"];
$aTests['Same class'] = array(
$aTests['Same class'] = [
'left' => "SELECT Contact WHERE name = 'Christie'",
'right' => "SELECT Contact WHERE org_id = 3",
'alias' => "Contact",
'result' => "SELECT `Contact` FROM Contact AS `Contact` WHERE ((`Contact`.`name` = 'Christie') AND (`Contact`.`org_id` = 3))");
'result' => "SELECT `Contact` FROM Contact AS `Contact` WHERE ((`Contact`.`name` = 'Christie') AND (`Contact`.`org_id` = 3))"];
$aTests['Different Alias'] = array(
$aTests['Different Alias'] = [
'left' => "SELECT Contact AS C WHERE C.name = 'Christie'",
'right' => "SELECT Contact AS CC WHERE CC.org_id = 3",
'alias' => "C",
'result' => "SELECT `C` FROM Contact AS `C` WHERE ((`C`.`name` = 'Christie') AND (`C`.`org_id` = 3))");
'result' => "SELECT `C` FROM Contact AS `C` WHERE ((`C`.`name` = 'Christie') AND (`C`.`org_id` = 3))"];
$aTests['Multiple selected classes'] = array(
$aTests['Multiple selected classes'] = [
'left' => "SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE 1",
'right' => "SELECT Location WHERE org_id = 3",
'alias' => "L",
'result' => "SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE (`L`.`org_id` = 3)");
'result' => "SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE (`L`.`org_id` = 3)"];
$aTests['Joined classes'] = array(
$aTests['Joined classes'] = [
'left' => "SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE 1",
'right' => "SELECT Person WHERE org_id = 3",
'alias' => "P",
'result' => "SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE (`P`.`org_id` = 3)");
'result' => "SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE (`P`.`org_id` = 3)"];
$aTests['Joined filter'] = array(
$aTests['Joined filter'] = [
'left' => "SELECT `P` FROM Person AS `P` WHERE 1",
'right' => "SELECT `P` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE `L`.org_id = 3",
'alias' => "P",
'result' => "SELECT `P` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE (`L`.`org_id` = 3)");
'result' => "SELECT `P` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE (`L`.`org_id` = 3)"];
$aTests['Joined filter on joined classes'] = array(
$aTests['Joined filter on joined classes'] = [
'left' => "SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE 1",
'right' => "SELECT Person FROM Person AS Person JOIN Location ON Person.location_id = Location.id WHERE Location.org_id = 3",
'alias' => "P",
'result' => "SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id JOIN Location AS `Location` ON `P`.location_id = `Location`.id WHERE (`Location`.`org_id` = 3)");
'result' => "SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id JOIN Location AS `Location` ON `P`.location_id = `Location`.id WHERE (`Location`.`org_id` = 3)"];
$aTests['Alias collision'] = array(
$aTests['Alias collision'] = [
'left' => "SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE 1",
'right' => "SELECT Person FROM Person AS Person JOIN Location AS `L` ON Person.location_id = `L`.id WHERE `L`.org_id = 3",
'alias' => "P",
'result' => "SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id JOIN Location AS `L1` ON `P`.location_id = `L1`.id WHERE (`L1`.`org_id` = 3)");
'result' => "SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id JOIN Location AS `L1` ON `P`.location_id = `L1`.id WHERE (`L1`.`org_id` = 3)"];
$aTests['Test Subclass1'] = array(
$aTests['Test Subclass1'] = [
'left' => "SELECT `U` FROM UserRequest AS `U` WHERE `U`.agent_id = 3",
'right' => "SELECT `Ticket` WHERE org_id = 3",
'alias' => "U",
'result' => "SELECT `U` FROM UserRequest AS `U` WHERE ((`U`.`agent_id` = 3) AND (`U`.`org_id` = 3))");
'result' => "SELECT `U` FROM UserRequest AS `U` WHERE ((`U`.`agent_id` = 3) AND (`U`.`org_id` = 3))"];
$aTests['Test Subclass and join'] = array(
$aTests['Test Subclass and join'] = [
'left' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Person AS `P` ON `UserRequest`.agent_id = `P`.id WHERE `UserRequest`.agent_id = 3",
'right' => "SELECT `Ticket` WHERE org_id = 3",
'alias' => "UserRequest",
'result' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Person AS `P` ON `UserRequest`.agent_id = `P`.id WHERE ((`UserRequest`.`agent_id` = 3) AND (`UserRequest`.`org_id` = 3))");
'result' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Person AS `P` ON `UserRequest`.agent_id = `P`.id WHERE ((`UserRequest`.`agent_id` = 3) AND (`UserRequest`.`org_id` = 3))"];
$aTests['Test Subclass and union'] = array(
$aTests['Test Subclass and union'] = [
'left' => "SELECT `U` FROM UserRequest AS `U` WHERE `U`.agent_id = 3 UNION SELECT `T` FROM Ticket AS `T` WHERE `T`.agent_id = 3 ",
'right' => "SELECT `Ticket` WHERE org_id = 3",
'alias' => "U",
'result' => "SELECT `U` FROM UserRequest AS `U` WHERE ((`U`.`agent_id` = 3) AND (`U`.`org_id` = 3)) UNION SELECT `T` FROM Ticket AS `T` WHERE ((`T`.`agent_id` = 3) AND (`T`.`org_id` = 3))");
'result' => "SELECT `U` FROM UserRequest AS `U` WHERE ((`U`.`agent_id` = 3) AND (`U`.`org_id` = 3)) UNION SELECT `T` FROM Ticket AS `T` WHERE ((`T`.`agent_id` = 3) AND (`T`.`org_id` = 3))"];
return $aTests;
}
/**
* @dataProvider IntersectProvider
*
@@ -169,47 +165,47 @@ class DBSearchIntersectTest extends ItopTestCase
public function IntersectProvider()
{
$aTests = array();
$aTests = [];
$aTests['Nested selects 2'] = array(
$aTests['Nested selects 2'] = [
'left' => "SELECT `U` FROM UserRequest AS `U` WHERE U.agent_id = 3",
'right' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Person AS `P` ON `UserRequest`.agent_id = `P`.id JOIN Organization AS `Organization` ON `P`.org_id = `Organization`.id WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` WHERE (`Organization`.`id` = `UserRequest`.`org_id`)))",
'result' => "SELECT `U` FROM UserRequest AS `U` JOIN Person AS `P` ON `U`.agent_id = `P`.id JOIN Organization AS `Organization` ON `P`.org_id = `Organization`.id WHERE ((`U`.`agent_id` = 3) AND (`U`.`org_id` IN (SELECT `Organization1` FROM Organization AS `Organization1` WHERE (`Organization1`.`id` = `U`.`org_id`))))");
'result' => "SELECT `U` FROM UserRequest AS `U` JOIN Person AS `P` ON `U`.agent_id = `P`.id JOIN Organization AS `Organization` ON `P`.org_id = `Organization`.id WHERE ((`U`.`agent_id` = 3) AND (`U`.`org_id` IN (SELECT `Organization1` FROM Organization AS `Organization1` WHERE (`Organization1`.`id` = `U`.`org_id`))))"];
$aTests['Nested selects'] = array(
$aTests['Nested selects'] = [
'left' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Person AS `P` ON `UserRequest`.agent_id = `P`.id JOIN Organization AS `Organization` ON `P`.org_id = `Organization`.id WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` WHERE (`Organization`.`id` = `UserRequest`.`org_id`)))",
'right' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE UserRequest.agent_id = 3",
'result' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Person AS `P` ON `UserRequest`.agent_id = `P`.id JOIN Organization AS `Organization` ON `P`.org_id = `Organization`.id WHERE ((`UserRequest`.`org_id` IN (SELECT `Organization1` FROM Organization AS `Organization1` WHERE (`Organization1`.`id` = `UserRequest`.`org_id`))) AND (`UserRequest`.`agent_id` = 3))");
'result' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Person AS `P` ON `UserRequest`.agent_id = `P`.id JOIN Organization AS `Organization` ON `P`.org_id = `Organization`.id WHERE ((`UserRequest`.`org_id` IN (SELECT `Organization1` FROM Organization AS `Organization1` WHERE (`Organization1`.`id` = `UserRequest`.`org_id`))) AND (`UserRequest`.`agent_id` = 3))"];
$aTests['Multiple selected classes inverted'] = array(
$aTests['Multiple selected classes inverted'] = [
'left' => "SELECT `L`, `P` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE 1",
'right' => "SELECT Person WHERE org_id = 3",
'result' => "SELECT `L`, `P` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE (`P`.`org_id` = 3)");
'result' => "SELECT `L`, `P` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE (`P`.`org_id` = 3)"];
// $aTests['Multiple selected classes inverted 2'] = array(
// 'left' => "SELECT `L`, `P`, `D` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id JOIN Server AS D ON D.location_id = L.id JOIN Person AS P2 ON P.manager_id = P2.id WHERE (`L`.`org_id` = 3)",
// 'right' => "SELECT Person WHERE org_id = 3",
// 'result' => "SELECT `L`, `P`, `D` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id JOIN Server AS `D` ON `D`.location_id = `L`.id JOIN Person AS `P2` ON `P`.manager_id = `P2`.id WHERE ((`L`.`org_id` = 3) AND (`P`.`org_id` = 3))");
// $aTests['Multiple selected classes inverted 2'] = array(
// 'left' => "SELECT `L`, `P`, `D` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id JOIN Server AS D ON D.location_id = L.id JOIN Person AS P2 ON P.manager_id = P2.id WHERE (`L`.`org_id` = 3)",
// 'right' => "SELECT Person WHERE org_id = 3",
// 'result' => "SELECT `L`, `P`, `D` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id JOIN Server AS `D` ON `D`.location_id = `L`.id JOIN Person AS `P2` ON `P`.manager_id = `P2`.id WHERE ((`L`.`org_id` = 3) AND (`P`.`org_id` = 3))");
$aTests['Same class'] = array(
$aTests['Same class'] = [
'left' => "SELECT Contact WHERE name = 'Christie'",
'right' => "SELECT Contact WHERE org_id = 3",
'result' => "SELECT `Contact` FROM Contact AS `Contact` WHERE ((`Contact`.`name` = 'Christie') AND (`Contact`.`org_id` = 3))");
'result' => "SELECT `Contact` FROM Contact AS `Contact` WHERE ((`Contact`.`name` = 'Christie') AND (`Contact`.`org_id` = 3))"];
$aTests['Different Alias'] = array(
$aTests['Different Alias'] = [
'left' => "SELECT Contact AS C WHERE C.name = 'Christie'",
'right' => "SELECT Contact AS CC WHERE CC.org_id = 3",
'result' => "SELECT `C` FROM Contact AS `C` WHERE ((`C`.`name` = 'Christie') AND (`C`.`org_id` = 3))");
'result' => "SELECT `C` FROM Contact AS `C` WHERE ((`C`.`name` = 'Christie') AND (`C`.`org_id` = 3))"];
$aTests['Multiple selected classes'] = array(
$aTests['Multiple selected classes'] = [
'left' => "SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE 1",
'right' => "SELECT Location WHERE org_id = 3",
'result' => "SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE (`L`.`org_id` = 3)");
'result' => "SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE (`L`.`org_id` = 3)"];
$aTests['Alias collision'] = array(
$aTests['Alias collision'] = [
'left' => "SELECT `P` FROM Person AS `P` WHERE 1",
'right' => "SELECT `Person` FROM Person AS `Person` JOIN Person AS `P` ON `P`.manager_id = `Person`.id WHERE `P`.org_id = 3",
'result' => "SELECT `P` FROM Person AS `P` JOIN Person AS `P1` ON `P1`.manager_id = `P`.id WHERE (`P1`.`org_id` = 3)");
'result' => "SELECT `P` FROM Person AS `P` JOIN Person AS `P1` ON `P1`.manager_id = `P`.id WHERE (`P1`.`org_id` = 3)"];
return $aTests;
}
@@ -352,100 +348,100 @@ class DBSearchIntersectTest extends ItopTestCase
public function IntersectOptimizationProvider()
{
$aQueries = array(
'Exact same query' => array(
$aQueries = [
'Exact same query' => [
'Base Query' => 'SELECT s FROM Service AS s JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "The World Company"',
'Filter OQL' => 'SELECT s FROM Service AS s JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "The World Company"',
'Result ' => "SELECT `s` FROM Service AS `s` JOIN Organization AS `o` ON `s`.org_id = `o`.id WHERE ((`o`.`name` = 'The World Company') AND (`o`.`name` = 'The World Company'))",
),
'Same query, other aliases' => array(
],
'Same query, other aliases' => [
'Base Query' => 'SELECT s FROM Service AS s JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "The World Company"',
'Filter OQL' => 'SELECT s2 FROM Service AS s2 JOIN Organization AS o2 ON s2.org_id = o2.id WHERE o2.name = "The World Company"',
'Result ' => "SELECT `s` FROM Service AS `s` JOIN Organization AS `o` ON `s`.org_id = `o`.id WHERE ((`o`.`name` = 'The World Company') AND (`o`.`name` = 'The World Company'))",
),
'Same aliases, different condition' => array(
],
'Same aliases, different condition' => [
'Base Query' => 'SELECT s FROM Service AS s JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "The World Company"',
'Filter OQL' => 'SELECT s FROM Service AS s JOIN Organization AS o ON s.org_id = o.id WHERE o.parent_id = 0',
'Result ' => "SELECT `s` FROM Service AS `s` JOIN Organization AS `o` ON `s`.org_id = `o`.id WHERE ((`o`.`name` = 'The World Company') AND (`o`.`parent_id` = 0))",
),
'Other aliases, different condition' => array(
],
'Other aliases, different condition' => [
'Base Query' => 'SELECT s FROM Service AS s JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "The World Company"',
'Filter OQL' => 'SELECT s2 FROM Service AS s2 JOIN Organization AS o2 ON s2.org_id = o2.id WHERE o2.parent_id = 0',
'Result ' => "SELECT `s` FROM Service AS `s` JOIN Organization AS `o` ON `s`.org_id = `o`.id WHERE ((`o`.`name` = 'The World Company') AND (`o`.`parent_id` = 0))",
),
'Same aliases, simpler query tree' => array(
],
'Same aliases, simpler query tree' => [
'Base Query' => 'SELECT s FROM Service AS s JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "The World Company"',
'Filter OQL' => 'SELECT s FROM Service AS s WHERE name LIKE "Save the World"',
'Result ' => "SELECT `s` FROM Service AS `s` JOIN Organization AS `o` ON `s`.org_id = `o`.id WHERE ((`o`.`name` = 'The World Company') AND (`s`.`name` LIKE 'Save the World'))",
),
'Other aliases, simpler query tree' => array(
],
'Other aliases, simpler query tree' => [
'Base Query' => 'SELECT s FROM Service AS s JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "The World Company"',
'Filter OQL' => 'SELECT s2 FROM Service AS s2 WHERE name LIKE "Save the World"',
'Result ' => "SELECT `s` FROM Service AS `s` JOIN Organization AS `o` ON `s`.org_id = `o`.id WHERE ((`o`.`name` = 'The World Company') AND (`s`.`name` LIKE 'Save the World'))",
),
'Same aliases, different query tree' => array(
],
'Same aliases, different query tree' => [
'Base Query' => 'SELECT s FROM Service AS s JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "The World Company"',
'Filter OQL' => 'SELECT s FROM Service AS s JOIN ServiceFamily AS f ON s.servicefamily_id = f.id WHERE s.org_id = 123 AND f.name = "Care"',
'Result ' => "SELECT `s` FROM Service AS `s` JOIN Organization AS `o` ON `s`.org_id = `o`.id JOIN ServiceFamily AS `f` ON `s`.servicefamily_id = `f`.id WHERE ((`o`.`name` = 'The World Company') AND ((`s`.`org_id` = 123) AND (`f`.`name` = 'Care')))",
),
'Other aliases, different query tree' => array(
],
'Other aliases, different query tree' => [
'Base Query' => 'SELECT s FROM Service AS s JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "The World Company"',
'Filter OQL' => 'SELECT s2 FROM Service AS s2 JOIN ServiceFamily AS f ON s2.servicefamily_id = f.id WHERE s2.org_id = 123 AND f.name = "Care"',
'Result ' => "SELECT `s` FROM Service AS `s` JOIN Organization AS `o` ON `s`.org_id = `o`.id JOIN ServiceFamily AS `f` ON `s`.servicefamily_id = `f`.id WHERE ((`o`.`name` = 'The World Company') AND ((`s`.`org_id` = 123) AND (`f`.`name` = 'Care')))",
),
],
'2 - Exact same query' => array(
'2 - Exact same query' => [
'Base Query' => 'SELECT o FROM Organization AS o JOIN Service AS s ON s.org_id = o.id WHERE s.name = "Help"',
'Filter OQL' => 'SELECT o FROM Organization AS o JOIN Service AS s ON s.org_id = o.id WHERE s.name = "Help"',
'Result ' => "SELECT `o` FROM Organization AS `o` JOIN Service AS `s` ON `s`.org_id = `o`.id WHERE ((`s`.`name` = 'Help') AND (`s`.`name` = 'Help'))",
),
'2 - Same query, other aliases' => array(
],
'2 - Same query, other aliases' => [
'Base Query' => 'SELECT o FROM Organization AS o JOIN Service AS s ON s.org_id = o.id WHERE s.name = "Help"',
'Filter OQL' => 'SELECT o2 FROM Organization AS o2 JOIN Service AS s2 ON s2.org_id = o2.id WHERE s2.name = "Help"',
'Result ' => "SELECT `o` FROM Organization AS `o` JOIN Service AS `s` ON `s`.org_id = `o`.id WHERE ((`s`.`name` = 'Help') AND (`s`.`name` = 'Help'))",
),
'2 - Same aliases, different condition' => array(
],
'2 - Same aliases, different condition' => [
'Base Query' => 'SELECT o FROM Organization AS o JOIN Service AS s ON s.org_id = o.id WHERE s.name = "Help"',
'Filter OQL' => 'SELECT o FROM Organization AS o JOIN Service AS s ON s.org_id = o.id WHERE s.servicefamily_id = 321',
'Result ' => "SELECT `o` FROM Organization AS `o` JOIN Service AS `s` ON `s`.org_id = `o`.id WHERE ((`s`.`name` = 'Help') AND (`s`.`servicefamily_id` = 321))",
),
'2 - Other aliases, different condition' => array(
],
'2 - Other aliases, different condition' => [
'Base Query' => 'SELECT o FROM Organization AS o JOIN Service AS s ON s.org_id = o.id WHERE s.name = "Help"',
'Filter OQL' => 'SELECT o2 FROM Organization AS o2 JOIN Service AS s2 ON s2.org_id = o2.id WHERE s2.servicefamily_id = 321',
'Result ' => "SELECT `o` FROM Organization AS `o` JOIN Service AS `s` ON `s`.org_id = `o`.id WHERE ((`s`.`name` = 'Help') AND (`s`.`servicefamily_id` = 321))",
),
'2 - Same aliases, simpler query tree' => array(
],
'2 - Same aliases, simpler query tree' => [
'Base Query' => 'SELECT o FROM Organization AS o JOIN Service AS s ON s.org_id = o.id WHERE s.name = "Help"',
'Filter OQL' => 'SELECT o FROM Organization AS o WHERE o.name = "Demo"',
'Result ' => "SELECT `o` FROM Organization AS `o` JOIN Service AS `s` ON `s`.org_id = `o`.id WHERE ((`s`.`name` = 'Help') AND (`o`.`name` = 'Demo'))",
),
'2 - Other aliases, simpler query tree' => array(
],
'2 - Other aliases, simpler query tree' => [
'Base Query' => 'SELECT o FROM Organization AS o JOIN Service AS s ON s.org_id = o.id WHERE s.name = "Help"',
'Filter OQL' => 'SELECT o2 FROM Organization AS o2 WHERE o2.name = "Demo"',
'Result ' => "SELECT `o` FROM Organization AS `o` JOIN Service AS `s` ON `s`.org_id = `o`.id WHERE ((`s`.`name` = 'Help') AND (`o`.`name` = 'Demo'))",
),
'2 - Same aliases, different query tree' => array(
],
'2 - Same aliases, different query tree' => [
'Base Query' => 'SELECT o FROM Organization AS o JOIN Service AS s ON s.org_id = o.id WHERE s.name = "Help"',
'Filter OQL' => 'SELECT o FROM Organization AS o JOIN Location AS l ON l.org_id = o.id WHERE l.name = "Paris"',
'Result ' => "SELECT `o` FROM Organization AS `o` JOIN Service AS `s` ON `s`.org_id = `o`.id JOIN Location AS `l` ON `l`.org_id = `o`.id WHERE ((`s`.`name` = 'Help') AND (`l`.`name` = 'Paris'))",
),
'2 - Other aliases, different query tree' => array(
],
'2 - Other aliases, different query tree' => [
'Base Query' => 'SELECT o FROM Organization AS o JOIN Service AS s ON s.org_id = o.id WHERE s.name = "Help"',
'Filter OQL' => 'SELECT o2 FROM Organization AS o2 JOIN Location AS l ON l.org_id = o2.id WHERE l.name = "Paris"',
'Result ' => "SELECT `o` FROM Organization AS `o` JOIN Service AS `s` ON `s`.org_id = `o`.id JOIN Location AS `l` ON `l`.org_id = `o`.id WHERE ((`s`.`name` = 'Help') AND (`l`.`name` = 'Paris'))",
),
],
'Internal query optimizations 1' => array(
'Internal query optimizations 1' => [
'Base Query' => 'SELECT o FROM Organization AS o',
'Filter OQL' => 'SELECT o FROM Organization AS o JOIN Location AS l ON l.org_id = o.id JOIN Organization AS p ON o.parent_id = p.id WHERE l.name = "Paris" AND p.code LIKE "toto"',
'Result ' => "SELECT `o` FROM Organization AS `o` JOIN Organization AS `p` ON `o`.parent_id = `p`.id JOIN Location AS `l` ON `l`.org_id = `o`.id WHERE ((`l`.`name` = 'Paris') AND (`p`.`code` LIKE 'toto'))",
),
'Internal query optimizations 2' => array(
],
'Internal query optimizations 2' => [
'Base Query' => 'SELECT r FROM UserRequest AS r JOIN Service AS s ON r.service_id = s.id JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "left_name"',
'Filter OQL' => 'SELECT r FROM UserRequest AS r JOIN Service AS s ON r.service_id = s.id JOIN Organization AS o ON s.org_id = o.id WHERE o.name = "right_name"',
'Result ' => "SELECT `r` FROM UserRequest AS `r` JOIN Service AS `s` ON `r`.service_id = `s`.id JOIN Organization AS `o` ON `s`.org_id = `o`.id WHERE ((`o`.`name` = 'left_name') AND (`o`.`name` = 'right_name'))",
),
);
],
];
return $aQueries;
}

View File

@@ -12,9 +12,9 @@ use DBSearch;
*
* @package Combodo\iTop\Test\UnitTest\Core
*/
class DBSearchJoinTest extends ItopDataTestCase {
const USE_TRANSACTION = false;
class DBSearchJoinTest extends ItopDataTestCase
{
public const USE_TRANSACTION = false;
protected function setUp(): void
{
@@ -43,9 +43,13 @@ class DBSearchJoinTest extends ItopDataTestCase {
$aRealiasingMap = [];
$oResultSearch = $oLeftSearch->Join($oRightSearch,
DBSearch::JOIN_REFERENCED_BY, $sParentAtt,
TREE_OPERATOR_EQUALS, $aRealiasingMap);
$oResultSearch = $oLeftSearch->Join(
$oRightSearch,
DBSearch::JOIN_REFERENCED_BY,
$sParentAtt,
TREE_OPERATOR_EQUALS,
$aRealiasingMap
);
$this->debug("\nRealiasing Map");
$this->debug($aRealiasingMap);
@@ -57,12 +61,9 @@ class DBSearchJoinTest extends ItopDataTestCase {
$this->debug("\nBefore renaming");
$this->debug($oResultSearch->ToOQL());
$aLevelsPropertiesKeys = ['L-1', 'L-1-1', 'L-1-1-1'];
foreach ($aLevelsPropertiesKeys as $sLevelAlias)
{
if (array_key_exists($sLevelAlias, $aRealiasingMap))
{
foreach ($aRealiasingMap[$sLevelAlias] as $sAliasToRename)
{
foreach ($aLevelsPropertiesKeys as $sLevelAlias) {
if (array_key_exists($sLevelAlias, $aRealiasingMap)) {
foreach ($aRealiasingMap[$sLevelAlias] as $sAliasToRename) {
$oResultSearch->RenameAlias($sAliasToRename, $sLevelAlias);
}
}
@@ -137,11 +138,14 @@ class DBSearchJoinTest extends ItopDataTestCase {
$oFilter1 = DBSearch::FromOQL($sReq1);
$oFilter2 = DBSearch::FromOQL($sReq2);
$aRealiasingMap = array();
$oFilter1 = $oFilter1->Join($oFilter2,
$aRealiasingMap = [];
$oFilter1 = $oFilter1->Join(
$oFilter2,
DBSearch::JOIN_REFERENCED_BY,
'org_id',
TREE_OPERATOR_EQUALS, $aRealiasingMap);
TREE_OPERATOR_EQUALS,
$aRealiasingMap
);
$this->debug("\nRealiasing Map");
$this->debug($aRealiasingMap);
@@ -150,14 +154,10 @@ class DBSearchJoinTest extends ItopDataTestCase {
$this->debug("\nJoined");
$this->debug($sRes1);
foreach($oFilter1->GetCriteria_ReferencedBy() as $sForeignClass => $aReferences)
{
foreach ($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator)
{
foreach ($aFiltersByOperator as $iOperatorCode => $aFilters)
{
foreach ($aFilters as $index => $oForeignFilter)
{
foreach ($oFilter1->GetCriteria_ReferencedBy() as $sForeignClass => $aReferences) {
foreach ($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) {
foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) {
foreach ($aFilters as $index => $oForeignFilter) {
$this->debug("\nReferencedBy");
$this->debug($oForeignFilter->ToOQL());
}

View File

@@ -1,4 +1,5 @@
<?php
// Copyright (c) 2010-2024 Combodo SAS
//
// This file is part of iTop.
@@ -26,7 +27,6 @@
namespace Combodo\iTop\Test\UnitTest\Core;
use CMDBSource;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use CoreOqlMultipleResultsForbiddenException;
@@ -36,7 +36,6 @@ use Exception;
use Expression;
use FunctionExpression;
/**
* @group itopStorageMgmt
* Tests of the DBSearch class.
@@ -46,7 +45,7 @@ use FunctionExpression;
*/
class DBSearchTest extends ItopDataTestCase
{
const CREATE_TEST_ORG = true;
public const CREATE_TEST_ORG = true;
/**
* @throws \Exception
@@ -77,25 +76,25 @@ class DBSearchTest extends ItopDataTestCase
$oExpr1 = Expression::FromOQL('UserRequest.org_id');
// Alias => Expression
$aGroupBy = array('org_id' => $oExpr1);
$aGroupBy = ['org_id' => $oExpr1];
$oTimeExpr = Expression::FromOQL('UserRequest.time_spent');
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
$oSumExpr = new FunctionExpression('SUM', [$oTimeExpr]);
$oAvgExpr = new FunctionExpression('AVG', [$oTimeExpr]);
$oMinExpr = new FunctionExpression('MIN', [$oTimeExpr]);
$oMaxExpr = new FunctionExpression('MAX', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => $oSumExpr,
'_itop_avg_' => $oAvgExpr,
'_itop_min_' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
];
// Alias => Order
$aOrderBy = array('_itop_sum_' => true, '_itop_count_' => true);
$aOrderBy = ['_itop_sum_' => true, '_itop_count_' => true];
$aArgs = array();
$aArgs = [];
$sSQL = $oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy, $iLimit);
$this->debug($sSQL);
@@ -104,24 +103,22 @@ class DBSearchTest extends ItopDataTestCase
$this->debug($aRes);
self::assertEquals(count($aCountRes), count($aRes));
for ($i = 0; $i < count($aCountRes); $i++)
{
for ($i = 0; $i < count($aCountRes); $i++) {
self::assertEquals($aCountRes[$i], $aRes[$i]['_itop_count_']);
}
}
public function UReqProvider()
{
return array(
"1 line" => array(1, 1, array(array(1, 0, 0)), 0, array('1')),
"2 same lines" => array(1, 1, array(array(1, 0, 0), array(1, 0, 0)), 0, array('2')),
"2 diff lines" => array(2, 2, array(array(1, 0, 0), array(1, 1, 1)), 0, array('1', '1')),
"4 lines" => array(2, 2, array(array(1, 0, 0), array(1, 1, 1), array(1, 0, 0), array(1, 1, 1)), 0, array('2', '2')),
"5 lines" => array(2, 2, array(array(1, 0, 0), array(1, 0, 0), array(1, 1, 1), array(1, 0, 0), array(1, 1, 1)), 0, array('2', '3')),
"6 lines" => array(2, 4, array(array(1, 0, 0), array(1, 1, 3), array(1, 1, 1), array(1, 1, 3), array(1, 0, 2), array(1, 1, 1)), 0, array('2', '4')),
"6 lines limit" => array(2, 4, array(array(1, 0, 0), array(1, 1, 3), array(1, 1, 1), array(1, 1, 1), array(1, 0, 0), array(1, 1, 1)), 1, array('2')),
);
return [
"1 line" => [1, 1, [[1, 0, 0]], 0, ['1']],
"2 same lines" => [1, 1, [[1, 0, 0], [1, 0, 0]], 0, ['2']],
"2 diff lines" => [2, 2, [[1, 0, 0], [1, 1, 1]], 0, ['1', '1']],
"4 lines" => [2, 2, [[1, 0, 0], [1, 1, 1], [1, 0, 0], [1, 1, 1]], 0, ['2', '2']],
"5 lines" => [2, 2, [[1, 0, 0], [1, 0, 0], [1, 1, 1], [1, 0, 0], [1, 1, 1]], 0, ['2', '3']],
"6 lines" => [2, 4, [[1, 0, 0], [1, 1, 3], [1, 1, 1], [1, 1, 3], [1, 0, 2], [1, 1, 1]], 0, ['2', '4']],
"6 lines limit" => [2, 4, [[1, 0, 0], [1, 1, 3], [1, 1, 1], [1, 1, 1], [1, 0, 0], [1, 1, 1]], 1, ['2']],
];
}
/**
@@ -133,32 +130,28 @@ class DBSearchTest extends ItopDataTestCase
*/
private function init_db($iOrgNb, $iPersonNb, $aReq)
{
$aOrgIds = array();
$aOrgIds = [];
$sOrgs = '';
for($i = 0; $i < $iOrgNb; $i++)
{
for ($i = 0; $i < $iOrgNb; $i++) {
$oObj = $this->CreateOrganization('UnitTest_Org'.$i);
$sKey = $oObj->GetKey();
$aOrgIds[] = $sKey;
if ($i > 0)
{
if ($i > 0) {
$sOrgs .= ",";
}
$sOrgs .= $sKey;
}
self::assertEquals($iOrgNb, count($aOrgIds));
$aPersonIds = array();
for($i = 0; $i < $iPersonNb; $i++)
{
$aPersonIds = [];
for ($i = 0; $i < $iPersonNb; $i++) {
$oObj = $this->CreatePerson($i, $aOrgIds[$i % $iOrgNb]);
$aPersonIds[] = $oObj->GetKey();
}
self::assertEquals($iPersonNb, count($aPersonIds));
$i = 0;
foreach($aReq as $aParams)
{
foreach ($aReq as $aParams) {
$oObj = $this->CreateUserRequest($i, [
'time_spent' => $aParams[0],
'org_id' => $aOrgIds[$aParams[1]],
@@ -180,31 +173,30 @@ class DBSearchTest extends ItopDataTestCase
$this->CreatePhysicalInterface(1, 1000, $oServer->GetKey());
$this->CreateFiberChannelInterface(1, 1000, $oServer->GetKey());
$oSearch = DBSearch::FromOQL("SELECT FiberChannelInterface AS FCI WHERE FCI.name = '1' UNION SELECT PhysicalInterface AS PHI WHERE PHI.name = '1'");
self::assertNotNull($oSearch);
$oExpr1 = Expression::FromOQL('FCI.name');
// Alias => Expression (first select reference)
$aGroupBy = array('group1' => $oExpr1);
$aGroupBy = ['group1' => $oExpr1];
$oTimeExpr = Expression::FromOQL('FCI.speed');
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
$oSumExpr = new FunctionExpression('SUM', [$oTimeExpr]);
$oAvgExpr = new FunctionExpression('AVG', [$oTimeExpr]);
$oMinExpr = new FunctionExpression('MIN', [$oTimeExpr]);
$oMaxExpr = new FunctionExpression('MAX', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => $oSumExpr,
'_itop_avg_' => $oAvgExpr,
'_itop_min_' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
];
// Alias => Order
$aOrderBy = array('group1' => true, '_itop_count_' => true);
$aOrderBy = ['group1' => true, '_itop_count_' => true];
$aArgs = array();
$aArgs = [];
$sSQL = $oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
$this->debug($sSQL);
@@ -224,34 +216,34 @@ class DBSearchTest extends ItopDataTestCase
// Alias => Expression (first select reference)
$oExpr1 = Expression::FromOQL('FiberChannelInterface.name');
$aGroupBy = array('group1' => $oExpr1);
$aGroupBy = ['group1' => $oExpr1];
$oTimeExpr = Expression::FromOQL('FiberChannelInterface.speed');
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
$oSumExpr = new FunctionExpression('SUM', [$oTimeExpr]);
$oAvgExpr = new FunctionExpression('AVG', [$oTimeExpr]);
$oMinExpr = new FunctionExpression('MIN', [$oTimeExpr]);
$oMaxExpr = new FunctionExpression('MAX', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => $oSumExpr,
'_itop_avg_' => $oAvgExpr,
'_itop_min_' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
$aArgs = array();
];
$aArgs = [];
// Alias => Order
$aOrderBy = array(
$aOrderBy = [
'group1' => true,
'_itop_sum_' => true,
'_itop_avg_' => true,
'_itop_min_' => true,
'_itop_max_' => true);
'_itop_max_' => true];
$sSQL = $oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
self::assertNotEmpty($sSQL);
// Alias => Order
$aOrderBy = array('nothing_good' => true);
$aOrderBy = ['nothing_good' => true];
$this->expectException("CoreException");
$oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
@@ -268,29 +260,29 @@ class DBSearchTest extends ItopDataTestCase
$oExpr1 = Expression::FromOQL('FCI.name');
// Alias => Expression (first select reference)
$aGroupBy = array('group1' => $oExpr1);
$aGroupBy = ['group1' => $oExpr1];
$oTimeExpr = Expression::FromOQL('FCI.speed');
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
$oSumExpr = new FunctionExpression('SUM', [$oTimeExpr]);
$oAvgExpr = new FunctionExpression('AVG', [$oTimeExpr]);
$oMinExpr = new FunctionExpression('MIN', [$oTimeExpr]);
$oMaxExpr = new FunctionExpression('MAX', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => $oSumExpr,
'_itop_avg_' => $oAvgExpr,
'group1' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
$aArgs = array();
];
$aArgs = [];
// Alias => Order
$aOrderBy = array(
$aOrderBy = [
'group1' => true,
'_itop_sum_' => true,
'_itop_avg_' => true,
'_itop_min_' => true,
'_itop_max_' => true);
'_itop_max_' => true];
$this->expectException("CoreException");
$oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
@@ -308,34 +300,34 @@ class DBSearchTest extends ItopDataTestCase
// Alias => Expression (first select reference)
$oExpr1 = Expression::FromOQL('FCI.name');
$aGroupBy = array('group1' => $oExpr1);
$aGroupBy = ['group1' => $oExpr1];
$oTimeExpr = Expression::FromOQL('FCI.speed');
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
$oSumExpr = new FunctionExpression('SUM', [$oTimeExpr]);
$oAvgExpr = new FunctionExpression('AVG', [$oTimeExpr]);
$oMinExpr = new FunctionExpression('MIN', [$oTimeExpr]);
$oMaxExpr = new FunctionExpression('MAX', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => $oSumExpr,
'_itop_avg_' => $oAvgExpr,
'_itop_min_' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
$aArgs = array();
];
$aArgs = [];
// Alias => Order
$aOrderBy = array(
$aOrderBy = [
'group1' => true,
'_itop_sum_' => true,
'_itop_avg_' => true,
'_itop_min_' => true,
'_itop_max_' => true);
'_itop_max_' => true];
$sSQL = $oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
self::assertNotEmpty($sSQL);
$aGroupBy = array('group1' => 'FCI.name');
$aGroupBy = ['group1' => 'FCI.name'];
$this->expectException("CoreException");
$oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
@@ -352,39 +344,39 @@ class DBSearchTest extends ItopDataTestCase
// Alias => Expression (first select reference)
$oExpr1 = Expression::FromOQL('FCI.name');
$aGroupBy = array('group1' => $oExpr1);
$aGroupBy = ['group1' => $oExpr1];
$oTimeExpr = Expression::FromOQL('FCI.speed');
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
$oSumExpr = new FunctionExpression('SUM', [$oTimeExpr]);
$oAvgExpr = new FunctionExpression('AVG', [$oTimeExpr]);
$oMinExpr = new FunctionExpression('MIN', [$oTimeExpr]);
$oMaxExpr = new FunctionExpression('MAX', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => $oSumExpr,
'_itop_avg_' => $oAvgExpr,
'_itop_min_' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
$aArgs = array();
];
$aArgs = [];
// Alias => Order
$aOrderBy = array(
$aOrderBy = [
'group1' => true,
'_itop_sum_' => true,
'_itop_avg_' => true,
'_itop_min_' => true,
'_itop_max_' => true);
'_itop_max_' => true];
$sSQL = $oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
self::assertNotEmpty($sSQL);
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => 'SumExpr',
'_itop_avg_' => $oAvgExpr,
'_itop_min_' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
];
$this->expectException("CoreException");
$oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
@@ -402,39 +394,39 @@ class DBSearchTest extends ItopDataTestCase
// Alias => Expression (first select reference)
$oExpr1 = Expression::FromOQL('FCI.name');
$aGroupBy = array('group1' => $oExpr1);
$aGroupBy = ['group1' => $oExpr1];
$oTimeExpr = Expression::FromOQL('FCI.speed');
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
$oSumExpr = new FunctionExpression('SUM', [$oTimeExpr]);
$oAvgExpr = new FunctionExpression('AVG', [$oTimeExpr]);
$oMinExpr = new FunctionExpression('MIN', [$oTimeExpr]);
$oMaxExpr = new FunctionExpression('MAX', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => $oSumExpr,
'_itop_avg_' => $oAvgExpr,
'_itop_min_' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
$aArgs = array();
];
$aArgs = [];
// Alias => Order
$aOrderBy = array(
$aOrderBy = [
'group1' => true,
'_itop_sum_' => true,
'_itop_avg_' => true,
'_itop_min_' => true,
'_itop_max_' => true);
'_itop_max_' => true];
$sSQL = $oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
self::assertNotEmpty($sSQL);
$aOrderBy = array(
$aOrderBy = [
'group1' => true,
'_itop_sum_' => true,
'_itop_avg_' => 'ASC',
'_itop_min_' => true,
'_itop_max_' => true);
'_itop_max_' => true];
$this->expectException("CoreException");
$oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
@@ -452,34 +444,34 @@ class DBSearchTest extends ItopDataTestCase
// Alias => Expression (first select reference)
$oExpr1 = Expression::FromOQL('FCI.name');
$aGroupBy = array('group1' => $oExpr1);
$aGroupBy = ['group1' => $oExpr1];
$oTimeExpr = Expression::FromOQL('FCI.speed');
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
$oSumExpr = new FunctionExpression('SUM', [$oTimeExpr]);
$oAvgExpr = new FunctionExpression('AVG', [$oTimeExpr]);
$oMinExpr = new FunctionExpression('MIN', [$oTimeExpr]);
$oMaxExpr = new FunctionExpression('MAX', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => $oSumExpr,
'_itop_avg_' => $oAvgExpr,
'_itop_min_' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
$aArgs = array();
];
$aArgs = [];
// Alias => Order
$aOrderBy = array(
$aOrderBy = [
'group1' => true,
'_itop_sum_' => true,
'_itop_avg_' => true,
'_itop_min_' => true,
'_itop_max_' => true);
'_itop_max_' => true];
$sSQL = $oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
self::assertNotEmpty($sSQL);
// Alias => Order
$aOrderBy = array('nothing_good' => true);
$aOrderBy = ['nothing_good' => true];
$this->expectException("CoreException");
$oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy);
@@ -493,29 +485,28 @@ class DBSearchTest extends ItopDataTestCase
*/
public function testNoGroupBy()
{
$aReq = array(array(1, 0, 0), array(1, 1, 3), array(1, 1, 1), array(1, 1, 1), array(1, 0, 0), array(1, 1, 1));
$aReq = [[1, 0, 0], [1, 1, 3], [1, 1, 1], [1, 1, 1], [1, 0, 0], [1, 1, 1]];
$sOrgs = $this->init_db(2, 4, $aReq);
$oSearch = DBSearch::FromOQL("SELECT UserRequest WHERE org_id IN ($sOrgs)");
self::assertNotNull($oSearch);
$oTimeExpr = Expression::FromOQL('UserRequest.time_spent');
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
$oSumExpr = new FunctionExpression('SUM', [$oTimeExpr]);
$oAvgExpr = new FunctionExpression('AVG', [$oTimeExpr]);
$oMinExpr = new FunctionExpression('MIN', [$oTimeExpr]);
$oMaxExpr = new FunctionExpression('MAX', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_sum_' => $oSumExpr,
'_itop_avg_' => $oAvgExpr,
'_itop_min_' => $oMinExpr,
'_itop_max_' => $oMaxExpr,
);
];
$aGroupBy = array();
$aOrderBy = array();
$aArgs = array();
$aGroupBy = [];
$aOrderBy = [];
$aArgs = [];
$sSQL = $oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy, 0);
$this->debug($sSQL);
@@ -546,18 +537,14 @@ class DBSearchTest extends ItopDataTestCase
$oSearch = DBSearch::FromOQL($sOql);
$bHasThrownException = false;
try
{
try {
$oFirstResult = $oSearch->GetFirstResult($bMustHaveOneResultMax);
}
catch (CoreOqlMultipleResultsForbiddenException $e)
{
} catch (CoreOqlMultipleResultsForbiddenException $e) {
$oFirstResult = null;
$bHasThrownException = true;
}
switch ($sReturn)
{
switch ($sReturn) {
case 'exception':
self::assertEquals(true, $bHasThrownException, 'Exception raised');
break;
@@ -572,33 +559,33 @@ class DBSearchTest extends ItopDataTestCase
public function GetFirstResultProvider()
{
return array(
'One result' => array(
return [
'One result' => [
'SELECT Person WHERE id = 1',
false,
'object',
),
'Multiple results, no exception' => array(
],
'Multiple results, no exception' => [
'SELECT Person',
false,
'object',
),
'Multiple results, with exception' => array(
],
'Multiple results, with exception' => [
'SELECT Person',
true,
'exception',
),
'Multiple results with "WHERE 1", with exception' => array(
],
'Multiple results with "WHERE 1", with exception' => [
'SELECT Person WHERE 1',
true,
'exception',
),
'No result' => array(
],
'No result' => [
'SELECT Person WHERE id = -1',
true,
'null',
),
);
],
];
}
/**
@@ -610,14 +597,11 @@ class DBSearchTest extends ItopDataTestCase
$oSearch = DBSearch::FromOQL("SELECT FiberChannelInterface AS FCI");
self::assertNotNull($oSearch);
try
{
try {
$oExpr1 = Expression::FromOQL('AVC(FCI.name)');
//$aGroupBy = array('group1' => $oExpr1);
//$oSearch->MakeGroupByQuery(array(), $aGroupBy, false, array(), array());
}
catch (Exception $e)
{
} catch (Exception $e) {
$sExceptionClass = get_class($e);
}
@@ -627,13 +611,10 @@ class DBSearchTest extends ItopDataTestCase
public function testSanity_GroupFunction_In_GroupByPart()
{
$sExceptionClass = '';
try
{
try {
$oSearch = DBSearch::FromOQL("SELECT FiberChannelInterface AS FCI WHERE COUNT(FCI.name) = AVC(FCI.name)");
//$oSearch->MakeGroupByQuery(array(), array(), false, array(), array());
}
catch (Exception $e)
{
} catch (Exception $e) {
$sExceptionClass = get_class($e);
}
@@ -643,19 +624,16 @@ class DBSearchTest extends ItopDataTestCase
public function testSanity_UnknownGroupFunction_In_SelectPart()
{
$sExceptionClass = '';
try
{
try {
$oTimeExpr = Expression::FromOQL('FCI.speed');
$oWrongExpr = new FunctionExpression('GABUZOMEU', array($oTimeExpr));
$oWrongExpr = new FunctionExpression('GABUZOMEU', [$oTimeExpr]);
// Alias => Expression
$aFunctions = array(
$aFunctions = [
'_itop_wrong_' => $oWrongExpr,
);
];
$oSearch = DBSearch::FromOQL("SELECT FiberChannelInterface AS FCI");
$oSearch->MakeGroupByQuery(array(), array(), false, $aFunctions, array());
}
catch (Exception $e)
{
$oSearch->MakeGroupByQuery([], [], false, $aFunctions, []);
} catch (Exception $e) {
$sExceptionClass = get_class($e);
}
@@ -673,14 +651,14 @@ class DBSearchTest extends ItopDataTestCase
*/
public function testSelectInWithVariableExpressions()
{
$aReq = array(array(1, 0, 0), array(1, 1, 3), array(1, 2, 1), array(1, 0, 1), array(1, 1, 0), array(1, 2, 1));
$aReq = [[1, 0, 0], [1, 1, 3], [1, 2, 1], [1, 0, 1], [1, 1, 0], [1, 2, 1]];
$sOrgs = $this->init_db(3, 4, $aReq);
$allOrgIds = explode(",", $sOrgs);
$TwoOrgIdsOnly = array($allOrgIds[0], $allOrgIds[1]);
$TwoOrgIdsOnly = [$allOrgIds[0], $allOrgIds[1]];
$oSearch = DBSearch::FromOQL("SELECT UserRequest WHERE org_id IN (:org_ids)");
self::assertNotNull($oSearch);
$oSet = new \CMDBObjectSet($oSearch, array(), array('org_ids' => $TwoOrgIdsOnly));
$oSet = new \CMDBObjectSet($oSearch, [], ['org_ids' => $TwoOrgIdsOnly]);
static::assertEquals(4, $oSet->Count());
// Content now generated with ajax call
@@ -703,7 +681,8 @@ class DBSearchTest extends ItopDataTestCase
/**
* @since 2.7.2 3.0.0 N°3324
*/
public function testAllowAllData() {
public function testAllowAllData()
{
$oSimpleSearch = \DBObjectSearch::FromOQL('SELECT FunctionalCI');
$oSimpleSearch->AllowAllData(false);
self::assertFalse($oSimpleSearch->IsAllDataAllowed(), 'DBSearch AllowData value');
@@ -715,7 +694,8 @@ class DBSearchTest extends ItopDataTestCase
$this->CheckNestedSearch($sNestedQuery, false);
}
private function CheckNestedSearch($sQuery, $bAllowAllData) {
private function CheckNestedSearch($sQuery, $bAllowAllData)
{
$oNestedQuerySearch = \DBObjectSearch::FromOQL($sQuery);
$oNestedQuerySearch->AllowAllData($bAllowAllData);
self::assertEquals($bAllowAllData, $oNestedQuerySearch->IsAllDataAllowed(), 'root DBSearch AllowData value');
@@ -746,110 +726,111 @@ class DBSearchTest extends ItopDataTestCase
$oSearch->MakeSelectQuery();
self::assertTrue(true);
}
/**
* @dataProvider QueriesProvider
* @param $sOQL
*
* @return void
*/
public function testQueries($sOQL)
{
$oSearch = DBSearch::FromOQL($sOQL);
$oSet = new DBObjectSet($oSearch);
if ($oSet->Count() > 0) {
$aSelectedAliases = array_keys($oSearch->GetSelectedClasses());
$aFirstRow = $oSet->FetchAssoc();
$aAliases = array_keys($aFirstRow);
$this->assertEquals($aSelectedAliases, $aAliases);
}
}
/**
* @dataProvider QueriesProvider
* @param $sOQL
*
* @return void
*/
public function testQueries($sOQL)
{
$oSearch = DBSearch::FromOQL($sOQL);
$oSet = new DBObjectSet($oSearch);
if ($oSet->Count() > 0) {
$aSelectedAliases = array_keys($oSearch->GetSelectedClasses());
$aFirstRow = $oSet->FetchAssoc();
$aAliases = array_keys($aFirstRow);
$this->assertEquals($aSelectedAliases, $aAliases);
}
}
public function QueriesProvider()
{
return [
['SELECT L,P FROM Person AS P JOIN Location AS L ON P.location_id=L.id'],
['SELECT P,L FROM Person AS P JOIN Location AS L ON P.location_id=L.id'],
];
}
public function SelectAttributeToArrayProvider()
{
return array(
'select id from FunctionalCI' => array(
'SELECT FunctionalCI',
'id',
),
'select name from FunctionalCI' => array(
'SELECT FunctionalCI',
'name',
),
'select org_id from FunctionalCI' => array(
'SELECT FunctionalCI',
'org_id',
),
'select organization_name from FunctionalCI' => array(
'SELECT FunctionalCI',
'organization_name',
),
'select business_criticity from FunctionalCI' => array(
'SELECT FunctionalCI',
'business_criticity',
),
'select org_id from FunctionalCI' => array(
'SELECT FunctionalCI',
'org_id',
),
'select email from Person' => array(
'SELECT Person',
'email',
),
'select phone from Person' => array(
'SELECT Person',
'phone',
),
'select picture from Person' => array(
'SELECT Person',
'picture',
),
'select description from Ticket' => array(
'SELECT Ticket',
'description',
),
'select start_date from Ticket' => array(
'SELECT Ticket',
'start_date',
),
'select private_log from Ticket' => array(
'SELECT Ticket',
'private_log',
),
);
}
public function QueriesProvider()
{
return [
['SELECT L,P FROM Person AS P JOIN Location AS L ON P.location_id=L.id'],
['SELECT P,L FROM Person AS P JOIN Location AS L ON P.location_id=L.id'],
];
}
public function SelectAttributeToArrayProvider()
{
return [
'select id from FunctionalCI' => [
'SELECT FunctionalCI',
'id',
],
'select name from FunctionalCI' => [
'SELECT FunctionalCI',
'name',
],
'select org_id from FunctionalCI' => [
'SELECT FunctionalCI',
'org_id',
],
'select organization_name from FunctionalCI' => [
'SELECT FunctionalCI',
'organization_name',
],
'select business_criticity from FunctionalCI' => [
'SELECT FunctionalCI',
'business_criticity',
],
'select org_id from FunctionalCI' => [
'SELECT FunctionalCI',
'org_id',
],
'select email from Person' => [
'SELECT Person',
'email',
],
'select phone from Person' => [
'SELECT Person',
'phone',
],
'select picture from Person' => [
'SELECT Person',
'picture',
],
'select description from Ticket' => [
'SELECT Ticket',
'description',
],
'select start_date from Ticket' => [
'SELECT Ticket',
'start_date',
],
'select private_log from Ticket' => [
'SELECT Ticket',
'private_log',
],
];
}
/**
* @dataProvider SelectAttributeToArrayProvider
*
* @return void
* @throws \ConfigException
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
public function testSelectAttributeToArray($sQuery, $sField){
/**
* @dataProvider SelectAttributeToArrayProvider
*
* @return void
* @throws \ConfigException
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
public function testSelectAttributeToArray($sQuery, $sField)
{
$oSearch = \DBObjectSearch::FromOQL($sQuery);
$aResToDataArray=[];
$oSet = new \DBObjectSet($oSearch);
while ($oRecord = $oSet->Fetch()) {
$aMappedRow[$sField] =$oRecord->Get($sField);
$aResToDataArray[] = $aMappedRow;
}
array_multisort (array_column($aResToDataArray, $sField), SORT_DESC, $aResToDataArray);
$aResToDataArray = [];
$oSet = new \DBObjectSet($oSearch);
while ($oRecord = $oSet->Fetch()) {
$aMappedRow[$sField] = $oRecord->Get($sField);
$aResToDataArray[] = $aMappedRow;
}
array_multisort(array_column($aResToDataArray, $sField), SORT_DESC, $aResToDataArray);
$aResSelectColumnToArray = $oSearch->SelectAttributeToArray($sField);
array_multisort (array_column($aResSelectColumnToArray, $sField), SORT_DESC, $aResSelectColumnToArray);
array_multisort(array_column($aResSelectColumnToArray, $sField), SORT_DESC, $aResSelectColumnToArray);
self::assertEquals( $aResToDataArray, $aResSelectColumnToArray, 'The array constructed using the OQL query and the result of testSelectAttributeToArray must be the same');
}
}
self::assertEquals($aResToDataArray, $aResSelectColumnToArray, 'The array constructed using the OQL query and the result of testSelectAttributeToArray must be the same');
}
}

View File

@@ -5,7 +5,6 @@ namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use DBObjectSearch;
/**
* Class DBSearchUpdateRealiasingMapTest
*
@@ -13,7 +12,7 @@ use DBObjectSearch;
*/
class DBSearchUpdateRealiasingMapTest extends ItopDataTestCase
{
const USE_TRANSACTION = false;
public const USE_TRANSACTION = false;
protected function setUp(): void
{
@@ -41,37 +40,37 @@ class DBSearchUpdateRealiasingMapTest extends ItopDataTestCase
'empty' => [
'OriginalMap' => null,
'AliasTranslation' => [],
'ExpectedMap' => null
'ExpectedMap' => null,
],
'Add 1 alias' => [
'OriginalMap' => [],
'AliasTranslation' => ['a' => ['*' => 'b']],
'ExpectedMap' => ['a' => ['b']]
'ExpectedMap' => ['a' => ['b']],
],
'Add 2 aliases' => [
'OriginalMap' => [],
'AliasTranslation' => ['a' => ['*' => 'b'], 'c' => ['*' => 'd']],
'ExpectedMap' => ['a' => ['b'], 'c' => ['d']]
'ExpectedMap' => ['a' => ['b'], 'c' => ['d']],
],
'Append 1 alias' => [
'OriginalMap' => ['a' => ['b']],
'AliasTranslation' => ['c' => ['*' => 'd']],
'ExpectedMap' => ['a' => ['b'], 'c' => ['d']]
'ExpectedMap' => ['a' => ['b'], 'c' => ['d']],
],
'Merge 1 alias' => [
'OriginalMap' => ['a' => ['b']],
'AliasTranslation' => ['a' => ['*' => 'd']],
'ExpectedMap' => ['a' => ['b', 'd']]
'ExpectedMap' => ['a' => ['b', 'd']],
],
'Merge same alias' => [
'OriginalMap' => ['a' => ['b']],
'AliasTranslation' => ['a' => ['*' => 'b']],
'ExpectedMap' => ['a' => ['b']]
'ExpectedMap' => ['a' => ['b']],
],
'Transitivity a->b + b->f = a->f' => [
'OriginalMap' => ['a' => ['b', 'd'], 'c' => ['e']],
'AliasTranslation' => ['b' => ['*' => 'f']],
'ExpectedMap' => ['a' => ['f', 'd'], 'c' => ['e']]
'ExpectedMap' => ['a' => ['f', 'd'], 'c' => ['e']],
],
];
}

View File

@@ -1,15 +1,14 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
class DBUnionSearchTest extends ItopDataTestCase
{
/**
* @dataProvider UnionSearchProvider
*

View File

@@ -6,8 +6,8 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase;
use EMail;
use utils;
class EMailTest extends ItopTestCase {
class EMailTest extends ItopTestCase
{
/**
* @return void
* @throws \ConfigException
@@ -20,7 +20,7 @@ class EMailTest extends ItopTestCase {
$oConfig = utils::GetConfig();
$sCurrentEmailTransport = $oConfig->Get('email_transport');
$sCurrentEmailAsync = $oConfig->Get('email_asynchronous');
// Set our email transport to file, so we can read it after
$oConfig->Set('email_transport', 'LogFile');
$oConfig->Set('email_asynchronous', false);
@@ -30,17 +30,17 @@ class EMailTest extends ItopTestCase {
$oEmail->SetRecipientFrom('email2@email2.com');
$oEmail->SetSubject('dummy subject');
$oEmail->SetBody('dummy body');
// Send the mail and check if there's any issue
$aIssues = [];
$oEmail->Send($aIssues);
$this->assertEmpty($aIssues);
// Check if our charset is correctly set
// We know this file may be used by other future test, but as we can't configure output filename, it is what it is
$sEmailContent = file_get_contents(APPROOT.'log/mail.log');
$this->assertStringContainsStringIgnoringCase('charset=UTF-8', $sEmailContent);
// Set our previous email transport value back, so it doesn't affect other tests
$oConfig->Set('email_transport', $sCurrentEmailTransport);
$oConfig->Set('email_asynchronous', $sCurrentEmailAsync);
@@ -84,4 +84,4 @@ class EMailTest extends ItopTestCase {
$oConfig->Set('email_transport', $sCurrentEmailTransport);
$oConfig->Set('email_asynchronous', $sCurrentEmailAsync);
}
}
}

View File

@@ -60,10 +60,9 @@ class EventIssueTest extends ItopDataTestCase
try {
$oEventIssue->DBInsert();
}
catch (CoreException $e) {
} catch (CoreException $e) {
$this->fail('we should be able to persist the object though it contains long values in its attributes: '.$e->getMessage());
}
$this->assertTrue(true);
}
}
}

View File

@@ -1,9 +1,7 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Core;
use CMDBSource;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use DateInterval;
@@ -15,7 +13,7 @@ use ScalarExpression;
class ExpressionEvaluateTest extends ItopDataTestCase
{
const USE_TRANSACTION = false;
public const USE_TRANSACTION = false;
/**
* @covers Expression::GetParameters()
@@ -38,14 +36,14 @@ class ExpressionEvaluateTest extends ItopDataTestCase
public function GetParametersProvider()
{
return array(
array('1 AND 0 OR :hello + :world', null, array('hello', 'world')),
array('1 AND 0 OR :hello + :world', 'this', array()),
array(':this->left + :this->right', null, array('this->left', 'this->right')),
array(':this->left + :this->right', 'this', array('left', 'right')),
array(':this->left + :this->right', 'that', array()),
array(':this_left + :this_right', 'this', array()),
);
return [
['1 AND 0 OR :hello + :world', null, ['hello', 'world']],
['1 AND 0 OR :hello + :world', 'this', []],
[':this->left + :this->right', null, ['this->left', 'this->right']],
[':this->left + :this->right', 'this', ['left', 'right']],
[':this->left + :this->right', 'that', []],
[':this_left + :this_right', 'this', []],
];
}
/**
@@ -59,8 +57,7 @@ class ExpressionEvaluateTest extends ItopDataTestCase
public function _testExpressionEvaluateAllAtOnce()
{
$aTestCases = $this->VariousExpressionsProvider();
foreach ($aTestCases as $sCaseId => $aTestArgs)
{
foreach ($aTestCases as $sCaseId => $aTestArgs) {
$this->debug("Case $sCaseId:");
$this->testVariousExpressions($aTestArgs[0], $aTestArgs[1]);
}
@@ -80,141 +77,137 @@ class ExpressionEvaluateTest extends ItopDataTestCase
public function testVariousExpressions($sExpression, $expectedValue)
{
$oExpression = Expression::FromOQL($sExpression);
$value = $oExpression->Evaluate(array());
$value = $oExpression->Evaluate([]);
$this->assertEquals($expectedValue, $value);
}
public function VariousExpressionsProvider()
{
if (false)
{
$aExpressions = array(
if (false) {
$aExpressions = [
// Test case to isolate for troubleshooting purposes
array("'a' IN ('a', 'b')", true),
);
}
else
{
$aExpressions = array(
["'a' IN ('a', 'b')", true],
];
} else {
$aExpressions = [
// The bare minimum
array('"blah"', 'blah'),
array('"\\\\"', '\\'),
['"blah"', 'blah'],
['"\\\\"', '\\'],
// Arithmetics
array('2+2', 4),
array('2+2-2', 2),
array('2*(3+4)', 14),
array('(2*3)+4', 10),
array('2*3+4', 10),
['2+2', 4],
['2+2-2', 2],
['2*(3+4)', 14],
['(2*3)+4', 10],
['2*3+4', 10],
// Strings
array("CONCAT('hello', 'world')", 'helloworld'),
["CONCAT('hello', 'world')", 'helloworld'],
// Not yet parsed - array("CONCAT_WS(' ', 'hello', 'world')", 'hello world'),
array("SUBSTR('abcdef', 2, 3)", 'bcd'),
array("TRIM(' Sin dolor ')", 'Sin dolor'),
["SUBSTR('abcdef', 2, 3)", 'bcd'],
["TRIM(' Sin dolor ')", 'Sin dolor'],
// Comparison operators
array('1 = 1', 1),
array('1 != 1', 0),
array('0 = 1', 0),
array('0 != 1', 1),
array('2 > 1', 1),
array('2 < 1', 0),
array('1 > 2', 0),
array('2 > 1', 1),
array('2 >= 1', 1),
array('2 >= 2', 1),
array("'the quick brown dog' LIKE '%QUICK%'", 1),
array("'the quick brown dog' LIKE '%SLOW%'", 0),
array("'the quick brown dog' LIKE '%QU_CK%'", 1),
array("'the quick brown dog' LIKE '%QU_ICK%'", 0),
array('"400 (km/h)" LIKE "400%"', 1),
array('"400 (km/h)" LIKE "100%"', 0),
array('"400 (km/h)" NOT LIKE "400%"', 0),
array('"400 (km/h)" NOT LIKE "100%"', 1),
array('"2020-06-12" > "2020-06-11"', 1),
array('"2020-06-12" < "2020-06-11"', 0),
array('" 2020-06-12" > "2020-06-11"', 0), // Leading spaces => a string
array('" 2020-06-12 " > "2020-06-11"', 0), // Trailing spaces => a string
array('"2020-06-12 17:35:13" > "2020-06-12 17:35:12"', 1),
array('"2020-06-12 17:35:13" < "2020-06-12 17:35:12"', 0),
array('"2020-06-12 17:35:13" > "2020-06-12"', 1),
array('"2020-06-12 17:35:13" < "2020-06-12"', 0),
array('"2020-06-12 00:00:00" = "2020-06-12"', 0),
['1 = 1', 1],
['1 != 1', 0],
['0 = 1', 0],
['0 != 1', 1],
['2 > 1', 1],
['2 < 1', 0],
['1 > 2', 0],
['2 > 1', 1],
['2 >= 1', 1],
['2 >= 2', 1],
["'the quick brown dog' LIKE '%QUICK%'", 1],
["'the quick brown dog' LIKE '%SLOW%'", 0],
["'the quick brown dog' LIKE '%QU_CK%'", 1],
["'the quick brown dog' LIKE '%QU_ICK%'", 0],
['"400 (km/h)" LIKE "400%"', 1],
['"400 (km/h)" LIKE "100%"', 0],
['"400 (km/h)" NOT LIKE "400%"', 0],
['"400 (km/h)" NOT LIKE "100%"', 1],
['"2020-06-12" > "2020-06-11"', 1],
['"2020-06-12" < "2020-06-11"', 0],
['" 2020-06-12" > "2020-06-11"', 0], // Leading spaces => a string
['" 2020-06-12 " > "2020-06-11"', 0], // Trailing spaces => a string
['"2020-06-12 17:35:13" > "2020-06-12 17:35:12"', 1],
['"2020-06-12 17:35:13" < "2020-06-12 17:35:12"', 0],
['"2020-06-12 17:35:13" > "2020-06-12"', 1],
['"2020-06-12 17:35:13" < "2020-06-12"', 0],
['"2020-06-12 00:00:00" = "2020-06-12"', 0],
// IN operator
array("'a' IN ('a')", true),
array("'a' IN ('b')", false),
array("'a' IN ('a', 'b')", true),
array("'z' IN ('a', 'b')", false),
array("'a' NOT IN ('a')", false),
array("'a' NOT IN ('b')", true),
array("'a' NOT IN ('a', 'b')", false),
array("'z' NOT IN ('a', 'b')", true),
["'a' IN ('a')", true],
["'a' IN ('b')", false],
["'a' IN ('a', 'b')", true],
["'z' IN ('a', 'b')", false],
["'a' NOT IN ('a')", false],
["'a' NOT IN ('b')", true],
["'a' NOT IN ('a', 'b')", false],
["'z' NOT IN ('a', 'b')", true],
// Logical operators
array('0 AND 0', 0),
array('1 AND 0', 0),
array('0 AND 1', 0),
array('1 AND 1', 1),
array('0 OR 0', 0),
array('0 OR 1', 1),
array('1 OR 0', 1),
array('1 OR 1', 1),
array('1 AND 0 OR 1', 1),
['0 AND 0', 0],
['1 AND 0', 0],
['0 AND 1', 0],
['1 AND 1', 1],
['0 OR 0', 0],
['0 OR 1', 1],
['1 OR 0', 1],
['1 OR 1', 1],
['1 AND 0 OR 1', 1],
// Casting
array('1 AND "blah"', 0),
array('1 AND "1"', 1),
array('1 AND "2"', 1),
array('1 AND "0"', 0),
array('1 AND "-1"', 1),
['1 AND "blah"', 0],
['1 AND "1"', 1],
['1 AND "2"', 1],
['1 AND "0"', 0],
['1 AND "-1"', 1],
// Null
array('NULL', null),
array('1 AND NULL', null),
array('CONCAT("Great but...", NULL)', null),
array('COALESCE(NULL, 123)', 123),
array('COALESCE(321, 123)', 321),
array('ISNULL(NULL)', 1),
array('ISNULL(123)', 0),
['NULL', null],
['1 AND NULL', null],
['CONCAT("Great but...", NULL)', null],
['COALESCE(NULL, 123)', 123],
['COALESCE(321, 123)', 321],
['ISNULL(NULL)', 1],
['ISNULL(123)', 0],
// Date functions
array("DATE('2020-03-12 13:18:30')", '2020-03-12'),
array("DATE_FORMAT('2009-10-04 22:23:00', '%Y %m %d %H %i %s')", '2009 10 04 22 23 00'),
array("DATE(NOW()) = CURRENT_DATE()", 1), // Could fail if executed around midnight!
array("TO_DAYS('2020-01-02')", 737791),
array("FROM_DAYS(737791)", '2020-01-02'),
array("FROM_DAYS(TO_DAYS('2020-01-02'))", '2020-01-02'), // Back and forth conversion to ensure it returns the same
array("YEAR('2020-05-03')", 2020),
array("MONTH('2020-05-03')", 5),
array("DAY('2020-05-03')", 3),
array("DATE_ADD('2020-02-28 18:00:00', INTERVAL 1 HOUR)", '2020-02-28 19:00:00'),
array("DATE_ADD('2020-02-28 18:00:00', INTERVAL 1 DAY)", '2020-02-29 18:00:00'),
array("DATE_SUB('2020-03-01 18:00:00', INTERVAL 1 HOUR)", '2020-03-01 17:00:00'),
array("DATE_SUB('2020-03-01 18:00:00', INTERVAL 1 DAY)", '2020-02-29 18:00:00'),
["DATE('2020-03-12 13:18:30')", '2020-03-12'],
["DATE_FORMAT('2009-10-04 22:23:00', '%Y %m %d %H %i %s')", '2009 10 04 22 23 00'],
["DATE(NOW()) = CURRENT_DATE()", 1], // Could fail if executed around midnight!
["TO_DAYS('2020-01-02')", 737791],
["FROM_DAYS(737791)", '2020-01-02'],
["FROM_DAYS(TO_DAYS('2020-01-02'))", '2020-01-02'], // Back and forth conversion to ensure it returns the same
["YEAR('2020-05-03')", 2020],
["MONTH('2020-05-03')", 5],
["DAY('2020-05-03')", 3],
["DATE_ADD('2020-02-28 18:00:00', INTERVAL 1 HOUR)", '2020-02-28 19:00:00'],
["DATE_ADD('2020-02-28 18:00:00', INTERVAL 1 DAY)", '2020-02-29 18:00:00'],
["DATE_SUB('2020-03-01 18:00:00', INTERVAL 1 HOUR)", '2020-03-01 17:00:00'],
["DATE_SUB('2020-03-01 18:00:00', INTERVAL 1 DAY)", '2020-02-29 18:00:00'],
// Misc. functions
array('IF(1, 123, 567)', 123),
array('IF(0, 123, 567)', 567),
array('ELT(3, "a", "b", "c")', 'c'),
array('ELT(0, "a", "b", "c")', null),
array('ELT(4, "a", "b", "c")', null),
array('INET_ATON("128.0.0.1")', 2147483649),
array('INET_NTOA(2147483649)', '128.0.0.1'),
);
['IF(1, 123, 567)', 123],
['IF(0, 123, 567)', 567],
['ELT(3, "a", "b", "c")', 'c'],
['ELT(0, "a", "b", "c")', null],
['ELT(4, "a", "b", "c")', null],
['INET_ATON("128.0.0.1")', 2147483649],
['INET_NTOA(2147483649)', '128.0.0.1'],
];
// N°5985 - Test bidirectional conversion across the centuries to ensure that it works on PHP 7.4 => 8.2+ even though the bug has been fixed in PHP 8.1 but still exists in PHP 7.4 => 8.1
for ($iUpperYearBound = 1925; $iUpperYearBound <= 2100; $iUpperYearBound = $iUpperYearBound + 25) {
$aExpressions[] = array("FROM_DAYS(TO_DAYS('$iUpperYearBound-01-02'))", "$iUpperYearBound-01-02");
$aExpressions[] = ["FROM_DAYS(TO_DAYS('$iUpperYearBound-01-02'))", "$iUpperYearBound-01-02"];
}
}
// Build a comprehensive index
$aRet = array();
foreach ($aExpressions as $aExp)
{
$aRet = [];
foreach ($aExpressions as $aExp) {
$aRet[$aExp[0]] = $aExp;
}
return $aRet;
@@ -231,27 +224,26 @@ class ExpressionEvaluateTest extends ItopDataTestCase
{
$sNewExpression = "return $sExpression;";
$oExpression = eval($sNewExpression);
$res = $oExpression->Evaluate(array());
$res = $oExpression->Evaluate([]);
$this->assertEquals($expectedValue, $res);
}
public function NotYetParsableExpressionsProvider()
{
$aExpressions = array(
array("new \\FunctionExpression('CONCAT_WS', array(new \\ScalarExpression(' '), new \\ScalarExpression('Hello'), new \ScalarExpression('world!')))", 'Hello world!'),
array("new \\ScalarExpression('windows\\system32')", 'windows\\system32'),
array("new \\BinaryExpression(new \\ScalarExpression('100%'), 'LIKE', new \\ScalarExpression('___\%'))", 1),
array("new \\BinaryExpression(new \ScalarExpression('1000'), 'LIKE', new \ScalarExpression('___\%'))", 0),
$aExpressions = [
["new \\FunctionExpression('CONCAT_WS', array(new \\ScalarExpression(' '), new \\ScalarExpression('Hello'), new \ScalarExpression('world!')))", 'Hello world!'],
["new \\ScalarExpression('windows\\system32')", 'windows\\system32'],
["new \\BinaryExpression(new \\ScalarExpression('100%'), 'LIKE', new \\ScalarExpression('___\%'))", 1],
["new \\BinaryExpression(new \ScalarExpression('1000'), 'LIKE', new \ScalarExpression('___\%'))", 0],
// Net yet parsed - array("TIME(NOW()) = CURRENT_TIME()", 1), // Not relevant
// Not yet parsed - array("DATE_ADD('2020-02-28 18:00:00', INTERVAL 1 WEEK)", '2020-03-06 18:00:00'),
// Not yet parsed - array("DATE_SUB('2020-03-01 18:00:00', INTERVAL 1 WEEK)", '2020-02-23 18:00:00'),
// Not yet parsed - array('ROUND(1.2345, 2)', 1.23),
// Not yet parsed - array('FLOOR(1.2)', 1),
);
];
// Build a comprehensive index
$aRet = array();
foreach ($aExpressions as $aExp)
{
$aRet = [];
foreach ($aExpressions as $aExp) {
$aRet[$aExp[0]] = $aExp;
}
return $aRet;
@@ -269,17 +261,15 @@ class ExpressionEvaluateTest extends ItopDataTestCase
$aTests = array_values($this->VariousExpressionsProvider());
// Expressions given as a PHP statement
foreach (array_values($this->NotYetParsableExpressionsProvider()) as $i => $aTest)
{
foreach (array_values($this->NotYetParsableExpressionsProvider()) as $i => $aTest) {
$sNewExpression = "return {$aTest[0]};";
$oExpression = eval($sNewExpression);
$sExpression = $oExpression->RenderExpression(true);
$aTests[] = array($sExpression, $aTest[1]);
$aTests[] = [$sExpression, $aTest[1]];
}
$aExpressions = array();
foreach ($aTests as $i => $aTest)
{
$aExpressions = [];
foreach ($aTests as $i => $aTest) {
$aExpressions[] = "{$aTest[0]} as test_$i";
}
@@ -289,8 +279,7 @@ class ExpressionEvaluateTest extends ItopDataTestCase
$this->debug($sQuery);
$aResults = CMDBSource::QueryToArray($sQuery);
foreach ($aTests as $i => $aTest)
{
foreach ($aTests as $i => $aTest) {
$value = $aResults[0]["test_$i"];
$expectedValue = $aTest[1];
$this->debug("Test #$i: {$aTests[$i][0]} => ".var_export($value, true));
@@ -352,15 +341,15 @@ class ExpressionEvaluateTest extends ItopDataTestCase
public function ExpressionWithParametersProvider()
{
return array(
return [
['`DBVariables["analyze_sample_percentage"]` > 10', ['DBVariables["analyze_sample_percentage"]' => 20], true],
['`DataBase["DBDataSize"]`', ['DataBase["DBDataSize"]' => 4096], 4096],
['`FileSystem["ItopInstallationIntegrity"]`', ['FileSystem["ItopInstallationIntegrity"]' => 'not_conform'], 'not_conform'],
['`DBTablesInfo["attachment"].DataSize` > 100', ['DBTablesInfo["attachment"].DataSize' => 200], true],
['`DBTablesInfo[].DataSize` > 100', ['DBTablesInfo[].DataSize' => 50], false],
['(`DBTablesInfo[].DataSize` > 100) AND (`DBTablesInfo[].DataFree` * 100 / (`DBTablesInfo[].DataSize` + `DBTablesInfo[].IndexSize` + `DBTablesInfo[].DataFree`) > 10)', ['DBTablesInfo[].DataSize' => 200, 'DBTablesInfo[].DataFree' => 100, 'DBTablesInfo[].IndexSize' => 10], true],
array('CONCAT(SUBSTR(name, 4), " cause")', array('name' => 'noble'), 'le cause'),
);
['CONCAT(SUBSTR(name, 4), " cause")', ['name' => 'noble'], 'le cause'],
];
}
/**
@@ -380,28 +369,24 @@ class ExpressionEvaluateTest extends ItopDataTestCase
$oExpression = Expression::FromOQL($sExpression);
$res = $oExpression->IsTrue();
if ($bExpectTrue)
{
if ($bExpectTrue) {
$this->assertTrue($res, 'arg: '.$sExpression);
}
else
{
} else {
$this->assertFalse($res, 'arg: '.$sExpression);
}
}
public function TrueExpressionsProvider()
{
$aExpressions = array(
array('1', true),
array('0 OR 0', false),
array('1 AND 1', true),
array('1 AND (1 OR 0)', true)
);
$aExpressions = [
['1', true],
['0 OR 0', false],
['1 AND 1', true],
['1 AND (1 OR 0)', true],
];
// Build a comprehensive index
$aRet = array();
foreach ($aExpressions as $aExp)
{
$aRet = [];
foreach ($aExpressions as $aExp) {
$aRet[$aExp[0]] = $aExp;
}
return $aRet;
@@ -423,60 +408,56 @@ class ExpressionEvaluateTest extends ItopDataTestCase
public function testTimeFormat($sFormat, $bProcessed, $sValueOrException)
{
$sDate = '2009-06-04 21:23:24';
$oExpression = new FunctionExpression('DATE_FORMAT', array(new ScalarExpression($sDate), new ScalarExpression("%$sFormat")));
if ($bProcessed)
{
$oExpression = new FunctionExpression('DATE_FORMAT', [new ScalarExpression($sDate), new ScalarExpression("%$sFormat")]);
if ($bProcessed) {
$sqlValue = CMDBSource::QueryToScalar("SELECT DATE_FORMAT('$sDate', '%$sFormat')");
$this->assertEquals($sqlValue, $sValueOrException, 'Check test against MySQL');
$res = $oExpression->Evaluate(array());
$res = $oExpression->Evaluate([]);
$this->assertEquals($sValueOrException, $res, 'Check evaluation');
}
else
{
} else {
static::expectException($sValueOrException);
$oExpression->Evaluate(array());
$oExpression->Evaluate([]);
}
}
public function TimeFormatsProvider()
{
$aTests = array(
array('a', true, 'Thu'),
array('b', true, 'Jun'),
array('c', true, '6'),
array('D', true, '4th'),
array('d', true, '04'),
array('e', true, '4'),
array('f', false, 'NotYetEvaluatedExpression'), // microseconds: no way!
array('H', true, '21'),
array('h', true, '09'),
array('I', true, '09'),
array('i', true, '23'),
array('j', true, '155'), // day of the year
array('k', true, '21'),
array('l', true, '9'),
array('M', true, 'June'),
array('m', true, '06'),
array('p', true, 'PM'),
array('r', true, '09:23:24 PM'),
array('S', true, '24'),
array('s', true, '24'),
array('T', true, '21:23:24'),
array('U', false, 'NotYetEvaluatedExpression'), // Week sunday based (mode 0)
array('u', false, 'NotYetEvaluatedExpression'), // Week monday based (mode 1)
array('V', false, 'NotYetEvaluatedExpression'), // Week sunday based (mode 2)
array('v', true, '23'), // Week monday based (mode 3 - ISO-8601)
array('W', true, 'Thursday'),
array('w', true, '4'),
array('X', false, 'NotYetEvaluatedExpression'),
array('x', true, '2009'), // to be used with %v (ISO - 8601)
array('Y', true, '2009'),
array('y', true, '09'),
);
$aRes = array();
foreach ($aTests as $aTest)
{
$aTests = [
['a', true, 'Thu'],
['b', true, 'Jun'],
['c', true, '6'],
['D', true, '4th'],
['d', true, '04'],
['e', true, '4'],
['f', false, 'NotYetEvaluatedExpression'], // microseconds: no way!
['H', true, '21'],
['h', true, '09'],
['I', true, '09'],
['i', true, '23'],
['j', true, '155'], // day of the year
['k', true, '21'],
['l', true, '9'],
['M', true, 'June'],
['m', true, '06'],
['p', true, 'PM'],
['r', true, '09:23:24 PM'],
['S', true, '24'],
['s', true, '24'],
['T', true, '21:23:24'],
['U', false, 'NotYetEvaluatedExpression'], // Week sunday based (mode 0)
['u', false, 'NotYetEvaluatedExpression'], // Week monday based (mode 1)
['V', false, 'NotYetEvaluatedExpression'], // Week sunday based (mode 2)
['v', true, '23'], // Week monday based (mode 3 - ISO-8601)
['W', true, 'Thursday'],
['w', true, '4'],
['X', false, 'NotYetEvaluatedExpression'],
['x', true, '2009'], // to be used with %v (ISO - 8601)
['Y', true, '2009'],
['y', true, '09'],
];
$aRes = [];
foreach ($aTests as $aTest) {
$aRes["Format %{$aTest[0]}"] = $aTest;
}
return $aRes;
@@ -501,13 +482,11 @@ class ExpressionEvaluateTest extends ItopDataTestCase
public function testEveryTimeFormat($sDate)
{
$aFormats = $this->TimeFormatsProvider();
$aSelects = array();
foreach ($aFormats as $sFormatDesc => $aFormatSpec)
{
$aSelects = [];
foreach ($aFormats as $sFormatDesc => $aFormatSpec) {
$sFormat = $aFormatSpec[0];
$bProcessed = $aFormatSpec[1];
if ($bProcessed)
{
if ($bProcessed) {
$aSelects["%$sFormat"] = "DATE_FORMAT('$sDate', '%$sFormat') AS `$sFormat`";
}
}
@@ -515,29 +494,27 @@ class ExpressionEvaluateTest extends ItopDataTestCase
$aRes = CMDBSource::QueryToArray($sSelects);
/** @var array $aMysqlDateFormatRsultsForAllFormats format as key, MySQL evaluated result as value */
$aMysqlDateFormatRsultsForAllFormats = $aRes[0];
foreach ($aFormats as $sFormatDesc => $aFormatSpec)
{
foreach ($aFormats as $sFormatDesc => $aFormatSpec) {
$sFormat = $aFormatSpec[0];
$bProcessed = $aFormatSpec[1];
if ($bProcessed)
{
$oExpression = new FunctionExpression('DATE_FORMAT', array(new ScalarExpression($sDate), new ScalarExpression("%$sFormat")));
$itopExpressionResult = $oExpression->Evaluate(array());
if ($bProcessed) {
$oExpression = new FunctionExpression('DATE_FORMAT', [new ScalarExpression($sDate), new ScalarExpression("%$sFormat")]);
$itopExpressionResult = $oExpression->Evaluate([]);
$this->assertSame($aMysqlDateFormatRsultsForAllFormats[$sFormat], $itopExpressionResult, "Format %$sFormat not matching MySQL for '$sDate'");
}
}
}
public function EveryTimeFormatProvider()
{
return array(
array('1971-07-19 8:40:00'),
array('1999-12-31 23:59:59'),
array('2000-01-01 00:00:00'),
array('2009-06-04 21:23:24'),
array('2020-02-29 23:59:59'),
array('2030-10-21 23:59:59'),
array('2050-12-21 23:59:59'),
);
return [
['1971-07-19 8:40:00'],
['1999-12-31 23:59:59'],
['2000-01-01 00:00:00'],
['2009-06-04 21:23:24'],
['2020-02-29 23:59:59'],
['2030-10-21 23:59:59'],
['2050-12-21 23:59:59'],
];
}
/**
@@ -557,8 +534,7 @@ class ExpressionEvaluateTest extends ItopDataTestCase
public function testEveryTimeFormatOnDateRange($sStartDate, $sInterval, $iRepeat)
{
$oDate = new DateTime($sStartDate);
for ($i = 0 ; $i < $iRepeat ; $i++)
{
for ($i = 0 ; $i < $iRepeat ; $i++) {
$sDate = date_format($oDate, 'Y-m-d H:i:s');
$this->debug("Checking '$sDate'");
$this->testEveryTimeFormat($sDate);
@@ -568,11 +544,11 @@ class ExpressionEvaluateTest extends ItopDataTestCase
public function EveryTimeFormatOnDateRangeProvider()
{
return array(
'10 years, each 17 days' => array('2000-01-01', 'P17D', 365 * 10 / 17),
'1 day, hour by hour' => array('2000-01-01 00:01:02', 'PT1H', 24),
'1 hour, minute by minute' => array('2000-01-01 00:01:02', 'PT1M', 60),
'1 minute, second by second' => array('2000-01-01 00:01:02', 'PT1S', 60),
);
return [
'10 years, each 17 days' => ['2000-01-01', 'P17D', 365 * 10 / 17],
'1 day, hour by hour' => ['2000-01-01 00:01:02', 'PT1H', 24],
'1 hour, minute by minute' => ['2000-01-01 00:01:02', 'PT1M', 60],
'1 minute, second by second' => ['2000-01-01 00:01:02', 'PT1S', 60],
];
}
}
}

View File

@@ -7,7 +7,7 @@ use Expression;
class ExpressionTest extends ItopDataTestCase
{
const USE_TRANSACTION = false;
public const USE_TRANSACTION = false;
/**
* @dataProvider ListParametersProvider
@@ -20,9 +20,8 @@ class ExpressionTest extends ItopDataTestCase
{
$oExpression = Expression::FromOQL($sOQL);
$aParameters = $oExpression->ListParameters();
$aResult = array();
foreach ($aParameters as $oVarExpr)
{
$aResult = [];
foreach ($aParameters as $oVarExpr) {
/** var \VariableExpression $oVarExpr */
$aResult[] = $oVarExpr->RenderExpression();
}
@@ -42,7 +41,7 @@ class ExpressionTest extends ItopDataTestCase
["name REGEXP :regexp", [':regexp']],
[" t.agent_id = :current_contact_id", [':current_contact_id']],
["INET_ATON(dev.managementip) > INET_ATON('10.22.32.224') AND INET_ATON(:ip) < INET_ATON('10.22.32.255')", [':ip']],
["((`UserRequest`.`status` IN ('closed','rejected','resolved')))", []]
["((`UserRequest`.`status` IN ('closed','rejected','resolved')))", []],
];
}
}

View File

@@ -13,7 +13,6 @@ use UserInternal;
use UserLocal;
use UserRightsProfile;
/**
* @group getSelectFilterTest
* @group sampleDataNeeded
@@ -33,20 +32,20 @@ class GetSelectFilterTest extends ItopDataTestCase
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');
$oRestProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => 'REST Services User'), true);
$oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => 'Administrator'), true);
$oRestProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => 'REST Services User'], true);
$oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", ['name' => 'Administrator'], true);
$this->sLogin = "getselectfilter-user-" . date('dmYHis');
$this->sLogin = "getselectfilter-user-".date('dmYHis');
// Ensure that we have at least one administrator account
if (is_object($oRestProfile) && is_object($oAdminProfile))
{
if (is_object($oRestProfile) && is_object($oAdminProfile)) {
$this->oUser = $this->CreateUser($this->sLogin, $oRestProfile->GetKey(), $this->sPassword);
$this->AddProfileToUser($this->oUser, $oAdminProfile->GetKey());
}
}
public function testGetSelectFilter() {
public function testGetSelectFilter()
{
$oUserRights = new UserRightsProfile();
$aClasses = get_declared_classes();
$aUserClasses = [User::class];
@@ -71,35 +70,28 @@ class GetSelectFilterTest extends ItopDataTestCase
$oConfig->Set('security.hide_administrators', false);
$oFilterProfiles = $oUserRights->GetSelectFilter($this->oUser, URP_Profiles::class);
if ($oFilterProfiles === true)
{
if ($oFilterProfiles === true) {
$oFilterProfiles = new DBObjectSearch(URP_Profiles::class);
}
$oSet = new DBObjectSet($oFilterProfiles);
$bAdminProfileFound = false;
while($oProfile = $oSet->Fetch())
{
if ($oProfile->GetKey() == 1)
{
while ($oProfile = $oSet->Fetch()) {
if ($oProfile->GetKey() == 1) {
$bAdminProfileFound = true;
break;
}
}
$this->assertEquals($bAdminProfileFound, true);
foreach($aUserLocalAncestors as $sUserClass)
{
foreach ($aUserLocalAncestors as $sUserClass) {
$bAdminUserFound = false;
$oFilterUser = $oUserRights->GetSelectFilter($this->oUser,$sUserClass);
if ($oFilterUser === true)
{
$oFilterUser = $oUserRights->GetSelectFilter($this->oUser, $sUserClass);
if ($oFilterUser === true) {
$oFilterUser = new DBObjectSearch($sUserClass);
}
$oSet = new DBObjectSet($oFilterUser);
while($oUser = $oSet->Fetch())
{
if($oUser->GetKey() == $this->oUser->GetKey())
{
while ($oUser = $oSet->Fetch()) {
if ($oUser->GetKey() == $this->oUser->GetKey()) {
$bAdminUserFound = true;
break;
}
@@ -108,29 +100,24 @@ class GetSelectFilterTest extends ItopDataTestCase
}
$oFilterLnkProfiles = $oUserRights->GetSelectFilter($this->oUser, URP_UserProfile::class);
if ($oFilterLnkProfiles === true)
{
if ($oFilterLnkProfiles === true) {
$oFilterLnkProfiles = new DBObjectSearch(URP_UserProfile::class);
}
$oSet = new DBObjectSet($oFilterLnkProfiles);
// There should some lnk referencing either our administrator account or the Administrator profile
$bUserFound = false;
$bProfileFound = false;
while($oLnk = $oSet->Fetch())
{
if($oLnk->Get('userid') == $this->oUser->GetKey())
{
while ($oLnk = $oSet->Fetch()) {
if ($oLnk->Get('userid') == $this->oUser->GetKey()) {
$bUserFound = true;
}
if($oLnk->Get('profileid') == 1)
{
if ($oLnk->Get('profileid') == 1) {
$bProfileFound = true;
}
}
$this->assertEquals($bUserFound, true);
$this->assertEquals($bProfileFound, true);
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Administrator account, Administrator profile and URP_UserProfile related to administrators are now hidden
// via GetSelectFilter
@@ -139,17 +126,14 @@ class GetSelectFilterTest extends ItopDataTestCase
$oFilterProfiles = $oUserRights->GetSelectFilter($this->oUser, URP_Profiles::class);
$this->assertNotEquals($oFilterProfiles, true); // This class must be filtered
$oSet = new DBObjectSet($oFilterProfiles);
while($oProfile = $oSet->Fetch())
{
while ($oProfile = $oSet->Fetch()) {
$this->assertNotEquals($oProfile->GetKey(), 1); // No profile should have id = 1 (Administrator)
}
foreach($aUserClasses as $sUserClass)
{
foreach ($aUserClasses as $sUserClass) {
$oFilterUser = $oUserRights->GetSelectFilter($this->oUser, $sUserClass);
$this->assertNotEquals($oFilterUser,true); // This class must be filtered
$this->assertNotEquals($oFilterUser, true); // This class must be filtered
$oSet = new DBObjectSet($oFilterUser);
while($oUser = $oSet->Fetch())
{
while ($oUser = $oSet->Fetch()) {
$this->assertNotEquals($oUser->GetKey(), $this->oUser->GetKey()); // Our administrator account should not be visible
}
}
@@ -158,8 +142,7 @@ class GetSelectFilterTest extends ItopDataTestCase
$this->assertNotEquals($oFilterLnkProfiles, true); // This class must be filtered
$oSet = new DBObjectSet($oFilterLnkProfiles);
// There should be no lnk referencing either our administrator account or the profile Administrator
while($oLnk = $oSet->Fetch())
{
while ($oLnk = $oSet->Fetch()) {
$this->assertNotEquals($oLnk->Get('userid'), $this->oUser->GetKey());
$this->assertNotEquals($oLnk->Get('profileid'), 1);
}

View File

@@ -1,10 +1,10 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -6,7 +7,6 @@
namespace Combodo\iTop\Test\UnitTest\Core\Log;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use Config;
use DeprecatedCallsLog;
@@ -14,10 +14,12 @@ use FileLog;
use IssueLog;
use LogAPI;
use utils;
use const E_USER_DEPRECATED;
use const ITOP_PHPUNIT_RUNNING_CONSTANT_NAME;
class DeprecatedCallsLogErrorHandlerTest extends ItopTestCase {
class DeprecatedCallsLogErrorHandlerTest extends ItopTestCase
{
public const DISABLE_DEPRECATEDCALLSLOG_ERRORHANDLER = false;
/**
@@ -26,7 +28,8 @@ class DeprecatedCallsLogErrorHandlerTest extends ItopTestCase {
*
* @runInSeparateProcess so that other tests won't set the constant !
*/
public function testPhpLibMethodNoticeCatched():void {
public function testPhpLibMethodNoticeCatched(): void
{
if (defined(ITOP_PHPUNIT_RUNNING_CONSTANT_NAME)) {
// Should not happen thanks to the process isolation !
$this->fail('Constant to disable error handler is set, so we cannot test :(');
@@ -50,9 +53,9 @@ class DeprecatedCallsLogErrorHandlerTest extends ItopTestCase {
$oMockConfig
->method("Get")
->willReturnCallback(function ($sConfigParameterName) {
if ($sConfigParameterName==='log_level_min'){
if ($sConfigParameterName === 'log_level_min') {
return [
DeprecatedCallsLog::ENUM_CHANNEL_PHP_LIBMETHOD => LogAPI::LEVEL_TRACE
DeprecatedCallsLog::ENUM_CHANNEL_PHP_LIBMETHOD => LogAPI::LEVEL_TRACE,
];
}
/** @noinspection NullPointerExceptionInspection */

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -6,7 +7,6 @@
namespace Combodo\iTop\Test\UnitTest\Core\Log;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use DeprecatedCallsLog;
@@ -208,7 +208,7 @@ class DeprecatedCallsLogTest extends ItopTestCase
'function' => 'require_once',
],
],
'out' => 'itop-root/env-production/core/main.php#1290'
'out' => 'itop-root/env-production/core/main.php#1290',
],
'From a persistent object method (deprecated PHP function)' => [
'in:stripped call stack' => [
@@ -262,7 +262,7 @@ class DeprecatedCallsLogTest extends ItopTestCase
'type' => '->',
],
],
'out' => 'Ticket->OnBeforeWriteTicket (itop-root/env-production/itop-tickets/model.itop-tickets.php#165), itself called from DBObject->FireEvent (itop-root/core/dbobject.class.php#6575)'
'out' => 'Ticket->OnBeforeWriteTicket (itop-root/env-production/itop-tickets/model.itop-tickets.php#165), itself called from DBObject->FireEvent (itop-root/core/dbobject.class.php#6575)',
],
];
}

View File

@@ -1,4 +1,5 @@
<?php
/*
* Copyright (C) 2013-2024 Combodo SAS
* This file is part of iTop.
@@ -18,12 +19,11 @@ namespace Combodo\iTop\Test\UnitTest\Core\Log;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use ExceptionLog;
require_once(__DIR__.'/ExceptionLogTest/Exceptions.php');
class ExceptionLogTest extends ItopDataTestCase
{
const USE_TRANSACTION = false;
public const USE_TRANSACTION = false;
protected function setUp(): void
{
@@ -46,16 +46,14 @@ class ExceptionLogTest extends ItopDataTestCase
switch ($code) {
case 'log_level_min':
if (is_null($logLevelMin))
{
if (is_null($logLevelMin)) {
$logLevelMin = '';//this should be the default value, if it did change, please fix it here
}
return $logLevelMin;
case 'log_level_min.write_in_db':
if (is_null($logLevelMinWriteInDb))
{
if (is_null($logLevelMinWriteInDb)) {
$logLevelMinWriteInDb = [ 'Exception' => 'Error', ];//this should be the default value, if it did change, please fix it here
}
@@ -69,12 +67,15 @@ class ExceptionLogTest extends ItopDataTestCase
foreach ($aLevels as $i => $sLevel) {
$sExpectedFile = __FILE__;
// @formatter:off
$oException = new $aExceptions[$i]("Iteration number $i"); $sExpectedLine = __LINE__; //Both should remain on the same line
$oException = new $aExceptions[$i]("Iteration number $i");
$sExpectedLine = __LINE__-1; //Both should remain on the same line
// @formatter:on
$iExpectedWriteNumber = $aExpectedWriteNumber[$i];
$iExpectedDbWriteNumber = $aExpectedDbWriteNumber[$i];
$aExpectedFileContext = array_merge($aContext, [
$aExpectedFileContext = array_merge(
$aContext,
[
'exception class' => get_class($oException),
'file' => $sExpectedFile,
'line' => $sExpectedLine,
@@ -294,6 +295,3 @@ class ExceptionLogTest extends ItopDataTestCase
$this->assertEquals('Ok', $resultFilePerDefaultWhenKeyNotFound);
}
}

View File

@@ -1,4 +1,5 @@
<?php
/*
* Copyright (C) 2013-2024 Combodo SAS
* This file is part of iTop.
@@ -14,10 +15,16 @@
*/
namespace {
class ChildException extends Exception {};
class GrandChildException extends ChildException {};
class ChildException extends Exception
{
};
class GrandChildException extends ChildException
{
};
}
namespace Namespaced\Exception {
class ExceptionInNamespace extends \ChildException {}
class ExceptionInNamespace extends \ChildException
{
}
}

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -13,7 +14,6 @@
namespace Combodo\iTop\Test\UnitTest\Core\Log;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
class LogAPITest extends ItopDataTestCase
@@ -21,7 +21,7 @@ class LogAPITest extends ItopDataTestCase
private $mockFileLog;
private $oMetaModelConfig;
protected function setUp():void
protected function setUp(): void
{
parent::setUp();
@@ -29,7 +29,6 @@ class LogAPITest extends ItopDataTestCase
$this->oMetaModelConfig = $this->createMock('Config');
}
/**
* @dataProvider LogApiProvider
* @test
@@ -58,7 +57,7 @@ class LogAPITest extends ItopDataTestCase
* @dataProvider LogWarningWithASpecificChannelProvider
* @test
*/
public function TestLogWarningWithASpecificChannel($expectedCallNb, $sExpectedLevel, $ConfigReturnedObject, $bExceptionRaised=false)
public function TestLogWarningWithASpecificChannel($expectedCallNb, $sExpectedLevel, $ConfigReturnedObject, $bExceptionRaised = false)
{
$this->oMetaModelConfig
->method("Get")
@@ -73,13 +72,12 @@ class LogAPITest extends ItopDataTestCase
->method($sExpectedLevel)
->with("log msg", "GaBuZoMeuChannel");
try{
try {
\IssueLog::Warning("log msg", "GaBuZoMeuChannel");
if ($bExceptionRaised) {
$this->fail("raised should have been raised");
}
}
catch(\Exception $e) {
} catch (\Exception $e) {
if (!$bExceptionRaised) {
$this->fail("raised should NOT have been raised");
}
@@ -93,7 +91,7 @@ class LogAPITest extends ItopDataTestCase
"Default Unknown Level" => [ 0, "Ok", 'TotoLevel', true],
"Info as Default Level" => [ 1 , "Warning", 'Info'],
"Error as Default Level" => [ 0, "Warning", 'Error'],
"Empty array" => [ 0, "Ok", array()],
"Empty array" => [ 0, "Ok", []],
"Channel configured on an undefined level" => [ 0, "Ok", ["GaBuZoMeuChannel" => "TotoLevel"], true],
"Channel defined with Error" => [ 0, "Warning", ["GaBuZoMeuChannel" => "Error"]],
"Channel defined with Info" => [ 1, "Warning", ["GaBuZoMeuChannel" => "Info"]],
@@ -104,7 +102,7 @@ class LogAPITest extends ItopDataTestCase
* @dataProvider LogOkWithASpecificChannel
* @test
*/
public function TestLogOkWithASpecificChannel($expectedCallNb, $sExpectedLevel, $ConfigReturnedObject, $bExceptionRaised=false)
public function TestLogOkWithASpecificChannel($expectedCallNb, $sExpectedLevel, $ConfigReturnedObject, $bExceptionRaised = false)
{
$this->oMetaModelConfig
->method("Get")
@@ -124,8 +122,7 @@ class LogAPITest extends ItopDataTestCase
if ($bExceptionRaised) {
$this->fail("raised should have been raised");
}
}
catch (\Exception $e) {
} catch (\Exception $e) {
if (!$bExceptionRaised) {
$this->fail("raised should NOT have been raised");
}
@@ -136,7 +133,7 @@ class LogAPITest extends ItopDataTestCase
{
return [
"empty config" => [1, "Ok", ''],
"Empty array" => [1, "Ok", array()],
"Empty array" => [1, "Ok", []],
];
}
@@ -169,7 +166,6 @@ class LogAPITest extends ItopDataTestCase
}
}
public function testGetLevelDefault()
{
$resultDb = $this->InvokeNonPublicStaticMethod(\LogAPI::class, 'GetLevelDefault', [\LogAPI::ENUM_CONFIG_PARAM_DB]);

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -6,15 +7,14 @@
namespace Combodo\iTop\Test\UnitTest\Core\Log;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use DailyRotatingLogFileNameBuilder;
use DateTime;
class LogFileNameBuilderTest extends ItopTestCase
{
const TEST_LOGFILE_PREFIX = 'fileNameBuilder.test';
const TEST_LOGFILE_EXTENSION = 'log';
public const TEST_LOGFILE_PREFIX = 'fileNameBuilder.test';
public const TEST_LOGFILE_EXTENSION = 'log';
/**
* @param $sLogFile
@@ -51,8 +51,7 @@ class LogFileNameBuilderTest extends ItopTestCase
$sLogFile = __DIR__.DIRECTORY_SEPARATOR.self::TEST_LOGFILE_PREFIX.'.'.self::TEST_LOGFILE_EXTENSION;
$oFileBuilder = new DailyRotatingLogFileNameBuilder($sLogFile);
if (file_exists($sLogFile))
{
if (file_exists($sLogFile)) {
unlink($sLogFile);
}
@@ -92,21 +91,21 @@ class LogFileNameBuilderTest extends ItopTestCase
public function ShouldRotateProvider()
{
return array(
'DAILY Same day' => array('DailyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-01 15:42', false),
'DAILY Same week, different day less 24h diff' => array('DailyRotatingLogFileNameBuilder', '2020-02-01 12:00', '2020-02-02 09:00', true),
'DAILY Same week, different day' => array('DailyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-02 00:00', true),
'DAILY 1 week diff' => array('DailyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-08 00:00', true),
'WEEKLY Same week' => array('WeeklyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-01 00:00', false),
'WEEKLY 1 week diff, same month' => array('WeeklyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-08 00:00', true),
'WEEKLY 2 weeks diff, same month' => array('WeeklyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-15 00:00', true),
'WEEKLY 1 week diff, different month' => array('WeeklyRotatingLogFileNameBuilder', '2020-01-27 00:00', '2020-02-03 00:00', true),
'WEEKLY same week, different month' => array('WeeklyRotatingLogFileNameBuilder', '2020-01-27 00:00', '2020-02-02 00:00', false),
'WEEKLY 1 week diff, different year' => array('WeeklyRotatingLogFileNameBuilder', '2019-12-30 00:00', '2020-01-06 00:00', true),
'WEEKLY same week, different year' => array('WeeklyRotatingLogFileNameBuilder', '2019-12-30 00:00', '2020-01-05 00:00', true),
'MONTHLY same month' => array('MonthlyRotatingLogFileNameBuilder', '2020-02-10 00:00', '2020-02-14 00:00', false),
'MONTHLY on first day which is a sunday' => array('MonthlyRotatingLogFileNameBuilder', '2020-01-30 00:00', '2020-02-01 00:00', true),
);
return [
'DAILY Same day' => ['DailyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-01 15:42', false],
'DAILY Same week, different day less 24h diff' => ['DailyRotatingLogFileNameBuilder', '2020-02-01 12:00', '2020-02-02 09:00', true],
'DAILY Same week, different day' => ['DailyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-02 00:00', true],
'DAILY 1 week diff' => ['DailyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-08 00:00', true],
'WEEKLY Same week' => ['WeeklyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-01 00:00', false],
'WEEKLY 1 week diff, same month' => ['WeeklyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-08 00:00', true],
'WEEKLY 2 weeks diff, same month' => ['WeeklyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-15 00:00', true],
'WEEKLY 1 week diff, different month' => ['WeeklyRotatingLogFileNameBuilder', '2020-01-27 00:00', '2020-02-03 00:00', true],
'WEEKLY same week, different month' => ['WeeklyRotatingLogFileNameBuilder', '2020-01-27 00:00', '2020-02-02 00:00', false],
'WEEKLY 1 week diff, different year' => ['WeeklyRotatingLogFileNameBuilder', '2019-12-30 00:00', '2020-01-06 00:00', true],
'WEEKLY same week, different year' => ['WeeklyRotatingLogFileNameBuilder', '2019-12-30 00:00', '2020-01-05 00:00', true],
'MONTHLY same month' => ['MonthlyRotatingLogFileNameBuilder', '2020-02-10 00:00', '2020-02-14 00:00', false],
'MONTHLY on first day which is a sunday' => ['MonthlyRotatingLogFileNameBuilder', '2020-01-30 00:00', '2020-02-01 00:00', true],
];
}
/**
@@ -131,15 +130,15 @@ class LogFileNameBuilderTest extends ItopTestCase
public function CronNextOccurrenceProvider()
{
return array(
'DAILY morning' => array('DailyRotatingLogFileNameBuilder', '2020-02-01 05:00', '2020-02-02 00:00'),
'DAILY midnight' => array('DailyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-02 00:00'),
'WEEKLY monday 12:42' => array('WeeklyRotatingLogFileNameBuilder', '2020-02-03 12:42', '2020-02-10 00:00'),
'WEEKLY monday 00:00' => array('WeeklyRotatingLogFileNameBuilder', '2020-02-03 00:00', '2020-02-10 00:00'),
'WEEKLY tuesday 12:42' => array('WeeklyRotatingLogFileNameBuilder', '2020-02-04 12:42', '2020-02-10 00:00'),
'WEEKLY sunday 12:42' => array('WeeklyRotatingLogFileNameBuilder', '2020-02-02 12:42', '2020-02-03 00:00'),
'MONTHLY 12/02 12:42' => array('MonthlyRotatingLogFileNameBuilder', '2020-02-12 12:42', '2020-03-01 00:00'),
);
return [
'DAILY morning' => ['DailyRotatingLogFileNameBuilder', '2020-02-01 05:00', '2020-02-02 00:00'],
'DAILY midnight' => ['DailyRotatingLogFileNameBuilder', '2020-02-01 00:00', '2020-02-02 00:00'],
'WEEKLY monday 12:42' => ['WeeklyRotatingLogFileNameBuilder', '2020-02-03 12:42', '2020-02-10 00:00'],
'WEEKLY monday 00:00' => ['WeeklyRotatingLogFileNameBuilder', '2020-02-03 00:00', '2020-02-10 00:00'],
'WEEKLY tuesday 12:42' => ['WeeklyRotatingLogFileNameBuilder', '2020-02-04 12:42', '2020-02-10 00:00'],
'WEEKLY sunday 12:42' => ['WeeklyRotatingLogFileNameBuilder', '2020-02-02 12:42', '2020-02-03 00:00'],
'MONTHLY 12/02 12:42' => ['MonthlyRotatingLogFileNameBuilder', '2020-02-12 12:42', '2020-03-01 00:00'],
];
}
/**

View File

@@ -197,13 +197,13 @@ class MetaModelMagicPlaceholderTest extends ItopDataTestCase
$this->assertEqualsShallow(
[
'gabu' => 'zomeu',
'current_contact_id' => '',
'current_contact_id' => '',
'current_user->object()' => '(current_user->object() : cannot be resolved)',
'current_user->not_existing_attribute' => '(current_user->not_existing_attribute : cannot be resolved)',
'current_user->not_existing_attribute' => '(current_user->not_existing_attribute : cannot be resolved)',
'current_user->login' => '(current_user->login : cannot be resolved)',
'current_contact->object()' => '(current_contact->object() : cannot be resolved)',
'current_contact->object()' => '(current_contact->object() : cannot be resolved)',
'current_contact->org_id' => '(current_contact->org_id : cannot be resolved)',
'current_contact->not_existing_attribute' => '(current_contact->not_existing_attribute : cannot be resolved)',
'current_contact->not_existing_attribute' => '(current_contact->not_existing_attribute : cannot be resolved)',
],
$aPlaceholders,
'AddMagicPlaceholders should add expected arguments and render them with an explicit error when the information could not be known'

View File

@@ -1,6 +1,5 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
@@ -16,11 +15,11 @@ use MetaModel;
*/
class MetaModelTest extends ItopDataTestCase
{
protected static $iDefaultUserOrgId = 1;
protected static $iDefaultUserCallerId = 1;
protected static $sDefaultUserRequestTitle = 'Unit test title';
protected static $sDefaultUserRequestDescription = 'Unit test description';
protected static $sDefaultUserRequestDescriptionAsHtml = '<p>Unit test description</p>';
protected static $iDefaultUserOrgId = 1;
protected static $iDefaultUserCallerId = 1;
protected static $sDefaultUserRequestTitle = 'Unit test title';
protected static $sDefaultUserRequestDescription = 'Unit test description';
protected static $sDefaultUserRequestDescriptionAsHtml = '<p>Unit test description</p>';
protected function setUp(): void
{
@@ -52,49 +51,49 @@ class MetaModelTest extends ItopDataTestCase
// multi-level hierarchy
$oServer1 = MetaModel::GetObjectByName('Server', 'Server1');
$sServer1Id = $oServer1->GetKey();
foreach (MetaModel::EnumParentClasses('Server',ENUM_PARENT_CLASSES_ALL) as $sClass) {
foreach (MetaModel::EnumParentClasses('Server', ENUM_PARENT_CLASSES_ALL) as $sClass) {
$this->assertEquals('Server', MetaModel::GetFinalClassName($sClass, $sServer1Id), 'Should return Server for all the classes in the hierarchy');
}
}
/**
* @group itopRequestMgmt
* @covers MetaModel::ApplyParams()
* @dataProvider ApplyParamsProvider
*
* @param string $sInput
* @param array $aParams
* @param string $sExpectedOutput
*
* @throws \Exception
*/
* @group itopRequestMgmt
* @covers MetaModel::ApplyParams()
* @dataProvider ApplyParamsProvider
*
* @param string $sInput
* @param array $aParams
* @param string $sExpectedOutput
*
* @throws \Exception
*/
public function testApplyParams($sInput, $aParams, $sExpectedOutput)
{
$oUserRequest = $this->createObject(
'UserRequest',
array(
'org_id' => static::$iDefaultUserOrgId,
'caller_id' => static::$iDefaultUserCallerId,
'title' => static::$sDefaultUserRequestTitle,
'description' => static::$sDefaultUserRequestDescriptionAsHtml,
)
);
$oUserRequest = $this->createObject(
'UserRequest',
[
'org_id' => static::$iDefaultUserOrgId,
'caller_id' => static::$iDefaultUserCallerId,
'title' => static::$sDefaultUserRequestTitle,
'description' => static::$sDefaultUserRequestDescriptionAsHtml,
]
);
$aParams['this->object()'] = $oUserRequest;
$aParams['this->object()'] = $oUserRequest;
$sGeneratedOutput = MetaModel::ApplyParams($sInput, $aParams);
$sGeneratedOutput = MetaModel::ApplyParams($sInput, $aParams);
$this->assertEquals($sExpectedOutput, $sGeneratedOutput, "ApplyParams test returned $sGeneratedOutput");
}
public function ApplyParamsProvider()
{
$sTitle = static::$sDefaultUserRequestTitle;
$sTitle = static::$sDefaultUserRequestTitle;
$aParams = [
$aParams = [
'simple' => 'I am simple',
'foo->bar' => 'I am bar', // N°2889 - Placeholder with an arrow that is not an object
];
'foo->bar' => 'I am bar', // N°2889 - Placeholder with an arrow that is not an object
];
return [
'Simple placeholder' => [
@@ -118,19 +117,19 @@ class MetaModelTest extends ItopDataTestCase
'Result: <a href="http://foo.bar/I am bar">Hyperlink</a>',
],
'Placeholder for an object string attribute (text format)' => [
'Title: $this->title$',
$aParams,
'Title: '.$sTitle,
'Title: $this->title$',
$aParams,
'Title: '.$sTitle,
],
'Placeholder for an object string attribute (html format)' => [
'Title: <p>$this-&gt;title$</p>',
$aParams,
'Title: <p>'.$sTitle.'</p>',
'Title: <p>$this-&gt;title$</p>',
$aParams,
'Title: <p>'.$sTitle.'</p>',
],
'Placeholder for an object string attribute url-encoded (html format)' => [
'Title: <a href="http://foo.bar/%24this-&gt;title%24">Hyperlink</a>',
$aParams,
'Title: <a href="http://foo.bar/'.$sTitle.'">Hyperlink</a>',
'Title: <a href="http://foo.bar/%24this-&gt;title%24">Hyperlink</a>',
$aParams,
'Title: <a href="http://foo.bar/'.$sTitle.'">Hyperlink</a>',
],
'Placeholder for an object HTML attribute as its default format' => [
'$this->description$',
@@ -171,14 +170,13 @@ class MetaModelTest extends ItopDataTestCase
public function GetDependentAttributesProvider()
{
$aRawCases = array(
array('Person', 'org_id', array('location_id', 'org_name', 'org_id_friendlyname', 'org_id_obsolescence_flag')),
array('Person', 'name', array('friendlyname')),
array('Person', 'status', array('obsolescence_flag')),
);
$aRet = array();
foreach ($aRawCases as $i => $aData)
{
$aRawCases = [
['Person', 'org_id', ['location_id', 'org_name', 'org_id_friendlyname', 'org_id_obsolescence_flag']],
['Person', 'name', ['friendlyname']],
['Person', 'status', ['obsolescence_flag']],
];
$aRet = [];
foreach ($aRawCases as $i => $aData) {
$aRet[$aData[0].'::'.$aData[1]] = $aData;
}
return $aRet;
@@ -205,16 +203,15 @@ class MetaModelTest extends ItopDataTestCase
public function GetPrerequisiteAttributesProvider()
{
$aRawCases = array(
array('Person', 'friendlyname', array('name', 'first_name')),
array('Person', 'obsolescence_flag', array('status')),
array('Person', 'org_id_friendlyname', array('org_id')),
array('Person', 'org_id', array()),
array('Person', 'org_name', array('org_id')),
);
$aRet = array();
foreach ($aRawCases as $i => $aData)
{
$aRawCases = [
['Person', 'friendlyname', ['name', 'first_name']],
['Person', 'obsolescence_flag', ['status']],
['Person', 'org_id_friendlyname', ['org_id']],
['Person', 'org_id', []],
['Person', 'org_name', ['org_id']],
];
$aRet = [];
foreach ($aRawCases as $i => $aData) {
$aRet[$aData[0].'::'.$aData[1]] = $aData;
}
return $aRet;
@@ -226,14 +223,18 @@ class MetaModelTest extends ItopDataTestCase
*/
public function testManualVersusAutomaticDependenciesOnExtKeys()
{
foreach (\MetaModel::GetClasses() as $sClass)
{
if (\MetaModel::IsAbstract($sClass)) continue;
foreach (\MetaModel::GetClasses() as $sClass) {
if (\MetaModel::IsAbstract($sClass)) {
continue;
}
foreach (\MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
if (\MetaModel::GetAttributeOrigin($sClass, $sAttCode) != $sClass) continue;
if (!$oAttDef instanceof \AttributeExternalKey) continue;
foreach (\MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
if (\MetaModel::GetAttributeOrigin($sClass, $sAttCode) != $sClass) {
continue;
}
if (!$oAttDef instanceof \AttributeExternalKey) {
continue;
}
$aManual = $oAttDef->Get('depends_on');
$aAuto = \MetaModel::GetPrerequisiteAttributes($sClass, $sAttCode);
@@ -254,7 +255,7 @@ class MetaModelTest extends ItopDataTestCase
* @param $interface
* @param null $sFilterInstanceOf
*/
public function testEnumPlugins($expectedInstanciationCalls, $expectedResults, $m_aExtensionClassNames, $m_aExtensionClasses, $interface, $sFilterInstanceOf=null)
public function testEnumPlugins($expectedInstanciationCalls, $expectedResults, $m_aExtensionClassNames, $m_aExtensionClasses, $interface, $sFilterInstanceOf = null)
{
$pluginInstanciationManager = new \PluginInstanciationManager();
$res = $pluginInstanciationManager->InstantiatePlugins($m_aExtensionClassNames, $interface);
@@ -282,7 +283,8 @@ class MetaModelTest extends ItopDataTestCase
}
}
public function enumPluginsProvider(){
public function enumPluginsProvider()
{
$aInterfaces = [
"empty conf" => [0, [], [], [], 'Wizzard'],
"simple instance retrieval" => [1, [Gryffindor::class => Gryffindor::class], ['Wizzard' => [Gryffindor::class]], [], 'Wizzard'],
@@ -458,36 +460,38 @@ class MetaModelTest extends ItopDataTestCase
];
}
/**
* @return void
* @throws CoreException
* @throws \OQLException
* @dataProvider PurgeDataProvider
*
*/
public function testPurgeData( $iMaxChunkSize, $iNbQueriesExpected){
// Set max_chunk_size to $iMaxChunkSize (default 1000) to test chunk deletion with only 10 items
$oConfig = MetaModel::GetConfig();
$oConfig->Set('purge_data.max_chunk_size', $iMaxChunkSize);
/**
* @return void
* @throws CoreException
* @throws \OQLException
* @dataProvider PurgeDataProvider
*
*/
public function testPurgeData($iMaxChunkSize, $iNbQueriesExpected)
{
// Set max_chunk_size to $iMaxChunkSize (default 1000) to test chunk deletion with only 10 items
$oConfig = MetaModel::GetConfig();
$oConfig->Set('purge_data.max_chunk_size', $iMaxChunkSize);
$aPkPerson = [];
for ($i=0; $i < 10; $i++) {
$oPerson = $this->CreatePerson($i, 1);
$sClass = get_class($oPerson);
$aPkPerson[] = $oPerson->GetKey();
}
$aPkPerson = [];
for ($i = 0; $i < 10; $i++) {
$oPerson = $this->CreatePerson($i, 1);
$sClass = get_class($oPerson);
$aPkPerson[] = $oPerson->GetKey();
}
$oFilter = DBObjectSearch::FromOQL('SELECT '.$sClass.' WHERE id IN ('.implode(',', $aPkPerson).')');
$iNbDelete = 0;
$oFilter = DBObjectSearch::FromOQL('SELECT '.$sClass.' WHERE id IN ('.implode(',', $aPkPerson).')');
$iNbDelete = 0;
$this->assertDBQueryCount($iNbQueriesExpected, function() use ($oFilter, &$iNbDelete) {
$this->assertDBQueryCount($iNbQueriesExpected, function () use ($oFilter, &$iNbDelete) {
$iNbDelete = MetaModel::PurgeData($oFilter);
} );
});
$this->assertEquals($iNbDelete, 10, 'MetaModel::PurgeData must delete 10 objects per batch of 2 items');
}
$this->assertEquals($iNbDelete, 10, 'MetaModel::PurgeData must delete 10 objects per batch of 2 items');
}
public function PurgeDataProvider(){
public function PurgeDataProvider()
{
return [
'Purge 10 items with a max_chunk_size of 2 should be perfomed in 5 steps + an additional query to verify that the job is complete' => [2, 16],
'Purge 10 items with a max_chunk_size of 3 should be perfomed in 4 steps' => [3, 12],
@@ -498,7 +502,6 @@ class MetaModelTest extends ItopDataTestCase
abstract class Wizzard
{
/**
* Wizzard constructor.
*/
@@ -509,23 +512,18 @@ abstract class Wizzard
class Gryffindor extends Wizzard
{
}
class Hufflepuff extends Wizzard
{
}
class Ravenclaw extends Wizzard
{
}
class Slytherin extends Wizzard
{
}
class Muggle
{
}

View File

@@ -2,14 +2,14 @@
class MockValueSetObjects extends ValueSetObjects
{
public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = array(), $bAllowAllData = false, $aModifierProperties = array())
public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = [], $bAllowAllData = false, $aModifierProperties = [])
{
parent::__construct($sFilterExp, $sValueAttCode , $aOrderBy, $bAllowAllData, $aModifierProperties );
parent::__construct($sFilterExp, $sValueAttCode, $aOrderBy, $bAllowAllData, $aModifierProperties);
}
public function GetFilterOQL(
$sOperation, $sContains
)
{
$sOperation,
$sContains
) {
return $this->GetFilter($sOperation, $sContains)->ToOQL();

View File

@@ -9,7 +9,6 @@
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use DBObjectSearch;
use DBSearch;
@@ -21,7 +20,6 @@ use UserRights;
class OQLParserTest extends ItopDataTestCase
{
/**
* @group iTopChangeMgt
* @group itopConfigMgmt
@@ -37,9 +35,9 @@ class OQLParserTest extends ItopDataTestCase
{
$this->debug($sQuery);
$oDbObjectSearch = DBObjectSearch::FromOQL($sQuery);
$sOql=$oDbObjectSearch->ToOQL();
$sOql = $oDbObjectSearch->ToOQL();
$this->debug($sOql);
self::assertEquals($sQuery,$sOql);
self::assertEquals($sQuery, $sOql);
}
public function testUnknownClassOqlException()
@@ -51,29 +49,28 @@ class OQLParserTest extends ItopDataTestCase
try {
DBSearch::FromOQL('SELECT UnknownClass');
$this->fail('An UnknownClassOqlException should have been thrown');
}
catch (UnknownClassOqlException $e) {
} catch (UnknownClassOqlException $e) {
$this->assertNotContains('DBProperty', $e->GetSuggestions(), 'user should not be recommanded to perform queries on classes his not allowed to see');
}
}
public function NestedQueryProvider()
{
return array(
array("SELECT `U` FROM User AS `U` JOIN Person AS `P` ON `U`.contactid = `P`.id WHERE ((`U`.`status` = 'enabled') AND (`U`.`id` NOT IN (SELECT `U` FROM User AS `U` JOIN Person AS `P` ON `U`.contactid = `P`.id JOIN URP_UserOrg AS `L` ON `L`.userid = `U`.id WHERE ((`U`.`status` = 'enabled') AND (`L`.`allowed_org_id` = `P`.`org_id`)) UNION SELECT `U` FROM User AS `U` WHERE ((`U`.`status` = 'enabled') AND (`U`.`id` NOT IN (SELECT `U` FROM User AS `U` JOIN URP_UserOrg AS `L` ON `L`.userid = `U`.id WHERE (`U`.`status` = 'enabled')))))))"),
array("SELECT `Ur` FROM UserRequest AS `Ur` WHERE (`Ur`.`id` NOT IN (SELECT `Ur` FROM UserRequest AS `Ur` JOIN lnkFunctionalCIToTicket AS `lnk` ON `lnk`.ticket_id = `Ur`.id WHERE 1))"),
array("SELECT `T` FROM Ticket AS `T` WHERE ((`T`.`finalclass` IN ('userrequest', 'change')) AND (`T`.`id` NOT IN (SELECT `Ur` FROM UserRequest AS `Ur` JOIN lnkFunctionalCIToTicket AS `lnk` ON `lnk`.ticket_id = `Ur`.id WHERE 1 UNION SELECT `C` FROM Change AS `C` JOIN lnkFunctionalCIToTicket AS `lnk` ON `lnk`.ticket_id = `C`.id WHERE 1)))"),
array("SELECT `PhysicalDevice` FROM PhysicalDevice AS `PhysicalDevice` WHERE ((`PhysicalDevice`.`status` = 'production') AND (`PhysicalDevice`.`id` NOT IN (SELECT `p` FROM PhysicalDevice AS `p` JOIN lnkFunctionalCIToProviderContract AS `l` ON `l`.functionalci_id = `p`.id WHERE 1)))"),
array('SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Person AS `P` ON `UserRequest`.agent_id = `P`.id JOIN Organization AS `Organization` ON `P`.org_id = `Organization`.id WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` WHERE (`Organization`.`id` = `UserRequest`.`org_id`)))'),
array('SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` WHERE (`Organization`.`id` = `UserRequest`.`org_id`)))'),
array('SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` WHERE 1))'),
array('SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (`UserRequest`.`org_id` NOT IN (SELECT `Organization` FROM Organization AS `Organization` WHERE 1))'),
array('SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` JOIN Organization AS `Organization1` ON `Organization`.parent_id BELOW `Organization1`.id WHERE (`Organization1`.`id` = \'3\')))'),
array('SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` WHERE (`Organization`.`id` = \'3\')))'),
array("SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE 1"),
array("SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`agent_id` = :current_contact_id) AND (`UserRequest`.`status` NOT IN ('closed', 'resolved')))"),
array("SELECT `L` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE 1"),
);
return [
["SELECT `U` FROM User AS `U` JOIN Person AS `P` ON `U`.contactid = `P`.id WHERE ((`U`.`status` = 'enabled') AND (`U`.`id` NOT IN (SELECT `U` FROM User AS `U` JOIN Person AS `P` ON `U`.contactid = `P`.id JOIN URP_UserOrg AS `L` ON `L`.userid = `U`.id WHERE ((`U`.`status` = 'enabled') AND (`L`.`allowed_org_id` = `P`.`org_id`)) UNION SELECT `U` FROM User AS `U` WHERE ((`U`.`status` = 'enabled') AND (`U`.`id` NOT IN (SELECT `U` FROM User AS `U` JOIN URP_UserOrg AS `L` ON `L`.userid = `U`.id WHERE (`U`.`status` = 'enabled')))))))"],
["SELECT `Ur` FROM UserRequest AS `Ur` WHERE (`Ur`.`id` NOT IN (SELECT `Ur` FROM UserRequest AS `Ur` JOIN lnkFunctionalCIToTicket AS `lnk` ON `lnk`.ticket_id = `Ur`.id WHERE 1))"],
["SELECT `T` FROM Ticket AS `T` WHERE ((`T`.`finalclass` IN ('userrequest', 'change')) AND (`T`.`id` NOT IN (SELECT `Ur` FROM UserRequest AS `Ur` JOIN lnkFunctionalCIToTicket AS `lnk` ON `lnk`.ticket_id = `Ur`.id WHERE 1 UNION SELECT `C` FROM Change AS `C` JOIN lnkFunctionalCIToTicket AS `lnk` ON `lnk`.ticket_id = `C`.id WHERE 1)))"],
["SELECT `PhysicalDevice` FROM PhysicalDevice AS `PhysicalDevice` WHERE ((`PhysicalDevice`.`status` = 'production') AND (`PhysicalDevice`.`id` NOT IN (SELECT `p` FROM PhysicalDevice AS `p` JOIN lnkFunctionalCIToProviderContract AS `l` ON `l`.functionalci_id = `p`.id WHERE 1)))"],
['SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Person AS `P` ON `UserRequest`.agent_id = `P`.id JOIN Organization AS `Organization` ON `P`.org_id = `Organization`.id WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` WHERE (`Organization`.`id` = `UserRequest`.`org_id`)))'],
['SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` WHERE (`Organization`.`id` = `UserRequest`.`org_id`)))'],
['SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` WHERE 1))'],
['SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (`UserRequest`.`org_id` NOT IN (SELECT `Organization` FROM Organization AS `Organization` WHERE 1))'],
['SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` JOIN Organization AS `Organization1` ON `Organization`.parent_id BELOW `Organization1`.id WHERE (`Organization1`.`id` = \'3\')))'],
['SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (`UserRequest`.`org_id` IN (SELECT `Organization` FROM Organization AS `Organization` WHERE (`Organization`.`id` = \'3\')))'],
["SELECT `L`, `P` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE 1"],
["SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`agent_id` = :current_contact_id) AND (`UserRequest`.`status` NOT IN ('closed', 'resolved')))"],
["SELECT `L` FROM Person AS `P` JOIN Location AS `L` ON `P`.location_id = `L`.id WHERE 1"],
];
}
/**
@@ -89,11 +86,9 @@ class OQLParserTest extends ItopDataTestCase
try {
$oOql = new OqlInterpreter($sQuery);
$oOql->ParseQuery();
}
catch (OQLParserException $e) {
} catch (OQLParserException $e) {
self::fail("OQL Parser stack overflow");
}
catch (OQLException $e) {
} catch (OQLException $e) {
self::fail("OQL Parser stack overflow");
}
self::assertTrue(true);

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Combodo\iTop\Test\UnitTest\Core;
@@ -37,8 +38,10 @@ class RestServicesSanitizeOutputTest extends ItopCustomDatamodelTestCase
*/
public function testSanitizeAttributeOnRequestedObject()
{
$oContactTest = MetaModel::NewObject('ContactTest', [
'password' => self::SIMPLE_PASSWORD
$oContactTest = MetaModel::NewObject(
'ContactTest',
[
'password' => self::SIMPLE_PASSWORD,
]
);
$oRestResultWithObject = new RestResultWithObjects();
@@ -46,7 +49,8 @@ class RestServicesSanitizeOutputTest extends ItopCustomDatamodelTestCase
$oRestResultWithObject->SanitizeContent();
static::assertJsonStringEqualsJsonString(
'{"objects":{"ContactTest::-1":{"code":0,"message":"ok","class":"ContactTest","key":-1,"fields":{"password":"*****"}}},"code":0,"message":null}',
json_encode($oRestResultWithObject));
json_encode($oRestResultWithObject)
);
}
/**
@@ -55,8 +59,10 @@ class RestServicesSanitizeOutputTest extends ItopCustomDatamodelTestCase
*/
public function testSanitizeAttributeExternalFieldOnLink()
{
$oContactTest = $this->createObject('ContactTest', [
'password' => self::SIMPLE_PASSWORD
$oContactTest = $this->createObject(
'ContactTest',
[
'password' => self::SIMPLE_PASSWORD,
]
);
@@ -64,26 +70,31 @@ class RestServicesSanitizeOutputTest extends ItopCustomDatamodelTestCase
'name' => 'test_server',
]);
// create lnkContactTestToServer
$oLnkContactTestToServer = $this->createObject('lnkContactTestToServer', [
'contact_test_id' => $oContactTest->GetKey(),
'test_server_id' => $oTestServer->GetKey()
'test_server_id' => $oTestServer->GetKey(),
]);
$oRestResultWithObject = new RestResultWithObjects();
$oRestResultWithObject->AddObject(0, 'ok', $oLnkContactTestToServer,
['lnkContactTestToServer' => ['contact_test_password']]);
$oRestResultWithObject->AddObject(
0,
'ok',
$oLnkContactTestToServer,
['lnkContactTestToServer' => ['contact_test_password']]
);
$oRestResultWithObject->SanitizeContent();
static::assertStringContainsString(
'*****',
json_encode($oRestResultWithObject));
json_encode($oRestResultWithObject)
);
static::assertStringNotContainsString(
self::SIMPLE_PASSWORD,
json_encode($oRestResultWithObject));
json_encode($oRestResultWithObject)
);
}
/**
@@ -92,7 +103,7 @@ class RestServicesSanitizeOutputTest extends ItopCustomDatamodelTestCase
public function testSanitizeAttributeOnObjectRelatedThroughNNRelation()
{
$oContactTest = $this->createObject('ContactTest', [
'password' => self::SIMPLE_PASSWORD
'password' => self::SIMPLE_PASSWORD,
]);
$oTestServer = $this->createObject('TestServer', [
@@ -102,26 +113,31 @@ class RestServicesSanitizeOutputTest extends ItopCustomDatamodelTestCase
// create lnkContactTestToServer
$this->createObject('lnkContactTestToServer', [
'contact_test_id' => $oContactTest->GetKey(),
'test_server_id' => $oTestServer->GetKey()
'test_server_id' => $oTestServer->GetKey(),
]);
$oTestServer->Reload();
$oRestResultWithObject = new RestResultWithObjects();
$oRestResultWithObject->AddObject(0, 'ok', $oTestServer,
['TestServer' => ['contact_list']]);
$oRestResultWithObject->AddObject(
0,
'ok',
$oTestServer,
['TestServer' => ['contact_list']]
);
$oRestResultWithObject->SanitizeContent();
static::assertStringContainsString(
'*****',
json_encode($oRestResultWithObject));
json_encode($oRestResultWithObject)
);
static::assertStringNotContainsString(
self::SIMPLE_PASSWORD,
json_encode($oRestResultWithObject));
json_encode($oRestResultWithObject)
);
}
/**
* @throws CoreException
* @throws CoreUnexpectedValue
@@ -149,11 +165,13 @@ class RestServicesSanitizeOutputTest extends ItopCustomDatamodelTestCase
static::assertStringContainsString(
'*****',
json_encode($oRestResultWithObject));
json_encode($oRestResultWithObject)
);
static::assertStringNotContainsString(
self::SIMPLE_PASSWORD,
json_encode($oRestResultWithObject));
json_encode($oRestResultWithObject)
);
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Combodo\iTop\Test\UnitTest\Core;
@@ -40,7 +41,7 @@ class RestServicesTest extends ItopDataTestCase
"operation": "core/check_credentials",
"user": "admin",
"password": "*****"
}'
}',
],
'core/update' => [
'{"operation": "core/update", "comment": "Update user", "class": "UserLocal", "key": {"id":1}, "output_fields": "first_name, password", "fields": {"password" : "123456"}}',
@@ -55,7 +56,7 @@ class RestServicesTest extends ItopDataTestCase
"fields": {
"password": "*****"
}
}'
}',
],
'core/create' => [
'{"operation": "core/create", "comment": "Create user", "class": "UserLocal", "fields": {"first_name": "John", "last_name": "Doe", "email": "jd@example/com", "password" : "123456"}}',
@@ -69,7 +70,7 @@ class RestServicesTest extends ItopDataTestCase
"email": "jd@example/com",
"password": "*****"
}
}'
}',
],
];
}
@@ -103,22 +104,22 @@ class RestServicesTest extends ItopDataTestCase
'core/update' => [
'core/update',
['comment' => 'Update user', 'class' => 'UserLocal', 'key' => ['login' => 'my_example'], 'output_fields' => 'password', 'fields' => ['password' => 'opkB!req57']],
'{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"","password":"*****"}}},"code":0,"message":null}'
'{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"","password":"*****"}}},"code":0,"message":null}',
],
'core/create' => [
'core/create',
['comment' => 'Create user', 'class' => 'UserLocal', 'fields' => ['password' => 'Azertyuiiop*12', 'login' => 'toto', 'profile_list' => [1]]],
'{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"","password":"*****"}}},"code":0,"message":null}'
'{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"","password":"*****"}}},"code":0,"message":null}',
],
'core/get' => [
'core/get',
['comment' => 'Get user', 'class' => 'UserLocal', 'key' => ['login' => 'my_example'], 'output_fields' => 'first_name, password'],
'{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"","password":"*****"}}},"code":0,"message":null}'
'{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"","password":"*****"}}},"code":0,"message":null}',
],
'core/check_credentials' => [
'core/check_credentials',
['user' => 'admin', 'password' => 'admin'],
'{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"","password":"*****"}}},"code":0,"message":null}'
'{"objects":{"UserLocal::-1":{"code":0,"message":"ok","class":"UserLocal","key":-1,"fields":{"login":"","password":"*****"}}},"code":0,"message":null}',
],
];
}

View File

@@ -1,4 +1,5 @@
<?php
/*!
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
@@ -14,66 +15,66 @@ use SodiumException;
*/
class SympleCryptTest extends ItopDataTestCase
{
public function DecryptClassProvider()
{
$aClassProvider = ['SimpleCrypt'=>['SimpleCrypt'],
'SimpleCryptSimpleEngine'=>['SimpleCryptSimpleEngine']];
if(function_exists('sodium_crypto_secretbox_open')){
$aClassProvider['SimpleCryptSodiumEngine'] = ['SimpleCryptSodiumEngine'] ;
}
if(function_exists('openssl_decrypt')){
$aClassProvider['SimpleCryptOpenSSLEngine'] = ['SimpleCryptOpenSSLEngine'];
$aClassProvider['SimpleCryptOpenSSLMcryptCompatibilityEngine'] = ['SimpleCryptOpenSSLMcryptCompatibilityEngine'];
}
return$aClassProvider;
}
/**
public function DecryptClassProvider()
{
$aClassProvider = ['SimpleCrypt' => ['SimpleCrypt'],
'SimpleCryptSimpleEngine' => ['SimpleCryptSimpleEngine']];
if (function_exists('sodium_crypto_secretbox_open')) {
$aClassProvider['SimpleCryptSodiumEngine'] = ['SimpleCryptSodiumEngine'] ;
}
if (function_exists('openssl_decrypt')) {
$aClassProvider['SimpleCryptOpenSSLEngine'] = ['SimpleCryptOpenSSLEngine'];
$aClassProvider['SimpleCryptOpenSSLMcryptCompatibilityEngine'] = ['SimpleCryptOpenSSLMcryptCompatibilityEngine'];
}
return$aClassProvider;
}
/**
* @param $sClass
* @dataProvider DecryptClassProvider
**/
**/
public function testDecryptWithNullValue($sClass)
{
$oSimpleCrypt = new $sClass();
$this->assertEquals(null, $oSimpleCrypt->Decrypt("dd", null));
}
/**
* @param $sClass
* @dataProvider DecryptClassProvider
**/
/**
* @param $sClass
* @dataProvider DecryptClassProvider
**/
public function testDecryptWithEmptyValue($sClass)
{
$oSimpleCrypt = new $sClass();
$this->assertEquals('', $oSimpleCrypt->Decrypt("dd", ""));
}
public function DecryptClassWithNonDecryptableValueProvider()
{
$aClassProvider = ['SimpleCrypt'=>['SimpleCrypt', '** decryption error **'],
// 'SimpleCryptSimpleEngine'=>['SimpleCryptSimpleEngine', ' ']
];
if(function_exists('sodium_crypto_secretbox_open')){
$aClassProvider['SimpleCryptSodiumEngine'] = ['SimpleCryptSodiumEngine', '', 'SodiumException'] ;
}
if(function_exists('openssl_decrypt')){
$aClassProvider['SimpleCryptOpenSSLEngine'] = ['SimpleCryptOpenSSLEngine', '** decryption error **'];
$aClassProvider['SimpleCryptOpenSSLMcryptCompatibilityEngine'] = ['SimpleCryptOpenSSLMcryptCompatibilityEngine', '** decryption error **'];
}
return$aClassProvider;
}
/**
* @param $sClass
* @param $sExpectedValue
* @dataProvider DecryptClassWithNonDecryptableValueProvider
**/
public function DecryptClassWithNonDecryptableValueProvider()
{
$aClassProvider = ['SimpleCrypt' => ['SimpleCrypt', '** decryption error **'],
// 'SimpleCryptSimpleEngine'=>['SimpleCryptSimpleEngine', ' ']
];
if (function_exists('sodium_crypto_secretbox_open')) {
$aClassProvider['SimpleCryptSodiumEngine'] = ['SimpleCryptSodiumEngine', '', 'SodiumException'] ;
}
if (function_exists('openssl_decrypt')) {
$aClassProvider['SimpleCryptOpenSSLEngine'] = ['SimpleCryptOpenSSLEngine', '** decryption error **'];
$aClassProvider['SimpleCryptOpenSSLMcryptCompatibilityEngine'] = ['SimpleCryptOpenSSLMcryptCompatibilityEngine', '** decryption error **'];
}
return$aClassProvider;
}
/**
* @param $sClass
* @param $sExpectedValue
* @dataProvider DecryptClassWithNonDecryptableValueProvider
**/
public function testDecrypWithNonDecryptableValue($sClass, $sExpectedValue = '', $sExpectedException = null)
{
if($sExpectedException !== null) {
$this->expectException($sExpectedException);
}
if ($sExpectedException !== null) {
$this->expectException($sExpectedException);
}
$oSimpleCrypt = new $sClass();
$result=$oSimpleCrypt->Decrypt("dd", "gabuzomeuuofteod");
$this->assertEquals($sExpectedValue, $result,'');
$result = $oSimpleCrypt->Decrypt("dd", "gabuzomeuuofteod");
$this->assertEquals($sExpectedValue, $result, '');
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Created by PhpStorm.
* User: Eric
@@ -8,7 +9,6 @@
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use CoreException;
use DeleteException;
@@ -22,7 +22,7 @@ use TagSetFieldData;
class TagSetFieldDataTest extends ItopDataTestCase
{
// Need database COMMIT in order to create the FULLTEXT INDEX of MySQL
const USE_TRANSACTION = false;
public const USE_TRANSACTION = false;
/**
* @throws \CoreException
@@ -65,33 +65,27 @@ class TagSetFieldDataTest extends ItopDataTestCase
$iCurrCount = count($aAllowedValues);
static::assertEquals(4, $iCurrCount - $iInitialCount);
try
{
try {
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag4', 'Fourth');
} catch (CoreException $e)
{
} catch (CoreException $e) {
$this->debug($e->getMessage());
}
$aAllowedValues = TagSetFieldData::GetAllowedValues(TAG_CLASS, TAG_ATTCODE);
$iCurrCount = count($aAllowedValues);
static::assertEquals(4, $iCurrCount - $iInitialCount);
try
{
try {
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag4', 'zembrek');
} catch (CoreException $e)
{
} catch (CoreException $e) {
$this->debug($e->getMessage());
}
$aAllowedValues = TagSetFieldData::GetAllowedValues(TAG_CLASS, TAG_ATTCODE);
$iCurrCount = count($aAllowedValues);
static::assertEquals(4, $iCurrCount - $iInitialCount);
try
{
try {
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'zembrek', 'Fourth');
} catch (CoreException $e)
{
} catch (CoreException $e) {
$this->debug($e->getMessage());
}
$aAllowedValues = TagSetFieldData::GetAllowedValues(TAG_CLASS, TAG_ATTCODE);
@@ -129,10 +123,10 @@ class TagSetFieldDataTest extends ItopDataTestCase
public function testComputeValues()
{
$sTagClass = TagSetFieldData::GetTagDataClassName(TAG_CLASS, TAG_ATTCODE);
$oTagData = $this->createObject($sTagClass, array(
$oTagData = $this->createObject($sTagClass, [
'code' => 'tag1',
'label' => 'First',
));
]);
$this->debug("Created {$oTagData->Get('obj_class')}::{$oTagData->Get('obj_attcode')}");
static::assertEquals(TAG_CLASS, $oTagData->Get('obj_class'));
@@ -150,8 +144,7 @@ class TagSetFieldDataTest extends ItopDataTestCase
{
try {
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, $sTagCode, 'First');
}
catch (CoreException $e) {
} catch (CoreException $e) {
static::assertTrue(true);
return;
}
@@ -161,22 +154,22 @@ class TagSetFieldDataTest extends ItopDataTestCase
public function InvalidTagCodeProvider()
{
return array(
'No space' => array('tag1 1'),
'No _' => array('tag_1'),
'No -' => array('tag-1'),
'No %' => array('tag%1'),
'At least 3 chars' => array(''),
'At least 3 chars 1' => array('a'),
'At least 3 chars 2' => array('ab'),
'No #' => array('#tag'),
'No !' => array('tag!'),
'Stop Word 1' => array('about'),
'Stop Word 2' => array('from'),
'Stop Word 3' => array('that'),
'Stop Word 4' => array('where'),
'Stop Word 5' => array('who'),
);
return [
'No space' => ['tag1 1'],
'No _' => ['tag_1'],
'No -' => ['tag-1'],
'No %' => ['tag%1'],
'At least 3 chars' => [''],
'At least 3 chars 1' => ['a'],
'At least 3 chars 2' => ['ab'],
'No #' => ['#tag'],
'No !' => ['tag!'],
'Stop Word 1' => ['about'],
'Stop Word 2' => ['from'],
'Stop Word 3' => ['that'],
'Stop Word 4' => ['where'],
'Stop Word 5' => ['who'],
];
}
/**
@@ -186,8 +179,7 @@ class TagSetFieldDataTest extends ItopDataTestCase
{
try {
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag1', 'First|Second');
}
catch (CoreException $e) {
} catch (CoreException $e) {
static::assertFalse(false);
return;
}
@@ -238,11 +230,9 @@ class TagSetFieldDataTest extends ItopDataTestCase
// Too long
$sTagCode = str_repeat('a', $iMaxLength + 1);
try
{
try {
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, $sTagCode, $sTagCode);
} catch (CoreException $e)
{
} catch (CoreException $e) {
$this->debug('Awaited: '.$e->getMessage());
static::assertTrue(true);
return;
@@ -259,30 +249,26 @@ class TagSetFieldDataTest extends ItopDataTestCase
/** @var \AttributeTagSet $oAttDef */
$oAttDef = MetaModel::GetAttributeDef(TAG_CLASS, TAG_ATTCODE);
$iMaxTags = $oAttDef->GetMaxItems();
for ($i = 0; $i < $iMaxTags; $i++)
{
for ($i = 0; $i < $iMaxTags; $i++) {
$sTagCode = 'MaxTag'.$i;
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, $sTagCode, $sTagCode);
}
$oObjWithTagSet = $this->CreateObjectWithTagSet();
$this->debug("Max number of tags is $iMaxTags");
$sValue = '';
for ($i = 0; $i < ($iMaxTags + 1); $i++)
{
try
{
for ($i = 0; $i < ($iMaxTags + 1); $i++) {
try {
$sTagCode = 'MaxTag'.$i;
$sValue .= "$sTagCode ";
$oObjWithTagSet->Set(TAG_ATTCODE, $sValue);
$oObjWithTagSet->DBWrite();
} catch (Exception $e)
{
} catch (Exception $e) {
// Should fail on the last iteration
static::assertEquals($iMaxTags, $i);
$this->debug("Setting (".($i+1).") tag(s) failed");
$this->debug("Setting (".($i + 1).") tag(s) failed");
return;
}
$this->debug("Setting (".($i+1).") tag(s) worked");
$this->debug("Setting (".($i + 1).") tag(s) worked");
}
static::assertFalse(true);

View File

@@ -8,7 +8,7 @@ use Person;
class TriggerOnStateEnterTest extends ItopDataTestCase
{
const CREATE_TEST_ORG = true;
public const CREATE_TEST_ORG = true;
protected function setUp(): void
{
@@ -86,4 +86,4 @@ class TriggerOnStateEnterTest extends ItopDataTestCase
]);
return MetaModel::GetObject('UserRequest', $iUserRequest);
}
}
}

View File

@@ -17,8 +17,7 @@ use TriggerOnObjectCreate;
*/
class TriggerTest extends ItopDataTestCase
{
const USE_TRANSACTION = false;
public const USE_TRANSACTION = false;
protected function setUp(): void
{
@@ -43,18 +42,16 @@ class TriggerTest extends ItopDataTestCase
try {
try {
MetaModel::NewObject('Toto');
}
catch (\Exception $e) {
} catch (\Exception $e) {
\utils::EnrichRaisedException($oTrigger, $e);
}
$this->assertTrue(false, "An exception should have been thrown");
}
catch (\CoreException $e1) {
} catch (\CoreException $e1) {
$this->assertEquals('CoreException', get_class($e1));
$this->assertStringStartsWith('Unknown class \'Toto\' (<b title="Trigger">TriggerOnObjectCreate</b>::-', $e1->getMessage());
$fullStackTraceAsString = $e1->getFullStackTraceAsString();
$this->assertStringContainsString("MetaModel::NewObject", $fullStackTraceAsString,"new enriched exception should contain root cause method: " . $fullStackTraceAsString);
$this->assertStringContainsString("MetaModel::NewObject", $fullStackTraceAsString, "new enriched exception should contain root cause method: ".$fullStackTraceAsString);
}
}
@@ -75,13 +72,11 @@ class TriggerTest extends ItopDataTestCase
try {
try {
MetaModel::NewObject('CoreException');
}
catch (\Exception $e) {
} catch (\Exception $e) {
\utils::EnrichRaisedException($oCmdbAbstract, $e);
}
$this->assertTrue(false, "An exception should have been thrown");
}
catch (\Exception $e1) {
} catch (\Exception $e1) {
$this->assertEquals($e, $e1);
}
}
@@ -113,13 +108,12 @@ class TriggerTest extends ItopDataTestCase
$this->assertStringContainsString($oPerson1->GetRawName(), $sTestLogFileContent);
$this->assertStringContainsString($sExceptionMessage, $sTestLogFileContent);
}
finally {
} finally {
IssueLog::Enable(APPROOT.'log/error.log');
}
}
}
class NonCmdbAbstractObject{
class NonCmdbAbstractObject
{
}

View File

@@ -1,6 +1,5 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
@@ -33,12 +32,9 @@ class UniquenessConstraintTest extends ItopTestCase
public function testUniquenessRuleValidityCheck($bIsRuleShouldBeValid, $bIsRuleOverride, $aRuleProperties)
{
$bRuleValidResult = true;
try
{
try {
MetaModel::CheckUniquenessRuleValidity($aRuleProperties, $bIsRuleOverride);
}
catch (CoreUnexpectedValue $e)
{
} catch (CoreUnexpectedValue $e) {
$bRuleValidResult = false;
}
@@ -47,32 +43,32 @@ class UniquenessConstraintTest extends ItopTestCase
public function uniquenessRuleValidityCheckProvider()
{
return array(
'simplest rule' => array(true, false, array('attributes' => array('name'))),
'with all properties' => array(
return [
'simplest rule' => [true, false, ['attributes' => ['name']]],
'with all properties' => [
true,
false,
array(
'attributes' => array('name'),
[
'attributes' => ['name'],
'filter' => 'name != \'\'',
'disabled' => false,
'is_blocking' => true,
),
),
'only disabled key without ancestor' => array(
],
],
'only disabled key without ancestor' => [
false,
false,
array(
[
'disabled' => true,
),
),
'only disabled key with ancestor' => array(
],
],
'only disabled key with ancestor' => [
true,
true,
array(
[
'disabled' => true,
),
),
);
],
],
];
}
}

View File

@@ -1,6 +1,5 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
@@ -16,7 +15,6 @@ use Team;
*/
class UniquenessMessageTest extends ItopDataTestCase
{
/** @inheritdoc */
protected function setUp(): void
{
@@ -34,10 +32,10 @@ class UniquenessMessageTest extends ItopDataTestCase
protected function CreateTeam($iNum)
{
/** @var Team $oTeam */
$oTeam = $this->createObject('Team', array(
$oTeam = $this->createObject('Team', [
'name' => 'Name_'.$iNum,
'org_id' => $this->getTestOrgId(),
));
]);
$this->debug("Created Team {$oTeam->GetName()} ({$oTeam->GetKey()})");
return $oTeam;

Some files were not shown because too many files have changed in this diff Show More