File Coverage

blib/lib/AnyEvent/MockTCPServer.pm
Criterion Covered Total %
statement 130 144 90.2
branch 9 16 56.2
condition 0 3 0.0
subroutine 28 31 90.3
pod 15 15 100.0
total 182 209 87.0


line stmt bran cond sub pod time code
1 5     5   453365 use strict;
  5         16  
  5         183  
2 5     5   36 use warnings;
  5         12  
  5         375  
3             package AnyEvent::MockTCPServer;
4             $AnyEvent::MockTCPServer::VERSION = '1.172150';
5             # ABSTRACT: Mock TCP Server using AnyEvent
6              
7              
8             1;
9              
10             use constant {
11             DEBUG => $ENV{ANYEVENT_MOCK_TCP_SERVER_DEBUG}
12 5     5   36 };
  5         16  
  5         437  
13 5     5   33 use AnyEvent;
  5         13  
  5         124  
14 5     5   45 use AnyEvent::Socket;
  5         13  
  5         403  
15 5     5   2676 use AnyEvent::Handle;
  5         40435  
  5         264  
16 5     5   60 use Test::More;
  5         16  
  5         59  
17 5     5   3700 use Sub::Name;
  5         2861  
  5         9416  
18              
19              
20             sub new {
21 5     5 1 40397 my $pkg = shift;
22 5         131 my $finished_cv = AnyEvent->condvar;
23             my $self =
24             {
25             connections => [],
26             listening => AnyEvent->condvar,
27             finished_cv => $finished_cv,
28             host => '127.0.0.1',
29             port => 0,
30             timeout => 2,
31             on_timeout => subname('default_client_on_timeout_cb' =>
32             sub {
33 1     1   100553 $finished_cv->end;
34 1         46 die "server timeout\n";
35 5         125 }),
36             @_
37             };
38 5         125 bless $self, $pkg;
39              
40 5         16 foreach (@{$self->{connections}}) {
  5         42  
41 5         90 $finished_cv->begin;
42             }
43              
44             $self->{server} =
45             tcp_server $self->{host}, $self->{port}, subname('accept_cb' =>
46             sub {
47 6     6   11821 my ($fh) = @_;
48 6         19 print STDERR "In server: $fh ", fileno($fh), "\n" if DEBUG;
49 6         15 my $handle;
50             $handle =
51             AnyEvent::Handle->new(fh => $fh,
52             on_error => subname('client_on_error_cb_'.$fh =>
53             sub {
54 1         224 my ($hdl, $fatal, $msg) = @_;
55 1         7 warn "error $msg\n";
56             $self->{on_error}->(@_)
57 1 50       10 if ($self->{on_error});
58 1         12 $hdl->destroy;
59             }),
60             timeout => $self->{timeout},
61             on_timeout => $self->{on_timeout},
62 6         146 );
63 6         907 print STDERR "Connection handle: $handle\n" if DEBUG;
64 6         30 $self->{handles}->{$handle} = $handle;
65 6         20 my $con = $self->{connections};
66 6 100       94 unless (@$con) {
67 1         11 die "Server received unexpected connection\n";
68             }
69 5         18 my $actions = shift @$con;
70 5         14 print STDERR "Actions: ", (scalar @$actions), "\n" if DEBUG;
71 5 100       22 unless (@$con) {
72 4         30 delete $self->{server};
73             }
74 5         125 $self->next_action($handle, $actions);
75             }), subname('prepare_cb' => sub {
76 5     5   1342 my ($fh, $host, $port) = @_;
77 5 50       29 die "tcp_server setup failed: $!\n" unless ($fh);
78 5         65 $self->{listening}->send([$host, $port]);
79 5         117 0;
80 5         233 });
81 5         299 return $self;
82             }
83              
84             sub DESTROY {
85 3     3   6289 my $self = shift;
86 3         17 delete $self->{listening};
87 3         9 delete $self->{server};
88 3         10 foreach (values %{$self->{handles}}) {
  3         146  
89 1 50       4 next unless (defined $_);
90 1         6 $_->destroy;
91 1         128 delete $self->{handles}->{$_};
92             }
93             }
94              
95              
96             sub listening {
97 8     8 1 53 shift->{listening};
98             }
99              
100              
101             sub connect_address {
102 6     6 1 46 @{shift->listening->recv};
  6         31  
103             }
104              
105              
106             sub connect_host {
107 1     1 1 1147 shift->listening->recv->[0];
108             }
109              
110              
111             sub connect_port {
112 1     1 1 742 shift->listening->recv->[1];
113             }
114              
115              
116             sub connect_string {
117 1     1 1 444 join ':', shift->connect_address
118             }
119              
120              
121             sub finished_cv {
122 0     0 1 0 my $self = shift;
123 0         0 $self->{finished_cv};
124             }
125              
126              
127             sub next_action {
128 13     13 1 55 my ($self, $handle, $actions) = @_;
129 13         35 print STDERR 'In handle connection ', scalar @$actions, "\n" if DEBUG;
130 13         43 my $action = shift @$actions;
131 13 100       53 unless (defined $action) {
132 3         9 print STDERR "closing connection\n" if DEBUG;
133 3         24 $handle->push_shutdown;
134 3         213 delete $self->{handles}->{$handle};
135 3         28 $self->{finished_cv}->end;
136 3         97 return;
137             }
138 10         38 my $method = shift @$action;
139 10         26 print STDERR "executing action: ", $method, "\n" if DEBUG;
140 10         103 $self->$method($handle, $actions, @$action);
141             }
142              
143              
144             sub send {
145 1     1 1 6 my ($self, $handle, $actions, $send, $desc) = @_;
146 1         3 print STDERR 'Sending: ', $send, ' ', $desc, "\n" if DEBUG;
147 1         3 print STDERR 'Sending ', length $send, " bytes\n" if DEBUG;
148 1         11 $handle->push_write($send);
149 1         215 $self->next_action($handle, $actions);
150             }
151              
152              
153             sub packsend {
154 2     2 1 11 my ($self, $handle, $actions, $data, $desc) = @_;
155 2         7 my $send = $data;
156 2         10 $send =~ s/\s+//g;
157 2         5 print STDERR 'Sending: ', $send, ' ', $desc, "\n" if DEBUG;
158 2         15 $send = pack 'H*', $send;
159 2         5 print STDERR 'Sending ', length $send, " bytes\n" if DEBUG;
160 2         15 $handle->push_write($send);
161 2         238 $self->next_action($handle, $actions);
162             }
163              
164              
165             sub recv {
166 1     1 1 6 my ($self, $handle, $actions, $recv, $desc) = @_;
167 1         4 print STDERR 'Waiting for ', $recv, ' ', $desc, "\n" if DEBUG;
168 1         2 my $len = length $recv;
169 1         3 print STDERR 'Waiting for ', $len, " bytes\n" if DEBUG;
170             $handle->push_read(chunk => $len,
171             sub {
172 1     1   200 my ($hdl, $data) = @_;
173 1         4 print STDERR "In receive handler\n" if DEBUG;
174 1         25 is($data, $recv,
175             '... correct message received by server - '.$desc);
176 1         454 $self->next_action($hdl, $actions);
177 1         21 1;
178 1         17 });
179             }
180              
181              
182             sub recvline {
183 0     0 1 0 my ($self, $handle, $actions, $recv, $desc) = @_;
184 0         0 print STDERR 'Waiting for ', $recv, ' ', $desc, "\n" if DEBUG;
185 0         0 print STDERR "Waiting for line\n" if DEBUG;
186             $handle->push_read(line =>
187             sub {
188 0     0   0 my ($hdl, $data) = @_;
189 0         0 print STDERR "In receive handler\n" if DEBUG;
190 0 0 0     0 $recv = $recv->() if (ref $recv && ref $recv eq 'CODE');
191 0 0       0 if (ref $recv) {
192 0         0 like($data, $recv,
193             '... correct message received by server - '.$desc);
194             } else {
195 0         0 is($data, $recv,
196             '... correct message received by server - '.$desc);
197             }
198 0         0 $self->next_action($hdl, $actions);
199 0         0 1;
200 0         0 });
201             }
202              
203              
204             sub packrecv {
205 4     4 1 46 my ($self, $handle, $actions, $data, $desc) = @_;
206 4         14 my $recv = $data;
207 4         17 $recv =~ s/\s+//g;
208 4         12 my $expect = $recv;
209 4         10 print STDERR 'Waiting for ', $recv, ' ', $desc, "\n" if DEBUG;
210 4         17 my $len = .5*length $recv;
211 4         10 print STDERR 'Waiting for ', $len, " bytes\n" if DEBUG;
212             $handle->push_read(chunk => $len,
213             sub {
214 2     2   2447 my ($hdl, $data) = @_;
215 2         5 print STDERR "In receive handler\n" if DEBUG;
216 2         13 my $got = uc unpack 'H*', $data;
217 2         19 is($got, $expect,
218             '... correct message received by server - '.$desc);
219 2         934 $self->next_action($hdl, $actions);
220 2         8 1;
221 4         46 });
222             }
223              
224              
225             sub sleep {
226 1     1 1 4 my ($self, $handle, $actions, $interval, $desc) = @_;
227 1         3 print STDERR 'Sleeping for ', $interval, ' ', $desc, "\n" if DEBUG;
228 1         3 my $w;
229             $w = AnyEvent->timer(after => $interval,
230             cb => sub {
231 1     1   99386 $self->next_action($handle, $actions);
232 1         15 undef $w;
233 1         13 });
234             }
235              
236              
237             sub code {
238 1     1 1 8 my ($self, $handle, $actions, $code, $desc) = @_;
239 1         6 print STDERR 'Executing ', $code, ' for ', $desc, "\n" if DEBUG;
240 1         11 $code->($self, $handle, $desc);
241 1         768 $self->next_action($handle, $actions);
242             }
243              
244             1;
245              
246             __END__