RequireOnceItopFile('setup/modelfactory.class.inc.php'); } /** * @param $sInitialXML * * @return \ModelFactory * @throws \ReflectionException */ protected function MakeVanillaModelFactory($sInitialXML): ModelFactory { /* @var MFDocument $oFactoryRoot */ $oFactory = new ModelFactory([]); $oInitialDocument = new MFDocument(); $oInitialDocument->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 ]; $aDeltas['_delta="define_and_must_exits"'] = [ 'sInitialXML' => << XML , 'sDeltaXML' => <<