GetCleanupSummary(null); $this->assertIsArray($aResult, 'Expected result to be an array when input is null.'); $this->assertEmpty($aResult, 'Expected result to be empty array when input is null.'); } //--- ExecuteCleanup tests --- public function testExecuteCleanup_DeleteOneObjPerClassWithoutLimit() { $this->GivenDFRTreeInDB(<<ExecuteCleanup($aClasses); $aExpected = [ ['DFRToUpdate', 1, 0 ], ['DFRToRemoveLeaf', 0, 1 ], ['DFRRemovedCollateral', 0, 1 ], ['DFRRemovedCollateralCascade', 0, 1 ], ]; $this->AssertSummaryEquals($aExpected, $aRes); } public function testExecuteCleanup_DeleteManyObjPerClassWithoutLimit() { $this->GivenDFRTreeInDB(<<ExecuteCleanup($aClasses); $aExpected = [ ['DFRToUpdate', 3, 0 ], ['DFRToRemoveLeaf', 0, 3 ], ['DFRRemovedCollateral', 0, 3 ], ['DFRRemovedCollateralCascade', 0, 3 ], ]; $this->AssertSummaryEquals($aExpected, $aRes); } public function testExecuteCleanup_CheckSummaryIsEnrichedAfterEachPass() { $aExecutionSummary = []; $this->GivenDFRTreeInDB( <<ExecuteCleanup($aClasses); $aExpected = [ ['DFRToUpdate', 3, 0 ], ['DFRToRemoveLeaf', 0, 3 ], ['DFRRemovedCollateral', 0, 3 ], ['DFRRemovedCollateralCascade', 0, 3 ], ]; $this->AssertSummaryEquals($aExpected, $aExecutionSummary); $this->GivenDFRTreeInDB( <<ExecuteCleanup($aClasses); $aExpected = [ ['DFRToUpdate', 1, 0, 0, 4 ], ['DFRToRemoveLeaf', 0, 1, 0, 0, 4 ], ['DFRRemovedCollateral', 0, 1, 0, 0, 4 ], ['DFRRemovedCollateralCascade', 0, 1, 0, 0, 4 ], ]; $this->AssertSummaryEquals($aExpected, $aExecutionSummary); } public function testGetCleanupSummary_DeleteManyObjPerClassWithoutLimit() { $this->GivenDFRTreeInDB(<<GetCleanupSummary($aClasses); $aExpected = [ ['DFRToUpdate', 3, 0 ], ['DFRToRemoveLeaf', 0, 3 ], ['DFRRemovedCollateral', 0, 3 ], ['DFRRemovedCollateralCascade', 0, 3 ], ]; $this->AssertSummaryEquals($aExpected, $aRes); } public function testExecuteCleanup_ManualDeleteShouldFail() { $this->GivenDFRTreeInDB(<<expectException(DataFeatureRemovalException::class); $this->expectExceptionMessage('Deletion Plan cannot be executed due to issues'); $oService = new DataCleanupService(); $oService->ExecuteCleanup($aClasses); } public function testGetCleanupSummary_ManualDeleteShouldFail() { $this->GivenDFRTreeInDB(<<GetCleanupSummary($aClasses); $aExpected = [ ['DFRManual', 0, 0, 3 ], ['DFRToRemoveLeaf', 0, 2], ]; $this->AssertSummaryEquals($aExpected, $aRes); } private function AssertSummaryEquals(array $expected, $actual, $sMessage = '') { $aExpected = []; foreach ($expected as $line) { $sClass = $line[0]; $iUpdate = $line[1]; $iDelete = $line[2]; $iIssue = $line[3] ?? 0; $iTotalUpdate = $line[4] ?? $iUpdate; $iTotalDelete = $line[5] ?? $iDelete; $oCleanupSummaryEntity = new DataCleanupSummaryEntity($sClass); $oCleanupSummaryEntity->iUpdateCount = $iUpdate; $oCleanupSummaryEntity->iDeleteCount = $iDelete; $oCleanupSummaryEntity->iIssueCount = $iIssue; $oCleanupSummaryEntity->iTotalUpdateCount = $iTotalUpdate; $oCleanupSummaryEntity->iTotalDeleteCount = $iTotalDelete; $aExpected[$sClass] = $oCleanupSummaryEntity; } $this->assertEquals($aExpected, $actual, $sMessage); } public static function ExecuteCleanup_StopInProcessKeepDatabaseOk(): array { return [ 'Stop after 1' => [ 1, [ ['DFRToUpdate', 1, 0], ], ], 'Stop after 2' => [ 2, [ ['DFRToUpdate', 1, 0], ['DFRRemovedCollateralCascade', 0, 1], ], ], 'Stop after 3' => [ 3, [ ['DFRToUpdate', 1, 0], ['DFRRemovedCollateralCascade', 0, 1], ['DFRRemovedCollateral', 0, 1], ], ], 'Stop after 4' => [ 4, [ ['DFRToUpdate', 1, 0], ['DFRRemovedCollateralCascade', 0, 1], ['DFRRemovedCollateral', 0, 1], ['DFRToRemoveLeaf', 0, 1], ], ], 'Stop after 5' => [ 5, [ ['DFRToUpdate', 2, 0], ['DFRRemovedCollateralCascade', 0, 1], ['DFRRemovedCollateral', 0, 1], ['DFRToRemoveLeaf', 0, 1], ], ], ]; } /** * @dataProvider ExecuteCleanup_StopInProcessKeepDatabaseOk */ public function testExecuteCleanup_StopInProcessKeepDatabaseOk(int $iExecutionCount, array $aExpected): void { $this->GivenDFRTreeInDB(<<GivenExecutionLimits($iExecutionCount); $this->SetNonPublicProperty($oDeletionPlaService, 'oExecutionLimits', $this->oExecutionLimits); $aRes = $oDeletionPlaService->ExecuteCleanup($aClasses); $this->AssertSummaryEquals($aExpected, $aRes); } private function GivenDFRTreeInDB(string $sTree) { $aTree = explode("\n", $sTree); foreach ($aTree as $sLine) { if (trim($sLine) === "") { continue; } $this->GivenDFRTreeLineInDB($sLine); } } private array $aIdByObjectName = []; private function GivenDFRTreeLineInDB(string $sLine) { [$sLeft, $sRight] = explode('<-', $sLine); $sLeft = trim($sLeft); $iLeftId = $this->aIdByObjectName[$sLeft] ?? 0; if ($iLeftId === 0) { [$sChildClass, ] = explode('_', $sLeft, 2); $iLeftId = $this->GivenObjectInDB($sChildClass, ['name' => $sLeft]); $this->aIdByObjectName[$sLeft] = $iLeftId; } $sRight = trim($sRight); [$sChildClass, ] = explode('_', $sRight, 2); $iRightId = $this->GivenObjectInDB($sChildClass, ['name' => $sRight, 'extkey_id' => $iLeftId]); $this->aIdByObjectName[$sRight] = $iRightId; } private function GivenExecutionLimits(int $iStopAfterCallNumberReached): void { $matcher = $this->any(); $this->oExecutionLimits = $this->createMock(ExecutionLimits::class); $this->oExecutionLimits->expects($matcher) ->method('ShouldStopExecution')->willReturnCallback(function () use ($matcher, $iStopAfterCallNumberReached) { $invocationCount = $matcher->getInvocationCount(); return ($invocationCount >= $iStopAfterCallNumberReached); }); } }