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
This commit is contained in:
Eric Espie
2024-05-28 09:22:35 +02:00
committed by Romain Quetiez
parent b8d8ec640d
commit 984f676d6e
11 changed files with 1137 additions and 1116 deletions

View File

@@ -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;
}
}

View File

@@ -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";
}
}
}
}
/**

View File

@@ -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();

View File

@@ -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.
*

View File

@@ -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'",

View File

@@ -1,102 +0,0 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use MetaModel;
use RelationGraph;
/**
* Class RelationGraphTest
*
* @package Combodo\iTop\Test\UnitTest\Core
*/
class RelationGraphTest extends ItopDataTestCase
{
const USE_TRANSACTION = false;
protected function setUp(): void
{
parent::setUp();
}
public function ComputeRelatedObjectsProvider()
{
return array(
'Server::1' => 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.');
}
}
}

View File

@@ -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'],

View File

@@ -0,0 +1,530 @@
<?php
// Copyright (c) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
//
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(<<<EOF
Hypervisor_1 -> 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(<<<EOF
Hypervisor_1 -> 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(<<<EOF
Hypervisor_1 -> 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(<<<EOF
Hypervisor_1 -> 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(<<<EOF
Hypervisor_1 -> 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(<<<DOT
Hypervisor_1 -> 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(<<<DOT
Hypervisor_1 -> 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(<<<EOF
Hypervisor_1 -> 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(<<<EOF
Hypervisor_1 -> 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(<<<DOT
Hypervisor_1 -> 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(<<<DOT
Hypervisor_1 -> 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(<<<DOT
Hypervisor_1 -> 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(<<<DOT
Hypervisor_1 <-> 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(<<<DOT
Hypervisor_1 -> 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();
}
}

View File

@@ -1,922 +0,0 @@
<?php
// Copyright (c) 2010-2024 Combodo SAS
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
//
/**
* 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;
/**
* <pre>
* Given:
*
* Server1+---->Hypervisor1+---->Person1
*
* Ticket+---->Server1 (manual)
*
* Result:
*
* Ticket+====>Server1,Hypervisor1
* |
* +====>Person1
* </pre>
*
* @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());
}
/**
* <pre>
* Given:
*
* Server1+---->Hypervisor1+---->Person1
*
* Ticket+---->Server1 (manual)
*
* Result:
*
* Ticket+====>Server1,Hypervisor1
* |
* +====>Person1
* </pre>
*
* @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());
}
/**
* <pre>
* Given:
*
* Server1+---->Hypervisor1+---->Person1
*
* Server2 Person2
*
* Ticket+---->Server1 (manual), Server2 (computed)
*
* Result:
*
* Ticket+====>Server1,Hypervisor1
* |
* +====>Person1
* </pre>
*
* @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.
*
* <pre>
* Given:
*
* Server1+---->Hypervisor1+---->Person1
*
* Ticket+---->Server1 (manual)
*
* Result:
*
* Ticket+====>Server1,Hypervisor1
* |
* +====>Person1
*
* Then remove Server1
*
* Result:
*
* Ticket+====>
* |
* +====>
*
* </pre>
*
* @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());
}
/**
* <pre>
*
* Server2+---->Hypervisor2+---->Person2
*
* Ticket+---->(empty)
*
* Result:
*
* Ticket+====>(empty)
* </pre>
*
* @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());
}
/**
* <pre>
* Server1
*
* Server2+---->Hypervisor2+---->Person2
*
* Ticket+---->Server1 (manual)
*
* Result:
*
* Ticket+====>Server1
* </pre>
*
* @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());
}
/**
* <pre>
* +-->Person1
* |
* +
* Server1+---->Hypervisor1+--+
* |
* v
* Farm (1)
* ^
* |
* Server2+---->Hypervisor2+--+
* +
* |
* +-->Person2
*
* Ticket+---->Server1 (manual)
*
* Result:
*
* Ticket+====>Server1,Hypervisor1
* |
* +====>Person1
* </pre>
*
* @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());
}
/**
* <pre>
* +-->Person1
* |
* +
* Server1+---->Hypervisor1+--+
* |
* v
* Farm (1)
* ^
* |
* Server2+---->Hypervisor2+--+
* +
* |
* +-->Person2
*
* Ticket+---->Server1 (manual), Hypervisor2 (manual)
*
* Result:
*
* Ticket+====>Server1,Hypervisor1,Farm,Hypervisor2
* |
* +====>Person1,Person2
* </pre>
*
* @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());
}
/**
* <pre>
* +-->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
* </pre>
*
* @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());
}
/**
* <pre>
* +-->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
* </pre>
*
* @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());
}
/**
* <pre>
* +-->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)
* </pre>
*
* @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());
}
/**
* <pre>
* +-->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)
* </pre>
*
* @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());
}
/**
* <pre>
* +-->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
* </pre>
*
* @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());
}
/**
* <pre>
* +-->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
* </pre>
*
* @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());
}
/**
* <pre>
* +-->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
* </pre>
*
* @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());
}
}

View File

@@ -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));

View File

@@ -0,0 +1,184 @@
<?php
namespace Combodo\iTop\Test\UnitTest;
use CMDBSource;
use MetaModel;
/**
* @covers ItopDataTestCase::GivenObjectInDB
*/
class GivenObjectInDBTest extends ItopDataTestCase
{
const CREATE_TEST_ORG = true;
public function testItShouldRelyOnFewerQueriesAsComparedToDBInsert()
{
$this->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' => '<p>tartampion</p>',
]
],
'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' => '<p>Created for unit tests.</p>',
'org_id' => 1,
]
],
];
}
}