|
|
@@ -0,0 +1,290 @@
|
|
|
+<?php
|
|
|
+declare(strict_types=1);
|
|
|
+
|
|
|
+namespace App\Tests\Unit\Service\Cron\Job;
|
|
|
+
|
|
|
+use App\Service\Cron\Job\CleanDb;
|
|
|
+use App\Service\Cron\UI\CronUIInterface;
|
|
|
+use App\Service\Utils\DatesUtils;
|
|
|
+use Doctrine\DBAL\Connection;
|
|
|
+use Doctrine\DBAL\Statement;
|
|
|
+use PHPUnit\Framework\MockObject\MockObject;
|
|
|
+use PHPUnit\Framework\TestCase;
|
|
|
+use Psr\Log\LoggerInterface;
|
|
|
+
|
|
|
+class TestableCleanDb extends CleanDb {
|
|
|
+ public function purgeDb(bool $commit = true): void {
|
|
|
+ parent::purgeDb($commit);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function purgeAuditTables(\DateTime $maxDate): int {
|
|
|
+ return parent::purgeAuditTables($maxDate);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function purgeMessages(\DateTime $maxDate): int {
|
|
|
+ return parent::purgeMessages($maxDate);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function purgeNotifications(\DateTime $maxDate): int {
|
|
|
+ return parent::purgeNotifications($maxDate);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+class CleanDbTest extends TestCase
|
|
|
+{
|
|
|
+ private CronUIInterface|MockObject $ui;
|
|
|
+ private MockObject|LoggerInterface $logger;
|
|
|
+ private Connection|MockObject $connection;
|
|
|
+
|
|
|
+ public function setUp(): void
|
|
|
+ {
|
|
|
+ $this->ui = $this->getMockBuilder(CronUIInterface::class)->disableOriginalConstructor()->getMock();
|
|
|
+ $this->logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
|
|
|
+
|
|
|
+ $this->connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
|
|
|
+ }
|
|
|
+
|
|
|
+ private function getMockFor(string $method): MockObject | TestableCleanDb {
|
|
|
+ $cleanDb = $this->getMockBuilder(TestableCleanDb::class)
|
|
|
+ ->setConstructorArgs([$this->connection])
|
|
|
+ ->setMethodsExcept([$method, 'setUI', 'setLoggerInterface'])
|
|
|
+ ->getMock();
|
|
|
+ $cleanDb->setUI($this->ui);
|
|
|
+ $cleanDb->setLoggerInterface($this->logger);
|
|
|
+
|
|
|
+ return $cleanDb;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testPreview(): void
|
|
|
+ {
|
|
|
+ $cleanDb = $this->getMockFor('preview');
|
|
|
+
|
|
|
+ $cleanDb->expects(self::once())->method('purgeDb')->with(false);
|
|
|
+
|
|
|
+ $cleanDb->preview();
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testExecute(): void
|
|
|
+ {
|
|
|
+ $cleanDb = $this->getMockFor('execute');
|
|
|
+
|
|
|
+ $cleanDb->expects(self::once())->method('purgeDb');
|
|
|
+
|
|
|
+ $cleanDb->execute();
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testPurgeDb(): void {
|
|
|
+ DatesUtils::setFakeDatetime('2022-01-08 00:00:00');
|
|
|
+
|
|
|
+ $maxDate = DatesUtils::new();
|
|
|
+ $maxDate->sub(new \DateInterval('P60D'));
|
|
|
+
|
|
|
+ $maxDateAudit = DatesUtils::new();
|
|
|
+ $maxDateAudit->sub(new \DateInterval('P180D'));
|
|
|
+
|
|
|
+ $cleanDb = $this->getMockFor('purgeDb');
|
|
|
+
|
|
|
+
|
|
|
+ $this->connection->expects($this->once())->method('beginTransaction');
|
|
|
+ $this->connection->expects($this->once())->method('setAutoCommit')->with(false);
|
|
|
+ $this->connection->expects($this->once())->method('commit');
|
|
|
+ $this->connection->expects($this->never())->method('rollback');
|
|
|
+
|
|
|
+ $cleanDb->expects(self::once())->method('purgeAuditTables')->with($maxDateAudit)->willReturn(100);
|
|
|
+ $cleanDb->expects(self::once())->method('purgeMessages')->with($maxDate)->willReturn(101);
|
|
|
+ $cleanDb->expects(self::once())->method('purgeNotifications')->with($maxDate)->willReturn(102);
|
|
|
+
|
|
|
+ $this->logger->expects(self::once())->method('info')->with('DB purged - 303 records permanently deleted');
|
|
|
+
|
|
|
+ $cleanDb->purgeDb();
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testPurgeDbNoCommit(): void {
|
|
|
+ DatesUtils::setFakeDatetime('2022-01-08 00:00:00');
|
|
|
+
|
|
|
+ $maxDate = DatesUtils::new();
|
|
|
+ $maxDate->sub(new \DateInterval('P60D'));
|
|
|
+
|
|
|
+ $maxDateAudit = DatesUtils::new();
|
|
|
+ $maxDateAudit->sub(new \DateInterval('P180D'));
|
|
|
+
|
|
|
+ $cleanDb = $this->getMockFor('purgeDb');
|
|
|
+
|
|
|
+ $this->connection->expects($this->once())->method('beginTransaction');
|
|
|
+ $this->connection->expects($this->once())->method('setAutoCommit')->with(false);
|
|
|
+ $this->connection->expects($this->never())->method('commit');
|
|
|
+ $this->connection->expects($this->once())->method('rollback');
|
|
|
+
|
|
|
+ $cleanDb->expects(self::once())->method('purgeAuditTables')->with($maxDateAudit)->willReturn(100);
|
|
|
+ $cleanDb->expects(self::once())->method('purgeMessages')->with($maxDate)->willReturn(101);
|
|
|
+ $cleanDb->expects(self::once())->method('purgeNotifications')->with($maxDate)->willReturn(102);
|
|
|
+
|
|
|
+ $this->ui->expects(self::once())->method('print')->with('DB purged - 303 records would be permanently deleted');
|
|
|
+
|
|
|
+ $cleanDb->purgeDb(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testPurgeDbWithError(): void {
|
|
|
+ DatesUtils::setFakeDatetime('2022-01-08 00:00:00');
|
|
|
+
|
|
|
+ $maxDate = DatesUtils::new();
|
|
|
+ $maxDate->sub(new \DateInterval('P60D'));
|
|
|
+
|
|
|
+ $maxDateAudit = DatesUtils::new();
|
|
|
+ $maxDateAudit->sub(new \DateInterval('P180D'));
|
|
|
+
|
|
|
+ $cleanDb = $this->getMockFor('purgeDb');
|
|
|
+
|
|
|
+ $this->connection->expects($this->once())->method('beginTransaction');
|
|
|
+ $this->connection->expects($this->once())->method('setAutoCommit')->with(false);
|
|
|
+ $this->connection->expects($this->never())->method('commit');
|
|
|
+ $this->connection->expects($this->once())->method('rollback');
|
|
|
+
|
|
|
+ $cleanDb->expects(self::once())->method('purgeAuditTables')->with($maxDateAudit)->willThrowException(new \Exception('Error'));
|
|
|
+
|
|
|
+ $this->expectException(\Exception::class);
|
|
|
+
|
|
|
+ $cleanDb->purgeDb(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testPurgeAuditTables(): void {
|
|
|
+ $maxDateAudit = DatesUtils::new('2022-06-30 00:00:00');
|
|
|
+ $maxDateAudit->sub(new \DateInterval('P180D'));
|
|
|
+
|
|
|
+ $cleanDb = $this->getMockFor('purgeAuditTables');
|
|
|
+
|
|
|
+ $schemaManager = $this->getMockBuilder(\Doctrine\DBAL\Schema\AbstractSchemaManager::class)->disableOriginalConstructor()->getMock();
|
|
|
+ $this->connection->method('getSchemaManager')->willReturn($schemaManager);
|
|
|
+
|
|
|
+ $schemaManager->method('listTableNames')->willReturn([
|
|
|
+ 'table1',
|
|
|
+ 'Audit_table1',
|
|
|
+ 'table2',
|
|
|
+ 'Audit_table2',
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $stmt1 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
|
|
|
+ $stmt2 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
|
|
|
+
|
|
|
+ $this->connection
|
|
|
+ ->expects(self::exactly(2))
|
|
|
+ ->method('prepare')
|
|
|
+ ->willReturnMap([
|
|
|
+ [
|
|
|
+ "DELETE a, r
|
|
|
+ FROM opentalent.Audit_table1 a
|
|
|
+ INNER JOIN opentalent.revisions r ON r.id = a.rev
|
|
|
+ WHERE r.timestamp < :maxDate;",
|
|
|
+ $stmt1
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ "DELETE a, r
|
|
|
+ FROM opentalent.Audit_table2 a
|
|
|
+ INNER JOIN opentalent.revisions r ON r.id = a.rev
|
|
|
+ WHERE r.timestamp < :maxDate;",
|
|
|
+ $stmt2
|
|
|
+ ]
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $stmt1
|
|
|
+ ->expects(self::once())
|
|
|
+ ->method('executeStatement')
|
|
|
+ ->with(['maxDate' => '2022-01-01'])
|
|
|
+ ->willReturn(100);
|
|
|
+
|
|
|
+ $stmt2
|
|
|
+ ->expects(self::once())
|
|
|
+ ->method('executeStatement')
|
|
|
+ ->with(['maxDate' => '2022-01-01'])
|
|
|
+ ->willReturn(100);
|
|
|
+
|
|
|
+ $this->assertEquals(200, $cleanDb->purgeAuditTables($maxDateAudit));
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testPurgeMessages(): void {
|
|
|
+ $maxDate = DatesUtils::new('2022-03-02');
|
|
|
+ $maxDate->sub(new \DateInterval('P60D'));
|
|
|
+
|
|
|
+ $cleanDb = $this->getMockFor('purgeMessages');
|
|
|
+
|
|
|
+ $stmt1 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
|
|
|
+ $stmt2 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
|
|
|
+
|
|
|
+ $this->connection
|
|
|
+ ->expects(self::exactly(2))
|
|
|
+ ->method('prepare')
|
|
|
+ ->willReturnMap([
|
|
|
+ [
|
|
|
+ "DELETE r
|
|
|
+ FROM opentalent.Message m
|
|
|
+ inner join opentalent.ReportMessage r on r.message_id = m.id
|
|
|
+ where (m.dateSent < :maxDate or (m.dateSent is null and m.createDate < :maxDate)) and m.isSystem = true and m.id > 0;",
|
|
|
+ $stmt1
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ "DELETE
|
|
|
+ FROM opentalent.Message
|
|
|
+ where (dateSent < :maxDate or (dateSent is null and createDate < :maxDate)) and isSystem = true and id > 0;",
|
|
|
+ $stmt2
|
|
|
+ ]
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $stmt1
|
|
|
+ ->expects(self::once())
|
|
|
+ ->method('executeStatement')
|
|
|
+ ->with(['maxDate' => '2022-01-01'])
|
|
|
+ ->willReturn(100);
|
|
|
+
|
|
|
+ $stmt2
|
|
|
+ ->expects(self::once())
|
|
|
+ ->method('executeStatement')
|
|
|
+ ->with(['maxDate' => '2022-01-01'])
|
|
|
+ ->willReturn(100);
|
|
|
+
|
|
|
+ $this->assertEquals(200, $cleanDb->purgeMessages($maxDate));
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testPurgeNotifications(): void {
|
|
|
+ $maxDate = DatesUtils::new('2022-03-02');
|
|
|
+ $maxDate->sub(new \DateInterval('P60D'));
|
|
|
+
|
|
|
+ $cleanDb = $this->getMockFor('purgeNotifications');
|
|
|
+
|
|
|
+ $stmt1 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
|
|
|
+ $stmt2 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
|
|
|
+
|
|
|
+ $this->connection
|
|
|
+ ->expects(self::exactly(2))
|
|
|
+ ->method('prepare')
|
|
|
+ ->willReturnMap([
|
|
|
+ [
|
|
|
+ "DELETE u
|
|
|
+ FROM opentalent.Information i
|
|
|
+ inner join opentalent.NotificationUser u on u.notification_id = i.id
|
|
|
+ where i.createDate < :maxDate and i.discr = 'notification';",
|
|
|
+ $stmt1
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ "DELETE
|
|
|
+ FROM opentalent.Information
|
|
|
+ where createDate < :maxDate and discr = 'notification';",
|
|
|
+ $stmt2
|
|
|
+ ]
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $stmt1
|
|
|
+ ->expects(self::once())
|
|
|
+ ->method('executeStatement')
|
|
|
+ ->with(['maxDate' => '2022-01-01'])
|
|
|
+ ->willReturn(100);
|
|
|
+
|
|
|
+ $stmt2
|
|
|
+ ->expects(self::once())
|
|
|
+ ->method('executeStatement')
|
|
|
+ ->with(['maxDate' => '2022-01-01'])
|
|
|
+ ->willReturn(100);
|
|
|
+
|
|
|
+ $this->assertEquals(200, $cleanDb->purgeNotifications($maxDate));
|
|
|
+ }
|
|
|
+}
|