README.md
1# NAME
2
3Test::TCP - testing TCP program
4
5# SYNOPSIS
6
7 use Test::TCP;
8
9 my $server = Test::TCP->new(
10 listen => 1,
11 code => sub {
12 my $socket = shift;
13 ...
14 },
15 );
16 my $client = MyClient->new(host => '127.0.0.1', port => $server->port);
17 undef $server; # kill child process on DESTROY
18
19If using a server that can only accept a port number, e.g. memcached:
20
21 use Test::TCP;
22
23 my $memcached = Test::TCP->new(
24 code => sub {
25 my $port = shift;
26
27 exec $bin, '-p' => $port;
28 die "cannot execute $bin: $!";
29 },
30 );
31 my $memd = Cache::Memcached->new({servers => ['127.0.0.1:' . $memcached->port]});
32 ...
33
34**N.B.**: This is vulnerable to race conditions, if another process binds
35to the same port after [Net::EmptyPort](https://metacpan.org/pod/Net::EmptyPort) found it available.
36
37And functional interface is available:
38
39 use Test::TCP;
40 test_tcp(
41 listen => 1,
42 client => sub {
43 my ($port, $server_pid) = @_;
44 # send request to the server
45 },
46 server => sub {
47 my $socket = shift;
48 # run server, calling $socket->accept
49 },
50 );
51
52 test_tcp(
53 client => sub {
54 my ($port, $server_pid) = @_;
55 # send request to the server
56 },
57 server => sub {
58 my $port = shift;
59 # run server, binding to $port
60 },
61 );
62
63# DESCRIPTION
64
65Test::TCP is a test utility to test TCP/IP-based server programs.
66
67# METHODS
68
69- test\_tcp
70
71 Functional interface.
72
73 test_tcp(
74 listen => 1,
75 client => sub {
76 my $port = shift;
77 # send request to the server
78 },
79 server => sub {
80 my $socket = shift;
81 # run server
82 },
83 # optional
84 host => '127.0.0.1', # specify '::1' to test using IPv6
85 port => 8080,
86 max_wait => 3, # seconds
87 );
88
89 If `listen` is false, `server` is instead passed a port number that
90 was free before it was called.
91
92- wait\_port
93
94 wait_port(8080);
95
96 Waits for a particular port is available for connect.
97
98# Object Oriented interface
99
100- my $server = Test::TCP->new(%args);
101
102 Create new instance of Test::TCP.
103
104 Arguments are following:
105
106 - $args{auto\_start}: Boolean
107
108 Call `$server->start()` after create instance.
109
110 Default: true
111
112 - $args{code}: CodeRef
113
114 The callback function. Argument for callback function is:
115 `$code->($socket)` or `$code->($port)`,
116 depending on the value of `listen`.
117
118 This parameter is required.
119
120 - $args{max\_wait} : Number
121
122 Will wait for at most `$max_wait` seconds before checking port.
123
124 See also [Net::EmptyPort](https://metacpan.org/pod/Net::EmptyPort).
125
126 _Default: 10_
127
128 - $args{listen} : Boolean
129
130 If true, open a listening socket and pass this to the callback.
131 Otherwise find a free port and pass the number of it to the callback.
132
133- $server->start()
134
135 Start the server process. Normally, you don't need to call this method.
136
137- $server->stop()
138
139 Stop the server process.
140
141- my $pid = $server->pid();
142
143 Get the pid of child process.
144
145- my $port = $server->port();
146
147 Get the port number of child process.
148
149# FAQ
150
151- How to invoke two servers?
152
153 You can call test\_tcp() twice!
154
155 test_tcp(
156 client => sub {
157 my $port1 = shift;
158 test_tcp(
159 client => sub {
160 my $port2 = shift;
161 # some client code here
162 },
163 server => sub {
164 my $port2 = shift;
165 # some server2 code here
166 },
167 );
168 },
169 server => sub {
170 my $port1 = shift;
171 # some server1 code here
172 },
173 );
174
175 Or use the OO interface instead.
176
177 my $server1 = Test::TCP->new(code => sub {
178 my $port1 = shift;
179 ...
180 });
181 my $server2 = Test::TCP->new(code => sub {
182 my $port2 = shift;
183 ...
184 });
185
186 # your client code here.
187 ...
188
189- How do you test server program written in other languages like memcached?
190
191 You can use `exec()` in child process.
192
193 use strict;
194 use warnings;
195 use utf8;
196 use Test::More;
197 use Test::TCP 1.08;
198 use File::Which;
199
200 my $bin = scalar which 'memcached';
201 plan skip_all => 'memcached binary is not found' unless defined $bin;
202
203 my $memcached = Test::TCP->new(
204 code => sub {
205 my $port = shift;
206
207 exec $bin, '-p' => $port;
208 die "cannot execute $bin: $!";
209 },
210 );
211
212 use Cache::Memcached;
213 my $memd = Cache::Memcached->new({servers => ['127.0.0.1:' . $memcached->port]});
214 $memd->set(foo => 'bar');
215 is $memd->get('foo'), 'bar';
216
217 done_testing;
218
219- How do I use address other than "127.0.0.1" for testing?
220
221 You can use the `host` parameter to specify the bind address.
222
223 # let the server bind to "0.0.0.0" for testing
224 test_tcp(
225 client => sub {
226 ...
227 },
228 server => sub {
229 ...
230 },
231 host => '0.0.0.0',
232 );
233
234- How should I write IPv6 tests?
235
236 You should use the ["can\_bind" in Net::EmptyPort](https://metacpan.org/pod/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"](#test_tcp) function to specify the same address as the bind address.
237
238 use Net::EmptyPort qw(can_bind);
239
240 plan skip_all => "IPv6 not available"
241 unless can_bind('::1');
242
243 test_tcp(
244 client => sub {
245 ...
246 },
247 server => sub {
248 ...
249 },
250 host => '::1',
251 );
252
253# AUTHOR
254
255Tokuhiro Matsuno <tokuhirom@gmail.com>
256
257# THANKS TO
258
259kazuhooku
260
261dragon3
262
263charsbar
264
265Tatsuhiko Miyagawa
266
267lestrrat
268
269# SEE ALSO
270
271# LICENSE
272
273This library is free software; you can redistribute it and/or modify
274it under the same terms as Perl itself.
275