diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-26 14:58:55 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-26 14:58:55 -0300 |
| commit | 64764fb9fac0227f8e0443e7c7519d73aec275b9 (patch) | |
| tree | cb4fc56eeb6ecce53854f9c530609cf01ab3349f /tests/RetryTest.php | |
| download | php-1fd1470890518a68130b3b9058fe1bebddca9f07.tar.gz | |
Initial importv0.1.0
Diffstat (limited to 'tests/RetryTest.php')
| -rw-r--r-- | tests/RetryTest.php | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/tests/RetryTest.php b/tests/RetryTest.php new file mode 100644 index 0000000..1b922b6 --- /dev/null +++ b/tests/RetryTest.php @@ -0,0 +1,127 @@ +<?php + +declare(strict_types=1); + +namespace Cepis\Tests; + +use Cepis\Client; +use Cepis\NetworkException; +use Cepis\RateLimitedException; +use Cepis\ServerErrorException; + +final class RetryTest extends ServerTestCase +{ + public function testRetriesOn500ThenSucceeds(): void + { + $this->server->respond('/01001000', [ + self::json(['erro' => 'interno'], 500), + self::json(self::SE_ADDRESS), + ]); + + self::assertSame('São Paulo', $this->client->lookup('01001000')->localidade); + self::assertSame(2, $this->server->countCalls('/01001000')); + } + + public function testExhaustsAttemptsThenThrows(): void + { + $this->server->respond('/01001000', [self::json(['erro' => 'interno'], 503)]); + + try { + $this->client->lookup('01001000'); + self::fail('expected ServerErrorException'); + } catch (ServerErrorException $exception) { + self::assertSame(503, $exception->status); + self::assertSame(3, $this->server->countCalls('/01001000')); + } + } + + public function testMaxAttemptsOneDisablesRetry(): void + { + $client = new Client(baseUrl: $this->server->url, timeout: 5.0, maxAttempts: 1); + $this->server->respond('/01001000', [self::raw(500, '{}')]); + + try { + $client->lookup('01001000'); + self::fail('expected ServerErrorException'); + } catch (ServerErrorException) { + self::assertSame(1, $this->server->countCalls('/01001000')); + } + } + + public function test429BecomesRateLimitedWithRetryAfter(): void + { + $this->server->respond('/01001000', [self::raw(429, '{}', ['Retry-After' => '7'])]); + + try { + $this->client->lookup('01001000'); + self::fail('expected RateLimitedException'); + } catch (RateLimitedException $exception) { + self::assertNotNull($exception->retryAfter); + self::assertEqualsWithDelta(7.0, $exception->retryAfter, 1e-9); + } + } + + public function testRetryAfterAcceptsAnHttpDate(): void + { + $date = gmdate('D, d M Y H:i:s \G\M\T', time() + 4); + $this->server->respond('/01001000', [self::raw(429, '{}', ['Retry-After' => $date])]); + + try { + $this->client->lookup('01001000'); + self::fail('expected RateLimitedException'); + } catch (RateLimitedException $exception) { + self::assertNotNull($exception->retryAfter); + self::assertGreaterThan(0.0, $exception->retryAfter); + self::assertLessThanOrEqual(5.0, $exception->retryAfter); + } + } + + public function testRetryAfterHonoursTheCap(): void + { + $this->server->respond('/01001000', [self::raw(429, '{}', ['Retry-After' => '3600'])]); + $started = self::monotonic(); + + try { + $this->client->lookup('01001000'); + self::fail('expected RateLimitedException'); + } catch (RateLimitedException) { + self::assertLessThan(5.0, self::monotonic() - $started); + } + } + + public function testNetworkErrorWhenNothingListens(): void + { + $client = new Client( + baseUrl: 'http://127.0.0.1:1', + timeout: 1.0, + maxAttempts: 2, + backoffBase: 0.001, + backoffMax: 0.01, + ); + + $this->expectException(NetworkException::class); + $client->lookup('01001000'); + } + + public function testTotalTimeoutBoundsTheWholeCall(): void + { + $client = new Client( + baseUrl: $this->server->url, + timeout: 5.0, + maxAttempts: 50, + backoffBase: 0.05, + backoffMax: 0.05, + totalTimeout: 0.3, + ); + $this->server->respond('/01001000', [self::raw(500, '{}')]); + $started = self::monotonic(); + + try { + $client->lookup('01001000'); + self::fail('expected ServerErrorException'); + } catch (ServerErrorException) { + self::assertLessThan(5.0, self::monotonic() - $started); + self::assertLessThan(50, $this->server->countCalls('/01001000')); + } + } +} |