Fetch
view release on metacpan or search on metacpan
t/11-keepalive.t view on Meta::CPAN
#!perl
use 5.008003;
use strict;
use warnings;
use IO::Socket::INET;
use Test::More;
use File::Spec ();
use Fetch;
# Keep-alive pooling: a persistent server tags every TCP connection with an
# incrementing id and echoes it, so we can see whether requests reuse one
# connection (pooling on) or open a fresh one each time (pooling off). The
# server forks per connection so several may be open at once.
my $srv = IO::Socket::INET->new(
LocalHost => '127.0.0.1', LocalPort => 0, Listen => 128, ReuseAddr => 1,
) or plan skip_all => "cannot listen: $!";
my $port = $srv->sockport;
my $base = "http://127.0.0.1:$port";
my $pid = fork;
plan skip_all => "cannot fork: $!" unless defined $pid;
if (!$pid) {
# Never hold the harness TAP pipe open, and never outlive the run:
# a leaked server child hangs the whole suite after this test is done.
open STDOUT, ">", File::Spec->devnull();
open STDERR, ">", File::Spec->devnull();
alarm 120;
$SIG{TERM} = sub { exit 0 };
$SIG{CHLD} = 'IGNORE';
my $connid = 0;
while (my $c = $srv->accept) {
my $id = ++$connid;
my $kid = fork;
if (defined $kid && $kid == 0) {
$c->autoflush(1);
while (my $line = <$c>) { # one iteration per request
my $close = 0;
while (my $h = <$c>) {
$close = 1 if $h =~ /^Connection:\s*close/i;
last if $h eq "\r\n";
}
my $b = "conn$id";
print $c "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n"
. "Content-Length: " . length($b) . "\r\n"
. ($close ? "Connection: close\r\n" : "")
. "\r\n$b";
last if $close;
}
close $c;
exit 0;
}
close $c; # parent keeps accepting
}
exit 0;
}
select(undef, undef, undef, 0.3);
plan tests => 5;
# ---- keep-alive on (default): one connection serves every request --------
{
my $ua = Fetch->new;
my @ids = map { $ua->get("$base/")->get->content } 1 .. 8;
my %seen; $seen{$_}++ for @ids;
is(scalar(keys %seen), 1, 'keep-alive reuses a single connection for 8 GETs');
is($ids[0], $ids[-1], 'first and last request landed on the same connection');
}
# ---- keep-alive off: a fresh connection every time -----------------------
{
my $ua = Fetch->new(keep_alive => 0);
my @ids = map { $ua->get("$base/")->get->content } 1 .. 5;
my %seen; $seen{$_}++ for @ids;
is(scalar(keys %seen), 5, 'keep_alive => 0 opens a new connection per request');
}
# ---- reuse stays correct: bodies are right and status holds --------------
{
my $ua = Fetch->new;
my @res = map { $ua->get("$base/")->get } 1 .. 4;
ok((!grep { $_->status != 200 } @res), 'every reused request is 200');
like($res[-1]->content, qr/^conn\d+$/, 'reused connection still returns a body');
}
END { local $?; if ($pid) { kill 'KILL', $pid; waitpid $pid, 0 } }
( run in 3.303 seconds using v1.01-cache-2.11-cpan-14f38c9f855 )