CleanUpTest.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\Files_Trashbin\Tests\Command;
  8. use OC\User\Manager;
  9. use OCA\Files_Trashbin\Command\CleanUp;
  10. use OCP\Files\IRootFolder;
  11. use OCP\IDBConnection;
  12. use Symfony\Component\Console\Exception\InvalidOptionException;
  13. use Symfony\Component\Console\Input\InputInterface;
  14. use Symfony\Component\Console\Output\NullOutput;
  15. use Symfony\Component\Console\Output\OutputInterface;
  16. use Test\TestCase;
  17. /**
  18. * Class CleanUpTest
  19. *
  20. * @group DB
  21. *
  22. * @package OCA\Files_Trashbin\Tests\Command
  23. */
  24. class CleanUpTest extends TestCase {
  25. /** @var CleanUp */
  26. protected $cleanup;
  27. /** @var \PHPUnit\Framework\MockObject\MockObject | Manager */
  28. protected $userManager;
  29. /** @var \PHPUnit\Framework\MockObject\MockObject | IRootFolder */
  30. protected $rootFolder;
  31. /** @var IDBConnection */
  32. protected $dbConnection;
  33. /** @var string */
  34. protected $trashTable = 'files_trash';
  35. /** @var string */
  36. protected $user0 = 'user0';
  37. protected function setUp(): void {
  38. parent::setUp();
  39. $this->rootFolder = $this->getMockBuilder('OCP\Files\IRootFolder')
  40. ->disableOriginalConstructor()->getMock();
  41. $this->userManager = $this->getMockBuilder('OC\User\Manager')
  42. ->disableOriginalConstructor()->getMock();
  43. $this->dbConnection = \OC::$server->getDatabaseConnection();
  44. $this->cleanup = new CleanUp($this->rootFolder, $this->userManager, $this->dbConnection);
  45. }
  46. /**
  47. * populate files_trash table with 10 dummy values
  48. */
  49. public function initTable() {
  50. $query = $this->dbConnection->getQueryBuilder();
  51. $query->delete($this->trashTable)->execute();
  52. for ($i = 0; $i < 10; $i++) {
  53. $query->insert($this->trashTable)
  54. ->values([
  55. 'id' => $query->expr()->literal('file'.$i),
  56. 'timestamp' => $query->expr()->literal($i),
  57. 'location' => $query->expr()->literal('.'),
  58. 'user' => $query->expr()->literal('user'.$i % 2)
  59. ])->execute();
  60. }
  61. $getAllQuery = $this->dbConnection->getQueryBuilder();
  62. $result = $getAllQuery->select('id')
  63. ->from($this->trashTable)
  64. ->execute()
  65. ->fetchAll();
  66. $this->assertSame(10, count($result));
  67. }
  68. /**
  69. * @dataProvider dataTestRemoveDeletedFiles
  70. * @param boolean $nodeExists
  71. */
  72. public function testRemoveDeletedFiles(bool $nodeExists) {
  73. $this->initTable();
  74. $this->rootFolder
  75. ->method('nodeExists')
  76. ->with('/' . $this->user0 . '/files_trashbin')
  77. ->willReturnOnConsecutiveCalls($nodeExists, false);
  78. if ($nodeExists) {
  79. $this->rootFolder
  80. ->method('get')
  81. ->with('/' . $this->user0 . '/files_trashbin')
  82. ->willReturn($this->rootFolder);
  83. $this->rootFolder
  84. ->method('delete');
  85. } else {
  86. $this->rootFolder->expects($this->never())->method('get');
  87. $this->rootFolder->expects($this->never())->method('delete');
  88. }
  89. $this->invokePrivate($this->cleanup, 'removeDeletedFiles', [$this->user0, new NullOutput(), false]);
  90. if ($nodeExists) {
  91. // if the delete operation was executed only files from user1
  92. // should be left.
  93. $query = $this->dbConnection->getQueryBuilder();
  94. $query->select('user')
  95. ->from($this->trashTable);
  96. $qResult = $query->execute();
  97. $result = $qResult->fetchAll();
  98. $qResult->closeCursor();
  99. $this->assertSame(5, count($result));
  100. foreach ($result as $r) {
  101. $this->assertSame('user1', $r['user']);
  102. }
  103. } else {
  104. // if no delete operation was executed we should still have all 10
  105. // database entries
  106. $getAllQuery = $this->dbConnection->getQueryBuilder();
  107. $result = $getAllQuery->select('id')
  108. ->from($this->trashTable)
  109. ->execute()
  110. ->fetchAll();
  111. $this->assertSame(10, count($result));
  112. }
  113. }
  114. public function dataTestRemoveDeletedFiles() {
  115. return [
  116. [true],
  117. [false]
  118. ];
  119. }
  120. /**
  121. * test remove deleted files from users given as parameter
  122. */
  123. public function testExecuteDeleteListOfUsers() {
  124. $userIds = ['user1', 'user2', 'user3'];
  125. $instance = $this->getMockBuilder('OCA\Files_Trashbin\Command\CleanUp')
  126. ->setMethods(['removeDeletedFiles'])
  127. ->setConstructorArgs([$this->rootFolder, $this->userManager, $this->dbConnection])
  128. ->getMock();
  129. $instance->expects($this->exactly(count($userIds)))
  130. ->method('removeDeletedFiles')
  131. ->willReturnCallback(function ($user) use ($userIds) {
  132. $this->assertTrue(in_array($user, $userIds));
  133. });
  134. $this->userManager->expects($this->exactly(count($userIds)))
  135. ->method('userExists')->willReturn(true);
  136. $inputInterface = $this->getMockBuilder('\Symfony\Component\Console\Input\InputInterface')
  137. ->disableOriginalConstructor()->getMock();
  138. $inputInterface->method('getArgument')
  139. ->with('user_id')
  140. ->willReturn($userIds);
  141. $inputInterface->method('getOption')
  142. ->willReturnMap([
  143. ['all-users', false],
  144. ['verbose', false],
  145. ]);
  146. $outputInterface = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')
  147. ->disableOriginalConstructor()->getMock();
  148. $this->invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]);
  149. }
  150. /**
  151. * test remove deleted files of all users
  152. */
  153. public function testExecuteAllUsers() {
  154. $userIds = [];
  155. $backendUsers = ['user1', 'user2'];
  156. $instance = $this->getMockBuilder('OCA\Files_Trashbin\Command\CleanUp')
  157. ->setMethods(['removeDeletedFiles'])
  158. ->setConstructorArgs([$this->rootFolder, $this->userManager, $this->dbConnection])
  159. ->getMock();
  160. $backend = $this->createMock(\OCP\UserInterface::class);
  161. $backend->method('getUsers')
  162. ->with('', 500, 0)
  163. ->willReturn($backendUsers);
  164. $instance->expects($this->exactly(count($backendUsers)))
  165. ->method('removeDeletedFiles')
  166. ->willReturnCallback(function ($user) use ($backendUsers) {
  167. $this->assertTrue(in_array($user, $backendUsers));
  168. });
  169. $inputInterface = $this->createMock(InputInterface::class);
  170. $inputInterface->method('getArgument')
  171. ->with('user_id')
  172. ->willReturn($userIds);
  173. $inputInterface->method('getOption')
  174. ->willReturnMap([
  175. ['all-users', true],
  176. ['verbose', false],
  177. ]);
  178. $outputInterface = $this->createMock(OutputInterface::class);
  179. $this->userManager
  180. ->method('getBackends')
  181. ->willReturn([$backend]);
  182. $this->invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]);
  183. }
  184. public function testExecuteNoUsersAndNoAllUsers() {
  185. $inputInterface = $this->createMock(InputInterface::class);
  186. $inputInterface->method('getArgument')
  187. ->with('user_id')
  188. ->willReturn([]);
  189. $inputInterface->method('getOption')
  190. ->willReturnMap([
  191. ['all-users', false],
  192. ['verbose', false],
  193. ]);
  194. $outputInterface = $this->createMock(OutputInterface::class);
  195. $this->expectException(InvalidOptionException::class);
  196. $this->expectExceptionMessage('Either specify a user_id or --all-users');
  197. $this->invokePrivate($this->cleanup, 'execute', [$inputInterface, $outputInterface]);
  198. }
  199. public function testExecuteUsersAndAllUsers() {
  200. $inputInterface = $this->createMock(InputInterface::class);
  201. $inputInterface->method('getArgument')
  202. ->with('user_id')
  203. ->willReturn(['user1', 'user2']);
  204. $inputInterface->method('getOption')
  205. ->willReturnMap([
  206. ['all-users', true],
  207. ['verbose', false],
  208. ]);
  209. $outputInterface = $this->createMock(OutputInterface::class);
  210. $this->expectException(InvalidOptionException::class);
  211. $this->expectExceptionMessage('Either specify a user_id or --all-users');
  212. $this->invokePrivate($this->cleanup, 'execute', [$inputInterface, $outputInterface]);
  213. }
  214. }