CleanDbTest.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Tests\Unit\Service\Cron\Job;
  4. use App\Service\Cron\Job\CleanDb;
  5. use App\Service\Cron\UI\CronUIInterface;
  6. use App\Service\Utils\DatesUtils;
  7. use Doctrine\DBAL\Connection;
  8. use Doctrine\DBAL\Statement;
  9. use PHPUnit\Framework\MockObject\MockObject;
  10. use PHPUnit\Framework\TestCase;
  11. use Psr\Log\LoggerInterface;
  12. class TestableCleanDb extends CleanDb {
  13. public function purgeDb(bool $commit = true): void {
  14. parent::purgeDb($commit);
  15. }
  16. public function purgeAuditTables(\DateTime $maxDate): int {
  17. return parent::purgeAuditTables($maxDate);
  18. }
  19. public function purgeMessages(\DateTime $maxDate): int {
  20. return parent::purgeMessages($maxDate);
  21. }
  22. public function purgeNotifications(\DateTime $maxDate): int {
  23. return parent::purgeNotifications($maxDate);
  24. }
  25. }
  26. class CleanDbTest extends TestCase
  27. {
  28. private CronUIInterface|MockObject $ui;
  29. private MockObject|LoggerInterface $logger;
  30. private Connection|MockObject $connection;
  31. public function setUp(): void
  32. {
  33. $this->ui = $this->getMockBuilder(CronUIInterface::class)->disableOriginalConstructor()->getMock();
  34. $this->logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
  35. $this->connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
  36. }
  37. private function getMockFor(string $method): MockObject | TestableCleanDb {
  38. $cleanDb = $this->getMockBuilder(TestableCleanDb::class)
  39. ->setConstructorArgs([$this->connection])
  40. ->setMethodsExcept([$method, 'setUI', 'setLoggerInterface'])
  41. ->getMock();
  42. $cleanDb->setUI($this->ui);
  43. $cleanDb->setLoggerInterface($this->logger);
  44. return $cleanDb;
  45. }
  46. public function testPreview(): void
  47. {
  48. $cleanDb = $this->getMockFor('preview');
  49. $cleanDb->expects(self::once())->method('purgeDb')->with(false);
  50. $cleanDb->preview();
  51. }
  52. public function testExecute(): void
  53. {
  54. $cleanDb = $this->getMockFor('execute');
  55. $cleanDb->expects(self::once())->method('purgeDb');
  56. $cleanDb->execute();
  57. }
  58. public function testPurgeDb(): void {
  59. DatesUtils::setFakeDatetime('2022-01-08 00:00:00');
  60. $maxDate = DatesUtils::new();
  61. $maxDate->sub(new \DateInterval('P60D'));
  62. $maxDateAudit = DatesUtils::new();
  63. $maxDateAudit->sub(new \DateInterval('P180D'));
  64. $cleanDb = $this->getMockFor('purgeDb');
  65. $this->connection->expects($this->once())->method('beginTransaction');
  66. $this->connection->expects($this->once())->method('setAutoCommit')->with(false);
  67. $this->connection->expects($this->once())->method('commit');
  68. $this->connection->expects($this->never())->method('rollback');
  69. $cleanDb->expects(self::once())->method('purgeAuditTables')->with($maxDateAudit)->willReturn(100);
  70. $cleanDb->expects(self::once())->method('purgeMessages')->with($maxDate)->willReturn(101);
  71. $cleanDb->expects(self::once())->method('purgeNotifications')->with($maxDate)->willReturn(102);
  72. $this->logger->expects(self::once())->method('info')->with('DB purged - 303 records permanently deleted');
  73. $cleanDb->purgeDb();
  74. }
  75. public function testPurgeDbNoCommit(): void {
  76. DatesUtils::setFakeDatetime('2022-01-08 00:00:00');
  77. $maxDate = DatesUtils::new();
  78. $maxDate->sub(new \DateInterval('P60D'));
  79. $maxDateAudit = DatesUtils::new();
  80. $maxDateAudit->sub(new \DateInterval('P180D'));
  81. $cleanDb = $this->getMockFor('purgeDb');
  82. $this->connection->expects($this->once())->method('beginTransaction');
  83. $this->connection->expects($this->once())->method('setAutoCommit')->with(false);
  84. $this->connection->expects($this->never())->method('commit');
  85. $this->connection->expects($this->once())->method('rollback');
  86. $cleanDb->expects(self::once())->method('purgeAuditTables')->with($maxDateAudit)->willReturn(100);
  87. $cleanDb->expects(self::once())->method('purgeMessages')->with($maxDate)->willReturn(101);
  88. $cleanDb->expects(self::once())->method('purgeNotifications')->with($maxDate)->willReturn(102);
  89. $this->ui->expects(self::once())->method('print')->with('DB purged - 303 records would be permanently deleted');
  90. $cleanDb->purgeDb(false);
  91. }
  92. public function testPurgeDbWithError(): void {
  93. DatesUtils::setFakeDatetime('2022-01-08 00:00:00');
  94. $maxDate = DatesUtils::new();
  95. $maxDate->sub(new \DateInterval('P60D'));
  96. $maxDateAudit = DatesUtils::new();
  97. $maxDateAudit->sub(new \DateInterval('P180D'));
  98. $cleanDb = $this->getMockFor('purgeDb');
  99. $this->connection->expects($this->once())->method('beginTransaction');
  100. $this->connection->expects($this->once())->method('setAutoCommit')->with(false);
  101. $this->connection->expects($this->never())->method('commit');
  102. $this->connection->expects($this->once())->method('rollback');
  103. $cleanDb->expects(self::once())->method('purgeAuditTables')->with($maxDateAudit)->willThrowException(new \Exception('Error'));
  104. $this->expectException(\Exception::class);
  105. $cleanDb->purgeDb(false);
  106. }
  107. public function testPurgeAuditTables(): void {
  108. $maxDateAudit = DatesUtils::new('2022-06-30 00:00:00');
  109. $maxDateAudit->sub(new \DateInterval('P180D'));
  110. $cleanDb = $this->getMockFor('purgeAuditTables');
  111. $schemaManager = $this->getMockBuilder(\Doctrine\DBAL\Schema\AbstractSchemaManager::class)->disableOriginalConstructor()->getMock();
  112. $this->connection->method('getSchemaManager')->willReturn($schemaManager);
  113. $schemaManager->method('listTableNames')->willReturn([
  114. 'table1',
  115. 'Audit_table1',
  116. 'table2',
  117. 'Audit_table2',
  118. ]);
  119. $stmt1 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
  120. $stmt2 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
  121. $this->connection
  122. ->expects(self::exactly(2))
  123. ->method('prepare')
  124. ->willReturnMap([
  125. [
  126. "DELETE a, r
  127. FROM opentalent.Audit_table1 a
  128. INNER JOIN opentalent.revisions r ON r.id = a.rev
  129. WHERE r.timestamp < :maxDate;",
  130. $stmt1
  131. ],
  132. [
  133. "DELETE a, r
  134. FROM opentalent.Audit_table2 a
  135. INNER JOIN opentalent.revisions r ON r.id = a.rev
  136. WHERE r.timestamp < :maxDate;",
  137. $stmt2
  138. ]
  139. ]);
  140. $stmt1
  141. ->expects(self::once())
  142. ->method('executeStatement')
  143. ->with(['maxDate' => '2022-01-01'])
  144. ->willReturn(100);
  145. $stmt2
  146. ->expects(self::once())
  147. ->method('executeStatement')
  148. ->with(['maxDate' => '2022-01-01'])
  149. ->willReturn(100);
  150. $this->assertEquals(200, $cleanDb->purgeAuditTables($maxDateAudit));
  151. }
  152. public function testPurgeMessages(): void {
  153. $maxDate = DatesUtils::new('2022-03-02');
  154. $maxDate->sub(new \DateInterval('P60D'));
  155. $cleanDb = $this->getMockFor('purgeMessages');
  156. $stmt1 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
  157. $stmt2 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
  158. $this->connection
  159. ->expects(self::exactly(2))
  160. ->method('prepare')
  161. ->willReturnMap([
  162. [
  163. "DELETE r
  164. FROM opentalent.Message m
  165. inner join opentalent.ReportMessage r on r.message_id = m.id
  166. where (m.dateSent < :maxDate or (m.dateSent is null and m.createDate < :maxDate)) and m.isSystem = true and m.id > 0;",
  167. $stmt1
  168. ],
  169. [
  170. "DELETE
  171. FROM opentalent.Message
  172. where (dateSent < :maxDate or (dateSent is null and createDate < :maxDate)) and isSystem = true and id > 0;",
  173. $stmt2
  174. ]
  175. ]);
  176. $stmt1
  177. ->expects(self::once())
  178. ->method('executeStatement')
  179. ->with(['maxDate' => '2022-01-01'])
  180. ->willReturn(100);
  181. $stmt2
  182. ->expects(self::once())
  183. ->method('executeStatement')
  184. ->with(['maxDate' => '2022-01-01'])
  185. ->willReturn(100);
  186. $this->assertEquals(200, $cleanDb->purgeMessages($maxDate));
  187. }
  188. public function testPurgeNotifications(): void {
  189. $maxDate = DatesUtils::new('2022-03-02');
  190. $maxDate->sub(new \DateInterval('P60D'));
  191. $cleanDb = $this->getMockFor('purgeNotifications');
  192. $stmt1 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
  193. $stmt2 = $this->getMockBuilder(Statement::class)->disableOriginalConstructor()->getMock();
  194. $this->connection
  195. ->expects(self::exactly(2))
  196. ->method('prepare')
  197. ->willReturnMap([
  198. [
  199. "DELETE u
  200. FROM opentalent.Information i
  201. inner join opentalent.NotificationUser u on u.notification_id = i.id
  202. where i.createDate < :maxDate and i.discr = 'notification';",
  203. $stmt1
  204. ],
  205. [
  206. "DELETE
  207. FROM opentalent.Information
  208. where createDate < :maxDate and discr = 'notification';",
  209. $stmt2
  210. ]
  211. ]);
  212. $stmt1
  213. ->expects(self::once())
  214. ->method('executeStatement')
  215. ->with(['maxDate' => '2022-01-01'])
  216. ->willReturn(100);
  217. $stmt2
  218. ->expects(self::once())
  219. ->method('executeStatement')
  220. ->with(['maxDate' => '2022-01-01'])
  221. ->willReturn(100);
  222. $this->assertEquals(200, $cleanDb->purgeNotifications($maxDate));
  223. }
  224. }