The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
use strict;
use warnings;

use Test::More;
use Plack::Loader;
use File::Temp;
use IO::Socket::INET;
use Net::EmptyPort qw(empty_port);
use Socket;

my $PORT_NUM   = 3;
my $UDS_NUM    = 4;
my $WORKER_NUM = 2;

my @tcp_socks = map {
    IO::Socket::INET->new(
        Listen    => Socket::SOMAXCONN(),
        Proto     => 'tcp',
        LocalPort => empty_port(),
        LocalAddr => '127.0.0.1',
        ReuseAddr => 1,
    ) or die "failed to listen:$!";
} (1..$PORT_NUM);

my @uds_socks = map {
    my ($fh, $filename) = File::Temp::tempfile(UNLINK=>0);
    close($fh);
    unlink($filename);
    IO::Socket::UNIX->new(
        Listen => Socket::SOMAXCONN(),
        Local  => $filename,
    ) or die "failed to listen to socket $filename:$!";
} (1..$UDS_NUM);

$ENV{SERVER_STARTER_PORT} = join ';', (
    map($_->sockport.'='.$_->fileno, @tcp_socks),
    map($_->hostpath.'='.$_->fileno, @uds_socks),
);

my $pid = fork;
if ( $pid == 0 ) {
    # server
    my $loader = Plack::Loader->load(
        'Starlet',
        max_workers => $WORKER_NUM,
    );
    $loader->run(sub{
        my $env = shift;
        [200, ['Content-Type'=>'text/html'], ["HELLO $env->{SERVER_PORT}"]];
    });
    exit;
}

sleep 1;

for my $listen_sock (@tcp_socks, @uds_socks) {
    my ($client, $port);
    if ($listen_sock->sockdomain == AF_INET) {
        $port = $listen_sock->sockport;
        $client = IO::Socket::INET->new(
            Proto    => 'tcp',
            PeerAddr => '127.0.0.1',
            PeerPort => $listen_sock->sockport,
            timeout  => 3,
        ) or die "failed to connect to socket $port:$!";
    }
    elsif ($listen_sock->sockdomain == AF_UNIX) {
        $port = $listen_sock->hostpath;
        $client = IO::Socket::UNIX->new(
            Peer    => $port,
            timeout => 3,
        ) or die "failed to connect to socket $port:$!";
    }
    else {
        die "unknown socket";
    }

    $client->syswrite("GET / HTTP/1.0\015\012\015\012");
    $client->sysread(my $buf, 1024);
    like $buf, qr/Starlet/;
    like $buf, qr/HELLO $port/;
}

done_testing();

kill 'TERM', $pid;
waitpid($pid,0);