From 995d04ec9779324b3fa23dbaac5c1732fc5d4b80 Mon Sep 17 00:00:00 2001 From: Matthias Neid Date: Fri, 15 Nov 2024 18:30:54 +0100 Subject: [PATCH] add support for file timestamps, fix creation of elements through links --- src/Exception/TouchException.php | 15 ++ .../Features/GetAccessTimestampInterface.php | 24 ++ .../Features/GetBirthTimestampInterface.php | 24 ++ .../GetModificationTimestampInterface.php | 24 ++ .../GetStatusChangeTimestampInterface.php | 24 ++ .../Features/SetAccessTimestampInterface.php | 27 ++ .../Features/SetBirthTimestampInterface.php | 27 ++ .../SetModificationTimestampInterface.php | 27 ++ .../SetStatusChangeTimestampInterface.php | 27 ++ src/System/FilesystemElement.php | 80 ++++++ src/System/FilesystemInterface.php | 15 +- src/System/Link/DirectoryLink.php | 15 +- src/System/Link/FileLink.php | 15 +- test/Unit/System/Directory/DirectoryTest.php | 38 ++- .../Directory/FilteredDirectoryTest.php | 6 + .../System/Directory/TempDirectoryTest.php | 16 +- test/Unit/System/File/FileTest.php | 5 + test/Unit/System/File/TempDiskFileTest.php | 9 + test/Unit/System/FilesystemTestCase.php | 233 +++++++++++++++++- test/Unit/System/Link/DeadLinkTest.php | 96 ++++++++ test/Unit/System/Link/DirectoryLinkTest.php | 52 +++- test/Unit/System/Link/FileLinkTest.php | 40 ++- test/Unit/System/Link/LinkTest.php | 31 ++- .../System/Stream/SocketStreamTestCase.php | 2 + .../System/Stream/SocketWriteStreamTest.php | 4 + .../Stream/Trait/SocketReadTestTrait.php | 12 + .../Stream/Trait/SocketWriteTestTrait.php | 1 + test/Unit/System/TmpDirTestCase.php | 1 + 28 files changed, 864 insertions(+), 26 deletions(-) create mode 100644 src/Exception/TouchException.php create mode 100644 src/Interfaces/Features/GetAccessTimestampInterface.php create mode 100644 src/Interfaces/Features/GetBirthTimestampInterface.php create mode 100644 src/Interfaces/Features/GetModificationTimestampInterface.php create mode 100644 src/Interfaces/Features/GetStatusChangeTimestampInterface.php create mode 100644 src/Interfaces/Features/SetAccessTimestampInterface.php create mode 100644 src/Interfaces/Features/SetBirthTimestampInterface.php create mode 100644 src/Interfaces/Features/SetModificationTimestampInterface.php create mode 100644 src/Interfaces/Features/SetStatusChangeTimestampInterface.php diff --git a/src/Exception/TouchException.php b/src/Exception/TouchException.php new file mode 100644 index 0000000..13e3d35 --- /dev/null +++ b/src/Exception/TouchException.php @@ -0,0 +1,15 @@ +path); } + /** + * @inheritDoc + * @throws StatException + */ + public function getAccessTimestamp(): int + { + $time = @fileatime($this->path); + if ($time === false) { + $error = error_get_last(); + throw new StatException("Could not get access timestamp (" . $this->path . ")" . ($error ? ": " . $error["message"] : ""), $this); + } + return $time; + } + + /** + * @inheritDoc + * @throws StatException + */ + public function getModificationTimestamp(): int + { + $time = @filemtime($this->path); + if ($time === false) { + $error = error_get_last(); + throw new StatException("Could not get modification timestamp (" . $this->path . ")" . ($error ? ": " . $error["message"] : ""), $this); + } + return $time; + } + + /** + * @inheritDoc + * @throws StatException + */ + public function getStatusChangeTimestamp(): int + { + $time = @filectime($this->path); + if ($time === false) { + $error = error_get_last(); + throw new StatException("Could not get status change timestamp (" . $this->path . ")" . ($error ? ": " . $error["message"] : ""), $this); + } + return $time; + } + + /** + * @inheritDoc + * @throws TouchException + * @throws StatException + */ + public function setAccessTimestamp(int $timestamp): static + { + if (!file_exists($this->path)) { + throw new StatException("Could not set access timestamp because element does not exist (" . $this->path . ")", $this); + } + + if (!@touch($this->path, $timestamp, $timestamp)) { + $error = error_get_last(); + throw new TouchException("Could not set access timestamp (" . $this->path . ")" . ($error ? ": " . $error["message"] : ""), $this); + } + return $this; + } + + /** + * @inheritDoc + * @throws TouchException + * @throws StatException + */ + public function setModificationTimestamp(int $timestamp): static + { + if (!file_exists($this->path)) { + throw new StatException("Could not set modification timestamp because element does not exist (" . $this->path . ")", $this); + } + + if (!@touch($this->path, mtime: $timestamp)) { + $error = error_get_last(); + throw new TouchException("Could not set modification timestamp (" . $this->path . ")" . ($error ? ": " . $error["message"] : ""), $this); + } + return $this; + } + /** * @return string[] */ diff --git a/src/System/FilesystemInterface.php b/src/System/FilesystemInterface.php index fbaeaaa..0bab3ed 100644 --- a/src/System/FilesystemInterface.php +++ b/src/System/FilesystemInterface.php @@ -4,7 +4,12 @@ use Aternos\IO\Interfaces\Features\DeleteInterface; use Aternos\IO\Interfaces\Features\ExistsInterface; +use Aternos\IO\Interfaces\Features\GetAccessTimestampInterface; +use Aternos\IO\Interfaces\Features\GetModificationTimestampInterface; +use Aternos\IO\Interfaces\Features\GetStatusChangeTimestampInterface; use Aternos\IO\Interfaces\Features\MovePathInterface; +use Aternos\IO\Interfaces\Features\SetAccessTimestampInterface; +use Aternos\IO\Interfaces\Features\SetModificationTimestampInterface; /** * Interface FilesystemInterface @@ -13,7 +18,15 @@ * * @package Aternos\IO\System */ -interface FilesystemInterface extends MovePathInterface, DeleteInterface, ExistsInterface +interface FilesystemInterface extends + MovePathInterface, + DeleteInterface, + ExistsInterface, + GetAccessTimestampInterface, + GetModificationTimestampInterface, + GetStatusChangeTimestampInterface, + SetAccessTimestampInterface, + SetModificationTimestampInterface { } \ No newline at end of file diff --git a/src/System/Link/DirectoryLink.php b/src/System/Link/DirectoryLink.php index db787a8..ac58924 100644 --- a/src/System/Link/DirectoryLink.php +++ b/src/System/Link/DirectoryLink.php @@ -8,6 +8,7 @@ use Aternos\IO\Interfaces\Features\GetPathInterface; use Aternos\IO\Interfaces\Types\DirectoryInterface; use Aternos\IO\Interfaces\Types\Link\DirectoryLinkInterface; +use Aternos\IO\System\Directory\Directory; use Generator; /** @@ -25,11 +26,21 @@ class DirectoryLink extends Link implements DirectoryLinkInterface */ public function getTarget(): DirectoryInterface { - $target = parent::getTarget(); + if ($this->target) { + return $this->target; + } + + $targetPath = $this->getTargetPath(); + + if (!$this->targetExists()) { + return $this->target = new Directory($targetPath); + } + + $target = static::getIOElementFromPath($targetPath); if (!$target instanceof DirectoryInterface) { throw new GetTargetException("Could not get directory link target because link target is not a directory (" . $this->path . ")", $this); } - return $target; + return $this->target = $target; } /** diff --git a/src/System/Link/FileLink.php b/src/System/Link/FileLink.php index 89afc79..f9dda7d 100644 --- a/src/System/Link/FileLink.php +++ b/src/System/Link/FileLink.php @@ -8,6 +8,7 @@ use Aternos\IO\Interfaces\Features\GetPathInterface; use Aternos\IO\Interfaces\Types\FileInterface; use Aternos\IO\Interfaces\Types\Link\FileLinkInterface; +use Aternos\IO\System\File\File; /** * Class FileLink @@ -34,11 +35,21 @@ public function close(): static */ public function getTarget(): FileInterface { - $target = parent::getTarget(); + if ($this->target) { + return $this->target; + } + + $targetPath = $this->getTargetPath(); + + if (!$this->targetExists()) { + return $this->target = new File($targetPath); + } + + $target = static::getIOElementFromPath($targetPath); if (!$target instanceof FileInterface) { throw new GetTargetException("Could not get file link target because link target is not a file (" . $this->path . ")", $this); } - return $target; + return $this->target = $target; } /** diff --git a/test/Unit/System/Directory/DirectoryTest.php b/test/Unit/System/Directory/DirectoryTest.php index 2df4c95..dbdf447 100644 --- a/test/Unit/System/Directory/DirectoryTest.php +++ b/test/Unit/System/Directory/DirectoryTest.php @@ -5,15 +5,16 @@ use Aternos\IO\Exception\CreateDirectoryException; use Aternos\IO\Exception\DeleteException; use Aternos\IO\Exception\GetTargetException; +use Aternos\IO\Exception\IOException; use Aternos\IO\Exception\MissingPermissionsException; -use Aternos\IO\System\Directory\Directory; -use Aternos\IO\System\Link\DirectoryLink; -use Aternos\IO\System\Link\FileLink; -use Aternos\IO\System\Link\Link; use Aternos\IO\Interfaces\IOElementInterface; use Aternos\IO\Interfaces\Types\DirectoryInterface; use Aternos\IO\Interfaces\Types\FileInterface; use Aternos\IO\Interfaces\Types\Link\LinkInterface; +use Aternos\IO\System\Directory\Directory; +use Aternos\IO\System\Link\DirectoryLink; +use Aternos\IO\System\Link\FileLink; +use Aternos\IO\System\Link\Link; use Aternos\IO\Test\Unit\System\FilesystemTestCase; use Generator; @@ -27,6 +28,7 @@ protected function createElement(string $path): Directory /** * @throws MissingPermissionsException * @throws GetTargetException + * @throws IOException */ public function testGetChildren(): void { @@ -52,6 +54,7 @@ public function testGetChildren(): void /** * @throws GetTargetException + * @throws IOException */ public function testThrowsExceptionOnGetChildrenWithMissingPermissions(): void { @@ -71,6 +74,7 @@ public function testThrowsExceptionOnGetChildrenWithMissingPermissions(): void /** * @throws MissingPermissionsException * @throws GetTargetException + * @throws IOException */ public function testGetChildrenRecursive(): void { @@ -99,6 +103,7 @@ public function testGetChildrenRecursive(): void * @return void * @throws MissingPermissionsException * @throws GetTargetException + * @throws IOException */ public function testThrowsExceptionOnGetChildrenRecursiveWithMissingPermissions(): void { @@ -118,6 +123,7 @@ public function testThrowsExceptionOnGetChildrenRecursiveWithMissingPermissions( /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testThrowsExceptionOnImpossibleDelete(): void { @@ -127,6 +133,11 @@ public function testThrowsExceptionOnImpossibleDelete(): void $element->delete(); } + /** + * @return void + * @throws CreateDirectoryException + * @throws IOException + */ public function testThrowsExceptionOnFailedCreation(): void { $this->expectException(CreateDirectoryException::class); @@ -137,6 +148,7 @@ public function testThrowsExceptionOnFailedCreation(): void /** * @throws CreateDirectoryException + * @throws IOException */ public function testCreate(): void { @@ -148,7 +160,10 @@ public function testCreate(): void } /** - * @throws DeleteException|MissingPermissionsException|GetTargetException + * @throws DeleteException + * @throws GetTargetException + * @throws MissingPermissionsException + * @throws IOException */ public function testDeleteRecursively(): void { @@ -169,6 +184,7 @@ public function testDeleteRecursively(): void /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testGetChildrenLinks(): void { @@ -193,6 +209,7 @@ public function testGetChildrenLinks(): void /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testDontFollowLinks(): void { @@ -216,6 +233,7 @@ public function testDontFollowLinks(): void /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testIgnoreOutsideLinks(): void { @@ -234,6 +252,7 @@ public function testIgnoreOutsideLinks(): void /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testIgnoreOutsideLinksRecursive(): void { @@ -255,6 +274,7 @@ public function testIgnoreOutsideLinksRecursive(): void /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testAllowOutsideLinks(): void { @@ -273,12 +293,14 @@ public function testAllowOutsideLinks(): void $this->assertInstanceOf(FileLink::class, $element); $target = $element->getTarget(); $this->assertInstanceOf(FileInterface::class, $target); + /** @var FileInterface $target */ $this->assertEquals($path . "/file", $target->getPath()); } /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testAllowOutsideLinksRecursive(): void { @@ -299,12 +321,14 @@ public function testAllowOutsideLinksRecursive(): void $this->assertInstanceOf(FileLink::class, $element); $target = $element->getTarget(); $this->assertInstanceOf(FileInterface::class, $target); + /** @var FileInterface $target */ $this->assertEquals($path . "/file", $target->getPath()); } /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testIgnoreOutsideLinkChains(): void { @@ -325,6 +349,7 @@ public function testIgnoreOutsideLinkChains(): void /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testAllowOutsideLinkChains(): void { @@ -347,6 +372,7 @@ public function testAllowOutsideLinkChains(): void /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testIgnoreInfiniteLinkLoops(): void { @@ -364,6 +390,7 @@ public function testIgnoreInfiniteLinkLoops(): void /** * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testIgnoreTooManyLinks(): void { @@ -386,6 +413,7 @@ public function testIgnoreTooManyLinks(): void * @return void * @throws GetTargetException * @throws MissingPermissionsException + * @throws IOException */ public function testLimitRecursiveDepth(): void { diff --git a/test/Unit/System/Directory/FilteredDirectoryTest.php b/test/Unit/System/Directory/FilteredDirectoryTest.php index e38be21..c4c70d5 100644 --- a/test/Unit/System/Directory/FilteredDirectoryTest.php +++ b/test/Unit/System/Directory/FilteredDirectoryTest.php @@ -3,6 +3,7 @@ namespace Aternos\IO\Test\Unit\System\Directory; use Aternos\IO\Exception\GetTargetException; +use Aternos\IO\Exception\IOException; use Aternos\IO\Exception\MissingPermissionsException; use Aternos\IO\Exception\PathOutsideElementException; use Aternos\IO\System\Directory\Directory; @@ -50,6 +51,7 @@ public function testGetNoFilters(): void * @throws GetTargetException * @throws MissingPermissionsException * @throws PathOutsideElementException + * @throws IOException */ public function testExcludesFiltered(): void { @@ -68,6 +70,7 @@ public function testExcludesFiltered(): void * @throws GetTargetException * @throws MissingPermissionsException * @throws PathOutsideElementException + * @throws IOException */ public function testExcludesFilteredExplicit(): void { @@ -87,6 +90,7 @@ public function testExcludesFilteredExplicit(): void * @throws GetTargetException * @throws MissingPermissionsException * @throws PathOutsideElementException + * @throws IOException */ public function testExcludesFilteredRecursive(): void { @@ -108,6 +112,7 @@ public function testExcludesFilteredRecursive(): void * @throws GetTargetException * @throws MissingPermissionsException * @throws PathOutsideElementException + * @throws IOException */ public function testIncludesOnlyFiltered(): void { @@ -127,6 +132,7 @@ public function testIncludesOnlyFiltered(): void * @throws GetTargetException * @throws MissingPermissionsException * @throws PathOutsideElementException + * @throws IOException */ public function testIncludesOnlyFilteredRecursive(): void { diff --git a/test/Unit/System/Directory/TempDirectoryTest.php b/test/Unit/System/Directory/TempDirectoryTest.php index e8feac4..f4e85d7 100644 --- a/test/Unit/System/Directory/TempDirectoryTest.php +++ b/test/Unit/System/Directory/TempDirectoryTest.php @@ -2,31 +2,42 @@ namespace Aternos\IO\Test\Unit\System\Directory; -use Aternos\IO\Exception\DeleteException; use Aternos\IO\Exception\IOException; use Aternos\IO\System\Directory\TempDirectory; use PHPUnit\Framework\TestCase; class TempDirectoryTest extends TestCase { + /** + * @throws IOException + */ public function testSelectsPathForTemporaryFile(): void { $directory = new TempDirectory(); $this->assertIsString($directory->getPath()); } + /** + * @throws IOException + */ public function testSelectsPathWithPrefix(): void { $directory = new TempDirectory("test-"); $this->assertStringStartsWith("test-", $directory->getName()); } + /** + * @throws IOException + */ public function testCreatesDirectoryOnConstruct(): void { $directory = new TempDirectory(); $this->assertDirectoryExists($directory->getPath()); } + /** + * @throws IOException + */ public function testDeletesDirectoryOnDestruct(): void { $directory = new TempDirectory(); @@ -36,6 +47,9 @@ public function testDeletesDirectoryOnDestruct(): void $this->assertDirectoryDoesNotExist($path); } + /** + * @throws IOException + */ public function testDoesNotDeleteDirectoryOnDestruct(): void { $directory = new TempDirectory("test-", false); diff --git a/test/Unit/System/File/FileTest.php b/test/Unit/System/File/FileTest.php index b22b205..b9736a2 100644 --- a/test/Unit/System/File/FileTest.php +++ b/test/Unit/System/File/FileTest.php @@ -110,6 +110,7 @@ public function testThrowsExceptionOnImpossibleRead(): void $reflectionObject = new ReflectionObject($element); $reflectionObject->getProperty("socketResource")->setValue($element, fopen($path, "w")); $this->expectException(ReadException::class); + /** @noinspection SpellCheckingInspection */ $this->expectExceptionMessage("Could not read from file: fread(): Read of 8192 bytes failed with errno=9 Bad file descriptor (" . $path . ")"); $element->read(4); } @@ -121,6 +122,7 @@ public function testThrowsExceptionOnInvalidPath(): void { $element = $this->createElement("/dev/null/test"); $this->expectException(IOException::class); + /** @noinspection SpellCheckingInspection */ $this->expectExceptionMessage("Could not open file: fopen(/dev/null/test): Failed to open stream: No such file or directory (/dev/null/test)"); $element->read(4); } @@ -136,6 +138,7 @@ public function testThrowsExceptionOnMissingReadPermissions(): void chmod($path, 0222); $element = $this->createElement($path); $this->expectException(MissingPermissionsException::class); + /** @noinspection SpellCheckingInspection */ $this->expectExceptionMessage("Could not read from file due to missing read permissions: fread(): Read of 8192 bytes failed with errno=9 Bad file descriptor (" . $path . ")"); $element->read(4); } @@ -289,6 +292,7 @@ public function testThrowsExceptionOnImpossibleWrite(): void $reflectionObject = new ReflectionObject($element); $reflectionObject->getProperty("socketResource")->setValue($element, fopen($path, "r")); $this->expectException(WriteException::class); + /** @noinspection SpellCheckingInspection */ $this->expectExceptionMessage("Could not write to file: fwrite(): Write of 4 bytes failed with errno=9 Bad file descriptor (" . $path . ")"); $element->write("test"); } @@ -304,6 +308,7 @@ public function testThrowsExceptionOnMissingWritePermissions(): void chmod($path, 0444); $element = $this->createElement($path); $this->expectException(MissingPermissionsException::class); + /** @noinspection SpellCheckingInspection */ $this->expectExceptionMessage("Could not write to file due to missing write permissions: fwrite(): Write of 4 bytes failed with errno=9 Bad file descriptor (" . $path . ")"); $element->write("test"); } diff --git a/test/Unit/System/File/TempDiskFileTest.php b/test/Unit/System/File/TempDiskFileTest.php index f0f7b1f..e09a942 100644 --- a/test/Unit/System/File/TempDiskFileTest.php +++ b/test/Unit/System/File/TempDiskFileTest.php @@ -12,6 +12,9 @@ class TempDiskFileTest extends TestCase { + /** + * @throws IOException + */ public function testSelectsPathForTemporaryFile(): void { $file = new TempDiskFile(); @@ -25,6 +28,9 @@ public function testSelectsPathWithPrefix(): void $this->assertStringStartsWith("test-", $file->getName()); } + /** + * @throws IOException + */ public function testDeletesFileOnDestruct(): void { $file = new TempDiskFile(); @@ -34,6 +40,9 @@ public function testDeletesFileOnDestruct(): void $this->assertFileDoesNotExist($path); } + /** + * @throws IOException + */ public function testDoesNotDeleteFileOnDestruct(): void { $file = new TempDiskFile("test-", false); diff --git a/test/Unit/System/FilesystemTestCase.php b/test/Unit/System/FilesystemTestCase.php index 2453ac2..5cd2859 100644 --- a/test/Unit/System/FilesystemTestCase.php +++ b/test/Unit/System/FilesystemTestCase.php @@ -2,13 +2,16 @@ namespace Aternos\IO\Test\Unit\System; +use Aternos\IO\Exception\IOException; use Aternos\IO\Exception\MoveException; use Aternos\IO\Exception\PathOutsideElementException; +use Aternos\IO\Exception\StatException; +use Aternos\IO\Exception\TouchException; +use Aternos\IO\Interfaces\Features\CreateInterface; +use Aternos\IO\Interfaces\IOElementInterface; use Aternos\IO\System\Directory\Directory; use Aternos\IO\System\FilesystemElement; use Aternos\IO\System\FilesystemInterface; -use Aternos\IO\Interfaces\Features\CreateInterface; -use Aternos\IO\Interfaces\IOElementInterface; abstract class FilesystemTestCase extends TmpDirTestCase { @@ -21,6 +24,7 @@ abstract protected function createElement(string $path): FilesystemElement|IOEle /** * @param FilesystemInterface $element * @return void + * @throws IOException */ protected function create(FilesystemInterface $element): void { @@ -42,6 +46,7 @@ protected function assertExists(string $path): void * @param string $path * @param FilesystemInterface[] $elements * @return FilesystemInterface + * @throws IOException */ protected function getByPathFromArray(string $path, array $elements): FilesystemInterface { @@ -57,6 +62,7 @@ protected function getByPathFromArray(string $path, array $elements): Filesystem * @param string $path * @param class-string $type * @param FilesystemInterface[] $elements + * @throws IOException */ protected function assertPathHasTypeInArray(string $path, string $type, array $elements): void { @@ -64,6 +70,10 @@ protected function assertPathHasTypeInArray(string $path, string $type, array $e $this->assertInstanceOf($type, $element); } + /** + * @return void + * @throws IOException + */ public function testGetPath(): void { $path = $this->getTmpPath() . "/test"; @@ -71,6 +81,10 @@ public function testGetPath(): void $this->assertEquals($path, $element->getPath()); } + /** + * @return void + * @throws IOException + */ public function testGetName(): void { $path = $this->getTmpPath() . "/test"; @@ -80,6 +94,7 @@ public function testGetName(): void /** * @throws PathOutsideElementException + * @throws IOException */ public function testGetRelativePath(): void { @@ -91,6 +106,7 @@ public function testGetRelativePath(): void /** * @throws PathOutsideElementException + * @throws IOException */ public function testGetRelativePathOutsideElement(): void { @@ -102,6 +118,7 @@ public function testGetRelativePathOutsideElement(): void /** * @throws PathOutsideElementException + * @throws IOException */ public function testGetRelativePathMultipleLayersOutsideElement(): void { @@ -114,6 +131,7 @@ public function testGetRelativePathMultipleLayersOutsideElement(): void /** * @return void * @throws PathOutsideElementException + * @throws IOException */ public function testGetRelativePathInOtherSubDirectory(): void { @@ -123,6 +141,11 @@ public function testGetRelativePathInOtherSubDirectory(): void $this->assertEquals("../sub-dir/test", $element->getRelativePathTo($directory, true)); } + /** + * @return void + * @throws IOException + * @throws PathOutsideElementException + */ public function testThrowsExceptionOnUnallowedRelativePathOutsideElement(): void { $path = $this->getTmpPath() . "/test"; @@ -136,6 +159,7 @@ public function testThrowsExceptionOnUnallowedRelativePathOutsideElement(): void /** * @return void * @throws MoveException + * @throws IOException */ public function testMovePath(): void { @@ -149,6 +173,11 @@ public function testMovePath(): void $this->assertFileDoesNotExist($path); } + /** + * @return void + * @throws IOException + * @throws MoveException + */ public function testThrowsExceptionOnImpossibleMove(): void { $path = $this->getTmpPath() . "/test"; @@ -162,6 +191,7 @@ public function testThrowsExceptionOnImpossibleMove(): void /** * @throws MoveException + * @throws IOException */ public function testChangeName(): void { @@ -175,6 +205,10 @@ public function testChangeName(): void $this->assertFileDoesNotExist($path); } + /** + * @return void + * @throws IOException + */ public function testCheckIfElementExists(): void { $path = $this->getTmpPath() . "/test"; @@ -184,6 +218,10 @@ public function testCheckIfElementExists(): void $this->assertTrue($element->exists()); } + /** + * @return void + * @throws IOException + */ public function testDelete(): void { $path = $this->getTmpPath() . "/test"; @@ -194,6 +232,10 @@ public function testDelete(): void $this->assertFalse(file_exists($path)); } + /** + * @return void + * @throws IOException + */ public function testDeleteNonExisting(): void { $path = $this->getTmpPath() . "/test"; @@ -203,6 +245,190 @@ public function testDeleteNonExisting(): void $this->assertFalse(file_exists($path)); } + /** + * @return void + * @throws IOException + * @throws StatException + */ + public function testGetModificationTimestamp(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->create($element); + $this->assertIsInt($element->getModificationTimestamp()); + $this->assertEquals(filemtime($path), $element->getModificationTimestamp()); + } + + /** + * @return void + * @throws IOException + * @throws StatException + */ + public function testGetModificationTimestampThrowsException(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->expectException(StatException::class); + /** @noinspection SpellCheckingInspection */ + $this->expectExceptionMessage("Could not get modification timestamp (" . $path . "): filemtime(): stat failed for " . $path); + $element->getModificationTimestamp(); + } + + /** + * @return void + * @throws IOException + * @throws StatException + */ + public function testGetAccessTimestamp(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->create($element); + $this->assertIsInt($element->getAccessTimestamp()); + $this->assertEquals(fileatime($path), $element->getAccessTimestamp()); + } + + /** + * @return void + * @throws IOException + * @throws StatException + */ + public function testGetAccessTimestampThrowsException(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->expectException(StatException::class); + /** @noinspection SpellCheckingInspection */ + $this->expectExceptionMessage("Could not get access timestamp (" . $path . "): fileatime(): stat failed for " . $path); + $element->getAccessTimestamp(); + } + + /** + * @return void + * @throws IOException + * @throws StatException + */ + public function testGetStatusChangeTimestamp(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->create($element); + $this->assertIsInt($element->getStatusChangeTimestamp()); + $this->assertEquals(filectime($path), $element->getStatusChangeTimestamp()); + } + + /** + * @return void + * @throws IOException + * @throws StatException + */ + public function testGetStatusChangeTimestampThrowsException(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->expectException(StatException::class); + /** @noinspection SpellCheckingInspection */ + $this->expectExceptionMessage("Could not get status change timestamp (" . $path . "): filectime(): stat failed for " . $path); + $element->getStatusChangeTimestamp(); + } + + /** + * @return void + * @throws IOException + * @throws StatException + * @throws TouchException + */ + public function testSetAccessTimestamp(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->create($element); + $timestamp = 1234567890; + $element->setAccessTimestamp($timestamp); + $this->assertEquals($timestamp, fileatime($path)); + $this->assertEquals($timestamp, $element->getAccessTimestamp()); + } + + /** + * @return void + * @throws IOException + * @throws StatException + * @throws TouchException + */ + public function testSetAccessTimestampThrowsExceptionOnMissingElement(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->expectException(StatException::class); + /** @noinspection SpellCheckingInspection */ + $this->expectExceptionMessage("Could not set access timestamp because element does not exist (" . $path . ")"); + $element->setAccessTimestamp(1234567890); + } + + /** + * @return void + * @throws IOException + * @throws StatException + * @throws TouchException + */ + public function testSetAccessTimestampThrowsExceptionOnImpossibleSet(): void + { + $element = $this->createElement("/"); + $this->expectException(TouchException::class); + $this->expectExceptionMessage("Could not set access timestamp (" . $element->getPath() . ")"); + $element->setAccessTimestamp(1234567890); + } + + /** + * @return void + * @throws IOException + * @throws StatException + * @throws TouchException + */ + public function testSetModificationTimestamp(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->create($element); + $timestamp = 1234567890; + $element->setModificationTimestamp($timestamp); + $this->assertEquals($timestamp, filemtime($path)); + $this->assertEquals($timestamp, $element->getModificationTimestamp()); + } + + /** + * @return void + * @throws IOException + * @throws StatException + * @throws TouchException + */ + public function testSetModificationTimestampThrowsExceptionOnMissingElement(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->expectException(StatException::class); + /** @noinspection SpellCheckingInspection */ + $this->expectExceptionMessage("Could not set modification timestamp because element does not exist (" . $path . ")"); + $element->setModificationTimestamp(1234567890); + } + + /** + * @return void + * @throws IOException + * @throws StatException + * @throws TouchException + */ + public function testSetModificationTimestampThrowsExceptionOnImpossibleSet(): void + { + $element = $this->createElement("/"); + $this->expectException(TouchException::class); + $this->expectExceptionMessage("Could not set modification timestamp (" . $element->getPath() . ")"); + $element->setModificationTimestamp(1234567890); + } + + /** + * @return void + */ public function testSerialize(): void { $path = $this->getTmpPath() . "/test"; @@ -211,6 +437,9 @@ public function testSerialize(): void $this->assertIsString($serialized); } + /** + * @return void + */ public function testSerializeContainsPath(): void { $path = $this->getTmpPath() . "/test"; diff --git a/test/Unit/System/Link/DeadLinkTest.php b/test/Unit/System/Link/DeadLinkTest.php index 1b12753..f5df47d 100644 --- a/test/Unit/System/Link/DeadLinkTest.php +++ b/test/Unit/System/Link/DeadLinkTest.php @@ -3,11 +3,15 @@ namespace Aternos\IO\Test\Unit\System\Link; use Aternos\IO\Exception\GetTargetException; +use Aternos\IO\Exception\IOException; +use Aternos\IO\Exception\StatException; +use Aternos\IO\Exception\TouchException; class DeadLinkTest extends LinkTest { /** * @throws GetTargetException + * @throws IOException */ public function testGetTargetPath(): void { @@ -18,6 +22,7 @@ public function testGetTargetPath(): void /** * @throws GetTargetException + * @throws IOException */ public function testGetFinalTargetPath(): void { @@ -28,6 +33,9 @@ public function testGetFinalTargetPath(): void $this->assertEquals($this->getTmpPath() . "/test-target", $element->getFinalTargetPath()); } + /** + * @throws IOException + */ public function testThrowsExceptionOnGetFinalTargetWithInfiniteLinkLoop(): void { symlink($this->getTmpPath() . "/a", $this->getTmpPath() . "/b"); @@ -39,6 +47,9 @@ public function testThrowsExceptionOnGetFinalTargetWithInfiniteLinkLoop(): void $element->getFinalTarget(); } + /** + * @throws IOException + */ public function testThrowsExceptionOnGetFinalTargetPathWithInfiniteLinkLoop(): void { symlink($this->getTmpPath() . "/a", $this->getTmpPath() . "/b"); @@ -50,6 +61,9 @@ public function testThrowsExceptionOnGetFinalTargetPathWithInfiniteLinkLoop(): v $element->getFinalTargetPath(); } + /** + * @throws IOException + */ public function testThrowsExceptionOnGetFinalTargetWithTooManyLinks(): void { $path = $this->getTmpPath(); @@ -62,6 +76,9 @@ public function testThrowsExceptionOnGetFinalTargetWithTooManyLinks(): void $element->getFinalTarget(); } + /** + * @throws IOException + */ public function testThrowsExceptionOnGetFinalTargetPathWithTooManyLinks(): void { $path = $this->getTmpPath(); @@ -73,4 +90,83 @@ public function testThrowsExceptionOnGetFinalTargetPathWithTooManyLinks(): void $this->expectExceptionMessage("Could not get link target because of too many levels of links (" . $path . "/41)"); $element->getFinalTargetPath(); } + + /** + * @return void + * @throws GetTargetException + * @throws IOException + */ + public function testThrowsExceptionOnGetTargetWithMissingTarget(): void + { + $this->expectException(GetTargetException::class); + $this->expectExceptionMessage("Could not get link target because target does not exist (" . $this->getTmpPath() . "/test-target" . ")"); + $element = $this->createElement($this->getTmpPath() . "/test"); + $this->create($element); + $element->getTarget(); + } + + public function testGetModificationTimestamp(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->create($element); + $this->expectException(StatException::class); + /** @noinspection SpellCheckingInspection */ + $this->expectExceptionMessage("Could not get modification timestamp (" . $path . "): filemtime(): stat failed for " . $path); + $element->getModificationTimestamp(); + } + + public function testGetAccessTimestamp(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->create($element); + $this->expectException(StatException::class); + /** @noinspection SpellCheckingInspection */ + $this->expectExceptionMessage("Could not get access timestamp (" . $path . "): fileatime(): stat failed for " . $path); + $element->getAccessTimestamp(); + } + + public function testGetStatusChangeTimestamp(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->create($element); + $this->expectException(StatException::class); + /** @noinspection SpellCheckingInspection */ + $this->expectExceptionMessage("Could not get status change timestamp (" . $path . "): filectime(): stat failed for " . $path); + $element->getStatusChangeTimestamp(); + } + + /** + * @return void + * @throws IOException + * @throws StatException + * @throws TouchException + */ + public function testSetAccessTimestamp(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->create($element); + $this->expectException(StatException::class); + $this->expectExceptionMessage("Could not set access timestamp because element does not exist (" . $path . ")"); + $element->setAccessTimestamp(0); + } + + /** + * @return void + * @throws IOException + * @throws StatException + * @throws TouchException + */ + public function testSetModificationTimestamp(): void + { + $path = $this->getTmpPath() . "/test"; + $element = $this->createElement($path); + $this->create($element); + $this->expectException(StatException::class); + $this->expectExceptionMessage("Could not set modification timestamp because element does not exist (" . $path . ")"); + $element->setModificationTimestamp(0); + } } \ No newline at end of file diff --git a/test/Unit/System/Link/DirectoryLinkTest.php b/test/Unit/System/Link/DirectoryLinkTest.php index 6453ce0..1cb339f 100644 --- a/test/Unit/System/Link/DirectoryLinkTest.php +++ b/test/Unit/System/Link/DirectoryLinkTest.php @@ -4,13 +4,14 @@ use Aternos\IO\Exception\DeleteException; use Aternos\IO\Exception\GetTargetException; +use Aternos\IO\Exception\IOException; use Aternos\IO\Exception\SetTargetException; -use Aternos\IO\System\Directory\Directory; -use Aternos\IO\System\File\File; -use Aternos\IO\System\Link\DirectoryLink; use Aternos\IO\Interfaces\IOElementInterface; use Aternos\IO\Interfaces\Types\DirectoryInterface; use Aternos\IO\Interfaces\Types\FileInterface; +use Aternos\IO\System\Directory\Directory; +use Aternos\IO\System\File\File; +use Aternos\IO\System\Link\DirectoryLink; use Generator; class DirectoryLinkTest extends LinkTest @@ -22,6 +23,8 @@ protected function createElement(string $path): DirectoryLink /** * @throws GetTargetException + * @throws IOException + * @throws IOException */ public function testGetTarget(): void { @@ -36,6 +39,8 @@ public function testGetTarget(): void /** * @return void * @throws GetTargetException + * @throws IOException + * @throws IOException */ public function testGetTargetTwiceReturnsSameObject(): void { @@ -46,6 +51,9 @@ public function testGetTargetTwiceReturnsSameObject(): void $this->assertSame($target, $element->getTarget()); } + /** + * @throws IOException + */ public function testThrowsExceptionOnGetTargetWithInvalidTarget(): void { touch($this->getTmpPath() . "/test-target"); @@ -56,8 +64,24 @@ public function testThrowsExceptionOnGetTargetWithInvalidTarget(): void $element->getTarget(); } + /** + * @return void + * @throws GetTargetException + * @throws IOException + */ + public function testGetNewTargetDirectoryIfMissing(): void + { + symlink($this->getTmpPath() . "/test-target", $this->getTmpPath() . "/test"); + $element = $this->createElement($this->getTmpPath() . "/test"); + $target = $element->getTarget(); + $this->assertInstanceOf(DirectoryInterface::class, $target); + /** @var DirectoryInterface $target */ + $this->assertEquals($this->getTmpPath() . "/test-target", $target->getPath()); + } + /** * @throws GetTargetException + * @throws IOException */ public function testGetTargetPath(): void { @@ -69,6 +93,7 @@ public function testGetTargetPath(): void /** * @throws GetTargetException + * @throws IOException */ public function testGetFinalTargetPath(): void { @@ -82,6 +107,8 @@ public function testGetFinalTargetPath(): void /** * @throws GetTargetException + * @throws IOException + * @throws IOException */ public function testGetTargetOnLinkChainGetsLink(): void { @@ -97,6 +124,8 @@ public function testGetTargetOnLinkChainGetsLink(): void /** * @throws GetTargetException + * @throws IOException + * @throws IOException */ public function testGetFinalTarget(): void { @@ -113,6 +142,7 @@ public function testGetFinalTarget(): void /** * @throws SetTargetException * @throws DeleteException + * @throws IOException */ public function testSetTarget(): void { @@ -126,6 +156,7 @@ public function testSetTarget(): void /** * @throws SetTargetException * @throws DeleteException + * @throws IOException */ public function testSetTargetReplacesTarget(): void { @@ -140,6 +171,7 @@ public function testSetTargetReplacesTarget(): void /** * @throws DeleteException + * @throws IOException */ public function testThrowsExceptionOnImpossibleSetTarget(): void { @@ -151,6 +183,7 @@ public function testThrowsExceptionOnImpossibleSetTarget(): void /** * @throws DeleteException + * @throws IOException */ public function testThrowsExceptionOnInvalidSetTarget(): void { @@ -164,6 +197,8 @@ public function testThrowsExceptionOnInvalidSetTarget(): void * @throws GetTargetException * @throws SetTargetException * @throws DeleteException + * @throws IOException + * @throws IOException */ public function testCreate(): void { @@ -176,6 +211,11 @@ public function testCreate(): void /** * @throws GetTargetException + * @throws IOException + * @throws IOException + * @throws IOException + * @throws IOException + * @throws IOException */ public function testGetChildren(): void { @@ -204,6 +244,12 @@ public function testGetChildren(): void /** * @throws GetTargetException + * @throws IOException + * @throws IOException + * @throws IOException + * @throws IOException + * @throws IOException + * @throws IOException */ public function testGetChildrenRecursive(): void { diff --git a/test/Unit/System/Link/FileLinkTest.php b/test/Unit/System/Link/FileLinkTest.php index f548bd8..db86951 100644 --- a/test/Unit/System/Link/FileLinkTest.php +++ b/test/Unit/System/Link/FileLinkTest.php @@ -6,10 +6,10 @@ use Aternos\IO\Exception\GetTargetException; use Aternos\IO\Exception\IOException; use Aternos\IO\Exception\SetTargetException; +use Aternos\IO\Interfaces\Types\FileInterface; use Aternos\IO\System\Directory\Directory; use Aternos\IO\System\File\File; use Aternos\IO\System\Link\FileLink; -use Aternos\IO\Interfaces\Types\FileInterface; use ReflectionException; use ReflectionObject; @@ -22,6 +22,7 @@ protected function createElement(string $path): FileLink /** * @throws GetTargetException + * @throws IOException */ public function testGetTarget(): void { @@ -30,12 +31,14 @@ public function testGetTarget(): void $element = $this->createElement($this->getTmpPath() . "/test"); $target = $element->getTarget(); $this->assertInstanceOf(FileInterface::class, $target); + /** @var FileInterface $target */ $this->assertEquals($this->getTmpPath() . "/test-target", $target->getPath()); } /** * @return void * @throws GetTargetException + * @throws IOException */ public function testGetTargetTwiceReturnsSameObject(): void { @@ -46,6 +49,11 @@ public function testGetTargetTwiceReturnsSameObject(): void $this->assertSame($target, $element->getTarget()); } + /** + * @return void + * @throws GetTargetException + * @throws IOException + */ public function testThrowsExceptionOnGetTargetWithInvalidTarget(): void { mkdir($this->getTmpPath() . "/test-target"); @@ -57,7 +65,23 @@ public function testThrowsExceptionOnGetTargetWithInvalidTarget(): void } /** + * @return void * @throws GetTargetException + * @throws IOException + */ + public function testGetNewTargetFileIfMissing(): void + { + symlink($this->getTmpPath() . "/test-target", $this->getTmpPath() . "/test"); + $element = $this->createElement($this->getTmpPath() . "/test"); + $target = $element->getTarget(); + $this->assertInstanceOf(FileInterface::class, $target); + /** @var FileInterface $target */ + $this->assertEquals($this->getTmpPath() . "/test-target", $target->getPath()); + } + + /** + * @throws GetTargetException + * @throws IOException */ public function testGetTargetPath(): void { @@ -69,6 +93,7 @@ public function testGetTargetPath(): void /** * @throws GetTargetException + * @throws IOException */ public function testGetFinalTargetPath(): void { @@ -82,6 +107,7 @@ public function testGetFinalTargetPath(): void /** * @throws GetTargetException + * @throws IOException */ public function testGetTargetOnLinkChainGetsLink(): void { @@ -97,6 +123,7 @@ public function testGetTargetOnLinkChainGetsLink(): void /** * @throws GetTargetException + * @throws IOException */ public function testGetFinalTarget(): void { @@ -113,6 +140,7 @@ public function testGetFinalTarget(): void /** * @throws SetTargetException * @throws DeleteException + * @throws IOException */ public function testSetTarget(): void { @@ -126,6 +154,7 @@ public function testSetTarget(): void /** * @throws SetTargetException * @throws DeleteException + * @throws IOException */ public function testSetTargetReplacesTarget(): void { @@ -140,6 +169,7 @@ public function testSetTargetReplacesTarget(): void /** * @throws DeleteException + * @throws IOException */ public function testThrowsExceptionOnImpossibleSetTarget(): void { @@ -151,6 +181,7 @@ public function testThrowsExceptionOnImpossibleSetTarget(): void /** * @throws DeleteException + * @throws IOException */ public function testThrowsExceptionOnInvalidSetTarget(): void { @@ -189,6 +220,7 @@ public function testClose(): void * @throws DeleteException * @throws GetTargetException * @throws SetTargetException + * @throws IOException */ public function testCreate(): void { @@ -204,6 +236,7 @@ public function testCreate(): void * @throws DeleteException * @throws GetTargetException * @throws SetTargetException + * @throws IOException */ public function testGetPosition(): void { @@ -223,6 +256,7 @@ public function testGetPosition(): void * @throws DeleteException * @throws GetTargetException * @throws SetTargetException + * @throws IOException */ public function testSetPosition(): void { @@ -239,6 +273,7 @@ public function testSetPosition(): void * @throws GetTargetException * @throws SetTargetException * @throws DeleteException + * @throws IOException */ public function testGetSize(): void { @@ -254,6 +289,7 @@ public function testGetSize(): void * @throws DeleteException * @throws GetTargetException * @throws SetTargetException + * @throws IOException */ public function testRead(): void { @@ -269,6 +305,7 @@ public function testRead(): void * @throws DeleteException * @throws GetTargetException * @throws SetTargetException + * @throws IOException */ public function testWrite(): void { @@ -284,6 +321,7 @@ public function testWrite(): void * @throws DeleteException * @throws GetTargetException * @throws SetTargetException + * @throws IOException */ public function testTruncate(): void { diff --git a/test/Unit/System/Link/LinkTest.php b/test/Unit/System/Link/LinkTest.php index e04947e..4ab0809 100644 --- a/test/Unit/System/Link/LinkTest.php +++ b/test/Unit/System/Link/LinkTest.php @@ -4,6 +4,7 @@ use Aternos\IO\Exception\DeleteException; use Aternos\IO\Exception\GetTargetException; +use Aternos\IO\Exception\IOException; use Aternos\IO\System\FilesystemInterface; use Aternos\IO\System\Link\Link; use Aternos\IO\Test\Unit\System\FilesystemTestCase; @@ -23,6 +24,10 @@ protected function createElement(string $path): Link protected function create(FilesystemInterface $element): void { symlink($this->getTmpPath() . "/test-target", $element->getPath()); + if (get_class($this) === LinkTest::class) { + touch($this->getTmpPath() . "/test-target"); + } + parent::create($element); } protected function assertExists(string $path): void @@ -32,6 +37,7 @@ protected function assertExists(string $path): void /** * @throws ReflectionException + * @throws IOException */ public function testThrowsExceptionOnImpossibleDelete(): void { @@ -45,34 +51,41 @@ public function testThrowsExceptionOnImpossibleDelete(): void /** * @return void * @throws GetTargetException + * @throws IOException */ - public function testThrowsExceptionOnGetTargetWithMissingLink(): void + public function testGetTargetTwiceReturnsSameObject(): void { - $this->expectException(GetTargetException::class); - $this->expectExceptionMessage("Could not get link target because link does not exist (" . $this->getTmpPath() . "/test" . ")"); + touch($this->getTmpPath() . "/test-target"); + symlink($this->getTmpPath() . "/test-target", $this->getTmpPath() . "/test"); $element = $this->createElement($this->getTmpPath() . "/test"); - $element->getTarget(); + $target = $element->getTarget(); + $this->assertSame($target, $element->getTarget()); } - public function testThrowsExceptionOnGetTargetWithNoLink(): void + /** + * @return void + * @throws GetTargetException + * @throws IOException + */ + public function testThrowsExceptionOnGetTargetWithMissingLink(): void { $this->expectException(GetTargetException::class); $this->expectExceptionMessage("Could not get link target because link does not exist (" . $this->getTmpPath() . "/test" . ")"); $element = $this->createElement($this->getTmpPath() . "/test"); - touch($element->getPath()); $element->getTarget(); } /** * @return void * @throws GetTargetException + * @throws IOException */ - public function testThrowsExceptionOnGetTargetWithMissingTarget(): void + public function testThrowsExceptionOnGetTargetWithNoLink(): void { $this->expectException(GetTargetException::class); - $this->expectExceptionMessage("Could not get link target because target does not exist (" . $this->getTmpPath() . "/test-target" . ")"); + $this->expectExceptionMessage("Could not get link target because link does not exist (" . $this->getTmpPath() . "/test" . ")"); $element = $this->createElement($this->getTmpPath() . "/test"); - $this->create($element); + touch($element->getPath()); $element->getTarget(); } diff --git a/test/Unit/System/Stream/SocketStreamTestCase.php b/test/Unit/System/Stream/SocketStreamTestCase.php index 74431d0..3cd9929 100644 --- a/test/Unit/System/Stream/SocketStreamTestCase.php +++ b/test/Unit/System/Stream/SocketStreamTestCase.php @@ -2,6 +2,7 @@ namespace Aternos\IO\Test\Unit\System\Stream; +use Aternos\IO\Exception\IOException; use Aternos\IO\Interfaces\Features\CloseInterface; use PHPUnit\Framework\TestCase; use ReflectionException; @@ -36,6 +37,7 @@ abstract protected function createStream(): CloseInterface; /** * @throws ReflectionException + * @throws IOException */ public function testClose(): void { diff --git a/test/Unit/System/Stream/SocketWriteStreamTest.php b/test/Unit/System/Stream/SocketWriteStreamTest.php index 670389e..a54b96d 100644 --- a/test/Unit/System/Stream/SocketWriteStreamTest.php +++ b/test/Unit/System/Stream/SocketWriteStreamTest.php @@ -2,6 +2,7 @@ namespace Aternos\IO\Test\Unit\System\Stream; +use Aternos\IO\Exception\IOException; use Aternos\IO\System\Socket\Stream\SocketWriteStream; use Aternos\IO\Test\Unit\System\Stream\Trait\SocketWriteTestTrait; @@ -14,6 +15,9 @@ protected function createStream(): SocketWriteStream return new SocketWriteStream($this->getLocalSocket()); } + /** + * @throws IOException + */ public function testGetName(): void { $stream = $this->createStream(); diff --git a/test/Unit/System/Stream/Trait/SocketReadTestTrait.php b/test/Unit/System/Stream/Trait/SocketReadTestTrait.php index 9e94fe2..4b404ca 100644 --- a/test/Unit/System/Stream/Trait/SocketReadTestTrait.php +++ b/test/Unit/System/Stream/Trait/SocketReadTestTrait.php @@ -2,6 +2,7 @@ namespace Aternos\IO\Test\Unit\System\Stream\Trait; +use Aternos\IO\Exception\IOException; use Aternos\IO\Exception\ReadException; use Aternos\IO\Interfaces\Types\Stream\ReadStreamInterface; use ReflectionException; @@ -11,6 +12,9 @@ trait SocketReadTestTrait { abstract protected function createStream(): ReadStreamInterface; + /** + * @throws IOException + */ public function testRead(): void { fwrite($this->getRemoteSocket(), "test"); @@ -19,12 +23,18 @@ public function testRead(): void $this->assertEquals("test", $stream->read(4)); } + /** + * @throws IOException + */ public function testReadEmpty(): void { $stream = $this->createStream(); $this->assertEquals("", $stream->read(4)); } + /** + * @throws IOException + */ public function testReadNothing(): void { fwrite($this->getRemoteSocket(), "test"); @@ -36,6 +46,7 @@ public function testReadNothing(): void /** * @return void * @throws ReflectionException + * @throws IOException */ public function testThrowsExceptionOnImpossibleRead(): void { @@ -45,6 +56,7 @@ public function testThrowsExceptionOnImpossibleRead(): void $reflectionObject->getProperty("socketResource")->setValue($stream, fopen("/dev/null", "w")); $this->expectException(ReadException::class); + /** @noinspection SpellCheckingInspection */ $this->expectExceptionMessage("Could not read from " . $stream->getName() . ": fread(): Read of 8192 bytes failed with errno=9 Bad file descriptor"); $stream->read(4); } diff --git a/test/Unit/System/Stream/Trait/SocketWriteTestTrait.php b/test/Unit/System/Stream/Trait/SocketWriteTestTrait.php index 2a0f6f1..3a2749d 100644 --- a/test/Unit/System/Stream/Trait/SocketWriteTestTrait.php +++ b/test/Unit/System/Stream/Trait/SocketWriteTestTrait.php @@ -50,6 +50,7 @@ public function testThrowsExceptionOnImpossibleWrite(): void $reflectionObject->getProperty("socketResource")->setValue($stream, fopen("/dev/null", "r")); $this->expectException(WriteException::class); + /** @noinspection SpellCheckingInspection */ $this->expectExceptionMessage("Could not write to " . $stream->getName() . ": fwrite(): Write of 4 bytes failed with errno=9 Bad file descriptor"); $stream->write("test"); } diff --git a/test/Unit/System/TmpDirTestCase.php b/test/Unit/System/TmpDirTestCase.php index e6ca740..6e13d71 100644 --- a/test/Unit/System/TmpDirTestCase.php +++ b/test/Unit/System/TmpDirTestCase.php @@ -11,6 +11,7 @@ abstract class TmpDirTestCase extends TestCase protected function getTmpPath(): string { if ($this->tmpPath === null) { + /** @noinspection SpellCheckingInspection */ $this->tmpPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid("aternos-io-test-"); mkdir($this->tmpPath); }