Test::TCP for perl
Perl Perl6
Latest commit a67fc54 Jun 30, 2016 @tokuhirom committed on GitHub Merge pull request #54 from tokuhirom/revert-53-master
Revert "Fix issue #43 - Make MSWin32 use check_port in the same way other platforms do."
Failed to load latest commit information.
lib Revert "Fix issue #43 - Make MSWin32 use check_port in the same way o… Jun 30, 2016
t Merge pull request #49 from bigpresh/nonlocal_bind_check May 13, 2016
xt Backward compatibility enhancements around wait_port(). Jun 11, 2013
.gitignore update .gitignore to ignore MYMETA.json Apr 2, 2015
.travis.yml added .travis.yml Mar 3, 2013
Changes Checking in changes prior to tagging of version 2.16. Apr 13, 2016
LICENSE minil-ized Mar 27, 2013
META.json Checking in changes prior to tagging of version 2.16. Apr 13, 2016
Makefile.PL
README.md
cpanfile
minil.toml

README.md

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 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.

      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 tokuhirom@gmail.com

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.