diff --git a/src/ComposerRequireChecker/JsonLoader.php b/src/ComposerRequireChecker/JsonLoader.php index 9770491a..19a4a23b 100644 --- a/src/ComposerRequireChecker/JsonLoader.php +++ b/src/ComposerRequireChecker/JsonLoader.php @@ -53,7 +53,7 @@ private static function getFileContentFromPath(string $path): string Assert::file($path); Assert::readable($path); } catch (InvalidArgumentException $exception) { - throw new NotReadable('unable to read ' . $path, 0, $exception); + throw new NotReadable('unable to read file: ' . $exception->getMessage(), 0, $exception); } $content = file_get_contents($path); diff --git a/test/ComposerRequireCheckerTest/JsonLoaderTest.php b/test/ComposerRequireCheckerTest/JsonLoaderTest.php index 0e8b3ce1..05d4b6c1 100644 --- a/test/ComposerRequireCheckerTest/JsonLoaderTest.php +++ b/test/ComposerRequireCheckerTest/JsonLoaderTest.php @@ -9,6 +9,8 @@ use ComposerRequireChecker\JsonLoader; use PHPUnit\Framework\TestCase; +use function file_exists; + /** @covers \ComposerRequireChecker\JsonLoader */ final class JsonLoaderTest extends TestCase { @@ -16,6 +18,8 @@ public function testHasErrorWithWrongPath(): void { $path = __DIR__ . '/wrong/path/non-existing-file.json'; $this->expectException(NotReadable::class); + $this->expectExceptionMessage('unable to read file: The file "' . $path . '" does not exist.'); + $this->expectExceptionCode(0); JsonLoader::getData($path); } @@ -23,6 +27,30 @@ public function testHasErrorWithInvalidFile(): void { $path = __DIR__ . '/../fixtures/invalidJson'; $this->expectException(InvalidJson::class); + $this->expectExceptionMessage('error parsing ' . $path . ': Syntax error'); + $this->expectExceptionCode(0); + JsonLoader::getData($path); + } + + public function testHasErrorWithUnreadableFile(): void + { + $path = '/etc/shadow'; + if (! file_exists($path)) { + $this->markTestSkipped('This system does not have ' . $path); + } + + $this->expectException(NotReadable::class); + $this->expectExceptionMessage('unable to read file: The path "' . $path . '" is not readable.'); + $this->expectExceptionCode(0); + JsonLoader::getData($path); + } + + public function testHasErrorWithDirectory(): void + { + $path = __DIR__; + $this->expectException(NotReadable::class); + $this->expectExceptionMessage('unable to read file: The path "' . $path . '" is not a file.'); + $this->expectExceptionCode(0); JsonLoader::getData($path); } @@ -30,9 +58,27 @@ public function testHasDataWithValidFileButNoArrayContent(): void { $path = __DIR__ . '/../fixtures/validJsonNotAnArray.json'; $this->expectException(InvalidJson::class); + $this->expectExceptionMessage('error parsing ' . $path . ': Expected an array.'); + $this->expectExceptionCode(0); + JsonLoader::getData($path); + } + + public function testHasDataWithValidFileButExcessiveDepth(): void + { + $path = __DIR__ . '/../fixtures/validJsonExcessiveDepth.json'; + $this->expectException(InvalidJson::class); + $this->expectExceptionMessage('error parsing ' . $path . ': Maximum stack depth exceeded'); + $this->expectExceptionCode(0); JsonLoader::getData($path); } + public function testHasDataWithValidFileWithVeryLargeDepth(): void + { + $path = __DIR__ . '/../fixtures/validJsonVeryLargeDepth.json'; + $data = JsonLoader::getData($path); + $this->assertEquals('bar', $data['foo'] ?? null); + } + public function testHasDataWithValidFile(): void { $path = __DIR__ . '/../fixtures/validJson.json'; diff --git a/test/fixtures/validJsonExcessiveDepth.json b/test/fixtures/validJsonExcessiveDepth.json new file mode 100644 index 00000000..cf74666d --- /dev/null +++ b/test/fixtures/validJsonExcessiveDepth.json @@ -0,0 +1,6 @@ +{ + "foo": "bar", + "baz": [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ + "This string is at a depth of 513, which is larger than the allowed maximum of 512. 512 is the built-in default." + ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +} diff --git a/test/fixtures/validJsonVeryLargeDepth.json b/test/fixtures/validJsonVeryLargeDepth.json new file mode 100644 index 00000000..e7d82555 --- /dev/null +++ b/test/fixtures/validJsonVeryLargeDepth.json @@ -0,0 +1,6 @@ +{ + "foo": "bar", + "baz": [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ + "This string is at a depth of 512, which is the largest allowed depth. 512 is the built-in default." + ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +}