Test::TCP for perl
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib cosmetic fixes for minil dist Jul 20, 2018
t Fix tests for '.' in @inc Jul 18, 2018
xt
.appveyor.yml Don't upgrade Test::Simple in Windows CI Jul 20, 2018
.gitignore cosmetic fixes for minil dist Jul 20, 2018
.mailmap cosmetic fixes for minil dist Jul 20, 2018
.travis.yml build 5.26 in Travis Jul 18, 2018
Changes Checking in changes prior to tagging of version 2.19. May 11, 2017
LICENSE minil-ized Mar 27, 2013
MANIFEST.SKIP cosmetic fixes for minil dist Jul 20, 2018
META.json regenerate Makefile.PL and META.json with latest minil Jul 23, 2018
Makefile.PL regenerate Makefile.PL and META.json with latest minil Jul 23, 2018
README.md Checking in changes prior to tagging of version 2.16. Apr 13, 2016
cpanfile IO::Socket::IP is required not only on test time Apr 6, 2015
minil.toml Convert to Makefile.PL Jun 23, 2014

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.