From 984f676d6eb8eb4ffc5c2d58d1629c038bb23ff3 Mon Sep 17 00:00:00 2001 From: Eric Espie Date: Tue, 28 May 2024 09:22:35 +0200 Subject: [PATCH] :white_check_mark: GivenObjectInDB() and additional improvements in the tests suite to address false positive and slow tests Rewrite tests on impact analysis to make them readable in the first place, then simplifiy the tests to focus on risk reduction, then complete with some edge case Rewrite tests on impact graph build when the current user has restricted access to some parts of the graph --- .../src/BaseTestCase/ItopDataTestCase.php | 450 ++++++++- .../src/BaseTestCase/ItopTestCase.php | 13 + .../unitary-tests/application/LoginTest.php | 9 - .../unitary-tests/core/DBObjectTest.php | 26 +- .../core/DBSearchIntersectTest.php | 8 +- .../unitary-tests/core/RelationGraphTest.php | 102 -- .../2.x/itop-config/BulkChangeExtKeyTest.php | 4 +- .../itop-tickets/UpdateImpactedItemsTest.php | 530 ++++++++++ .../2.x/itop-tickets/itopTicketTest.php | 922 ------------------ .../sources/Application/Status/StatusTest.php | 5 +- .../php-unit-tests/GivenObjectInDBTest.php | 184 ++++ 11 files changed, 1137 insertions(+), 1116 deletions(-) delete mode 100644 tests/php-unit-tests/unitary-tests/core/RelationGraphTest.php create mode 100644 tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/UpdateImpactedItemsTest.php delete mode 100644 tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/itopTicketTest.php create mode 100644 tests/php-unit-tests/unitary-tests/tests/php-unit-tests/GivenObjectInDBTest.php diff --git a/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php b/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php index 525583097..3baab4203 100644 --- a/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php +++ b/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php @@ -127,7 +127,7 @@ abstract class ItopDataTestCase extends ItopTestCase } if (static::CREATE_TEST_ORG) { - $this->CreateTestOrganization(); + $this->GivenTestOrganization(); } $oConfig = MetaModel::GetConfig(); @@ -136,6 +136,8 @@ abstract class ItopDataTestCase extends ItopTestCase // Config file is corrupted, let's fix it $oConfig->SetEncryptionKey("6eb9d9afa3ee0fbcebe622a33bf57aaeafb7c37998fd24c403c2522c2d60117f"); } + // Align the PHP executable with the one used to launch the whole test process + $oConfig->Set('php_path', PHP_BINARY); } /** @@ -907,59 +909,6 @@ abstract class ItopDataTestCase extends ItopTestCase return $oObject; } - /** - * Check or Display the CI list of a Ticket. - * - * @param Ticket $oTicket - * @param array $aWaitedCIList { iCIId => sImpactCode } - * - * @throws Exception - */ - protected function CheckFunctionalCIList($oTicket, $aWaitedCIList = array()) - { - $this->debug("\nResulting functionalcis_list {$oTicket->Get('ref')} ({$oTicket->Get('functionalcis_list')->Count()}):"); - foreach ($oTicket->Get('functionalcis_list') as $oLnk) - { - $this->debug($oLnk->Get('functionalci_name')." => ".$oLnk->Get('impact_code').""); - $iId = $oLnk->Get('functionalci_id'); - if (!empty($aWaitedCIList)) - { - $this->assertArrayHasKey($iId, $aWaitedCIList); - $this->assertEquals($aWaitedCIList[$iId], $oLnk->Get('impact_code')); - } - } - } - - /** - * Check or Display the Contact list of a DBObject (having a contacts_list). - * Can also control other attributes of the link. - * - * @param Ticket $oTicket - * @param array $aWaitedContactList { iContactId => array(attcode => value) } - * - * @throws Exception - */ - protected function CheckContactList($oTicket, $aWaitedContactList = array()) - { - $this->debug("\nResulting contacts_list {$oTicket->Get('ref')} ({$oTicket->Get('contacts_list')->Count()}):"); - foreach ($oTicket->Get('contacts_list') as $oLnk) - { - $this->debug($oLnk->Get('contact_id_friendlyname')." => ".$oLnk->Get('role_code')); - $iId = $oLnk->Get('contact_id'); - if (!empty($aWaitedContactList)) - { - $this->assertArrayHasKey($iId, $aWaitedContactList); - foreach ($aWaitedContactList[$iId] as $sAttCode => $oValue) - { - if (MetaModel::IsValidAttCode(get_class($oTicket), $sAttCode)) - { - $this->assertEquals($oValue, $oLnk->Get($sAttCode)); - } - } - } - } - } - protected function CreateTestOrganization() { // Create a specific organization for the tests @@ -1046,4 +995,397 @@ abstract class ItopDataTestCase extends ItopTestCase return $ret; } + + + protected function DBInsertSingleTable($sTableClass, $aValues, $iKey = 0) + { + $sTable = MetaModel::DBGetTable($sTableClass); + // Abstract classes or classes having no specific attribute do not have an associated table + if ($sTable == '') { + return false; + } + + // fields in first array, values in the second + $aFieldsToWrite = array(); + $aValuesToWrite = array(); + + if (!empty($iKey) && ($iKey >= 0)) { + // Add it to the list of fields to write + $aFieldsToWrite[] = '`'.MetaModel::DBGetKey($sTableClass).'`'; + $aValuesToWrite[] = CMDBSource::Quote($iKey); + } + + $aHierarchicalKeys = array(); + + foreach (MetaModel::ListAttributeDefs($sTableClass) as $sAttCode => $oAttDef) { + // Skip this attribute if not defined in this table + if ((!MetaModel::IsAttributeOrigin($sTableClass, $sAttCode) && !$oAttDef->CopyOnAllTables()) + || $oAttDef->IsExternalField()) { + continue; + } + if ($oAttDef->IsWritable() && !$oAttDef->IsNullAllowed() && !array_key_exists($sAttCode, $aValues) && $oAttDef->IsNull($oAttDef->GetDefaultValue())) { + throw new Exception("GivenObjectInDB('$sTableClass'), mandatory attribute '$sAttCode' is missing"); + } + $currentValue = array_key_exists($sAttCode, $aValues) ? $aValues[$sAttCode] : $oAttDef->GetDefaultValue(); + $aAttColumns = $oAttDef->GetSQLValues($currentValue); + foreach ($aAttColumns as $sColumn => $sValue) { + $aFieldsToWrite[] = "`$sColumn`"; + $aValuesToWrite[] = CMDBSource::Quote($sValue); + } + if ($oAttDef->IsHierarchicalKey()) { + $aHierarchicalKeys[$sAttCode] = $oAttDef; + } + } + + if (count($aValuesToWrite) == 0) { + return false; + } + + if (count($aHierarchicalKeys) > 0) { + foreach ($aHierarchicalKeys as $sAttCode => $oAttDef) { + $currentValue = isset($aValues[$sAttCode]) ? $aValues[$sAttCode] : $oAttDef->GetDefaultValue(); + $aHKValues = MetaModel::HKInsertChildUnder($currentValue, $oAttDef, $sTable); + $aFieldsToWrite[] = '`'.$oAttDef->GetSQLRight().'`'; + $aValuesToWrite[] = $aHKValues[$oAttDef->GetSQLRight()]; + $aFieldsToWrite[] = '`'.$oAttDef->GetSQLLeft().'`'; + $aValuesToWrite[] = $aHKValues[$oAttDef->GetSQLLeft()]; + } + } + $sInsertSQL = "INSERT INTO `$sTable` (".join(',', $aFieldsToWrite).') VALUES ('.join(', ', $aValuesToWrite).')'; + $iNewKey = CMDBSource::InsertInto($sInsertSQL); + // Note that it is possible to have a key defined here, and the autoincrement expected, this is acceptable in a non root class + if (empty($iKey)) { + // Take the autonumber + $iKey = "$iNewKey"; + } + + return $iKey; + } + + /** + * @param string $sClass + * @param array $aParams + * + * @return DBObject + * @throws Exception + */ + protected function GivenObject(string $sClass, array $aParams): DBObject + { + $oMyObj = MetaModel::NewObject($sClass); + foreach ($aParams as $sAttCode => $oValue) + { + $oMyObj->Set($sAttCode, $oValue); + } + + return $oMyObj; + } + + /** + * @param string $sClass + * @param array $aValues + * + * @return DBObject + * @throws Exception + */ + protected function GivenObjectInDB($sClass, $aValues) + { + // Check and complete the values + foreach ($aValues as $sAttCode => $oValue) { + if (MetaModel::IsValidAttCode($sClass, $sAttCode) === false) { + throw new \Exception("GivenObjectInDB('$sClass'), invalid attribute code '$sAttCode'"); + } + } + $sOrgIdAttCode = $sClass::MapContextParam('org_id'); + if ($sOrgIdAttCode !== null) { + if (!isset($aValues[$sOrgIdAttCode])) { + $aValues[$sOrgIdAttCode] = $this->getTestOrgId(); + } + } + $aValues['finalclass'] = $sClass; + + $sRootClass = MetaModel::GetRootClass($sClass); + + // First query built upon on the root class, because the ID must be created first + $iKey = $this->DBInsertSingleTable($sRootClass, $aValues); + + // Then do the leaf class, if different from the root class + if ($sClass != $sRootClass) { + $this->DBInsertSingleTable($sClass, $aValues, $iKey); + } + + // Then do the other classes + foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass) { + if ($sParentClass == $sRootClass) { + continue; + } + $this->DBInsertSingleTable($sParentClass, $aValues, $iKey); + } + + // Then cope with the links + foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { + if (!$oAttDef->IsLinkSet()) { + continue; + } + if (!isset($aValues[$sAttCode])) { + continue; + } + + $sLinkClass = $oAttDef->GetLinkedClass(); + $sExtKeyToMe = $oAttDef->GetExtKeyToMe(); + + if ($aValues[$sAttCode] instanceof \DBObjectSet) { + $oSet = $aValues[$sAttCode]; + $oSet->Rewind(); + while ($oLnk = $oSet->Fetch()) { + $aLnkValues = []; + foreach (MetaModel::ListAttributeDefs($sLinkClass) as $sLnkAttCode => $oLnkAttDef) { + if ($sLnkAttCode == $sExtKeyToMe) { + $aLnkValues[$sLnkAttCode] = $iKey; + } else { + $aLnkValues[$sLnkAttCode] = $oLnk->Get($sLnkAttCode); + } + } + $this->GivenObjectInDB($sLinkClass, $aLnkValues); + } + } elseif (is_array($aValues[$sAttCode])) { + foreach ($aValues[$sAttCode] as $sLnkValues) { + $aLnkKeyValuePairs = explode(';', $sLnkValues); + $aLnkValues = []; + foreach ($aLnkKeyValuePairs as $sLnkKeyValue) { + $iSep = strpos($sLnkKeyValue, ':'); + if ($iSep === false) { + throw new \Exception("GivenObjectInDB($sClass), unexpected value format for $sAttCode, missing ':' in '$sLnkKeyValue'"); + } + $sLnkAttCode = substr($sLnkKeyValue, 0, $iSep); + $sLnkValue = substr($sLnkKeyValue, $iSep + 1); + $aLnkValues[$sLnkAttCode] = $sLnkValue; + } + foreach (MetaModel::ListAttributeDefs($sLinkClass) as $sLnkAttCode => $oLnkAttDef) { + if ($sLnkAttCode == $sExtKeyToMe) { + $aLnkValues[$sLnkAttCode] = $iKey; + } + } + $this->GivenObjectInDB($sLinkClass, $aLnkValues); + } + } else { + throw new \Exception("createObject($sClass), unexpected value type for $sAttCode"); + } + } + + return $iKey; + } + + /** + * Create an Organization in database + * + * @param string $sName + * + * @throws Exception + */ + protected function GivenOrganization($sName): string + { + $sId = $this->GivenObjectInDB('Organization', [ + 'name' => $sName, + ]); + $this->debug("Created Organization $sName"); + + return $sId; + } + + protected function GivenTestOrganization(): void + { + // Create a specific organization for the tests + $this->iTestOrgId = $this->GivenOrganization('UnitTestOrganization'); + } + + /** + * Create a Farm in database + * + * @param int $iNum + * @param string $sRedundancy + * + * @throws Exception + */ + protected function GivenFarmInDB($iNum, $sRedundancy = '1'): string + { + $sName = 'Farm_'.$iNum; + $sId = $this->GivenObjectInDB('Farm', [ + 'name' => $sName, + 'org_id' => $this->getTestOrgId(), + 'redundancy' => $sRedundancy, + ]); + $this->debug("Created $sName ($sId) redundancy $sRedundancy"); + + return $sId; + } + + protected function GivenServerInDB($iNum, $iRackUnit = null): string + { + $sName = 'Server_'.$iNum; + $sId = $this->GivenObjectInDB('Server', [ + 'name' => $sName, + 'org_id' => $this->getTestOrgId(), + 'nb_u' => $iRackUnit, + ]); + $this->debug("Created $sName ($sId)"); + + return $sId; + } + + protected function GivenHypervisorInDB($iNum, $sServerId, $sFarmId = 0): string + { + $sName = 'Hypervisor_'.$iNum; + $sId = $this->GivenObjectInDB('Hypervisor', [ + 'name' => $sName, + 'org_id' => $this->getTestOrgId(), + 'server_id' => $sServerId, + 'farm_id' => $sFarmId, + ]); + if ($sFarmId === 0) { + $this->debug("Created $sName ($sId) on server $sServerId"); + } else { + $this->debug("Created $sName ($sId) on server $sServerId part of farm $sFarmId"); + } + + return $sId; + } + + protected function GivenPersonInDB($iNum, $iOrgId = 0): string + { + $sName = 'Person_'.$iNum; + $sId = $this->GivenObjectInDB('Person', [ + 'name' => $sName, + 'first_name' => 'Test', + 'org_id' => ($iOrgId == 0 ? $this->getTestOrgId() : $iOrgId), + ]); + $this->debug("Created $sName ($sId)"); + + return $sId; + } + + protected function GivenLnkContactToFunctionalCIInDB($sContactId, $sCIId): string + { + $sClass = 'lnkContactToFunctionalCI'; + $sId = $this->GivenObjectInDB($sClass, [ + 'contact_id' => $sContactId, + 'functionalci_id' => $sCIId, + ]); + $this->debug("Created $sClass::$sId linking contact $sContactId and CI $sCIId"); + + return $sId; + } + + protected function GivenVirtualMachineInDB($iNum, $sVirtualHostId): string + { + $sName = 'VirtualMachine_'.$iNum; + $sId = $this->GivenObjectInDB('VirtualMachine', [ + 'name' => $sName, + 'org_id' => $this->getTestOrgId(), + 'virtualhost_id' => $sVirtualHostId, + ]); + $this->debug("Created $sName ($sId) on virtual host $sVirtualHostId"); + + return $sId; + } + + protected function GivenTicketObject($iNum): \UserRequest + { + $sTitle = 'TICKET_'.$iNum; + $sRef = 'Ticket_'.$iNum; + + /** @var \UserRequest $oTicket */ + $oTicket = $this->GivenObject('UserRequest', [ + 'ref' => $sRef, + 'title' => $sTitle, + 'description' => 'Created for unit tests.', + 'org_id' => $this->getTestOrgId(), + ]); + $this->debug("Created $sTitle ($sRef)"); + + return $oTicket; + } + + protected function AddLnkFunctionalCIToTicketObject($sCIId, $oTicket, $sImpactCode = 'manual'): array + { + $oNewLink = $this->GivenObject('lnkFunctionalCIToTicket', [ + 'functionalci_id' => $sCIId, + 'impact_code' => $sImpactCode, + ]); + + $oCIs = $oTicket->Get('functionalcis_list'); + $oCIs->AddItem($oNewLink); + $oTicket->Set('functionalcis_list', $oCIs); + + $this->debug("Added CI $sCIId to {$oTicket->Get('ref')} with {$sImpactCode}"); + + return array($sCIId => $sImpactCode); + } + + protected function RemoveLnkFunctionalCIToTicketObject($sCIId, $oTicket) + { + $oCIs = $oTicket->Get('functionalcis_list'); + foreach ($oCIs as $oLnk) + { + if ($oLnk->Get('functionalci_id') == $sCIId) + { + $sImpactCode = $oLnk->Get('impact_code'); + $oCIs->RemoveItem($oLnk->GetKey()); + $oTicket->Set('functionalcis_list', $oCIs); + $this->debug("Removed CI $sCIId from {$oTicket->Get('ref')} ({$sImpactCode})"); + + return; + } + } + $this->debug("ERROR: CI $sCIId not attached to {$oTicket->Get('ref')}"); + $this->assertTrue(false); + } + + protected function AddLnkContactToTicketObject($sContactId, $oTicket, $sRoleCode, $aParams = array()): array + { + $aParams['contact_id'] = $sContactId; + $aParams['role_code'] = $sRoleCode; + $oNewLink = $this->GivenObject('lnkContactToTicket', $aParams); + + $oCIs = $oTicket->Get('contacts_list'); + $oCIs->AddItem($oNewLink); + $oTicket->Set('contacts_list', $oCIs); + + $this->debug("Added contact $sContactId to {$oTicket->Get('ref')} with {$sRoleCode}"); + + return array($sContactId => $sRoleCode); + } + + protected function RemoveLnkContactToTicketObject($sContactId, $oTicket) + { + $oContacts = $oTicket->Get('contacts_list'); + foreach ($oContacts as $oLnk) + { + if ($oLnk->Get('contact_id') == $sContactId) + { + $sRoleCode = $oLnk->Get('role_code'); + $oContacts->RemoveItem($oLnk->GetKey()); + $oTicket->Set('contacts_list', $oContacts); + $this->debug("Removed contact $sContactId from {$oTicket->Get('ref')} ({$sRoleCode})"); + + return; + } + } + } + + protected function GivenUserRestrictedToAnOrganizationInDB(int $iOrganization, string $sProfileId): string + { + $sLogin = 'demo_test_'.uniqid(__CLASS__, true); + $iUser = $this->GivenObjectInDB('UserLocal', [ + 'login' => $sLogin, + 'password' => 'tagada-Secret,007', + 'language' => 'EN US', + 'profile_list' => [ + 'profileid:'.$sProfileId + ], + 'allowed_org_list' => [ + 'allowed_org_id:'.$iOrganization + ], + ]); + return $sLogin; + } } diff --git a/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php b/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php index 0706b3d27..a89e24ba3 100644 --- a/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php +++ b/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php @@ -57,6 +57,19 @@ abstract class ItopTestCase extends TestCase // setUp might be called multiple times, so protecting the define() call ! define(ITOP_PHPUNIT_RUNNING_CONSTANT_NAME, true); } + + // This is mostly for interactive usage, to warn the developer that the tests will be slow and point her to the php.ini file + static $bCheckedXDebug = false; + if (!$bCheckedXDebug) { + $bCheckedXDebug = true; + if (extension_loaded('xdebug') && ini_get('xdebug.mode') != '') { + echo "Xdebug is enabled (xdebug.mode='".ini_get('xdebug.mode')."'), this will slow down the tests.\n"; + $sIniFile = php_ini_loaded_file(); + if ($sIniFile) { + echo "This can be tuned in $sIniFile\n"; + } + } + } } /** diff --git a/tests/php-unit-tests/unitary-tests/application/LoginTest.php b/tests/php-unit-tests/unitary-tests/application/LoginTest.php index 583d30d3d..5b0ba61ce 100644 --- a/tests/php-unit-tests/unitary-tests/application/LoginTest.php +++ b/tests/php-unit-tests/unitary-tests/application/LoginTest.php @@ -40,15 +40,6 @@ class LoginTest extends ItopDataTestCase { parent::tearDown(); } - public function testLoginInfiniteLoopFix() { - $iTimeStamp = microtime(true); - $sOutput = $this->CallItopUrlByCurl(sprintf("/pages/UI.php?login_mode=%s", $this->sLoginMode)); - $iElapsedInMs = (microtime(true) - $iTimeStamp) * 1000; - $sMaxExecutionInS = 1; - $this->assertTrue($iElapsedInMs < $sMaxExecutionInS * 1000, "iTop answered in $iElapsedInMs ms. it should do it in less than $sMaxExecutionInS seconds (max_execution_time)"); - $this->assertFalse(strpos($sOutput, "Fatal error"), "no fatal error due to max execution time should be returned" . $sOutput); - } - protected function CallItopUrlByCurl($sUri, ?array $aPostFields=[]){ $ch = curl_init(); diff --git a/tests/php-unit-tests/unitary-tests/core/DBObjectTest.php b/tests/php-unit-tests/unitary-tests/core/DBObjectTest.php index 58377f1af..84ab44413 100644 --- a/tests/php-unit-tests/unitary-tests/core/DBObjectTest.php +++ b/tests/php-unit-tests/unitary-tests/core/DBObjectTest.php @@ -522,7 +522,7 @@ class DBObjectTest extends ItopDataTestCase $oPersonOfMyCompanyOrg = MetaModel::GetObjectByName(Person::class, 'My first name My last name'); $sConfigurationManagerProfileId = 3; // Access to Person objects - $oUserWithAllowedOrgs = $this->CreateDemoOrgUser($oDemoOrg, $sConfigurationManagerProfileId); + $sLogin = $this->GivenUserRestrictedToAnOrganizationInDB($oDemoOrg->GetKey(), $sConfigurationManagerProfileId); $oAdminUser = MetaModel::GetObjectByName(User::class, 'admin', false); if (is_null($oAdminUser)) { @@ -533,7 +533,7 @@ class DBObjectTest extends ItopDataTestCase $oPersonObject = $this->CreatePerson(0, $oMyCompanyOrg->GetKey()); //--- Now we can do some tests ! - UserRights::Login($oUserWithAllowedOrgs->Get('login')); + UserRights::Login($sLogin); $this->ResetMetaModelQueyCacheGetObject(); try { @@ -594,10 +594,10 @@ class DBObjectTest extends ItopDataTestCase $oPersonOnDemoOrg = MetaModel::GetObjectByName(Person::class, 'Claude Monet'); $sConfigManagerProfileId = 3; // access to Team and Contact objects - $oUserWithAllowedOrgs = $this->CreateDemoOrgUser($oDemoOrg, $sConfigManagerProfileId); + $sLogin = $this->GivenUserRestrictedToAnOrganizationInDB($oDemoOrg->GetKey(), $sConfigManagerProfileId); //--- Now we can do some tests ! - UserRights::Login($oUserWithAllowedOrgs->Get('login')); + UserRights::Login($sLogin); $this->ResetMetaModelQueyCacheGetObject(); $oTeam = MetaModel::NewObject(Team::class, [ @@ -699,10 +699,10 @@ class DBObjectTest extends ItopDataTestCase $oPersonOnDemoOrg = MetaModel::GetObjectByName(Person::class, 'Claude Monet'); $sConfigManagerProfileId = 3; // access to Team and Contact objects - $oUserWithAllowedOrgs = $this->CreateDemoOrgUser($oDemoOrg, $sConfigManagerProfileId); + $sLogin = $this->GivenUserRestrictedToAnOrganizationInDB($oDemoOrg->GetKey(), $sConfigManagerProfileId); //--- Now we can do some tests ! - UserRights::Login($oUserWithAllowedOrgs->Get('login')); + UserRights::Login($sLogin); $this->ResetMetaModelQueyCacheGetObject(); $oAttachment = MetaModel::NewObject(Attachment::class, [ @@ -729,20 +729,6 @@ class DBObjectTest extends ItopDataTestCase } } - private function CreateDemoOrgUser(Organization $oDemoOrg, string $sProfileId): User - { - utils::GetConfig()->SetModuleSetting('authent-local', 'password_validation.pattern', ''); - $oUserWithAllowedOrgs = $this->CreateContactlessUser('demo_test_' . uniqid(__CLASS__, true), $sProfileId); - /** @var \URP_UserOrg $oUserOrg */ - $oUserOrg = \MetaModel::NewObject('URP_UserOrg', ['allowed_org_id' => $oDemoOrg->GetKey(),]); - $oAllowedOrgList = $oUserWithAllowedOrgs->Get('allowed_org_list'); - $oAllowedOrgList->AddItem($oUserOrg); - $oUserWithAllowedOrgs->Set('allowed_org_list', $oAllowedOrgList); - $oUserWithAllowedOrgs->DBWrite(); - - return $oUserWithAllowedOrgs; - } - /** * Test attribute integer incrementation. * diff --git a/tests/php-unit-tests/unitary-tests/core/DBSearchIntersectTest.php b/tests/php-unit-tests/unitary-tests/core/DBSearchIntersectTest.php index 7e4c6c6fc..4a49ac3cc 100644 --- a/tests/php-unit-tests/unitary-tests/core/DBSearchIntersectTest.php +++ b/tests/php-unit-tests/unitary-tests/core/DBSearchIntersectTest.php @@ -186,10 +186,10 @@ class DBSearchIntersectTest extends ItopTestCase '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)"); - $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( 'left' => "SELECT Contact WHERE name = 'Christie'", diff --git a/tests/php-unit-tests/unitary-tests/core/RelationGraphTest.php b/tests/php-unit-tests/unitary-tests/core/RelationGraphTest.php deleted file mode 100644 index 153a8b8f4..000000000 --- a/tests/php-unit-tests/unitary-tests/core/RelationGraphTest.php +++ /dev/null @@ -1,102 +0,0 @@ - array('Server',1), - 'Server::2' => array('Server',2), - ); - } - - /** - * @dataProvider ComputeRelatedObjectsProvider - * - * @param $sClass - * @param $iKey - * - * @return void - * @throws \ArchivedObjectException - * @throws \CoreException - */ - public function testComputeRelatedObjectsDown($sClass, $iKey) - { - $oServer = MetaModel::GetObject($sClass, $iKey); - MetaModel::GetConfig()->Set('relations.complete_analysis', true); - - $oGraphTrue = new RelationGraph(); - $oGraphTrue->AddSourceObject($oServer); - $oGraphTrue->ComputeRelatedObjectsDown('impacts', 10, true); - - - MetaModel::GetConfig()->Set('relations.complete_analysis', false); - $oGraphFalse = new RelationGraph(); - $oGraphFalse->AddSourceObject($oServer); - $oGraphFalse->ComputeRelatedObjectsDown('impacts', 10, true); - - $aNodeFalse = $oGraphFalse->_GetNodes(); - $aNodeTrue = $oGraphFalse->_GetNodes(); - - //test if the 2 graph contains the same objects - $this->assertEquals(count($aNodeFalse), count($aNodeFalse),'With the admin user, the impact analysis down must have the same number of impacted items whatever the value of the "relations.complete_analysis" parameter.'); - foreach ($aNodeTrue as $sKey =>$oNodeTrue){ - $this->assertArrayHasKey($sKey, $aNodeFalse,'With the admin user, the impact analysis down must have the same results whatever the value of the "relations.complete_analysis" parameter.'); - } - } - - /** - * @dataProvider ComputeRelatedObjectsProvider - * - * @param $sClass - * @param $iKey - * - * @return void - * @throws \ArchivedObjectException - * @throws \CoreException - */ - public function testComputeRelatedObjectsUp($sClass, $iKey) - { - $oServer = MetaModel::GetObject($sClass, $iKey); - MetaModel::GetConfig()->Set('relations.complete_analysis', true); - - $oGraphTrue = new RelationGraph(); - $oGraphTrue->AddSourceObject($oServer); - $oGraphTrue->ComputeRelatedObjectsUp('impacts', 10, true); - - - MetaModel::GetConfig()->Set('relations.complete_analysis', false); - $oGraphFalse = new RelationGraph(); - $oGraphFalse->AddSourceObject($oServer); - $oGraphFalse->ComputeRelatedObjectsUp('impacts', 10, true); - - $aNodeFalse = $oGraphFalse->_GetNodes(); - $aNodeTrue = $oGraphFalse->_GetNodes(); - - //test if the 2 graph contains the same objects - $this->assertEquals(count($aNodeFalse), count($aNodeFalse),'With the admin user, the impact analysis up must have the same number of impacted items whatever the value of the "relations.complete_analysis" parameter.'); - foreach ($aNodeTrue as $sKey =>$oNodeTrue){ - $this->assertArrayHasKey($sKey, $aNodeFalse,'With the admin user, the impact analysis up must have the same results whatever the value of the "relations.complete_analysis" parameter.'); - } - } - -} diff --git a/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-config/BulkChangeExtKeyTest.php b/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-config/BulkChangeExtKeyTest.php index a6106580b..f30675e0d 100644 --- a/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-config/BulkChangeExtKeyTest.php +++ b/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-config/BulkChangeExtKeyTest.php @@ -111,7 +111,7 @@ class BulkChangeExtKeyTest extends ItopDataTestCase { ] ); - list($oOrg2, $oUser) = $this->createAnotherUserInAnotherOrg(); + [$oOrg2, $oUser] = $this->createAnotherUserInAnotherOrg(); \UserRights::Login($oUser->Get('login')); $this->performBulkChangeTest( @@ -127,7 +127,7 @@ class BulkChangeExtKeyTest extends ItopDataTestCase { */ public function testExternalFieldIssueImportFail_SomeObjectVisibleByCurrentUser($bIsRackReconKey){ $this->deleteAllRacks(); - list($oOrg2, $oUser) = $this->createAnotherUserInAnotherOrg(); + [$oOrg2, $oUser] = $this->createAnotherUserInAnotherOrg(); $this->createRackObjects( [ $this->getTestOrgId() => ['RackTest1', 'RackTest2'], diff --git a/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/UpdateImpactedItemsTest.php b/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/UpdateImpactedItemsTest.php new file mode 100644 index 000000000..74d33a7b0 --- /dev/null +++ b/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/UpdateImpactedItemsTest.php @@ -0,0 +1,530 @@ + +// + +namespace Combodo\iTop\Test\UnitTest\Module\iTopTickets; + +use Combodo\iTop\Test\UnitTest\ItopDataTestCase; +use Exception; +use MetaModel; +use Organization; +use UserRights; + + +/** + * @group itopVirtualizationMgmt + * @group itopConfigMgmt + * @group itopTickets + */ +class UpdateImpactedItemsTest extends ItopDataTestCase +{ + const CREATE_TEST_ORG = true; + /** + * @var Object Names to Ids + */ + private array $aCIs = []; + + protected function setUp(): void + { + parent::setUp(); + $this->aCIs = []; + } + + protected function tearDown(): void + { + parent::tearDown(); + UserRights::Logoff(); + $this->ResetMetaModelQueyCacheGetObject(); + } + + public function testImpactShouldBePropagatedToDirectDescendants() + { + /** + * Server1 +----> Hypervisor1 + * +====> Person1 + */ + $this->GivenCITreeInDB(<< Server_1 + Server_1 <-> Person_1 + EOF); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Server_1' => 'manual' + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Server_1' => 'manual', + 'Hypervisor_1' => 'computed', + 'Test Person_1' => 'computed' + ]); + } + + public function testImpactShouldBePropagatedInOneWayOnly() + { + /** + * Server1 +----> Hypervisor1 + * Server2 +----> Hypervisor1 + */ + $this->GivenCITreeInDB(<< Server_1 + Hypervisor_1 -> Server_2 + EOF); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Server_1' => 'manual' + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Server_1' => 'manual', + 'Hypervisor_1' => 'computed' + ]); + } + + public function testImpactShouldBePropagatedRecursively() + { + /** + * Server1 +----> Hypervisor1 +----> Farm +====> Person1 + */ + $this->GivenCITreeInDB(<< Server_1, Farm_1 + Farm_1 <-> Person_1 + EOF); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Server_1' => 'manual' + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Server_1' => 'manual', + 'Hypervisor_1' => 'computed', + 'Farm_1' => 'computed', + 'Test Person_1' => 'computed' + ]); + } + + public function testImpactShouldNotBeFurtherPropagatedWhenCINotAllowed() + { + /** + * Server1 +----> Hypervisor1 +----> Farm + */ + $this->GivenCITreeInDB(<< Server_1, Farm_1 + EOF); + $this->GivenCINotAllowedToCurrentUser('Hypervisor_1'); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Server_1' => 'manual' + ]); + + MetaModel::GetConfig()->Set('relations.complete_analysis', false); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Server_1' => 'manual', + ]); + } + + public function testImpactShouldBeFurtherPropagatedAboveCINotAllowedWhenCompleteAnalysisRequested() + { + /** + * Server1 +----> Hypervisor1 +----> Farm + */ + $this->GivenCITreeInDB(<< Server_1, Farm_1 + EOF); + $this->GivenCINotAllowedToCurrentUser('Hypervisor_1'); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Server_1' => 'manual' + ]); + + MetaModel::GetConfig()->Set('relations.complete_analysis', true); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Server_1' => 'manual', + 'Farm_1' => 'computed', + ]); + } + + public function testImpactShouldBePropagatedToAllDescendantsOfSameClass() + { + /** + * Server1 +----> Hypervisor1 + * +----> Hypervisor2 + */ + $this->GivenCITreeInDB(<< Server_1 + Hypervisor_2 -> Server_1 + DOT); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Server_1' => 'manual', + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Server_1' => 'manual', + 'Hypervisor_1' => 'computed', + 'Hypervisor_2' => 'computed', + ]); + } + public function testNodesImpactedByTwoWaysShouldBeFoundOnce() + { + /** + * +------------------+ + * Hypervisor1 | + * +====> Person1 +----> Farm1 + * Hypervisor2 | + * +------------------+ + */ + $this->GivenCITreeInDB(<< Farm_1 + Hypervisor_2 -> Farm_1 + Hypervisor_1 <-> Person_1 + Hypervisor_2 <-> Person_1 + DOT); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Hypervisor_1' => 'manual', + 'Hypervisor_2' => 'manual', + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Hypervisor_1' => 'manual', + 'Hypervisor_2' => 'manual', + 'Farm_1' => 'computed', + 'Test Person_1' => 'computed' + ]); + } + public function testPreviouslyComputedNodesShouldBeIgnored() + { + /** + * Server1 +----> Hypervisor1 +----> Person1 + * + * Server2 +----> Person2 + */ + $this->GivenCITreeInDB(<< Server_1 + Hypervisor_1 <-> Person_1 + Server_2 <-> Person_2 + EOF); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Server_1' => 'manual', + 'Server_2' => 'computed', + 'Person_2' => 'computed' + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Server_1' => 'manual', + 'Hypervisor_1' => 'computed', + 'Test Person_1' => 'computed' + ]); + } + + public function testPreviouslyComputedNodesShouldBeIgnoredCausingTheListToCollapse() + { + /** + * Server1 +----> Hypervisor1 +----> Person1 + */ + $this->GivenCITreeInDB(<< Server_1 + Hypervisor_1 <-> Person_1 + EOF); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Hypervisor_1' => 'computed', + 'Person_1' => 'computed' + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, []); + } + + + public function testNoImpactWhenNoCI() + { + $oTicket = $this->GivenTicketWithCIsOrPersons([]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, []); + } + + public function testRedundancyShouldPreventPropagationOfImpact() + { + /** + * Hypervisor1 + * +----> Farm1 + * Hypervisor2 + */ + $this->GivenCITreeInDB(<< Farm_1 + Hypervisor_2 -> Farm_1 + DOT); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Hypervisor_1' => 'manual' + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Hypervisor_1' => 'manual' + ]); + } + + public function testRedundancyShouldNotPreventPropagationWhenEverySourceIsImpacted() + { + /** + * Hypervisor1 + * +----> Farm1 + * Hypervisor2 + */ + $this->GivenCITreeInDB(<< Farm_1 + Hypervisor_2 -> Farm_1 + DOT); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Hypervisor_1' => 'manual', + 'Hypervisor_2' => 'manual' + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Hypervisor_1' => 'manual', + 'Hypervisor_2' => 'manual', + 'Farm_1' => 'computed' + ]); + } + + public function testCIsMarkedAsNotImpactedShouldRemainMarkedAndShouldNotPropagateTheImpact() + { + /** + * Server1 +----> Hypervisor1 +----> Farm1 + * +====> Person1 + */ + $this->GivenCITreeInDB(<< Server_1, Farm_1 + Hypervisor_1 <-> Person_1 + DOT); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Server_1' => 'manual', + 'Hypervisor_1' => 'not_impacted', + 'Person_1' => 'do_not_notify' + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Server_1' => 'manual', + 'Hypervisor_1' => 'not_impacted', + 'Test Person_1' => 'do_not_notify' + ]); + } + + public function testCIsMarkedAsNotImpactedShouldRemainMarkedWhenNotInImpactGraph() + { + /** + * Hypervisor1 +====> Person1 + */ + $this->GivenCITreeInDB(<< Person_1 + DOT); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'Hypervisor_1' => 'not_impacted', + 'Person_1' => 'do_not_notify' + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'Hypervisor_1' => 'not_impacted', + 'Test Person_1' => 'do_not_notify' + ]); + } + + public function testRedundancyShouldBeEvaluatedOnOtherTicketsToo() + { + /** + * Hypervisor1 + * +----> Farm1 + * Hypervisor2 + */ + $this->GivenCITreeInDB(<< Farm_1 + Hypervisor_2 -> Farm_1 + DOT); + $oTicket1 = $this->GivenTicketWithCIsOrPersons([ + 'Hypervisor_1' => 'manual', + ]); + + $oTicket1->DBWrite(); // impact analysis + $this->GivenRelationContextQueryWillFindTicket($oTicket1->GetKey()); + + $oTicket2 = $this->GivenTicketWithCIsOrPersons([ + 'Hypervisor_2' => 'manual', + ]); + + /// TEST Begins Here + $oTicket2->UpdateImpactedItems(); + + // The second ticket should have the impact propagated + $this->assertCIsOrPersonsListEquals($oTicket2, [ + 'Hypervisor_2' => 'manual', + 'Farm_1' => 'computed', + ]); + + $this->ReloadObject($oTicket1); // reload the links + + // The first ticket should remain in its initial state + $this->assertCIsOrPersonsListEquals($oTicket1, [ + 'Hypervisor_1' => 'manual', + ]); + } + + private function assertCIsOrPersonsListEquals(\UserRequest $oTicket, array $aExpected) + { + $aActual = []; + foreach ($oTicket->Get('functionalcis_list') as $oLnk) { + $sKey = $oLnk->Get('functionalci_id_friendlyname'); + $aActual[$sKey] = $oLnk->Get('impact_code'); + } + foreach ($oTicket->Get('contacts_list') as $oLnk) { + $sKey = $oLnk->Get('contact_id_friendlyname'); + $aActual[$sKey] = $oLnk->Get('role_code'); + } + $this->assertEquals($aExpected, $aActual, 'Unexpected value for functionalcis_list'); + } + + + /** + * @param int|string|null $sTicketId + * + * @return void + */ + public function GivenRelationContextQueryWillFindTicket(int|string|null $sTicketId): void + { + $aRelationContext = \MetaModel::GetConfig()->GetModuleSetting('itop-tickets', 'relation_context'); + $aRelationContext['UserRequest']['impacts']['down']['items'][0]['oql'] = "SELECT FCI, R + FROM FunctionalCI AS FCI + JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id + JOIN UserRequest AS R ON L.ticket_id = R.id + WHERE (R.id = $sTicketId)"; + \MetaModel::GetConfig()->SetModuleSetting('itop-tickets', 'relation_context', $aRelationContext); + } + private function GivenCITreeInDB(string $sTree) + { + $aTree = explode("\n", $sTree); + foreach ($aTree as $sLine) { + $this->GivenCITreeLineInDB($sLine); + } + } + + private function GivenCITreeLineInDB(string $sLine) + { + if (strpos($sLine, '<->') !== false) { + list($sCI, $sPerson) = explode('<->', $sLine); + $sPersonId = $this->GivenCIOrPersonInDB(trim($sPerson)); + $sCIId = $this->GivenCIOrPersonInDB(trim($sCI)); + $this->GivenLnkContactToFunctionalCIInDB($sPersonId, $sCIId); + return; + } + list($sCIParent, $sChildren) = explode('->', $sLine); + $aChildren = explode(',', $sChildren); + $aChildren = array_map('trim', $aChildren); + $aChildrenIdsByClass = []; + foreach ($aChildren as $sChildCI) { + list($sChildClass, ) = explode('_', $sChildCI, 2); + $aChildrenIdsByClass[$sChildClass] = $this->GivenCIOrPersonInDB($sChildCI); + } + $this->GivenCIOrPersonInDB($sCIParent, $aChildrenIdsByClass); + } + + private function GivenCIOrPersonInDB(string $sDescriptor, array $aChildrenIdsByClass = []): string + { + $sDescriptor = trim($sDescriptor); + if (isset($this->aCIs[$sDescriptor])) { + return $this->aCIs[$sDescriptor]; + } + list($sClass, $sRef) = explode('_', $sDescriptor, 2); + switch ($sClass) { + case 'Server': + $sCIId = $this->GivenServerInDB($sRef); + break; + case 'Hypervisor': + $sCIId = $this->GivenHypervisorInDB($sRef, $aChildrenIdsByClass['Server'] ?? 0, $aChildrenIdsByClass['Farm'] ?? 0); + break; + case 'Person': + $sCIId = $this->GivenPersonInDB($sRef); + break; + case 'Farm': + $sCIId = $this->GivenFarmInDB($sRef); + break; + case 'VirtualMachine': + $sCIId = $this->GivenVirtualMachineInDB($sRef, $aChildrenIdsByClass['Farm']); + break; + default: + throw new Exception("Unhandled class $sClass"); + } + $this->aCIs[$sDescriptor] = $sCIId; + return $this->aCIs[$sDescriptor]; + } + + private function GivenTicketWithCIsOrPersons(array $aLinkedObjects) : \UserRequest + { + $oTicket = $this->GivenTicketObject(1); + foreach ($aLinkedObjects as $sObjectDescriptor => $sRole) { + $sClass = trim(explode('_', $sObjectDescriptor)[0]); + if ($sClass === 'Person') { + $this->AddLnkContactToTicketObject($this->GivenCIOrPersonInDB($sObjectDescriptor), $oTicket, $sRole); + continue; + } + $this->AddLnkFunctionalCIToTicketObject($this->GivenCIOrPersonInDB($sObjectDescriptor), $oTicket, $sRole); + } + return $oTicket; + } + + private function GivenCINotAllowedToCurrentUser(string $sCIDescriptor) + { + $iAnotherOrg = $this->GivenObjectInDB(Organization::class, ['name' => 'Another Org']); + + // Change the organization of the CI to 'Another Org' + $sCIDescriptor = trim($sCIDescriptor); + if (!isset($this->aCIs[$sCIDescriptor])) { + throw new Exception("CI $sCIDescriptor not found"); + } + $sCIId = $this->aCIs[$sCIDescriptor]; + + $oCI = \MetaModel::GetObject('FunctionalCI', $sCIId); + $oCI->Set('org_id', $iAnotherOrg); + $oCI->DBUpdate(); + + $sConfigManagerProfileId = 3; // access to CIs + $sLogin = $this->GivenUserRestrictedToAnOrganizationInDB($this->getTestOrgId(), $sConfigManagerProfileId); + + UserRights::Login($sLogin); + $this->ResetMetaModelQueyCacheGetObject(); + } +} diff --git a/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/itopTicketTest.php b/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/itopTicketTest.php deleted file mode 100644 index b10224c13..000000000 --- a/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/itopTicketTest.php +++ /dev/null @@ -1,922 +0,0 @@ - -// - -/** - * Created by PhpStorm. - * User: Eric - * Date: 18/12/2017 - * Time: 13:34 - */ - -namespace Combodo\iTop\Test\UnitTest\Module\iTopTickets; - -use Combodo\iTop\Test\UnitTest\ItopDataTestCase; -use Exception; - - -/** - * @group itopVirtualizationMgmt - * @group itopConfigMgmt - * @group itopTickets - */ -class ItopTicketTest extends ItopDataTestCase -{ - const CREATE_TEST_ORG = true; - - /** - *
-	 * Given:
-	 *
-	 * Server1+---->Hypervisor1+---->Person1
-	 *
-	 * Ticket+---->Server1 (manual)
-	 *
-	 * Result:
-	 *
-	 * Ticket+====>Server1,Hypervisor1
-	 *       |
-	 *       +====>Person1
-	 * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_Basic() - { - $oTicket = $this->CreateTicket(1); - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1); - $oPerson1 = $this->CreatePerson(1); - $this->AddContactToCI($oPerson1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $aAwaitedCIs = $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - // Add the computed CIs - $aAwaitedCIs = $aAwaitedCIs + array($oHypervisor1->GetKey() => 'computed'); - - $this->CheckFunctionalCIList($oTicket, $aAwaitedCIs); - - // Computed Contacts - $aAwaitedContacts = array($oPerson1->GetKey() => array('role_code' => 'computed')); - $this->CheckContactList($oTicket, $aAwaitedContacts); - $this->assertEquals(2, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket->Get('contacts_list')->Count()); - } - - /** - *
-     * Given:
-     *
-     * Server1+---->Hypervisor1+---->Person1
-     *
-     * Ticket+---->Server1 (manual)
-     *
-     * Result:
-     *
-     * Ticket+====>Server1,Hypervisor1
-     *       |
-     *       +====>Person1
-     * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_Basic2() - { - $oTicket = $this->CreateTicket(1); - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1); - $oPerson1 = $this->CreatePerson(1); - $this->AddContactToCI($oPerson1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $oTicket->DBUpdate(); // trigger the impact update - - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(2, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket->Get('contacts_list')->Count()); - - // Try removing computed entries - $this->RemoveCIFromTicket($oHypervisor1, $oTicket); - $this->RemoveContactFromTicket($oPerson1, $oTicket); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(2, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket->Get('contacts_list')->Count()); - } - - /** - *
-     * Given:
-     *
-     * Server1+---->Hypervisor1+---->Person1
-     *
-     * Server2    Person2
-     *
-     * Ticket+---->Server1 (manual), Server2 (computed)
-     *
-     * Result:
-     *
-     * Ticket+====>Server1,Hypervisor1
-     *       |
-     *       +====>Person1
-     * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_RemoveUnecessaryEntries() - { - $oTicket = $this->CreateTicket(1); - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1); - $oPerson1 = $this->CreatePerson(1); - $this->AddContactToCI($oPerson1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $oServer2 = $this->CreateServer(2); - $oPerson2 = $this->CreatePerson(2); - - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $this->AddCIToTicket($oServer2, $oTicket, 'computed'); - $this->AddContactToTicket($oPerson2, $oTicket, 'computed'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(2, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket->Get('contacts_list')->Count()); - } - - /** - * Create a first impact chain then remove the root cause, all the chain should be removed. - * - *
-     * Given:
-     *
-     * Server1+---->Hypervisor1+---->Person1
-     *
-     * Ticket+---->Server1 (manual)
-     *
-     * Result:
-     *
-     * Ticket+====>Server1,Hypervisor1
-     *       |
-     *       +====>Person1
-     *
-     * Then remove Server1
-     *
-     * Result:
-     *
-     * Ticket+====>
-     *       |
-     *       +====>
-     *
-     * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_RemoveUnecessaryEntries2() - { - $oTicket = $this->CreateTicket(1); - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1); - $oPerson1 = $this->CreatePerson(1); - $this->AddContactToCI($oPerson1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(2, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket->Get('contacts_list')->Count()); - - $this->RemoveCIFromTicket($oServer1, $oTicket); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(0, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(0, $oTicket->Get('contacts_list')->Count()); - } - - - /** - *
-     *
-     * Server2+---->Hypervisor2+---->Person2
-     *
-     * Ticket+---->(empty)
-     *
-     * Result:
-     *
-     * Ticket+====>(empty)
-     * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_NoImpact() - { - $oTicket = $this->CreateTicket(1); - $oServer2 = $this->CreateServer(2); - $oPerson2 = $this->CreatePerson(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2); - $this->AddContactToCI($oPerson2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(0, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(0, $oTicket->Get('contacts_list')->Count()); - } - - /** - *
-	 * Server1
-	 *
-	 * Server2+---->Hypervisor2+---->Person2
-	 *
-	 * Ticket+---->Server1 (manual)
-	 *
-	 * Result:
-	 *
-	 * Ticket+====>Server1
-	 * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_NoImpact2() - { - $oTicket = $this->CreateTicket(1); - $oServer1 = $this->CreateServer(1); - $oServer2 = $this->CreateServer(2); - $oPerson2 = $this->CreatePerson(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2); - $this->AddContactToCI($oPerson2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(1, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(0, $oTicket->Get('contacts_list')->Count()); - } - - /** - *
-	 *                    +-->Person1
-	 *                    |
-	 *                    +
-	 * Server1+---->Hypervisor1+--+
-	 *                            |
-	 *                            v
-	 *                            Farm (1)
-	 *                            ^
-	 *                            |
-	 * Server2+---->Hypervisor2+--+
-	 *                    +
-	 *                    |
-	 *                    +-->Person2
-	 *
-	 * Ticket+---->Server1 (manual)
-	 *
-	 * Result:
-	 *
-	 * Ticket+====>Server1,Hypervisor1
-	 *       |
-	 *       +====>Person1
-	 * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_Redundancy() - { - $oFarm = $this->CreateFarm(1); - - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1, $oFarm); - $oContact1 = $this->CreatePerson(1); - $this->AddContactToCI($oContact1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $oServer2 = $this->CreateServer(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2, $oFarm); - $oContact2 = $this->CreatePerson(2); - $this->AddContactToCI($oContact2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $oTicket = $this->CreateTicket(1); - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(2, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket->Get('contacts_list')->Count()); - } - - /** - *
-	 *                    +-->Person1
-	 *                    |
-	 *                    +
-	 * Server1+---->Hypervisor1+--+
-	 *                            |
-	 *                            v
-	 *                            Farm (1)
-	 *                            ^
-	 *                            |
-	 * Server2+---->Hypervisor2+--+
-	 *                    +
-	 *                    |
-	 *                    +-->Person2
-	 *
-	 * Ticket+---->Server1 (manual), Hypervisor2 (manual)
-	 *
-	 * Result:
-	 *
-	 * Ticket+====>Server1,Hypervisor1,Farm,Hypervisor2
-	 *       |
-	 *       +====>Person1,Person2
-	 * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_Redundancy2() - { - $oFarm = $this->CreateFarm(1); - - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1, $oFarm); - $oContact1 = $this->CreatePerson(1); - $this->AddContactToCI($oContact1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $oServer2 = $this->CreateServer(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2, $oFarm); - $oContact2 = $this->CreatePerson(2); - $this->AddContactToCI($oContact2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $oTicket = $this->CreateTicket(1); - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $this->AddCIToTicket($oHypervisor2, $oTicket, 'manual'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(4, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(2, $oTicket->Get('contacts_list')->Count()); - } - - - /** - *
-	 *                    +-->Person1
-	 *                    |
-	 *                    +
-	 * Server1+---->Hypervisor1+--+  +-->VM1
-	 *                            |  |
-	 *                            v  +
-	 *                            Farm (1)
-	 *                            ^  +
-	 *                            |  |
-	 * Server2+---->Hypervisor2+--+  +-->VM2
-	 *                    +
-	 *                    |
-	 *                    +-->Person2
-	 *
-	 * Ticket+---->Server1 (manual), Hypervisor2 (manual)
-	 *
-	 * Result:
-	 *
-	 * Ticket+====>Server1,Hypervisor1,Farm,Hypervisor2,VM1,VM2
-	 *       |
-	 *       +====>Person1,Person2
-	 * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_Redundancy3() - { - $oFarm = $this->CreateFarm(1); - - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1, $oFarm); - $oContact1 = $this->CreatePerson(1); - $this->AddContactToCI($oContact1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $oServer2 = $this->CreateServer(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2, $oFarm); - $oContact2 = $this->CreatePerson(2); - $this->AddContactToCI($oContact2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $this->CreateVirtualMachine(1, $oFarm); - $this->CreateVirtualMachine(2, $oFarm); - - $oTicket = $this->CreateTicket(1); - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $this->AddCIToTicket($oHypervisor2, $oTicket, 'manual'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(6, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(2, $oTicket->Get('contacts_list')->Count()); - } - - /** - *
-     *                    +-->Person1
-     *                    |
-     *                    +
-     * Server1+---->Hypervisor1+--+  +-->VM1
-     *                            |  |
-     *                            v  +
-     *                            Farm (1)
-     *                            ^  +
-     *                            |  |
-     * Server2+---->Hypervisor2+--+  +-->VM2
-     *                    +
-     *                    |
-     *                    +-->Person2
-     *
-     * Ticket+---->Server1 (manual), Server2 (manual), Hypervisor2 (not_impacted)
-     *
-     * Result:
-     *
-     * Ticket+====>Server1,Hypervisor1,Server2,Hypervisor2
-     *       |
-     *       +====>Person1
-     * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_Exclusion() - { - $oFarm = $this->CreateFarm(1); - - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1, $oFarm); - $oContact1 = $this->CreatePerson(1); - $this->AddContactToCI($oContact1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $oServer2 = $this->CreateServer(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2, $oFarm); - $oContact2 = $this->CreatePerson(2); - $this->AddContactToCI($oContact2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $this->CreateVirtualMachine(1, $oFarm); - $this->CreateVirtualMachine(2, $oFarm); - - $oTicket = $this->CreateTicket(1); - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $this->AddCIToTicket($oServer2, $oTicket, 'manual'); - $this->AddCIToTicket($oHypervisor2, $oTicket, 'not_impacted'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(4, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket->Get('contacts_list')->Count()); - } - - /** - *
-     *                    +-->Person1
-     *                    |
-     *                    +
-     * Server1+---->Hypervisor1+--+  +-->VM1
-     *                            |  |
-     *                            v  +
-     *                            Farm (1)
-     *                            ^  +
-     *                            |  |
-     * Server2+---->Hypervisor2+--+  +-->VM2
-     *                    +
-     *                    |
-     *                    +-->Person2
-     *
-     * Ticket+---->Server1 (manual), Server2 (manual)
-     *       |
-     *       +---->Person2 (do_not_notify)
-     *
-     * Result:
-     *
-     * Ticket+====>Server1,Hypervisor1,Server2,Hypervisor2,Farm,VM1,VM2
-     *       |
-     *       +====>Person1,Person2 (do_not_notify)
-     * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_Exclusion2() - { - $oFarm = $this->CreateFarm(1); - - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1, $oFarm); - $oContact1 = $this->CreatePerson(1); - $this->AddContactToCI($oContact1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $oServer2 = $this->CreateServer(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2, $oFarm); - $oContact2 = $this->CreatePerson(2); - $this->AddContactToCI($oContact2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $this->CreateVirtualMachine(1, $oFarm); - $this->CreateVirtualMachine(2, $oFarm); - - $oTicket = $this->CreateTicket(1); - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $this->AddCIToTicket($oServer2, $oTicket, 'manual'); - $this->AddContactToTicket($oContact2, $oTicket, 'do_not_notify'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(7, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(2, $oTicket->Get('contacts_list')->Count()); - } - - /** - *
-     *                    +-->Person1
-     *                    |
-     *                    +
-     * Server1+---->Hypervisor1+--+  +-->VM1
-     *                            |  |
-     *                            v  +
-     *                            Farm (1)
-     *                            ^  +
-     *                            |  |
-     * Server2+---->Hypervisor2+--+  +-->VM2
-     *                    +
-     *                    |
-     *                    +-->Person2
-     *
-     * Ticket+---->Server1 (manual), Server2 (manual), Hypervisor2 (not_impacted)
-     *       |
-     *       +---->Person2 (do_not_notify)
-     *
-     * Result:
-     *
-     * Ticket+====>Server1,Hypervisor1,Server2,Hypervisor2
-     *       |
-     *       +====>Person1,Person2 (do_not_notify)
-     * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_Exclusion3() - { - $oFarm = $this->CreateFarm(1); - - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1, $oFarm); - $oContact1 = $this->CreatePerson(1); - $this->AddContactToCI($oContact1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $oServer2 = $this->CreateServer(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2, $oFarm); - $oContact2 = $this->CreatePerson(2); - $this->AddContactToCI($oContact2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $this->CreateVirtualMachine(1, $oFarm); - $this->CreateVirtualMachine(2, $oFarm); - - $oTicket = $this->CreateTicket(1); - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $this->AddCIToTicket($oServer2, $oTicket, 'manual'); - $this->AddCIToTicket($oHypervisor2, $oTicket, 'not_impacted'); - $this->AddContactToTicket($oContact2, $oTicket, 'do_not_notify'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(4, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(2, $oTicket->Get('contacts_list')->Count()); - } - - /** - *
-     *                    +-->Person1
-     *                    |
-     *                    +
-     * Server1+---->Hypervisor1+--+  +-->VM1
-     *                            |  |
-     *                            v  +
-     *                            Farm (1)
-     *                            ^  +
-     *                            |  |
-     * Server2+---->Hypervisor2+--+  +-->VM2
-     *                    +
-     *                    |
-     *                    +-->Person2
-     *
-     * Ticket+---->Server1 (manual), Hypervisor2 (not_impacted)
-     *
-     * Result:
-     *
-     * Ticket+====>Server1,Hypervisor1, Hypervisor2 (not_impacted)
-     *       |
-     *       +====>Person1
-     * 
- * - * @throws Exception - */ - public function testUpdateImpactedItems_Exclusion4() - { - $oFarm = $this->CreateFarm(1); - - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1, $oFarm); - $oContact1 = $this->CreatePerson(1); - $this->AddContactToCI($oContact1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $oServer2 = $this->CreateServer(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2, $oFarm); - $oContact2 = $this->CreatePerson(2); - $this->AddContactToCI($oContact2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $this->CreateVirtualMachine(1, $oFarm); - $this->CreateVirtualMachine(2, $oFarm); - - $oTicket = $this->CreateTicket(1); - $this->AddCIToTicket($oServer1, $oTicket, 'manual'); - $this->AddCIToTicket($oHypervisor2, $oTicket, 'not_impacted'); - $oTicket->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket); // reload the links - - $this->CheckFunctionalCIList($oTicket); - $this->CheckContactList($oTicket); - $this->assertEquals(3, $oTicket->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket->Get('contacts_list')->Count()); - } - - /** - *
-     *                    +-->Person1
-     *                    |
-     *                    +
-     * Server1+---->Hypervisor1+--+  +-->VM1
-     *                            |  |
-     *                            v  +
-     *                            Farm (1)
-     *                            ^  +
-     *                            |  |
-     * Server2+---->Hypervisor2+--+  +-->VM2
-     *                    +
-     *                    |
-     *                    +-->Person2
-     *
-     * Ticket1+---->Server1 (manual)
-     *
-     * Result:
-     *
-     * Ticket1+====>Server1,Hypervisor1
-     *        |
-     *        +====>Person1
-     *
-     * Then:
-     *
-     * Ticket2+---->Server2 (manual)
-     *
-     * Result:
-     *
-     * Ticket2+====>Server2,Hypervisor2,Farm,VM1,VM2
-     *        |
-     *        +====>Person2
-     * 
- * - * @throws \ArchivedObjectException - * @throws Exception - */ - public function testUpdateImpactedItems_Redundancy_two_tickets() - { - $oFarm = $this->CreateFarm(1); - - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1, $oFarm); - $oContact1 = $this->CreatePerson(1); - $this->AddContactToCI($oContact1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $oServer2 = $this->CreateServer(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2, $oFarm); - $oContact2 = $this->CreatePerson(2); - $this->AddContactToCI($oContact2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $oVM1 = $this->CreateVirtualMachine(1, $oFarm); - $oVM2 = $this->CreateVirtualMachine(2, $oFarm); - - // Ticket1+---->Server1 (manual) - $oTicket1 = $this->CreateTicket(1); - $this->AddCIToTicket($oServer1, $oTicket1, 'manual'); - $oTicket1->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket1); // reload the links - - // Ticket1+====>Server1,Hypervisor1 - // | - // +====>Person1 - $this->CheckFunctionalCIList($oTicket1); - $this->CheckContactList($oTicket1); - $this->assertEquals(2, $oTicket1->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket1->Get('contacts_list')->Count()); - - // Ticket2+---->Hypervisor2 (manual) - $oTicket2 = $this->CreateTicket(2); - $this->AddCIToTicket($oServer2, $oTicket2, 'manual'); - $oTicket2->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket2); // reload the links - - // Ticket2+====>Farm,Hypervisor2,VM1,VM2,Server2 - // | - // +====>Person2 - $aWaitedCIList = array( - $oFarm->GetKey() => 'computed', - $oVM1->GetKey() => 'computed', - $oVM2->GetKey() => 'computed', - $oHypervisor2->GetKey() => 'computed', - $oServer2->GetKey() => 'manual'); - $this->CheckFunctionalCIList($oTicket2, $aWaitedCIList); - $this->CheckContactList($oTicket2); - $this->assertEquals(2, $oTicket2->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket2->Get('contacts_list')->Count()); - - // The first ticket is not impacted - $this->debug("\nCheck that the first ticket has not changed."); - $this->ReloadObject($oTicket1); // reload the links - - // Ticket1+====>Server1,Hypervisor1 - // | - // +====>Person1 - $this->CheckFunctionalCIList($oTicket1); - $this->CheckContactList($oTicket1); - $this->assertEquals(2, $oTicket1->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket1->Get('contacts_list')->Count()); - } - - /** - *
-     *                    +-->Person1
-     *                    |
-     *                    +
-     * Server1+---->Hypervisor1+--+  +-->VM1
-     *                            |  |
-     *                            v  +
-     * Server3+---->Hypervisor3+->Farm (1)
-     *                            ^  +
-     *                            |  |
-     * Server2+---->Hypervisor2+--+  +-->VM2
-     *                    +
-     *                    |
-     *                    +-->Person2
-     *
-     * Ticket1+---->Server1 (manual), Hypervisor2(manual)
-     *
-     * Result:
-     *
-     * Ticket1+====>Server1,Hypervisor1, Hypervisor2
-     *        |
-     *        +====>Person1, Person2
-     *
-     * Then:
-     *
-     * Ticket2+---->Server2 (manual), Hypervisor3 (manual)
-     *
-     * Result:
-     *
-     * Ticket2+====>Server2,Hypervisor2,Hypervisor3,Farm,VM1,VM2
-     *        |
-     *        +====>Person2
-     * 
- * - * @throws \ArchivedObjectException - * @throws Exception - */ - public function testUpdateImpactedItems_Redundancy_two_tickets2() - { - $oFarm = $this->CreateFarm(1); - - $oServer1 = $this->CreateServer(1); - $oHypervisor1 = $this->CreateHypervisor(1, $oServer1, $oFarm); - $oContact1 = $this->CreatePerson(1); - $this->AddContactToCI($oContact1, $oHypervisor1); - $oHypervisor1->DBUpdate(); - - $oServer2 = $this->CreateServer(2); - $oHypervisor2 = $this->CreateHypervisor(2, $oServer2, $oFarm); - $oContact2 = $this->CreatePerson(2); - $this->AddContactToCI($oContact2, $oHypervisor2); - $oHypervisor2->DBUpdate(); - - $oServer3 = $this->CreateServer(3); - $oHypervisor3 = $this->CreateHypervisor(3, $oServer3, $oFarm); - - - $oVM1 = $this->CreateVirtualMachine(1, $oFarm); - $oVM2 = $this->CreateVirtualMachine(2, $oFarm); - - // Ticket1+---->Server1 (manual), Hypervisor2(manual) - $oTicket1 = $this->CreateTicket(1); - $this->AddCIToTicket($oServer1, $oTicket1, 'manual'); - $this->AddCIToTicket($oHypervisor2, $oTicket1, 'manual'); - $oTicket1->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket1); // reload the links - - // Ticket1+====>Server1,Hypervisor1,Hypervisor2 - // | - // +====>Person1,Person2 - $this->CheckFunctionalCIList($oTicket1); - $this->CheckContactList($oTicket1); - $this->assertEquals(3, $oTicket1->Get('functionalcis_list')->Count()); - $this->assertEquals(2, $oTicket1->Get('contacts_list')->Count()); - - // Ticket2+---->Server2 (manual) - $oTicket2 = $this->CreateTicket(2); - $this->AddCIToTicket($oServer2, $oTicket2, 'manual'); - $this->AddCIToTicket($oHypervisor3, $oTicket2, 'manual'); - $oTicket2->DBUpdate(); // trigger the impact update - $this->ReloadObject($oTicket2); // reload the links - - // Ticket2+====>Farm,Hypervisor2,VM1,VM2,Server2 - // | - // +====>Person2 - $aWaitedCIList = array( - $oFarm->GetKey() => 'computed', - $oVM1->GetKey() => 'computed', - $oVM2->GetKey() => 'computed', - $oHypervisor2->GetKey() => 'computed', - $oHypervisor3->GetKey() => 'manual', - $oServer2->GetKey() => 'manual'); - $this->CheckFunctionalCIList($oTicket2, $aWaitedCIList); - $this->CheckContactList($oTicket2); - $this->assertEquals(3, $oTicket2->Get('functionalcis_list')->Count()); - $this->assertEquals(1, $oTicket2->Get('contacts_list')->Count()); - - // The first ticket is not impacted - $this->debug("\nCheck that the first ticket has not changed."); - $this->ReloadObject($oTicket1); // reload the links - - // Ticket1+====>Server1,Hypervisor1,Hypervisor2 - // | - // +====>Person1,Person2 - $this->CheckFunctionalCIList($oTicket1); - $this->CheckContactList($oTicket1); - $this->assertEquals(3, $oTicket1->Get('functionalcis_list')->Count()); - $this->assertEquals(2, $oTicket1->Get('contacts_list')->Count()); - } - -} diff --git a/tests/php-unit-tests/unitary-tests/sources/Application/Status/StatusTest.php b/tests/php-unit-tests/unitary-tests/sources/Application/Status/StatusTest.php index e8a589a17..a91bc4aa2 100644 --- a/tests/php-unit-tests/unitary-tests/sources/Application/Status/StatusTest.php +++ b/tests/php-unit-tests/unitary-tests/sources/Application/Status/StatusTest.php @@ -20,9 +20,7 @@ class StatusTest extends ItopTestCase protected function GetPHPCommand() { - $this->RequireOnceItopFile('application/utils.inc.php'); - $oConfig = new Config(ITOP_DEFAULT_CONFIG_FILE); - return $oConfig->Get('php_path'); + return PHP_BINARY; } public function testStatusPageRepliesAsExpected() @@ -30,6 +28,7 @@ class StatusTest extends ItopTestCase $sPath = APPROOT.'/webservices/status.php'; $sPHP = $this->GetPHPCommand(); +echo "About to execute: $sPHP $sPath\n"; exec("$sPHP $sPath", $aOutput, $iRet); $this->assertEquals(0, $iRet, "Problem executing status page: $sPath, $iRet, aOutput:\n".var_export($aOutput, true)); diff --git a/tests/php-unit-tests/unitary-tests/tests/php-unit-tests/GivenObjectInDBTest.php b/tests/php-unit-tests/unitary-tests/tests/php-unit-tests/GivenObjectInDBTest.php new file mode 100644 index 000000000..d26397e1d --- /dev/null +++ b/tests/php-unit-tests/unitary-tests/tests/php-unit-tests/GivenObjectInDBTest.php @@ -0,0 +1,184 @@ +assertDBQueryCount(14, function() use (&$iKey) { + $iKey = $this->createObject('Organization', ['name' => 'The world company']); + }); + + $this->assertDBQueryCount(2, function() use (&$iKey) { + $iKey = $this->GivenObjectInDB('Organization', ['name' => 'The world company']); + }); + } + + public function testItShouldFillInTheOrganizationWhenOmitted() + { + $iPerson = $this->GivenObjectInDB('Person', [ + 'name' => 'Doe', + 'first_name' => 'John', + ]); + + $oPerson = MetaModel::GetObject('Person', $iPerson); + + $this->assertEquals( + $this->getTestOrgId(), + $oPerson->Get('org_id'), + "When omitted, the org_id should be set to getTestOrgId()" + ); + } + + public function testItShouldHandleLinksetToo() + { + $iPerson = $this->GivenObjectInDB('Person', [ + 'name' => 'Doe', + 'first_name' => 'John', + ]); + + $iTeam = $this->GivenObjectInDB('Team', [ + 'name' => 'The A Team', + 'persons_list' => [ + "person_id:$iPerson;role_id:1" + ], + ]); + + $oSet = new \DBObjectSet(\DBObjectSearch::FromOQL("SELECT lnkPersonToTeam AS lnk WHERE lnk.team_id = $iTeam AND lnk.person_id = $iPerson")); + $this->assertEquals(1, $oSet->Count(), "The link between the team and the person should be there"); + $oLnk = $oSet->Fetch(); + $this->assertEquals(1, $oLnk->Get('role_id'), "The role should be correctly set"); + } + + public function testItShouldFailExplicitlyWhenAnAttributeCodeIsUnknown() + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage("GivenObjectInDB('Organization'), invalid attribute code 'amen'"); + + $this->GivenObjectInDB('Organization', ['amen' => 'The world company']); + } + + public function testItShouldFailExplicitlyWhenAMandatoryAttributeIsMissing() + { + // Note : a mandatory attribute is an attribute for which the default value cannot be used by default + // because it is not nullable and the default is "null" + + $this->expectException(\Exception::class); + $this->expectExceptionMessage("GivenObjectInDB('Organization'), mandatory attribute 'name' is missing"); + + $this->GivenObjectInDB('Organization', []); + } + + /** + * @dataProvider SampleObjectsProvider + */ + public function testItShouldMakeExactSameObjectsASDBInsert($sClass, $aValues) + { + $oObjectCreatedWithCompleteStack = parent::createObject($sClass, $aValues); + + $oObjectFromDBStandard = MetaModel::GetObject($sClass, $oObjectCreatedWithCompleteStack->GetKey()); + + // Create by the mean of the efficient method + $iKey = $this->GivenObjectInDB($sClass, $aValues); + + // Check that it is readable (no exception) + $oObjectFromDBOptimized = MetaModel::GetObject($sClass, $iKey); + + // Check that an object created by the mean of the std APIs will have the same values + foreach ($aValues as $sAttCode => $value) + { + static::assertEquals( + $oObjectFromDBStandard->Get($sAttCode), + $oObjectFromDBOptimized->Get($sAttCode), + "The value of the attribute '$sAttCode' should be the same as for an object recorded with DBObject::DBInsert" + ); + } + } + + public function SampleObjectsProvider() + { + return [ + 'Organization' => [ + 'class' => 'Organization', + 'values' => [ + 'name' => 'Orga tartampion', + ] + ], + 'FAQCategory' => [ + 'class' => 'FAQCategory', + 'values' => [ + 'name' => 'FAQCategory_phpunit', + ] + ], + 'Server' => [ + 'class' => 'Server', + 'values' => [ + 'name' => 'Server tartampion', + 'org_id' => 1, + 'nb_u' => 123, + ] + ], + 'TagSetFieldDataFor_FAQ__domains' => [ + 'class' => 'TagSetFieldDataFor_FAQ__domains', + 'values' => [ + 'code' => 'tagada'.uniqid(), + 'label' => 'label for tagada'.uniqid(), + 'obj_class' => 'FAQ', + 'obj_attcode' => 'domains', + 'description' => '

tartampion

', + ] + ], + 'Hypervisor' => [ + 'class' => 'Hypervisor', + 'values' => [ + 'name' => 'Hypervisor_tartampion', + 'org_id' => 1, + 'server_id' => 1, + 'farm_id' => 0, + ] + ], + 'Rack' => [ + 'class' => 'Rack', + 'values' => [ + 'name' => "rackamuffin", + 'description' => "rackadescription", + 'org_id' => 1 + ] + ], + 'Person' => [ + 'class' => 'Person', + 'values' => [ + 'name' => 'Person_tartampion', + 'first_name' => 'Test', + 'org_id' => 1, + ] + ], + 'Farm' => [ + 'class' => 'Farm', + 'values' => [ + 'name' => 'Farm_tartampion', + 'org_id' => 1, + 'redundancy' => '1', + ] + ], + 'UserRequest' => [ + 'class' => 'UserRequest', + 'values' => [ + 'ref' => 'Ticket_tartampion', + 'title' => 'TICKET_TARTAMPION as a title', + 'description' => '

Created for unit tests.

', + 'org_id' => 1, + ] + ], + ]; + } +}