Entropic Thoughts

Custom TCP Test Harness in Perl

Custom TCP Test Harness in Perl

I recently needed to write a simple application that was going to run a long time and issue many requests to another service, but with a focus on reliability.

I tried something I haven’t done before, and I don’t regret it; it paid for the up-front effort many times over. Here’s a basic tcp server in Perl, most of the implementation lifted right out of perldoc/perlipc:

use v5.16;
use strict;
use warnings;
use autodie qw( :all );

use Socket;

socket(my $server, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
setsockopt($server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1));
bind($server, sockaddr_in(8021, INADDR_ANY));
listen($server, SOMAXCONN);

for (my $paddr; $paddr = accept(my $client, $server); close $client) {
    eval qx( cat main.pl );
}

Note what happens when we have accepted a client socket: we eval the contents of main.pl. This means main.pl is re-parsed on every connection, so whenever we change it, the change will be picked up with the next connection attempt. We don’t have to restart anything.

What do we do in main.pl? Whatever we want! We can implement the protocol of the client, or, perhaps more productively, break it in mean ways. Here are some examples of things I did to test how robust my client implementation was:

The sky is the limit! I learned a lot about how my client behaves in the presence of failures by doing this, and I could iterate much quicker than I expected.

Of course, this only works when the protocol is simple enough that it’s possible to re-implement relevant portions of it in Perl. But I think it’s often possible to find a simple enough subset to make it worth it, at least when reliability is a priority.