From cd010afb48c7a8601ebfc04bbfc4427fc5d9ea80 Mon Sep 17 00:00:00 2001 From: Romain Quetiez Date: Tue, 8 Nov 2022 19:43:07 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B05704=20-=20Unit=20tests=20on=20XML=20ass?= =?UTF-8?q?embly=20(#329)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add a complete test suite for XML assembly * Add a complete test suite for XML assembly * Dispatched the test of GetDelta into real unit tests * Add test for GetDelta on a rename operation * Add comments on a weird case and a case on rename * Update XML version after rebase from develop to support/2.7 * Fix phpdoc about coverage * Remove ModelFactory::GetRootDirs and ItopTestCase::RecurseRmDir+CreateTmpDir+RecurseMkDir+RecurseCopy, that were meant to be introduced in iTop 3.0 and have been copied here by mistake, when rebasing the branch from develop to 2.7.0 * Update test/ItopTestCase.php Co-authored-by: Molkobain * Update test/setup/ModelFactoryTest.php Co-authored-by: Molkobain * Update test/ItopTestCase.php Co-authored-by: Molkobain Co-authored-by: Pierre Goiffon Co-authored-by: Molkobain --- setup/modelfactory.class.inc.php | 156 ---- test/ItopTestCase.php | 36 + test/setup/ModelFactoryTest.php | 1269 ++++++++++++++++++++++++++++++ 3 files changed, 1305 insertions(+), 156 deletions(-) create mode 100644 test/setup/ModelFactoryTest.php diff --git a/setup/modelfactory.class.inc.php b/setup/modelfactory.class.inc.php index 123e5cca3..c9d92e41c 100644 --- a/setup/modelfactory.class.inc.php +++ b/setup/modelfactory.class.inc.php @@ -1658,162 +1658,6 @@ EOF return $aResult; } - public function TestAlteration() - { - $sDOMOriginal = 'undefined'; - $sDOMModified = 'undefined'; - $sDOMRebuilt = 'undefined'; - $sDeltaXML = 'undefined'; - try - { - $sHeader = ''; - $sOriginalXML = - << - - Text - - D1 - D2 - - - - first a - - - first a - blah - - -EOF; - - $this->oDOMDocument = new MFDocument(); - $this->oDOMDocument->loadXML($sOriginalXML); - - // DOM Get the original values, then modify its contents by the mean of the API - $oRoot = $this->GetNodes('//itop_design')->item(0); - //$oRoot->Dump(); - $sDOMOriginal = $oRoot->Dump(true); - - $oNode = $oRoot->GetNodes('a/b')->item(0); - $oNew = $this->oDOMDocument->CreateElement('b', 'New text'); - $oNode->parentNode->RedefineChildNode($oNew); - - $oNode = $oRoot->GetNodes('a/c')->item(0); - $oNewC = $this->oDOMDocument->CreateElement('c'); - $oNewC->setAttribute('id', '1'); - $oNode->parentNode->RedefineChildNode($oNewC); - - $oNewC->appendChild($this->oDOMDocument->CreateElement('d', 'x')); - $oNewC->appendChild($this->oDOMDocument->CreateElement('d', 'y')); - $oNewC->appendChild($this->oDOMDocument->CreateElement('d', 'z')); - $oNamedNode = $this->oDOMDocument->CreateElement('z'); - $oNamedNode->setAttribute('id', 'abc'); - $oNewC->AddChildNode($oNamedNode); - $oNewC->AddChildNode($this->oDOMDocument->CreateElement('r', 'to be replaced')); - - // Alter this "modified node", no flag should be set in its subnodes - $oNewC->Rename('blah'); - $oNewC->Rename('foo'); - $oNewC->AddChildNode($this->oDOMDocument->CreateElement('y', '(no flag)')); - $oNewC->AddChildNode($this->oDOMDocument->CreateElement('x', 'To delete programmatically')); - $oSubNode = $oNewC->GetUniqueElement('z'); - $oSubNode->Rename('abcdef'); - $oSubNode = $oNewC->GetUniqueElement('x'); - $oSubNode->Delete(); - $oNewC->RedefineChildNode($this->oDOMDocument->CreateElement('r', 'replacement')); - - $oNode = $oRoot->GetNodes("//a[@id='second a']")->item(0); - $oNode->Rename('el 2o A'); - $oNode->Rename('el secundo A'); - $oNew = $this->oDOMDocument->CreateElement('e', 'Something new here'); - $oNode->AddChildNode($oNew); - $oNewA = $this->oDOMDocument->CreateElement('a'); - $oNewA->setAttribute('id', 'new a'); - $oNode->AddChildNode($oNewA); - $oSubnode = $this->oDOMDocument->CreateElement('parent', 'el secundo A'); - $oSubnode->setAttribute('id', 'to be changed'); - $oNewA->AddChildNode($oSubnode); - $oNewA->AddChildNode($this->oDOMDocument->CreateElement('f', 'Welcome to the newcomer')); - $oNewA->AddChildNode($this->oDOMDocument->CreateElement('x', 'To delete programmatically')); - - // Alter this "new a", as it is new, no flag should be set - $oNewA->Rename('new_a'); - $oSubNode = $oNewA->GetUniqueElement('parent'); - $oSubNode->Rename('alter ego'); - $oNewA->RedefineChildNode($this->oDOMDocument->CreateElement('f', 'dummy data')); - $oSubNode = $oNewA->GetUniqueElement('x'); - $oSubNode->Delete(); - - $oNode = $oRoot->GetNodes("//a[@id='third a']")->item(0); - $oNode->Delete(); - - //$oRoot->Dump(); - $sDOMModified = $oRoot->Dump(true); - - // Compute the delta - // - $sDeltaXML = $this->GetDelta(); - //echo "
\n";
-			//echo htmlentities($sDeltaXML);
-			//echo "
\n"; - - // Reiterating - try to remake the DOM by applying the computed delta - // - $this->oDOMDocument = new MFDocument(); - $this->oDOMDocument->loadXML($sOriginalXML); - $oRoot = $this->GetNodes('//itop_design')->item(0); - //$oRoot->Dump(); - echo "

Rebuild the DOM - Delta applied...

\n"; - $oDeltaDoc = new MFDocument(); - $oDeltaDoc->loadXML($sDeltaXML); - - //$oDeltaDoc->Dump(); - //$this->oDOMDocument->Dump(); - $oDeltaRoot = $oDeltaDoc->childNodes->item(0); - $this->LoadDelta($oDeltaRoot, $this->oDOMDocument); - //$oRoot->Dump(); - $sDOMRebuilt = $oRoot->Dump(true); - } - catch (Exception $e) - { - echo "

Exception: ".$e->getMessage()."

\n"; - echo "
\n";
-			debug_print_backtrace();
-			echo "
\n"; - } - $sArrStyle = "font-size: 40;"; - echo "\n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo "
\n"; - echo "

DOM - Original values

\n"; - echo "
".htmlentities($sDOMOriginal)."
\n"; - echo "
⇒ ⇒ ⇒
\n"; - echo "

DOM - Altered with various changes

\n"; - echo "
".htmlentities($sDOMModified)."
\n"; - echo "
\n"; - echo "

DOM - Rebuilt from the Delta

\n"; - echo "
".htmlentities($sDOMRebuilt)."
\n"; - echo "
\n"; - echo "

Delta (Computed by ModelFactory)

\n"; - echo "
".htmlentities($sDeltaXML)."
\n"; - echo "
⇒ ⇒ ⇒
\n"; - } // TEST ! - - /** * Extracts some nodes from the DOM * diff --git a/test/ItopTestCase.php b/test/ItopTestCase.php index 16d403cfe..18c6c6a68 100644 --- a/test/ItopTestCase.php +++ b/test/ItopTestCase.php @@ -136,4 +136,40 @@ class ItopTestCase extends TestCase return $method->invokeArgs($oObject, $aArgs); } + + + /** + * @param object $oObject + * @param string $sProperty + * + * @return mixed property + * + * @throws \ReflectionException + * @since 2.7.8 3.0.3 3.1.0 + */ + public function GetNonPublicProperty(object $oObject, string $sProperty) + { + $class = new \ReflectionClass(get_class($oObject)); + $property = $class->getProperty($sProperty); + $property->setAccessible(true); + + return $property->getValue($oObject); + } + + /** + * @param object $oObject + * @param string $sProperty + * @param $value + * + * @throws \ReflectionException + * @since 2.7.8 3.0.3 3.1.0 + */ + public function SetNonPublicProperty(object $oObject, string $sProperty, $value) + { + $class = new \ReflectionClass(get_class($oObject)); + $property = $class->getProperty($sProperty); + $property->setAccessible(true); + + $property->setValue($oObject, $value); + } } \ No newline at end of file diff --git a/test/setup/ModelFactoryTest.php b/test/setup/ModelFactoryTest.php new file mode 100644 index 000000000..9c92be468 --- /dev/null +++ b/test/setup/ModelFactoryTest.php @@ -0,0 +1,1269 @@ +preserveWhiteSpace = false; + $oInitialDocument->loadXML($sInitialXML); + + $this->SetNonPublicProperty($oFactory, 'oDOMDocument', $oInitialDocument); + $this->SetNonPublicProperty($oFactory, 'oRoot', $oInitialDocument->firstChild); + + return $oFactory; + } + + /** + * @param $sXML + * + * @return false|string + */ + protected function CanonicalizeXML($sXML) + { + // Canonicalize the expected XML (to cope with indentation) + $oExpectedDocument = new DOMDocument(); + $oExpectedDocument->preserveWhiteSpace = false; + $oExpectedDocument->loadXML($sXML); + $oExpectedDocument->formatOutput = true; + return $oExpectedDocument->saveXML($oExpectedDocument->firstChild); + } + + /** + * @param $sExpected + * @param $sActual + */ + protected function AssertEqualiTopXML($sExpected, $sActual) + { + // Note: assertEquals reports the differences in a diff which is easier to interpret (in PHPStorm) + // as compared to the report given by assertEqualXMLStructure + static::assertEquals($this->CanonicalizeXML($sExpected), $this->CanonicalizeXML($sActual)); + } + + /** + * Assertion ignoring some of the unexpected decoration brought by DOM Elements. + */ + protected function AssertEqualModels(string $sExpectedXML, ModelFactory $oFactory) + { + return $this->AssertEqualiTopXML($sExpectedXML, $oFactory->Dump(null, true)); + } + + /** + * @dataProvider providerDeltas + * @covers ModelFactory::LoadDelta + * @covers ModelFactory::ApplyChanges + */ + public function testAlterationByXMLDelta($sInitialXML, $sDeltaXML, $sExpectedXML) + { + $oFactory = $this->MakeVanillaModelFactory($sInitialXML); + $oFactoryRoot = $this->GetNonPublicProperty($oFactory, 'oDOMDocument'); + + $oDocument = new MFDocument(); + $oDocument->loadXML($sDeltaXML); + /* @var MFElement $oDeltaRoot */ + $oDeltaRoot = $oDocument->firstChild; + + if ($sExpectedXML === null) { + $this->expectException('Exception'); + } + $oFactory->LoadDelta($oDeltaRoot, $oFactoryRoot); + $oFactory->ApplyChanges(); + + $this->AssertEqualModels($sExpectedXML, $oFactory); + } + + /** + * @return array + */ + public function providerDeltas() + { + // Basic (structure) + $aDeltas['No change at all'] = [ + 'sInitialXML' => << + + +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << + + +XML, + ]; + $aDeltas['No change at all - mini delta'] = [ + 'sInitialXML' => << + + +XML, + 'sDeltaXML' => << +XML, + 'sExpectedXML' => << + + +XML, + ]; + $aDeltas['_delta="merge" implicit'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << + + +XML, + ]; + $aDeltas['_delta="merge" explicit'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << + + +XML, + ]; + $aDeltas['_delta="merge" does not handle data'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + Ghost busters!!! + +XML, + 'sExpectedXML' => << + + +XML, + ]; + $aDeltas['_delta="merge" recursively'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + + + + + + +XML, + 'sExpectedXML' => << + + + + + + +XML, + ]; + + // Define or redefine + $aDeltas['_delta="define" without id'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << + + +XML, + ]; + $aDeltas['_delta="define" with id'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << + + +XML, + ]; + $aDeltas['_delta="define" but existing node'] = [ + 'sInitialXML' => << + + +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => null, + ]; + $aDeltas['_delta="redefine" without id'] = [ + 'sInitialXML' => << + Initial BB + +XML, + 'sDeltaXML' => << + Gainsbourg + +XML, + 'sExpectedXML' => << + Gainsbourg + +XML, + ]; + $aDeltas['_delta="redefine" with id'] = [ + 'sInitialXML' => << + Initial BB + +XML, + 'sDeltaXML' => << + Gainsbourg + +XML, + 'sExpectedXML' => << + Gainsbourg + +XML, + ]; + $aDeltas['_delta="redefine" but missing node'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + Gainsbourg + +XML, + 'sExpectedXML' => null, + ]; + $aDeltas['_delta="force" without id + missing node'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + Hulk + +XML, + 'sExpectedXML' => << + Hulk + +XML, + ]; + $aDeltas['_delta="force" with id + missing node'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + Hulk + +XML, + 'sExpectedXML' => << + Hulk + +XML, + ]; + $aDeltas['_delta="force" without id + existing node'] = [ + 'sInitialXML' => << + Initial BB + +XML, + 'sDeltaXML' => << + Gainsbourg + +XML, + 'sExpectedXML' => << + Gainsbourg + +XML, + ]; + $aDeltas['_delta="force" with id + existing node'] = [ + 'sInitialXML' => << + Initial BB + +XML, + 'sDeltaXML' => << + Gainsbourg + +XML, + 'sExpectedXML' => << + Gainsbourg + +XML, + ]; + + // Rename + $aDeltas['rename'] = [ + 'sInitialXML' => << + Kryptonite + +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << + Kryptonite + +XML, + ]; + $aDeltas['rename but missing node NOT INTUITIVE!!!'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << + + +XML, + ]; + + // Delete + $aDeltas['_delta="delete" without id'] = [ + 'sInitialXML' => << + Initial BB + +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << +XML, + ]; + $aDeltas['_delta="delete" with id'] = [ + 'sInitialXML' => << + Initial BB + +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << +XML, + ]; + $aDeltas['_delta="delete" but missing node'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => null, + ]; + $aDeltas['_delta="delete_if_exists" without id + existing node'] = [ + 'sInitialXML' => << + Initial BB + +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << +XML, + ]; + $aDeltas['_delta="delete_if_exists" with id + existing node'] = [ + 'sInitialXML' => << + Initial BB + +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << +XML, + ]; + $aDeltas['_delta="delete_if_exists" without id + missing node'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << +XML, + ]; + $aDeltas['_delta="delete_if_exists" with id + missing node'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + + +XML, + 'sExpectedXML' => << +XML, + ]; + + // Conditionals + $aDeltas['_delta="must_exist"'] = [ + 'sInitialXML' => << + + +XML, + 'sDeltaXML' => << + + + + +XML, + 'sExpectedXML' => << + + + + +XML, + ]; + $aDeltas['_delta="must_exist on missing node"'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + + + + +XML, + 'sExpectedXML' => null, + ]; + $aDeltas['_delta="if_exists on missing node"'] = [ + 'sInitialXML' => << + +XML, + 'sDeltaXML' => << + + + + +XML, + 'sExpectedXML' => << + +XML, + ]; + $aDeltas['_delta="if_exists on existing node"'] = [ + 'sInitialXML' => << + + +XML, + 'sDeltaXML' => << + + + + +XML, + 'sExpectedXML' => << + + + + +XML, + ]; + $aDeltas['_delta="define_if_not_exists on missing node"'] = [ + 'sInitialXML' => << +XML, + 'sDeltaXML' => << + The incredible Hulk + +XML, + 'sExpectedXML' => << + The incredible Hulk + +XML, + ]; + $aDeltas['_delta="define_if_not_exists on existing node"'] = [ + 'sInitialXML' => << + Luke Banner + +XML, + 'sDeltaXML' => << + The incredible Hulk + +XML, + 'sExpectedXML' => << + Luke Banner + +XML, + ]; + + return $aDeltas; + } + + /** + * @dataProvider providerAlterationAPIs + * @covers \ModelFactory::GetDelta + * @covers \MFElement::AddChildNode + * @covers \MFElement::RedefineChildNode + * @covers \MFElement::SetChildNode + * @covers \MFElement::Delete + */ + public function testAlterationsByAPIs($sInitialXML, $sOperation, $sExpectedXML) + { + $oFactory = $this->MakeVanillaModelFactory($sInitialXML); + + if ($sExpectedXML === null) { + $this->expectException('Exception'); + } + switch ($sOperation) { + case 'Delete': + /* @var MFElement $oTargetNode */ + $oTargetNode = $oFactory->GetNodes('//target_tag', null, false)->item(0); + $oTargetNode->Delete(); + break; + case 'AddChildNodeToContainer': + $oContainerNode = $oFactory->GetNodes('//container_tag', null, false)->item(0); + + $oFactoryRoot = $this->GetNonPublicProperty($oFactory, 'oDOMDocument'); + $oChild = $oFactoryRoot->CreateElement('target_tag', 'Hello, I\'m a newly added node'); + + /* @var MFElement $oContainerNode */ + $oContainerNode->AddChildNode($oChild); + break; + + case 'RedefineChildNodeToContainer': + $oContainerNode = $oFactory->GetNodes('//container_tag', null, false)->item(0); + + $oFactoryRoot = $this->GetNonPublicProperty($oFactory, 'oDOMDocument'); + $oChild = $oFactoryRoot->CreateElement('target_tag', 'Hello, I\'m replacing the previous node'); + + /* @var MFElement $oContainerNode */ + $oContainerNode->RedefineChildNode($oChild); + break; + + case 'SetChildNodeToContainer': + $oContainerNode = $oFactory->GetNodes('//container_tag', null, false)->item(0); + + $oFactoryRoot = $this->GetNonPublicProperty($oFactory, 'oDOMDocument'); + $oChild = $oFactoryRoot->CreateElement('target_tag', 'Hello, I\'m replacing the previous node'); + + /* @var MFElement $oContainerNode */ + $oContainerNode->SetChildNode($oChild); + break; + + default: + static::fail("Unknown operation '$sOperation'"); + } + + if ($sExpectedXML !== null) { + $this->AssertEqualModels($sExpectedXML, $oFactory); + } + } + + /** + * @return array[] + */ + public function providerAlterationAPIs() + { + define('CASE_NO_FLAG', << + + + + +XML + ); + define('CASE_ABOVE_A_FLAG', << + + + Blah + + + +XML + ); + define('CASE_IN_A_DEFINITION', << + + + Blah + + + +XML + ); + define('CASE_FLAG_ON_TARGET_define', << + + + + +XML + ); + define('CASE_FLAG_ON_TARGET_redefine', << + + + + +XML + ); + define('CASE_FLAG_ON_TARGET_needed', << + + + + +XML + ); + define('CASE_FLAG_ON_TARGET_forced', << + + + + +XML + ); + define('CASE_FLAG_ON_TARGET_removed', << + + + + +XML + ); + define('CASE_FLAG_ON_TARGET_old_id', << + + + + +XML + ); + define('CASE_MISSING_TARGET', << + + +XML + ); + $aData = [ + 'CASE_NO_FLAG Delete' => [CASE_NO_FLAG , 'Delete', << + + + + +XML + ], + 'CASE_ABOVE_A_FLAG Delete' => [CASE_ABOVE_A_FLAG , 'Delete', << + + + + +XML + ], + 'CASE_IN_A_DEFINITION Delete' => [CASE_IN_A_DEFINITION , 'Delete', << + + +XML + ], + 'CASE_FLAG_ON_TARGET_define Delete' => [CASE_FLAG_ON_TARGET_define , 'Delete', << + + +XML + ], + 'CASE_FLAG_ON_TARGET_redefine Delete' => [CASE_FLAG_ON_TARGET_redefine , 'Delete', << + + + + +XML + ], + 'CASE_FLAG_ON_TARGET_needed Delete' => [CASE_FLAG_ON_TARGET_needed , 'Delete', << + + +XML + ], + 'CASE_FLAG_ON_TARGET_forced Delete' => [CASE_FLAG_ON_TARGET_forced , 'Delete', << + + +XML + ], + 'CASE_FLAG_ON_TARGET_removed Delete' => [CASE_FLAG_ON_TARGET_removed , 'Delete', null + ], + 'CASE_FLAG_ON_TARGET_old_id Delete' => [CASE_FLAG_ON_TARGET_old_id , 'Delete', << + + + + +XML + ], + 'CASE_NO_FLAG AddChildNode' => [CASE_NO_FLAG , 'AddChildNodeToContainer', null + ], + 'CASE_ABOVE_A_FLAG AddChildNode' => [CASE_ABOVE_A_FLAG , 'AddChildNodeToContainer', null + ], + 'CASE_IN_A_DEFINITION AddChildNode' => [CASE_IN_A_DEFINITION , 'AddChildNodeToContainer', null + ], + 'CASE_FLAG_ON_TARGET_define AddChildNode' => [CASE_FLAG_ON_TARGET_define , 'AddChildNodeToContainer', null + ], + 'CASE_FLAG_ON_TARGET_redefine AddChildNode' => [CASE_FLAG_ON_TARGET_redefine , 'AddChildNodeToContainer', null + ], + 'CASE_FLAG_ON_TARGET_needed AddChildNode' => [CASE_FLAG_ON_TARGET_needed , 'AddChildNodeToContainer', null + ], + 'CASE_FLAG_ON_TARGET_forced AddChildNode' => [CASE_FLAG_ON_TARGET_forced , 'AddChildNodeToContainer', null + ], + 'CASE_FLAG_ON_TARGET_removed AddChildNode' => [CASE_FLAG_ON_TARGET_removed , 'AddChildNodeToContainer', << + + Hello, I'm a newly added node + + +XML + ], + 'CASE_FLAG_ON_TARGET_old_id AddChildNode' => [CASE_FLAG_ON_TARGET_old_id , 'AddChildNodeToContainer', null + ], + 'CASE_MISSING_TARGET AddChildNode' => [CASE_MISSING_TARGET , 'AddChildNodeToContainer', << + + Hello, I'm a newly added node + + +XML + ], + 'CASE_NO_FLAG RedefineChildNode' => [CASE_NO_FLAG , 'RedefineChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_ABOVE_A_FLAG RedefineChildNode' => [CASE_ABOVE_A_FLAG , 'RedefineChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_IN_A_DEFINITION RedefineChildNode' => [CASE_IN_A_DEFINITION , 'RedefineChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_FLAG_ON_TARGET_define RedefineChildNode' => [CASE_FLAG_ON_TARGET_define , 'RedefineChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_FLAG_ON_TARGET_redefine RedefineChildNode' => [CASE_FLAG_ON_TARGET_redefine , 'RedefineChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + // Note: buggy case ? + 'CASE_FLAG_ON_TARGET_needed RedefineChildNode' => [CASE_FLAG_ON_TARGET_needed , 'RedefineChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_FLAG_ON_TARGET_forced RedefineChildNode' => [CASE_FLAG_ON_TARGET_forced , 'RedefineChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_FLAG_ON_TARGET_removed RedefineChildNode' => [CASE_FLAG_ON_TARGET_removed , 'RedefineChildNodeToContainer', null + ], + 'CASE_FLAG_ON_TARGET_old_id RedefineChildNode' => [CASE_FLAG_ON_TARGET_old_id , 'RedefineChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_MISSING_TARGET RedefineChildNode' => [CASE_MISSING_TARGET , 'RedefineChildNodeToContainer', null + ], + 'CASE_NO_FLAG SetChildNode' => [CASE_NO_FLAG , 'SetChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_ABOVE_A_FLAG SetChildNode' => [CASE_ABOVE_A_FLAG , 'SetChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_IN_A_DEFINITION SetChildNode' => [CASE_IN_A_DEFINITION , 'SetChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_FLAG_ON_TARGET_define SetChildNode' => [CASE_FLAG_ON_TARGET_define , 'SetChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_FLAG_ON_TARGET_redefine SetChildNode' => [CASE_FLAG_ON_TARGET_redefine , 'SetChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + // Note: buggy case ? + 'CASE_FLAG_ON_TARGET_needed SetChildNode' => [CASE_FLAG_ON_TARGET_needed , 'SetChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_FLAG_ON_TARGET_forced SetChildNode' => [CASE_FLAG_ON_TARGET_forced , 'SetChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_FLAG_ON_TARGET_removed SetChildNode' => [CASE_FLAG_ON_TARGET_removed , 'SetChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_FLAG_ON_TARGET_old_id SetChildNode' => [CASE_FLAG_ON_TARGET_old_id , 'SetChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + 'CASE_MISSING_TARGET SetChildNode' => [CASE_MISSING_TARGET , 'SetChildNodeToContainer', << + + Hello, I'm replacing the previous node + + +XML + ], + ]; + return $aData; + } + + /** + * @covers \ModelFactory::LoadDelta + * @covers \ModelFactory::GetDelta + * @covers \ModelFactory::GetDeltaDocument + * @dataProvider providerGetDelta + */ + public function testGetDelta($sInitialXMLInternal, $sExpectedXMLDelta) + { + // constants aren't accessible in the data provider :( + $sExpectedXMLDelta = str_replace('##ITOP_DESIGN_LATEST_VERSION##', ITOP_DESIGN_LATEST_VERSION, $sExpectedXMLDelta); + + $oFactory = $this->MakeVanillaModelFactory($sInitialXMLInternal); + + // Get the delta back + $sNewDeltaXML = $oFactory->GetDelta(); + + static::AssertEqualiTopXML($sExpectedXMLDelta, $sNewDeltaXML); + } + + /** + * @return array[] + */ + public function providerGetDelta() + { + return [ + 'no alteration' => [ + 'sInitialXMLInternal' => << + Roger Moore + + + +XML, + // Weird, but seems ok as of now + 'sExpectedXMLDelta' => << + +XML + , + ], + '_alteration="added" singleton' => [ + 'sInitialXMLInternal' => << + + +XML, + 'sExpectedXMLDelta' => << + + + + +XML + ], + '_alteration="added" with value' => [ + 'sInitialXMLInternal' => << + Roger Moore + +XML, + 'sExpectedXMLDelta' => << + + Roger Moore + +XML + ], + '_alteration="added" with subtree' => [ + 'sInitialXMLInternal' => << + + Moore + Roger + + +XML, + 'sExpectedXMLDelta' => << + + + Moore + Roger + + +XML + ], + '_alteration="forced" singleton' => [ + 'sInitialXMLInternal' => << + + +XML, + 'sExpectedXMLDelta' => << + + + +XML + ], + '_alteration="forced" with value' => [ + 'sInitialXMLInternal' => << + Roger Moore + +XML, + 'sExpectedXMLDelta' => << + + Roger Moore + +XML + ], + '_alteration="forced" with subtree' => [ + 'sInitialXMLInternal' => << + + Moore + Roger + + +XML, + 'sExpectedXMLDelta' => << + + + Moore + Roger + + +XML + ], + '_alteration="needed" singleton' => [ + 'sInitialXMLInternal' => << + + +XML, + 'sExpectedXMLDelta' => << + + + +XML + ], + '_alteration="needed" with value' => [ + 'sInitialXMLInternal' => << + Roger Moore + +XML, + 'sExpectedXMLDelta' => << + + Roger Moore + +XML + ], + '_alteration="needed" with subtree' => [ + 'sInitialXMLInternal' => << + + Moore + Roger + + +XML, + 'sExpectedXMLDelta' => << + + + Moore + Roger + + +XML + ], + '_alteration="replaced" with value' => [ + 'sInitialXMLInternal' => << + Sean Connery + +XML, + 'sExpectedXMLDelta' => << + + Sean Connery + +XML + ], + '_alteration="replaced" with subtree' => [ + 'sInitialXMLInternal' => << + + Sean + Connery + + +XML, + 'sExpectedXMLDelta' => << + + + Sean + Connery + + +XML + ], + '_alteration="removed"' => [ + 'sInitialXMLInternal' => << + + +XML, + 'sExpectedXMLDelta' => << + + + +XML + ], + '_old_id' => [ + 'sInitialXMLInternal' => << + + +XML, + 'sExpectedXMLDelta' => << + + + +XML + ], + '_old_id with subtree' => [ + 'sInitialXMLInternal' => << + + etc. + + +XML, + 'sExpectedXMLDelta' => << + + + etc. + + +XML + ], + ]; + } +}