.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Test::TCP 3pm" .TH Test::TCP 3pm "2020-09-08" "perl v5.30.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Test::TCP \- testing TCP program .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Test::TCP; \& \& my $server = Test::TCP\->new( \& listen => 1, \& code => sub { \& my $socket = shift; \& ... \& }, \& ); \& my $client = MyClient\->new(host => \*(Aq127.0.0.1\*(Aq, port => $server\->port); \& undef $server; # kill child process on DESTROY .Ve .PP If using a server that can only accept a port number, e.g. memcached: .PP .Vb 1 \& use Test::TCP; \& \& my $memcached = Test::TCP\->new( \& code => sub { \& my $port = shift; \& \& exec $bin, \*(Aq\-p\*(Aq => $port; \& die "cannot execute $bin: $!"; \& }, \& ); \& my $memd = Cache::Memcached\->new({servers => [\*(Aq127.0.0.1:\*(Aq . $memcached\->port]}); \& ... .Ve .PP \&\fBN.B.\fR: This is vulnerable to race conditions, if another process binds to the same port after Net::EmptyPort found it available. .PP And functional interface is available: .PP .Vb 12 \& 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 \& }, \& ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Test::TCP is a test utility to test TCP/IP\-based server programs. .SH "METHODS" .IX Header "METHODS" .IP "test_tcp" 4 .IX Item "test_tcp" Functional interface. .Sp .Vb 10 \& test_tcp( \& listen => 1, \& client => sub { \& my $port = shift; \& # send request to the server \& }, \& server => sub { \& my $socket = shift; \& # run server \& }, \& # optional \& host => \*(Aq127.0.0.1\*(Aq, # specify \*(Aq::1\*(Aq to test using IPv6 \& port => 8080, \& max_wait => 3, # seconds \& ); .Ve .Sp If \f(CW\*(C`listen\*(C'\fR is false, \f(CW\*(C`server\*(C'\fR is instead passed a port number that was free before it was called. .IP "wait_port" 4 .IX Item "wait_port" .Vb 1 \& wait_port(8080); .Ve .Sp Waits for a particular port is available for connect. .SH "Object Oriented interface" .IX Header "Object Oriented interface" .ie n .IP "my $server = Test::TCP\->new(%args);" 4 .el .IP "my \f(CW$server\fR = Test::TCP\->new(%args);" 4 .IX Item "my $server = Test::TCP->new(%args);" Create new instance of Test::TCP. .Sp Arguments are following: .RS 4 .ie n .IP "$args{auto_start}: Boolean" 4 .el .IP "\f(CW$args\fR{auto_start}: Boolean" 4 .IX Item "$args{auto_start}: Boolean" Call \f(CW\*(C`$server\->start()\*(C'\fR after create instance. .Sp Default: true .ie n .IP "$args{code}: CodeRef" 4 .el .IP "\f(CW$args\fR{code}: CodeRef" 4 .IX Item "$args{code}: CodeRef" The callback function. Argument for callback function is: \&\f(CW\*(C`$code\->($socket)\*(C'\fR or \f(CW\*(C`$code\->($port)\*(C'\fR, depending on the value of \f(CW\*(C`listen\*(C'\fR. .Sp This parameter is required. .ie n .IP "$args{max_wait} : Number" 4 .el .IP "\f(CW$args\fR{max_wait} : Number" 4 .IX Item "$args{max_wait} : Number" Will wait for at most \f(CW$max_wait\fR seconds before checking port. .Sp See also Net::EmptyPort. .Sp \&\fIDefault: 10\fR .ie n .IP "$args{listen} : Boolean" 4 .el .IP "\f(CW$args\fR{listen} : Boolean" 4 .IX Item "$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. .RE .RS 4 .RE .ie n .IP "$server\->\fBstart()\fR" 4 .el .IP "\f(CW$server\fR\->\fBstart()\fR" 4 .IX Item "$server->start()" Start the server process. Normally, you don't need to call this method. .ie n .IP "$server\->\fBstop()\fR" 4 .el .IP "\f(CW$server\fR\->\fBstop()\fR" 4 .IX Item "$server->stop()" Stop the server process. .ie n .IP "my $pid = $server\->\fBpid()\fR;" 4 .el .IP "my \f(CW$pid\fR = \f(CW$server\fR\->\fBpid()\fR;" 4 .IX Item "my $pid = $server->pid();" Get the pid of child process. .ie n .IP "my $port = $server\->\fBport()\fR;" 4 .el .IP "my \f(CW$port\fR = \f(CW$server\fR\->\fBport()\fR;" 4 .IX Item "my $port = $server->port();" Get the port number of child process. .SH "FAQ" .IX Header "FAQ" .IP "How to invoke two servers?" 4 .IX Item "How to invoke two servers?" You can call \fBtest_tcp()\fR twice! .Sp .Vb 10 \& 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 \& }, \& ); .Ve .Sp Or use the \s-1OO\s0 interface instead. .Sp .Vb 8 \& my $server1 = Test::TCP\->new(code => sub { \& my $port1 = shift; \& ... \& }); \& my $server2 = Test::TCP\->new(code => sub { \& my $port2 = shift; \& ... \& }); \& \& # your client code here. \& ... .Ve .IP "How do you test server program written in other languages like memcached?" 4 .IX Item "How do you test server program written in other languages like memcached?" You can use \f(CW\*(C`exec()\*(C'\fR in child process. .Sp .Vb 6 \& use strict; \& use warnings; \& use utf8; \& use Test::More; \& use Test::TCP 1.08; \& use File::Which; \& \& my $bin = scalar which \*(Aqmemcached\*(Aq; \& plan skip_all => \*(Aqmemcached binary is not found\*(Aq unless defined $bin; \& \& my $memcached = Test::TCP\->new( \& code => sub { \& my $port = shift; \& \& exec $bin, \*(Aq\-p\*(Aq => $port; \& die "cannot execute $bin: $!"; \& }, \& ); \& \& use Cache::Memcached; \& my $memd = Cache::Memcached\->new({servers => [\*(Aq127.0.0.1:\*(Aq . $memcached\->port]}); \& $memd\->set(foo => \*(Aqbar\*(Aq); \& is $memd\->get(\*(Aqfoo\*(Aq), \*(Aqbar\*(Aq; \& \& done_testing; .Ve .ie n .IP "How do I use address other than ""127.0.0.1"" for testing?" 4 .el .IP "How do I use address other than ``127.0.0.1'' for testing?" 4 .IX Item "How do I use address other than 127.0.0.1 for testing?" You can use the \f(CW\*(C`host\*(C'\fR parameter to specify the bind address. .Sp .Vb 10 \& # let the server bind to "0.0.0.0" for testing \& test_tcp( \& client => sub { \& ... \& }, \& server => sub { \& ... \& }, \& host => \*(Aq0.0.0.0\*(Aq, \& ); .Ve .IP "How should I write IPv6 tests?" 4 .IX Item "How should I write IPv6 tests?" You should use the \*(L"can_bind\*(R" in Net::EmptyPort function to check if the program can bind to the loopback address of IPv6, as well as the \f(CW\*(C`host\*(C'\fR parameter of the \*(L"test_tcp\*(R" function to specify the same address as the bind address. .Sp .Vb 1 \& use Net::EmptyPort qw(can_bind); \& \& plan skip_all => "IPv6 not available" \& unless can_bind(\*(Aq::1\*(Aq); \& \& test_tcp( \& client => sub { \& ... \& }, \& server => sub { \& ... \& }, \& host => \*(Aq::1\*(Aq, \& ); .Ve .SH "AUTHOR" .IX Header "AUTHOR" Tokuhiro Matsuno .SH "THANKS TO" .IX Header "THANKS TO" kazuhooku .PP dragon3 .PP charsbar .PP Tatsuhiko Miyagawa .PP lestrrat .SH "SEE ALSO" .IX Header "SEE ALSO" .SH "LICENSE" .IX Header "LICENSE" This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.