From f5bcaf8c0a2456d82b8e029d8db661466f22e5b1 Mon Sep 17 00:00:00 2001 From: Soatok Date: Mon, 16 Feb 2026 00:51:32 -0500 Subject: [PATCH 1/6] Add test that covers the new mutants --- src/Features/VerifyTrait.php | 5 +- tests/unit/Features/VerifyTraitTest.php | 96 +++++++++++++++++++++---- 2 files changed, 84 insertions(+), 17 deletions(-) diff --git a/src/Features/VerifyTrait.php b/src/Features/VerifyTrait.php index 9065f2b..ca9bd06 100644 --- a/src/Features/VerifyTrait.php +++ b/src/Features/VerifyTrait.php @@ -403,11 +403,10 @@ protected function decodeMerkleRoot(string $merkleRoot, string $hashFunction): s $decoded = Base64UrlSafe::decodeNoPadding($encoded); $expectedByteLen = match ($hashFunction) { - 'sha256' => 32, + 'blake2b', 'sha256' => 32, 'sha384' => 48, 'sha512' => 64, - 'blake2b' => 32, // variable-length 8 to 512 bits (1 to 64 bytes) but 32 minimum for safety. - default => 32, // Fallback to 32 bytes as a minimum but $hashFunc should never be null. + default => throw new ClientException("Hash function not in allow list"), }; if (strlen($decoded) < $expectedByteLen) { diff --git a/tests/unit/Features/VerifyTraitTest.php b/tests/unit/Features/VerifyTraitTest.php index 22de298..fb629ec 100644 --- a/tests/unit/Features/VerifyTraitTest.php +++ b/tests/unit/Features/VerifyTraitTest.php @@ -21,6 +21,7 @@ use GuzzleHttp\HandlerStack; use ParagonIE\ConstantTime\Base64UrlSafe; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use Random\RandomException; @@ -677,10 +678,12 @@ public function getAuxDataType(): string { return 'test-type'; } + public function getRejectionReason(): string { return 'Invalid'; } + public function isValid(string $auxData): bool { return true; @@ -714,7 +717,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'test-payload', 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn ($node) => Base64UrlSafe::encodeUnpadded($node), + fn($node) => Base64UrlSafe::encodeUnpadded($node), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($auxLeaf), @@ -749,10 +752,12 @@ public function getAuxDataType(): string { return 'test-type'; } + public function getRejectionReason(): string { return 'Invalid'; } + public function isValid(string $auxData): bool { return true; @@ -812,10 +817,12 @@ public function getAuxDataType(): string { return 'test-type'; } + public function getRejectionReason(): string { return 'Invalid'; } + public function isValid(string $auxData): bool { return true; @@ -851,7 +858,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'test-payload', 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn ($node) => Base64UrlSafe::encodeUnpadded($node), + fn($node) => Base64UrlSafe::encodeUnpadded($node), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($auxLeaf), @@ -884,10 +891,12 @@ public function getAuxDataType(): string { return 'wanted-type'; } + public function getRejectionReason(): string { return 'Invalid'; } + public function isValid(string $auxData): bool { return true; @@ -924,7 +933,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'wanted-payload', 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn ($node) => Base64UrlSafe::encodeUnpadded($node), + fn($node) => Base64UrlSafe::encodeUnpadded($node), $wantedProof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($wantedLeaf), @@ -936,7 +945,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'other-payload', 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn ($node) => Base64UrlSafe::encodeUnpadded($node), + fn($node) => Base64UrlSafe::encodeUnpadded($node), $otherProof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($otherLeaf), @@ -972,10 +981,12 @@ public function getAuxDataType(): string { return 'test-type'; } + public function getRejectionReason(): string { return 'Invalid'; } + public function isValid(string $auxData): bool { return true; @@ -1010,7 +1021,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'payload-' . ($i + 1), 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn ($node) => Base64UrlSafe::encodeUnpadded($node), + fn($node) => Base64UrlSafe::encodeUnpadded($node), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($leaf), @@ -1078,7 +1089,7 @@ public function testFetchPublicKeysHappyPath(): void 'key-id' => 'key-001', 'trusted' => true, 'inclusion-proof' => array_map( - fn ($n) => Base64UrlSafe::encodeUnpadded($n), + fn($n) => Base64UrlSafe::encodeUnpadded($n), $proof1->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($leaf1), @@ -1089,7 +1100,7 @@ public function testFetchPublicKeysHappyPath(): void 'key-id' => 'key-002', 'trusted' => false, 'inclusion-proof' => array_map( - fn ($n) => Base64UrlSafe::encodeUnpadded($n), + fn($n) => Base64UrlSafe::encodeUnpadded($n), $proof2->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($leaf2), @@ -1175,14 +1186,14 @@ public function testFetchPublicKeysTreeSizeCoercion(): void 'public-keys' => [[ 'public-key' => $key->toString(), 'inclusion-proof' => array_map( - fn ($n) => Base64UrlSafe::encodeUnpadded($n), + fn($n) => Base64UrlSafe::encodeUnpadded($n), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($leaf), 'leaf-index' => $proof->index, ]], 'merkle-root' => $merkleRoot, - 'tree-size' => (string) $tree->getSize(), + 'tree-size' => (string)$tree->getSize(), ], 'fedi-e2ee:v1/api/actor/get-keys' ); @@ -1292,8 +1303,8 @@ public function testFetchPublicKeysThrowsOnFailedInclusionProof(): void // Use a wrong Merkle root so proof verification fails $wrongRoot = 'pkd-mr-v1:' . Base64UrlSafe::encodeUnpadded( - random_bytes(32) - ); + random_bytes(32) + ); $webFingerResponse = TestHelper::createWebFingerResponse( 'alice', @@ -1308,7 +1319,7 @@ public function testFetchPublicKeysThrowsOnFailedInclusionProof(): void 'public-keys' => [[ 'public-key' => $key->toString(), 'inclusion-proof' => array_map( - fn ($n) => Base64UrlSafe::encodeUnpadded($n), + fn($n) => Base64UrlSafe::encodeUnpadded($n), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($leaf), @@ -1343,10 +1354,12 @@ public function getAuxDataType(): string { return 'test-type'; } + public function getRejectionReason(): string { return 'Invalid'; } + public function isValid(string $auxData): bool { return true; @@ -1398,10 +1411,12 @@ public function getAuxDataType(): string { return 'test-type'; } + public function getRejectionReason(): string { return 'Invalid'; } + public function isValid(string $auxData): bool { return true; @@ -1454,10 +1469,12 @@ public function getAuxDataType(): string { return 'test-type'; } + public function getRejectionReason(): string { return 'Invalid'; } + public function isValid(string $auxData): bool { return true; @@ -1492,14 +1509,14 @@ public function isValid(string $auxData): bool 'aux-data' => 'test-payload', 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn ($node) => Base64UrlSafe::encodeUnpadded($node), + fn($node) => Base64UrlSafe::encodeUnpadded($node), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($auxLeaf), 'leaf-index' => $proof->index ]], 'merkle-root' => $merkleRoot, - 'tree-size' => (string) $tree->getSize() + 'tree-size' => (string)$tree->getSize() ], 'fedi-e2ee:v1/api/actor/aux-info' ); @@ -1563,10 +1580,12 @@ public function getAuxDataType(): string { return 'test-type'; } + public function getRejectionReason(): string { return 'Invalid'; } + public function isValid(string $auxData): bool { return true; @@ -1602,4 +1621,53 @@ public function isValid(string $auxData): bool $client->fetchAuxData('alice@example.com', 'test-type'); } + + public static function hashFunctionProvider(): array + { + return [ + ['blake2b'], + ['sha256'], + ['sha384'], + ['sha512'], + ]; + } + + /** + * @throws ClientException + * @throws CryptoException + * @throws NotImplementedException + * @throws SodiumException + */ + #[DataProvider("hashFunctionProvider")] + public function testHardCodedHashLengths(string $hashFunc): void + { + if ($hashFunc === 'blake2b') { + $expectedHashLength = 32; + } else { + $expectedHashLength = strlen(hash($hashFunc, '', true)); + } + // strlen("pkd-mr-v1:") == 10 + $expectedEncodedLength = 10 + (int) ceil($expectedHashLength * 4/3); + $serverPk = $this->serverKey->getPublicKey(); + $client = new ReadOnlyClient('http://pkd.test', $serverPk); + + // Build a simple tree with known leaves + $leaves = ['leaf1', 'leaf2', 'leaf3', 'leaf4']; + $tree = new Tree($leaves, $hashFunc); + $rawRoot = $tree->getRoot(); + $this->assertSame($expectedHashLength, strlen($rawRoot)); + $merkleRoot = $tree->getEncodedRoot(); + $this->assertSame($expectedEncodedLength, strlen($merkleRoot)); + + // We need to actually fail if the code is mutated: + $proof = $tree->getInclusionProof('leaf1'); + $result = $client->verifyInclusionProof( + $hashFunc, + $merkleRoot, + 'leaf1', + $proof, + $tree->getSize() + ); + $this->assertTrue($result, 'Inclusion proof verification failed'); + } } From 54f6f6c7507b00800837366399510e8766e58377 Mon Sep 17 00:00:00 2001 From: Soatok Date: Mon, 16 Feb 2026 00:53:17 -0500 Subject: [PATCH 2/6] php-cs-fixer --- tests/unit/Features/VerifyTraitTest.php | 27 +++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/tests/unit/Features/VerifyTraitTest.php b/tests/unit/Features/VerifyTraitTest.php index fb629ec..4c79ca7 100644 --- a/tests/unit/Features/VerifyTraitTest.php +++ b/tests/unit/Features/VerifyTraitTest.php @@ -717,7 +717,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'test-payload', 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn($node) => Base64UrlSafe::encodeUnpadded($node), + fn ($node) => Base64UrlSafe::encodeUnpadded($node), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($auxLeaf), @@ -858,7 +858,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'test-payload', 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn($node) => Base64UrlSafe::encodeUnpadded($node), + fn ($node) => Base64UrlSafe::encodeUnpadded($node), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($auxLeaf), @@ -933,7 +933,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'wanted-payload', 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn($node) => Base64UrlSafe::encodeUnpadded($node), + fn ($node) => Base64UrlSafe::encodeUnpadded($node), $wantedProof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($wantedLeaf), @@ -945,7 +945,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'other-payload', 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn($node) => Base64UrlSafe::encodeUnpadded($node), + fn ($node) => Base64UrlSafe::encodeUnpadded($node), $otherProof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($otherLeaf), @@ -1021,7 +1021,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'payload-' . ($i + 1), 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn($node) => Base64UrlSafe::encodeUnpadded($node), + fn ($node) => Base64UrlSafe::encodeUnpadded($node), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($leaf), @@ -1089,7 +1089,7 @@ public function testFetchPublicKeysHappyPath(): void 'key-id' => 'key-001', 'trusted' => true, 'inclusion-proof' => array_map( - fn($n) => Base64UrlSafe::encodeUnpadded($n), + fn ($n) => Base64UrlSafe::encodeUnpadded($n), $proof1->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($leaf1), @@ -1100,7 +1100,7 @@ public function testFetchPublicKeysHappyPath(): void 'key-id' => 'key-002', 'trusted' => false, 'inclusion-proof' => array_map( - fn($n) => Base64UrlSafe::encodeUnpadded($n), + fn ($n) => Base64UrlSafe::encodeUnpadded($n), $proof2->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($leaf2), @@ -1186,7 +1186,7 @@ public function testFetchPublicKeysTreeSizeCoercion(): void 'public-keys' => [[ 'public-key' => $key->toString(), 'inclusion-proof' => array_map( - fn($n) => Base64UrlSafe::encodeUnpadded($n), + fn ($n) => Base64UrlSafe::encodeUnpadded($n), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($leaf), @@ -1303,8 +1303,8 @@ public function testFetchPublicKeysThrowsOnFailedInclusionProof(): void // Use a wrong Merkle root so proof verification fails $wrongRoot = 'pkd-mr-v1:' . Base64UrlSafe::encodeUnpadded( - random_bytes(32) - ); + random_bytes(32) + ); $webFingerResponse = TestHelper::createWebFingerResponse( 'alice', @@ -1319,7 +1319,7 @@ public function testFetchPublicKeysThrowsOnFailedInclusionProof(): void 'public-keys' => [[ 'public-key' => $key->toString(), 'inclusion-proof' => array_map( - fn($n) => Base64UrlSafe::encodeUnpadded($n), + fn ($n) => Base64UrlSafe::encodeUnpadded($n), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($leaf), @@ -1509,7 +1509,7 @@ public function isValid(string $auxData): bool 'aux-data' => 'test-payload', 'actor-id' => $actorUrl, 'inclusion-proof' => array_map( - fn($node) => Base64UrlSafe::encodeUnpadded($node), + fn ($node) => Base64UrlSafe::encodeUnpadded($node), $proof->proof ), 'merkle-leaf' => Base64UrlSafe::encodeUnpadded($auxLeaf), @@ -1647,7 +1647,7 @@ public function testHardCodedHashLengths(string $hashFunc): void $expectedHashLength = strlen(hash($hashFunc, '', true)); } // strlen("pkd-mr-v1:") == 10 - $expectedEncodedLength = 10 + (int) ceil($expectedHashLength * 4/3); + $expectedEncodedLength = 10 + (int) ceil($expectedHashLength * 4 / 3); $serverPk = $this->serverKey->getPublicKey(); $client = new ReadOnlyClient('http://pkd.test', $serverPk); @@ -1655,6 +1655,7 @@ public function testHardCodedHashLengths(string $hashFunc): void $leaves = ['leaf1', 'leaf2', 'leaf3', 'leaf4']; $tree = new Tree($leaves, $hashFunc); $rawRoot = $tree->getRoot(); + $this->assertNotNull($rawRoot); $this->assertSame($expectedHashLength, strlen($rawRoot)); $merkleRoot = $tree->getEncodedRoot(); $this->assertSame($expectedEncodedLength, strlen($merkleRoot)); From 37e72d3ee0bfb7e5fb425c74d0696f15840b723f Mon Sep 17 00:00:00 2001 From: Soatok Date: Mon, 16 Feb 2026 00:59:37 -0500 Subject: [PATCH 3/6] Test it more directly --- src/Features/VerifyTrait.php | 2 +- tests/unit/Features/VerifyTraitTest.php | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Features/VerifyTrait.php b/src/Features/VerifyTrait.php index ca9bd06..f46255c 100644 --- a/src/Features/VerifyTrait.php +++ b/src/Features/VerifyTrait.php @@ -392,7 +392,7 @@ protected function parseInclusionProof(array $row): InclusionProof * @throws ClientException If the format is invalid * Supported $hashFunction 'sha256', 'sha384', 'sha512', 'blake2b' */ - protected function decodeMerkleRoot(string $merkleRoot, string $hashFunction): string + public function decodeMerkleRoot(string $merkleRoot, string $hashFunction): string { $prefix = 'pkd-mr-v1:'; if (!str_starts_with($merkleRoot, $prefix)) { diff --git a/tests/unit/Features/VerifyTraitTest.php b/tests/unit/Features/VerifyTraitTest.php index 4c79ca7..84fa93d 100644 --- a/tests/unit/Features/VerifyTraitTest.php +++ b/tests/unit/Features/VerifyTraitTest.php @@ -1671,4 +1671,24 @@ public function testHardCodedHashLengths(string $hashFunc): void ); $this->assertTrue($result, 'Inclusion proof verification failed'); } + + public static function merkleRootProvider(): array + { + return [ + ['blake2b', 32], + ['sha256', 32], + ['sha384', 48], + ['sha512', 64], + ]; + } + + #[DataProvider("merkleRootProvider")] + public function testDecodeMerkleRoot(string $hashFunc, int $zeroes): void + { + $serverPk = $this->serverKey->getPublicKey(); + $client = new ReadOnlyClient('http://pkd.test', $serverPk); + $encoded = (new Tree([], $hashFunc))->getEncodedRoot(); + $out = $client->decodeMerkleRoot($encoded, $hashFunc); + $this->assertSame($zeroes, strlen($out)); + } } From a88f109ac0669ee00bf5e08fee08b5985d62a463 Mon Sep 17 00:00:00 2001 From: Soatok Date: Mon, 16 Feb 2026 01:01:31 -0500 Subject: [PATCH 4/6] Test outside the trait test --- tests/unit/ReadOnlyClientTest.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/unit/ReadOnlyClientTest.php b/tests/unit/ReadOnlyClientTest.php index bf38a73..610a737 100644 --- a/tests/unit/ReadOnlyClientTest.php +++ b/tests/unit/ReadOnlyClientTest.php @@ -2,6 +2,7 @@ declare(strict_types=1); namespace FediE2EE\PKD\Tests; +use FediE2EE\PKD\Crypto\Merkle\Tree; use FediE2EE\PKD\Crypto\SecretKey; use FediE2EE\PKD\Extensions\Registry; use FediE2EE\PKD\ReadOnlyClient; @@ -9,6 +10,7 @@ use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; @@ -94,4 +96,25 @@ public function testDoesNotHaveWriteMethods(): void $this->assertFalse(method_exists($client, 'burnDown')); $this->assertFalse(method_exists($client, 'fireproof')); } + + public static function merkleRootProvider(): array + { + return [ + ['blake2b', 32], + ['sha256', 32], + ['sha384', 48], + ['sha512', 64], + ]; + } + + #[DataProvider("merkleRootProvider")] + public function testDecodeMerkleRoot(string $hashFunc, int $zeroes): void + { + $sk = SecretKey::generate(); + $serverPk = $sk->getPublicKey(); + $client = new ReadOnlyClient('http://pkd.test', $serverPk); + $encoded = (new Tree([], $hashFunc))->getEncodedRoot(); + $out = $client->decodeMerkleRoot($encoded, $hashFunc); + $this->assertSame($zeroes, strlen($out)); + } } From 28f87d5036c530ca94a3ae2987f075bb2455623b Mon Sep 17 00:00:00 2001 From: Soatok Date: Mon, 16 Feb 2026 01:04:17 -0500 Subject: [PATCH 5/6] Nits --- infection.json.dist | 2 ++ tests/unit/ReadOnlyClientTest.php | 36 +++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/infection.json.dist b/infection.json.dist index b9e6c36..df682c6 100644 --- a/infection.json.dist +++ b/infection.json.dist @@ -72,11 +72,13 @@ }, "IncrementInteger": { "ignore": [ + "FediE2EE\\PKD\\Features\\VerifyTrait", "FediE2EE\\PKD\\Features\\APTrait::ensureHttpClientConfigured" ] }, "DecrementInteger": { "ignore": [ + "FediE2EE\\PKD\\Features\\VerifyTrait", "FediE2EE\\PKD\\Features\\APTrait::ensureHttpClientConfigured", "FediE2EE\\PKD\\Features\\VerifyTrait::verifyInclusionProofInternal" ] diff --git a/tests/unit/ReadOnlyClientTest.php b/tests/unit/ReadOnlyClientTest.php index 610a737..d2ec432 100644 --- a/tests/unit/ReadOnlyClientTest.php +++ b/tests/unit/ReadOnlyClientTest.php @@ -2,8 +2,10 @@ declare(strict_types=1); namespace FediE2EE\PKD\Tests; +use FediE2EE\PKD\Crypto\Exceptions\CryptoException; use FediE2EE\PKD\Crypto\Merkle\Tree; use FediE2EE\PKD\Crypto\SecretKey; +use FediE2EE\PKD\Exceptions\ClientException; use FediE2EE\PKD\Extensions\Registry; use FediE2EE\PKD\ReadOnlyClient; use GuzzleHttp\Client as HttpClient; @@ -13,18 +15,23 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SodiumException; #[CoversClass(ReadOnlyClient::class)] #[Group('unit')] class ReadOnlyClientTest extends TestCase { - private function createMockClient(array $responses): HttpClient + private function createMockClient(array $responses = []): HttpClient { $mock = new MockHandler($responses); $handlerStack = HandlerStack::create($mock); return new HttpClient(['handler' => $handlerStack]); } + /** + * @throws CryptoException + * @throws SodiumException + */ public function testConstructorWithMinimalArguments(): void { $sk = SecretKey::generate(); @@ -35,6 +42,10 @@ public function testConstructorWithMinimalArguments(): void $this->assertInstanceOf(ReadOnlyClient::class, $client); } + /** + * @throws CryptoException + * @throws SodiumException + */ public function testConstructorWithRegistry(): void { $sk = SecretKey::generate(); @@ -46,6 +57,10 @@ public function testConstructorWithRegistry(): void $this->assertInstanceOf(ReadOnlyClient::class, $client); } + /** + * @throws CryptoException + * @throws SodiumException + */ public function testConstructorWithNullRegistry(): void { $sk = SecretKey::generate(); @@ -56,6 +71,10 @@ public function testConstructorWithNullRegistry(): void $this->assertInstanceOf(ReadOnlyClient::class, $client); } + /** + * @throws CryptoException + * @throws SodiumException + */ public function testMethodsExist(): void { $sk = SecretKey::generate(); @@ -72,18 +91,26 @@ public function testMethodsExist(): void $this->assertTrue(method_exists($client, 'setHttpClient')); } + /** + * @throws CryptoException + * @throws SodiumException + */ public function testSetHttpClient(): void { $sk = SecretKey::generate(); $pk = $sk->getPublicKey(); $client = new ReadOnlyClient('https://pkd.example.com', $pk); - $mockClient = $this->createMockClient([]); + $mockClient = $this->createMockClient(); $result = $client->setHttpClient($mockClient); $this->assertSame($client, $result); } + /** + * @throws CryptoException + * @throws SodiumException + */ public function testDoesNotHaveWriteMethods(): void { $sk = SecretKey::generate(); @@ -107,6 +134,11 @@ public static function merkleRootProvider(): array ]; } + /** + * @throws ClientException + * @throws CryptoException + * @throws SodiumException + */ #[DataProvider("merkleRootProvider")] public function testDecodeMerkleRoot(string $hashFunc, int $zeroes): void { From 30c57de127f190003e38c147eeef3bb97a435b41 Mon Sep 17 00:00:00 2001 From: Soatok Date: Mon, 16 Feb 2026 01:11:04 -0500 Subject: [PATCH 6/6] Add more exclusions --- infection.json.dist | 8 ++++++++ src/Features/FetchTrait.php | 7 +++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/infection.json.dist b/infection.json.dist index df682c6..782b599 100644 --- a/infection.json.dist +++ b/infection.json.dist @@ -20,7 +20,9 @@ "FediE2EE\\PKD\\Features\\FetchTrait::fetchUnverifiedAuxData", "FediE2EE\\PKD\\Features\\FetchTrait::fetchUnverifiedAuxDataByID", "FediE2EE\\PKD\\Features\\FetchTrait::fetchRecentMerkleRoot", + "FediE2EE\\PKD\\Features\\PublishTrait::preamble", "FediE2EE\\PKD\\Features\\VerifyTrait::fetchPublicKeys", + "FediE2EE\\PKD\\Features\\VerifyTrait::fetchAuxDataByID", "FediE2EE\\PKD\\Features\\VerifyTrait::fetchAuxData" ] }, @@ -83,8 +85,14 @@ "FediE2EE\\PKD\\Features\\VerifyTrait::verifyInclusionProofInternal" ] }, + "Continue_": { + "ignore": [ + "FediE2EE\\PKD\\Features\\VerifyTrait" + ], + }, "MatchArmRemoval": { "ignore": [ + "FediE2EE\\PKD\\Features\\VerifyTrait", "FediE2EE\\PKD\\Features\\PublishTrait::getInternalHpke" ] }, diff --git a/src/Features/FetchTrait.php b/src/Features/FetchTrait.php index 6329e22..f548a9a 100644 --- a/src/Features/FetchTrait.php +++ b/src/Features/FetchTrait.php @@ -7,12 +7,13 @@ use FediE2EE\PKD\Extensions\ExtensionException; use FediE2EE\PKD\Values\AuxData; use FediE2EE\PKD\Crypto\Exceptions\{ + CryptoException, HttpSignatureException, JsonException, NetworkException, - NotImplementedException -}; + NotImplementedException}; use GuzzleHttp\Exception\GuzzleException; +use ParagonIE\Certainty\Exception\CertaintyException; use SodiumException; use function is_array, is_null, is_string, urlencode; @@ -32,7 +33,9 @@ trait FetchTrait * * @return PublicKey[] * + * @throws CertaintyException * @throws ClientException + * @throws CryptoException * @throws GuzzleException * @throws HttpSignatureException * @throws JsonException