CleanDbTest.php 10 KB

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