aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_trashbin/tests/Command
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_trashbin/tests/Command')
-rw-r--r--apps/files_trashbin/tests/Command/CleanUpTest.php134
-rw-r--r--apps/files_trashbin/tests/Command/ExpireTest.php27
-rw-r--r--apps/files_trashbin/tests/Command/ExpireTrashTest.php156
3 files changed, 212 insertions, 105 deletions
diff --git a/apps/files_trashbin/tests/Command/CleanUpTest.php b/apps/files_trashbin/tests/Command/CleanUpTest.php
index 2f582ed428b..41ed0e1e960 100644
--- a/apps/files_trashbin/tests/Command/CleanUpTest.php
+++ b/apps/files_trashbin/tests/Command/CleanUpTest.php
@@ -1,35 +1,20 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Trashbin\Tests\Command;
-use OC\User\Manager;
use OCA\Files_Trashbin\Command\CleanUp;
use OCP\Files\IRootFolder;
use OCP\IDBConnection;
+use OCP\IUserManager;
+use OCP\Server;
+use OCP\UserInterface;
+use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Exception\InvalidOptionException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\NullOutput;
@@ -44,33 +29,19 @@ use Test\TestCase;
* @package OCA\Files_Trashbin\Tests\Command
*/
class CleanUpTest extends TestCase {
-
- /** @var CleanUp */
- protected $cleanup;
-
- /** @var \PHPUnit\Framework\MockObject\MockObject | Manager */
- protected $userManager;
-
- /** @var \PHPUnit\Framework\MockObject\MockObject | IRootFolder */
- protected $rootFolder;
-
- /** @var IDBConnection */
- protected $dbConnection;
-
- /** @var string */
- protected $trashTable = 'files_trash';
-
- /** @var string */
- protected $user0 = 'user0';
+ protected IUserManager&MockObject $userManager;
+ protected IRootFolder&MockObject $rootFolder;
+ protected IDBConnection $dbConnection;
+ protected CleanUp $cleanup;
+ protected string $trashTable = 'files_trash';
+ protected string $user0 = 'user0';
protected function setUp(): void {
parent::setUp();
- $this->rootFolder = $this->getMockBuilder('OCP\Files\IRootFolder')
- ->disableOriginalConstructor()->getMock();
- $this->userManager = $this->getMockBuilder('OC\User\Manager')
- ->disableOriginalConstructor()->getMock();
+ $this->rootFolder = $this->createMock(IRootFolder::class);
+ $this->userManager = $this->createMock(IUserManager::class);
- $this->dbConnection = \OC::$server->getDatabaseConnection();
+ $this->dbConnection = Server::get(IDBConnection::class);
$this->cleanup = new CleanUp($this->rootFolder, $this->userManager, $this->dbConnection);
}
@@ -78,31 +49,28 @@ class CleanUpTest extends TestCase {
/**
* populate files_trash table with 10 dummy values
*/
- public function initTable() {
+ public function initTable(): void {
$query = $this->dbConnection->getQueryBuilder();
- $query->delete($this->trashTable)->execute();
+ $query->delete($this->trashTable)->executeStatement();
for ($i = 0; $i < 10; $i++) {
$query->insert($this->trashTable)
->values([
- 'id' => $query->expr()->literal('file'.$i),
+ 'id' => $query->expr()->literal('file' . $i),
'timestamp' => $query->expr()->literal($i),
'location' => $query->expr()->literal('.'),
- 'user' => $query->expr()->literal('user'.$i % 2)
- ])->execute();
+ 'user' => $query->expr()->literal('user' . $i % 2)
+ ])->executeStatement();
}
$getAllQuery = $this->dbConnection->getQueryBuilder();
$result = $getAllQuery->select('id')
->from($this->trashTable)
- ->execute()
+ ->executeQuery()
->fetchAll();
- $this->assertSame(10, count($result));
+ $this->assertCount(10, $result);
}
- /**
- * @dataProvider dataTestRemoveDeletedFiles
- * @param boolean $nodeExists
- */
- public function testRemoveDeletedFiles(bool $nodeExists) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestRemoveDeletedFiles')]
+ public function testRemoveDeletedFiles(bool $nodeExists): void {
$this->initTable();
$this->rootFolder
->method('nodeExists')
@@ -119,7 +87,7 @@ class CleanUpTest extends TestCase {
$this->rootFolder->expects($this->never())->method('get');
$this->rootFolder->expects($this->never())->method('delete');
}
- $this->invokePrivate($this->cleanup, 'removeDeletedFiles', [$this->user0, new NullOutput(), false]);
+ self::invokePrivate($this->cleanup, 'removeDeletedFiles', [$this->user0, new NullOutput(), false]);
if ($nodeExists) {
// if the delete operation was executed only files from user1
@@ -128,11 +96,11 @@ class CleanUpTest extends TestCase {
$query->select('user')
->from($this->trashTable);
- $qResult = $query->execute();
+ $qResult = $query->executeQuery();
$result = $qResult->fetchAll();
$qResult->closeCursor();
- $this->assertSame(5, count($result));
+ $this->assertCount(5, $result);
foreach ($result as $r) {
$this->assertSame('user1', $r['user']);
}
@@ -142,12 +110,12 @@ class CleanUpTest extends TestCase {
$getAllQuery = $this->dbConnection->getQueryBuilder();
$result = $getAllQuery->select('id')
->from($this->trashTable)
- ->execute()
+ ->executeQuery()
->fetchAll();
- $this->assertSame(10, count($result));
+ $this->assertCount(10, $result);
}
}
- public function dataTestRemoveDeletedFiles() {
+ public static function dataTestRemoveDeletedFiles(): array {
return [
[true],
[false]
@@ -157,21 +125,20 @@ class CleanUpTest extends TestCase {
/**
* test remove deleted files from users given as parameter
*/
- public function testExecuteDeleteListOfUsers() {
+ public function testExecuteDeleteListOfUsers(): void {
$userIds = ['user1', 'user2', 'user3'];
- $instance = $this->getMockBuilder('OCA\Files_Trashbin\Command\CleanUp')
- ->setMethods(['removeDeletedFiles'])
+ $instance = $this->getMockBuilder(CleanUp::class)
+ ->onlyMethods(['removeDeletedFiles'])
->setConstructorArgs([$this->rootFolder, $this->userManager, $this->dbConnection])
->getMock();
$instance->expects($this->exactly(count($userIds)))
->method('removeDeletedFiles')
- ->willReturnCallback(function ($user) use ($userIds) {
+ ->willReturnCallback(function ($user) use ($userIds): void {
$this->assertTrue(in_array($user, $userIds));
});
$this->userManager->expects($this->exactly(count($userIds)))
->method('userExists')->willReturn(true);
- $inputInterface = $this->getMockBuilder('\Symfony\Component\Console\Input\InputInterface')
- ->disableOriginalConstructor()->getMock();
+ $inputInterface = $this->createMock(\Symfony\Component\Console\Input\InputInterface::class);
$inputInterface->method('getArgument')
->with('user_id')
->willReturn($userIds);
@@ -180,28 +147,27 @@ class CleanUpTest extends TestCase {
['all-users', false],
['verbose', false],
]);
- $outputInterface = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')
- ->disableOriginalConstructor()->getMock();
- $this->invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]);
+ $outputInterface = $this->createMock(\Symfony\Component\Console\Output\OutputInterface::class);
+ self::invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]);
}
/**
* test remove deleted files of all users
*/
- public function testExecuteAllUsers() {
+ public function testExecuteAllUsers(): void {
$userIds = [];
$backendUsers = ['user1', 'user2'];
- $instance = $this->getMockBuilder('OCA\Files_Trashbin\Command\CleanUp')
- ->setMethods(['removeDeletedFiles'])
+ $instance = $this->getMockBuilder(CleanUp::class)
+ ->onlyMethods(['removeDeletedFiles'])
->setConstructorArgs([$this->rootFolder, $this->userManager, $this->dbConnection])
->getMock();
- $backend = $this->createMock(\OCP\UserInterface::class);
+ $backend = $this->createMock(UserInterface::class);
$backend->method('getUsers')
->with('', 500, 0)
->willReturn($backendUsers);
$instance->expects($this->exactly(count($backendUsers)))
->method('removeDeletedFiles')
- ->willReturnCallback(function ($user) use ($backendUsers) {
+ ->willReturnCallback(function ($user) use ($backendUsers): void {
$this->assertTrue(in_array($user, $backendUsers));
});
$inputInterface = $this->createMock(InputInterface::class);
@@ -217,10 +183,10 @@ class CleanUpTest extends TestCase {
$this->userManager
->method('getBackends')
->willReturn([$backend]);
- $this->invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]);
+ self::invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]);
}
- public function testExecuteNoUsersAndNoAllUsers() {
+ public function testExecuteNoUsersAndNoAllUsers(): void {
$inputInterface = $this->createMock(InputInterface::class);
$inputInterface->method('getArgument')
->with('user_id')
@@ -235,10 +201,10 @@ class CleanUpTest extends TestCase {
$this->expectException(InvalidOptionException::class);
$this->expectExceptionMessage('Either specify a user_id or --all-users');
- $this->invokePrivate($this->cleanup, 'execute', [$inputInterface, $outputInterface]);
+ self::invokePrivate($this->cleanup, 'execute', [$inputInterface, $outputInterface]);
}
- public function testExecuteUsersAndAllUsers() {
+ public function testExecuteUsersAndAllUsers(): void {
$inputInterface = $this->createMock(InputInterface::class);
$inputInterface->method('getArgument')
->with('user_id')
@@ -253,6 +219,6 @@ class CleanUpTest extends TestCase {
$this->expectException(InvalidOptionException::class);
$this->expectExceptionMessage('Either specify a user_id or --all-users');
- $this->invokePrivate($this->cleanup, 'execute', [$inputInterface, $outputInterface]);
+ self::invokePrivate($this->cleanup, 'execute', [$inputInterface, $outputInterface]);
}
}
diff --git a/apps/files_trashbin/tests/Command/ExpireTest.php b/apps/files_trashbin/tests/Command/ExpireTest.php
index dd9e2c2b254..5a66dac8c6e 100644
--- a/apps/files_trashbin/tests/Command/ExpireTest.php
+++ b/apps/files_trashbin/tests/Command/ExpireTest.php
@@ -1,25 +1,10 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Trashbin\Tests\Command;
@@ -34,7 +19,7 @@ use Test\TestCase;
* @package OCA\Files_Trashbin\Tests\Command
*/
class ExpireTest extends TestCase {
- public function testExpireNonExistingUser() {
+ public function testExpireNonExistingUser(): void {
$command = new Expire('test');
$command->handle();
diff --git a/apps/files_trashbin/tests/Command/ExpireTrashTest.php b/apps/files_trashbin/tests/Command/ExpireTrashTest.php
new file mode 100644
index 00000000000..23bf0d8f121
--- /dev/null
+++ b/apps/files_trashbin/tests/Command/ExpireTrashTest.php
@@ -0,0 +1,156 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\Files_Trashbin\Tests\Command;
+
+use OCA\Files_Trashbin\Command\ExpireTrash;
+use OCA\Files_Trashbin\Expiration;
+use OCA\Files_Trashbin\Helper;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Files\IRootFolder;
+use OCP\Files\Node;
+use OCP\IConfig;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\Server;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Test\TestCase;
+
+/**
+ * Class ExpireTrashTest
+ *
+ * @group DB
+ *
+ * @package OCA\Files_Trashbin\Tests\Command
+ */
+class ExpireTrashTest extends TestCase {
+ private Expiration $expiration;
+ private Node $userFolder;
+ private IConfig $config;
+ private IUserManager $userManager;
+ private IUser $user;
+ private ITimeFactory $timeFactory;
+
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->config = Server::get(IConfig::class);
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->expiration = Server::get(Expiration::class);
+ $this->invokePrivate($this->expiration, 'timeFactory', [$this->timeFactory]);
+
+ $userId = self::getUniqueID('user');
+ $this->userManager = Server::get(IUserManager::class);
+ $this->user = $this->userManager->createUser($userId, $userId);
+
+ $this->loginAsUser($userId);
+ $this->userFolder = Server::get(IRootFolder::class)->getUserFolder($userId);
+ }
+
+ protected function tearDown(): void {
+ $this->logout();
+
+ if (isset($this->user)) {
+ $this->user->delete();
+ }
+
+ $this->invokePrivate($this->expiration, 'timeFactory', [Server::get(ITimeFactory::class)]);
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider retentionObligationProvider
+ */
+ public function testRetentionObligation(string $obligation, string $quota, int $elapsed, int $fileSize, bool $shouldExpire): void {
+ $this->config->setSystemValues(['trashbin_retention_obligation' => $obligation]);
+ $this->expiration->setRetentionObligation($obligation);
+
+ $this->user->setQuota($quota);
+
+ $bytes = 'ABCDEFGHIKLMNOPQRSTUVWXYZ';
+
+ $file = 'foo.txt';
+ $this->userFolder->newFile($file, substr($bytes, 0, $fileSize));
+
+ $filemtime = $this->userFolder->get($file)->getMTime();
+ $this->timeFactory->expects($this->any())
+ ->method('getTime')
+ ->willReturn($filemtime + $elapsed);
+ $this->userFolder->get($file)->delete();
+ $this->userFolder->getStorage()
+ ->getCache()
+ ->put('files_trashbin', ['size' => $fileSize, 'unencrypted_size' => $fileSize]);
+
+ $userId = $this->user->getUID();
+ $trashFiles = Helper::getTrashFiles('/', $userId);
+ $this->assertEquals(1, count($trashFiles));
+
+ $outputInterface = $this->createMock(OutputInterface::class);
+ $inputInterface = $this->createMock(InputInterface::class);
+ $inputInterface->expects($this->any())
+ ->method('getArgument')
+ ->with('user_id')
+ ->willReturn([$userId]);
+
+ $command = new ExpireTrash(
+ Server::get(LoggerInterface::class),
+ Server::get(IUserManager::class),
+ $this->expiration
+ );
+
+ $this->invokePrivate($command, 'execute', [$inputInterface, $outputInterface]);
+
+ $trashFiles = Helper::getTrashFiles('/', $userId);
+ $this->assertEquals($shouldExpire ? 0 : 1, count($trashFiles));
+ }
+
+ public function retentionObligationProvider(): array {
+ $hour = 3600; // 60 * 60
+
+ $oneDay = 24 * $hour;
+ $fiveDays = 24 * 5 * $hour;
+ $tenDays = 24 * 10 * $hour;
+ $elevenDays = 24 * 11 * $hour;
+
+ return [
+ ['disabled', '20 B', 0, 1, false],
+
+ ['auto', '20 B', 0, 5, false],
+ ['auto', '20 B', 0, 21, true],
+
+ ['0, auto', '20 B', 0, 21, true],
+ ['0, auto', '20 B', $oneDay, 5, false],
+ ['0, auto', '20 B', $oneDay, 19, true],
+ ['0, auto', '20 B', 0, 19, true],
+
+ ['auto, 0', '20 B', $oneDay, 19, true],
+ ['auto, 0', '20 B', $oneDay, 21, true],
+ ['auto, 0', '20 B', 0, 5, false],
+ ['auto, 0', '20 B', 0, 19, true],
+
+ ['1, auto', '20 B', 0, 5, false],
+ ['1, auto', '20 B', $fiveDays, 5, false],
+ ['1, auto', '20 B', $fiveDays, 21, true],
+
+ ['auto, 1', '20 B', 0, 21, true],
+ ['auto, 1', '20 B', 0, 5, false],
+ ['auto, 1', '20 B', $fiveDays, 5, true],
+ ['auto, 1', '20 B', $oneDay, 5, false],
+
+ ['2, 10', '20 B', $fiveDays, 5, false],
+ ['2, 10', '20 B', $fiveDays, 20, true],
+ ['2, 10', '20 B', $elevenDays, 5, true],
+
+ ['10, 2', '20 B', $fiveDays, 5, false],
+ ['10, 2', '20 B', $fiveDays, 21, false],
+ ['10, 2', '20 B', $tenDays, 5, false],
+ ['10, 2', '20 B', $elevenDays, 5, true]
+ ];
+ }
+}