# NAME Test::TCP - testing TCP program # SYNOPSIS use Test::TCP; my $server = Test::TCP->new( listen => 1, code => sub { my $socket = shift; ... }, ); my $client = MyClient->new(host => '127.0.0.1', port => $server->port); undef $server; # kill child process on DESTROY If using a server that can only accept a port number, e.g. memcached: use Test::TCP; my $memcached = Test::TCP->new( code => sub { my $port = shift; exec $bin, '-p' => $port; die "cannot execute $bin: $!"; }, ); my $memd = Cache::Memcached->new({servers => ['127.0.0.1:' . $memcached->port]}); ... **N.B.**: This is vulnerable to race conditions, if another process binds to the same port after [Net::EmptyPort](https://metacpan.org/pod/Net::EmptyPort) found it available. And functional interface is available: use Test::TCP; test_tcp( listen => 1, client => sub { my ($port, $server_pid) = @_; # send request to the server }, server => sub { my $socket = shift; # run server, calling $socket->accept }, ); test_tcp( client => sub { my ($port, $server_pid) = @_; # send request to the server }, server => sub { my $port = shift; # run server, binding to $port }, ); # DESCRIPTION Test::TCP is a test utility to test TCP/IP-based server programs. # METHODS - test\_tcp Functional interface. test_tcp( listen => 1, client => sub { my $port = shift; # send request to the server }, server => sub { my $socket = shift; # run server }, # optional host => '127.0.0.1', # specify '::1' to test using IPv6 port => 8080, max_wait => 3, # seconds ); If `listen` is false, `server` is instead passed a port number that was free before it was called. - wait\_port wait_port(8080); Waits for a particular port is available for connect. # Object Oriented interface - my $server = Test::TCP->new(%args); Create new instance of Test::TCP. Arguments are following: - $args{auto\_start}: Boolean Call `$server->start()` after create instance. Default: true - $args{code}: CodeRef The callback function. Argument for callback function is: `$code->($socket)` or `$code->($port)`, depending on the value of `listen`. This parameter is required. - $args{max\_wait} : Number Will wait for at most `$max_wait` seconds before checking port. See also [Net::EmptyPort](https://metacpan.org/pod/Net::EmptyPort). _Default: 10_ - $args{listen} : Boolean If true, open a listening socket and pass this to the callback. Otherwise find a free port and pass the number of it to the callback. - $server->start() Start the server process. Normally, you don't need to call this method. - $server->stop() Stop the server process. - my $pid = $server->pid(); Get the pid of child process. - my $port = $server->port(); Get the port number of child process. # FAQ - How to invoke two servers? You can call test\_tcp() twice! test_tcp( client => sub { my $port1 = shift; test_tcp( client => sub { my $port2 = shift; # some client code here }, server => sub { my $port2 = shift; # some server2 code here }, ); }, server => sub { my $port1 = shift; # some server1 code here }, ); Or use the OO interface instead. my $server1 = Test::TCP->new(code => sub { my $port1 = shift; ... }); my $server2 = Test::TCP->new(code => sub { my $port2 = shift; ... }); # your client code here. ... - How do you test server program written in other languages like memcached? You can use `exec()` in child process. use strict; use warnings; use utf8; use Test::More; use Test::TCP 1.08; use File::Which; my $bin = scalar which 'memcached'; plan skip_all => 'memcached binary is not found' unless defined $bin; my $memcached = Test::TCP->new( code => sub { my $port = shift; exec $bin, '-p' => $port; die "cannot execute $bin: $!"; }, ); use Cache::Memcached; my $memd = Cache::Memcached->new({servers => ['127.0.0.1:' . $memcached->port]}); $memd->set(foo => 'bar'); is $memd->get('foo'), 'bar'; done_testing; - How do I use address other than "127.0.0.1" for testing? You can use the `host` parameter to specify the bind address. # let the server bind to "0.0.0.0" for testing test_tcp( client => sub { ... }, server => sub { ... }, host => '0.0.0.0', ); - How should I write IPv6 tests? You should use the \`Net::EmptyPort::can\_bind\` function to check if the program can bind to the loopback address of IPv6, as well as the \`host\` parameter of the \`test\_tcp\` function to specify the same address as the bind address. use Net::EmptyPort qw(can_bind); plan skip_all => "IPv6 not available" unless can_bind('::1'); test_tcp( client => sub { ... }, server => sub { ... }, host => '::1', ); # AUTHOR Tokuhiro Matsuno # THANKS TO kazuhooku dragon3 charsbar Tatsuhiko Miyagawa lestrrat # SEE ALSO # LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.