From d45efeacca74b42250dd52da0e7eb1b3b84a84f7 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Tue, 20 Aug 2024 17:57:42 +0545 Subject: [PATCH] test: fix archive tests --- ...ected-failures-localAPI-on-OCIS-storage.md | 5 -- .../features/apiArchiver/downloadById.feature | 20 ++--- .../features/bootstrap/ArchiverContext.php | 73 ++++++++++++++++--- vendor-bin/behat/composer.json | 46 ++++++------ 4 files changed, 94 insertions(+), 50 deletions(-) diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md index bcf8e516a69..d545cd63ea4 100644 --- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md @@ -13,11 +13,6 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiArchiver/downloadByPath.feature:171](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L171) - [apiArchiver/downloadByPath.feature:172](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L172) -#### [Downloaded /Shares tar contains resource (files|folder) with leading / in Response](https://github.com/owncloud/ocis/issues/4636) - -- [apiArchiver/downloadById.feature:173](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadById.feature#L173) -- [apiArchiver/downloadById.feature:174](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadById.feature#L174) - #### [Shared mount folder gets deleted when overwritten by a file from personal space](https://github.com/owncloud/ocis/issues/7208) - [apiSpacesShares/copySpaces.feature:696](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpacesShares/copySpaces.feature#L696) diff --git a/tests/acceptance/features/apiArchiver/downloadById.feature b/tests/acceptance/features/apiArchiver/downloadById.feature index d30dbe92d00..968ee81a755 100644 --- a/tests/acceptance/features/apiArchiver/downloadById.feature +++ b/tests/acceptance/features/apiArchiver/downloadById.feature @@ -13,7 +13,7 @@ Feature: download multiple resources bundled into an archive Scenario Outline: download a single file Given user "Alice" has uploaded file with content "some data" to "/textfile0.txt" - When user "Alice" downloads the archive of "/textfile0.txt" using the resource id and setting these headers + When user "Alice" downloads the archive of "/textfile0.txt" using the resource id and setting these headers: | header | value | | User-Agent | | Then the HTTP status code should be "200" @@ -22,7 +22,7 @@ Feature: download multiple resources bundled into an archive | textfile0.txt | some data | Examples: | user-agent | archive-type | - | Linux | zip | + | Linux | tar | | Windows NT | zip | @@ -30,7 +30,7 @@ Feature: download multiple resources bundled into an archive Given user "Alice" has created folder "my_data" And user "Alice" has uploaded file with content "some data" to "/my_data/textfile0.txt" And user "Alice" has uploaded file with content "more data" to "/my_data/an_other_file.txt" - When user "Alice" downloads the archive of "/my_data" using the resource id and setting these headers + When user "Alice" downloads the archive of "/my_data" using the resource id and setting these headers: | header | value | | User-Agent | | Then the HTTP status code should be "200" @@ -41,7 +41,7 @@ Feature: download multiple resources bundled into an archive Examples: | user-agent | archive-type | | Linux | zip | - | Windows NT | zip | + | Windows NT | tar | Scenario: download multiple files and folders @@ -158,16 +158,16 @@ Feature: download multiple resources bundled into an archive | shareType | user | | permissionsRole | Viewer | And user "Brian" has a share "more_data" synced - When user "Brian" downloads the archive of "/Shares" using the resource id and setting these headers + When user "Brian" downloads the archive of "/Shares" using the resource id and setting these headers: | header | value | | User-Agent | | Then the HTTP status code should be "200" And the downloaded archive should contain these files: - | name | content | - | Shares/textfile0.txt | some data | - | Shares/textfile1.txt | other data | - | Shares/my_data/textfile2.txt | some data | - | Shares/more_data/an_other_file.txt | more data | + | name | content | + | textfile0.txt | some data | + | textfile1.txt | other data | + | my_data/textfile2.txt | some data | + | more_data/an_other_file.txt | more data | Examples: | user-agent | archive-type | | Linux | tar | diff --git a/tests/acceptance/features/bootstrap/ArchiverContext.php b/tests/acceptance/features/bootstrap/ArchiverContext.php index 256ef56e4c9..55957f1028a 100644 --- a/tests/acceptance/features/bootstrap/ArchiverContext.php +++ b/tests/acceptance/features/bootstrap/ArchiverContext.php @@ -28,6 +28,9 @@ use TestHelpers\SetupHelper; use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; +use splitbrain\PHPArchive\Tar; +use splitbrain\PHPArchive\Zip; +use splitbrain\PHPArchive\Archive; require_once 'bootstrap.php'; @@ -62,6 +65,38 @@ public function setUpScenario(BeforeScenarioScope $scope): void { ); } + /** + * @param string $type + * + * @return Archive + */ + public function getArchiveClass(string $type): Archive { + if ($type === 'zip') { + return new Zip(); + } elseif ($type === 'tar') { + return new Tar(); + } else { + throw new Exception('Unknown archive type: ' . $type); + } + } + + /** + * @param string $dir + * + * @return void + */ + public function removeDir(string $dir): void { + $items = \glob("$dir/*"); + foreach ($items as $item) { + if (\is_dir($item)) { + $this->removeDir($item); + } else { + \unlink($item); + } + } + \rmdir($dir); + } + /** * @param string $user * @param string $resource @@ -92,9 +127,10 @@ private function getArchiverQueryString( } /** - * @When user :user downloads the archive of :resource using the resource :addressType and setting these headers + * @When /^user "([^"]*)" downloads the (zip|tar) archive of "([^"]*)" using the resource (id|ids|path|paths) and setting these headers:$/ * * @param string $user + * @param string $archiveType * @param string $resource * @param string $addressType id|path * @param TableNode $headersTable @@ -104,8 +140,9 @@ private function getArchiverQueryString( * @throws GuzzleException * @throws Exception */ - public function userDownloadsTheArchive( + public function userDownloadsTheZipOrTarArchiveOfResourceUsingResourceIdOrPathAndSettingTheseHeaders( string $user, + string $archiveType, string $resource, string $addressType, TableNode $headersTable @@ -118,7 +155,7 @@ public function userDownloadsTheArchive( foreach ($headersTable as $row) { $headers[$row['header']] = $row ['value']; } - $this->featureContext->setResponse($this->downloadArchive($user, $resource, $addressType, null, $headers)); + $this->featureContext->setResponse($this->downloadArchive($user, $resource, $addressType, $archiveType, null, $headers)); } /** @@ -140,13 +177,14 @@ public function userDownloadsTheArchiveOfItemOfUser( string $owner, string $addressType ): void { - $this->featureContext->setResponse($this->downloadArchive($downloader, $resource, $addressType, $owner)); + $this->featureContext->setResponse($this->downloadArchive($downloader, $resource, $addressType, null, $owner)); } /** * @param string $downloader * @param string $resource * @param string $addressType + * @param string|null $archiveType * @param string|null $owner * @param array|null $headers * @@ -158,12 +196,16 @@ public function downloadArchive( string $downloader, string $resource, string $addressType, + ?string $archiveType = null, ?string $owner = null, ?array $headers = null ): ResponseInterface { $owner = $owner ?? $downloader; $downloader = $this->featureContext->getActualUsername($downloader); $queryString = $this->getArchiverQueryString($owner, $resource, $addressType); + if ($archiveType !== null) { + $queryString .= '&output-format=' . $archiveType; + } return HttpRequestHelper::get( $this->featureContext->getBaseUrl() . '/archiver?' . $queryString, $this->featureContext->getStepLineRef(), @@ -220,28 +262,34 @@ public function theDownloadedArchiveShouldContainTheseFiles(string $type, TableN $this->featureContext->verifyTableNodeColumns($expectedFiles, ['name', 'content']); $contents = $this->featureContext->getResponse()->getBody()->getContents(); $tempFile = \tempnam(\sys_get_temp_dir(), 'OcAcceptanceTests_'); + $tempExtractFolder = $tempFile; \unlink($tempFile); // we only need the name $tempFile = $tempFile . '.' . $type; // it needs the extension \file_put_contents($tempFile, $contents); // open the archive - $archiveData = new RecursiveIteratorIterator( - new PharData($tempFile), - RecursiveIteratorIterator::SELF_FIRST - ); + $tar = $this->getArchiveClass($type); + $tar->open($tempFile); + $archiveData = $tar->contents(); + + // extract the archive + $tar->open($tempFile); + $tar->extract($tempExtractFolder); + $tar->close(); + foreach ($expectedFiles->getHash() as $expectedItem) { $expectedPath = trim($expectedItem['name'], "/"); $found = false; foreach ($archiveData as $info) { // get only the parent folder path for the given item - $actualPath = explode(".$type", $info->getPathname())[1]; - $actualPath = trim($actualPath, "/"); + $actualPath = $info->getPath(); if ($expectedPath === $actualPath) { - if (!$info->isDir()) { + if (!$info->getIsdir()) { + $fileContent = \file_get_contents("$tempExtractFolder/$actualPath"); Assert::assertEquals( $expectedItem['content'], - $info->getContent(), + $fileContent, __METHOD__ . " content of '" . $expectedPath . "' not as expected" ); @@ -255,5 +303,6 @@ public function theDownloadedArchiveShouldContainTheseFiles(string $type, TableN } } \unlink($tempFile); + $this->removeDir($tempExtractFolder); } } diff --git a/vendor-bin/behat/composer.json b/vendor-bin/behat/composer.json index 07344d2cc5e..19d2f0a8ef5 100644 --- a/vendor-bin/behat/composer.json +++ b/vendor-bin/behat/composer.json @@ -1,27 +1,27 @@ { - "config" : { - "platform": { - "php": "8.2" - }, - "allow-plugins": { - "composer/package-versions-deprecated": true - } + "config": { + "platform": { + "php": "8.2" }, - "require": { - "behat/behat": "^3.13", - "behat/gherkin": "^4.9", - "behat/mink": "1.7.1", - "friends-of-behat/mink-extension": "^2.7", - "ciaranmcnulty/behat-stepthroughextension" : "dev-master", - "rdx/behat-variables": "^1.2", - "sensiolabs/behat-page-object-extension": "^2.3", - "symfony/translation": "^5.4", - "sabre/xml": "^2.2", - "guzzlehttp/guzzle": "^7.7", - "phpunit/phpunit": "^9.6", - "laminas/laminas-ldap": "^2.15", - "ankitpokhrel/tus-php": "^2.3", - "wapmorgan/unified-archive": "^1.1.10", - "swaggest/json-schema": "^0.12.42" + "allow-plugins": { + "composer/package-versions-deprecated": true } + }, + "require": { + "behat/behat": "^3.13", + "behat/gherkin": "^4.9", + "behat/mink": "1.7.1", + "friends-of-behat/mink-extension": "^2.7", + "ciaranmcnulty/behat-stepthroughextension": "dev-master", + "rdx/behat-variables": "^1.2", + "sensiolabs/behat-page-object-extension": "^2.3", + "symfony/translation": "^5.4", + "sabre/xml": "^2.2", + "guzzlehttp/guzzle": "^7.7", + "phpunit/phpunit": "^9.6", + "laminas/laminas-ldap": "^2.15", + "ankitpokhrel/tus-php": "^2.3", + "swaggest/json-schema": "^0.12.42", + "splitbrain/php-archive": "^1.3" } +}