summaryrefslogtreecommitdiffstats
path: root/t/04-retry.t
diff options
context:
space:
mode:
Diffstat (limited to 't/04-retry.t')
-rw-r--r--t/04-retry.t147
1 files changed, 147 insertions, 0 deletions
diff --git a/t/04-retry.t b/t/04-retry.t
new file mode 100644
index 0000000..d304b5a
--- /dev/null
+++ b/t/04-retry.t
@@ -0,0 +1,147 @@
+use strict;
+use warnings;
+use utf8;
+
+use FindBin ();
+use lib "$FindBin::Bin/lib";
+
+use Test::More;
+use TestServer qw(se_address json new_client);
+
+use Cepis;
+use Time::HiRes ();
+
+{
+ my $server = TestServer->new(
+ routes => {
+ '/01001000' => [
+ [ 500, json( { erro => 'interno' } ), {} ],
+ [ 200, json( se_address() ), {} ],
+ ]
+ }
+ );
+ my $client = new_client($server);
+
+ is( $client->lookup('01001000')->localidade, 'São Paulo', 'a retry recovers' );
+ is( $server->count('/01001000'), 2, 'it took two attempts' );
+ $server->stop;
+}
+
+{
+ my $server = TestServer->new(
+ routes => { '/01001000' => [ 503, json( { erro => 'interno' } ), {} ] } );
+ my $client = new_client($server);
+
+ my $ok = eval { $client->lookup('01001000'); 1 };
+ ok( !$ok, 'exhausting the attempts throws' );
+ isa_ok( $@, 'Cepis::Error::ServerError' );
+ is( $@->status, 503, 'the status of the last attempt is exposed' );
+ is( $server->count('/01001000'), 3, 'three attempts by default' );
+ $server->stop;
+}
+
+{
+ my $server = TestServer->new( routes => { '/01001000' => [ 500, '{}', {} ] } );
+ my $client = new_client( $server, max_attempts => 1 );
+
+ my $ok = eval { $client->lookup('01001000'); 1 };
+ ok( !$ok, 'max_attempts of 1 still throws' );
+ is( $server->count('/01001000'), 1, 'and disables retrying' );
+ $server->stop;
+}
+
+{
+ my $server = TestServer->new(
+ routes => { '/01001000' => [ 429, '{}', { 'Retry-After' => '7' } ] } );
+ my $client = new_client($server);
+
+ my $ok = eval { $client->lookup('01001000'); 1 };
+ ok( !$ok, 'a 429 throws' );
+ isa_ok( $@, 'Cepis::Error::RateLimited' );
+ cmp_ok( abs( $@->retry_after - 7 ), '<', 1e-9, 'Retry-After in seconds is read' );
+ $server->stop;
+}
+
+{
+ my @day = qw(Sun Mon Tue Wed Thu Fri Sat);
+ my @month = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
+ my @t = gmtime( time + 4 );
+ my $date = sprintf '%s, %02d %s %04d %02d:%02d:%02d GMT', $day[ $t[6] ], $t[3],
+ $month[ $t[4] ], $t[5] + 1900, $t[2], $t[1], $t[0];
+
+ my $server = TestServer->new(
+ routes => { '/01001000' => [ 429, '{}', { 'Retry-After' => $date } ] } );
+ my $client = new_client($server);
+
+ my $ok = eval { $client->lookup('01001000'); 1 };
+ ok( !$ok, 'a 429 with an HTTP date throws' );
+ isa_ok( $@, 'Cepis::Error::RateLimited' );
+ cmp_ok( $@->retry_after, '>', 0, 'the date form is parsed too' );
+ cmp_ok( $@->retry_after, '<=', 5, 'and lands where it should' );
+ $server->stop;
+}
+
+{
+ my $server = TestServer->new(
+ routes => { '/01001000' => [ 429, '{}', { 'Retry-After' => '3600' } ] } );
+ my $client = new_client($server);
+
+ my $started = Time::HiRes::time();
+ my $ok = eval { $client->lookup('01001000'); 1 };
+ ok( !$ok, 'an absurd Retry-After still throws' );
+ cmp_ok( Time::HiRes::time() - $started, '<', 5, 'and is capped by backoff_max' );
+ $server->stop;
+}
+
+{
+ my $client = Cepis::Client->new(
+ base_url => 'http://127.0.0.1:1',
+ max_attempts => 2,
+ backoff_base => 0.001,
+ backoff_max => 0.01,
+ timeout => 1.0,
+ );
+
+ my $ok = eval { $client->lookup('01001000'); 1 };
+ ok( !$ok, 'nothing listening throws' );
+ isa_ok( $@, 'Cepis::Error::Network' );
+ like( "$@", qr/127\.0\.0\.1:1/, 'the message names the URL' );
+}
+
+{
+ my $server = TestServer->new( routes => { '/01001000' => [ 500, '{}', {} ] } );
+ my $client = new_client(
+ $server,
+ max_attempts => 50,
+ backoff_base => 0.05,
+ backoff_max => 0.05,
+ total_timeout => 0.3,
+ );
+
+ my $started = Time::HiRes::time();
+ my $ok = eval { $client->lookup('01001000'); 1 };
+ ok( !$ok, 'the call still throws' );
+ isa_ok( $@, 'Cepis::Error::ServerError' );
+ cmp_ok( Time::HiRes::time() - $started, '<', 3, 'total_timeout bounds the whole call' );
+ cmp_ok( $server->count('/01001000'), '<', 50, 'and cuts the attempts short' );
+ $server->stop;
+}
+
+{
+ my $server = TestServer->new(
+ routes => {
+ '/01001000' => [
+ [ 502, '{}', {} ],
+ [ 504, '{}', {} ],
+ [ 200, json( se_address() ), {} ],
+ ]
+ }
+ );
+ my $client = new_client($server);
+
+ is( $client->lookup('01001000')->uf, 'SP', '502 and 504 are retried too' );
+ is( $server->count('/01001000'), 3, 'across three attempts' );
+ $server->stop;
+}
+
+done_testing();