tenbyonethousand.pl
#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
use LWP::UserAgent;
use Sloop::Server;
use Sloop::Logger;
my $PORT_NO = 8181;
my $LOCALHOST = 'localhost';
my $num_clients = 10;
$num_clients = $ARGV[0] if $ARGV[0];
my $num_requests = 1000;
$num_requests = $ARGV[1] if $ARGV[1];
my $tenth = $num_requests / 10;
if (defined $ARGV[2]) {
print "PID $$...waiting for HUP.\n";
my $go = 0;
$SIG{HUP} = sub {
$go = 1;
};
sleep 1 while (!$go);
}
my $page = <<END;
<!DOCTYPE html>
<html>
<body>
<h1>Hello World</h1>
</body>
</html>
END
my ($big, $blen) = randomInput(1234567);
print STDERR "Big payload size: $blen bytes\n";
my $pid = fork;
die "Fork failed: $!" if $pid == -1;
if ($pid) {
open my $null, '>', '/dev/null' or die "Could not open /dev/null: $!";
my $sloop = Sloop::Server->new (
port => $PORT_NO,
logger => Sloop::Logger->new(logs=>[\*STDERR, \*STDERR, $null])
);
die "\n\nInitialize Sloop::Server failed!\n\n" if (!$sloop);
$sloop->{handlers} = {
'/' => sub {
$_[0]->reply(\$page);
},
big => sub {
$_[0]->reply(\$big, type => 'application/octet-stream');
},
done => sub {
print STDERR "Server exiting.\n";
exit 0;
}
};
print STDERR "Server starting...\n";
$sloop->run;
} else {
sleep 1;
print STDERR "Starting clients...\n";
my $n = $num_clients;
my @pids;
for (my $i = 0; $i < $n; $i++) {
$pid = fork;
if ($pid == -1) { print STDERR "Fork $i failed: $!" }
elsif (!$pid) {
clientGo($i);
$i = $n;
} else { push @pids, $pid }
}
waitpid($_, 0) foreach (@pids);
print STDERR "Clients done.\n";
my $stop = LWP::UserAgent->new();
$stop->get("http://$LOCALHOST:$PORT_NO/done", timeout=>1);
}
sub clientGo {
my $id = shift;
my $client = LWP::UserAgent->new();
my $i = 0;
for (; $i < $num_requests; $i++) {
print STDERR "Client $id completed $i requests.\n"
if $i && !($i % $tenth);
if ($i % 2) {
my $reply = $client->get("http://$LOCALHOST:$PORT_NO/");
reqFail($i, $id, $reply) if $reply->content ne $page;
} else {
my $reply = $client->get("http://$LOCALHOST:$PORT_NO/big");
reqFail($i, $id, $reply) if $reply->content ne $big;
}
}
print STDERR "Client $id completed $i requests.\n";
exit 0;
}
sub reqFail {
my ($clientN, $reqN, $resp) = (shift, shift, shift);
print STDERR "Client $clientN mismatch at $reqN\n";
my $check = $resp->header("Client-Warning");
if ($check && $check eq "Internal response") {
print STDERR $resp->content."\n";
}
exit 0;
}
sub randomInput {
my $len = shift;
open my $fh, '<', '/dev/urandom' or die "Could not open /dev/urandom: $!\n";
my $data;
my $bytes = read $fh, $data, $len;
return ($data, $len);
}