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   427244 use strict;
  5         14  
  5         206  
2 5     5   29 use warnings;
  5         12  
  5         349  
3             package AnyEvent::MockTCPServer;
4             $AnyEvent::MockTCPServer::VERSION = '1.142230';
5             # ABSTRACT: Mock TCP Server using AnyEvent
6              
7              
8             1;
9              
10             use constant {
11 5         330 DEBUG => $ENV{ANYEVENT_MOCK_TCP_SERVER_DEBUG}
12 5     5   25 };
  5         16  
13 5     5   29 use AnyEvent;
  5         12  
  5         144  
14 5     5   31 use AnyEvent::Socket;
  5         8  
  5         525  
15 5     5   6939 use AnyEvent::Handle;
  5         87203  
  5         218  
16 5     5   57 use Test::More;
  5         9  
  5         52  
17 5     5   6701 use Sub::Name;
  5         5035  
  5         12356  
18              
19              
20             sub new {
21 5     5 1 67483 my $pkg = shift;
22 5         157 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 => undef,
30             timeout => 2,
31             on_timeout => subname('default_client_on_timeout_cb' =>
32             sub {
33 1     1   100045 $finished_cv->end;
34 1         75 die "server timeout\n";
35 5         155 }),
36             @_
37             };
38 5         155 bless $self, $pkg;
39              
40 5         13 foreach (@{$self->{connections}}) {
  5         41  
41 5         122 $finished_cv->begin;
42             }
43              
44             $self->{server} =
45             tcp_server $self->{host}, $self->{port}, subname('accept_cb' =>
46             sub {
47 6     6   10988 my ($fh) = @_;
48 6         13 print STDERR "In server: $fh ", fileno($fh), "\n" if DEBUG;
49 6         12 my $handle;
50             $handle =
51             AnyEvent::Handle->new(fh => $fh,
52             on_error => subname('client_on_error_cb_'.$fh =>
53             sub {
54 1         242 my ($hdl, $fatal, $msg) = @_;
55 1         12 warn "error $msg\n";
56 1 50       14 $self->{on_error}->(@_)
57             if ($self->{on_error});
58 1         15 $hdl->destroy;
59 6         233 }),
60             timeout => $self->{timeout},
61             on_timeout => $self->{on_timeout},
62             );
63 6         700 print STDERR "Connection handle: $handle\n" if DEBUG;
64 6         31 $self->{handles}->{$handle} = $handle;
65 6         17 my $con = $self->{connections};
66 6 100       26 unless (@$con) {
67 1         14 die "Server received unexpected connection\n";
68             }
69 5         9 my $actions = shift @$con;
70 5         10 print STDERR "Actions: ", (scalar @$actions), "\n" if DEBUG;
71 5 100       27 unless (@$con) {
72 4         23 delete $self->{server};
73             }
74 5         131 $self->next_action($handle, $actions);
75             }), subname('prepare_cb' => sub {
76 5     5   1165 my ($fh, $host, $port) = @_;
77 5 50       35 die "tcp_server setup failed: $!\n" unless ($fh);
78 5         56 $self->{listening}->send([$host, $port]);
79 5         144 0;
80 5         369 });
81 5         345 return $self;
82             }
83              
84             sub DESTROY {
85 3     3   4880 my $self = shift;
86 3         15 delete $self->{listening};
87 3         8 delete $self->{server};
88 3         6 foreach (values %{$self->{handles}}) {
  3         278  
89 1 50       5 next unless (defined $_);
90 1         8 $_->destroy;
91 1         159 delete $self->{handles}->{$_};
92             }
93             }
94              
95              
96             sub listening {
97 8     8 1 62 shift->{listening};
98             }
99              
100              
101             sub connect_address {
102 6     6 1 39 @{shift->listening->recv};
  6         25  
103             }
104              
105              
106             sub connect_host {
107 1     1 1 666 shift->listening->recv->[0];
108             }
109              
110              
111             sub connect_port {
112 1     1 1 751 shift->listening->recv->[1];
113             }
114              
115              
116             sub connect_string {
117 1     1 1 486 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 28 my ($self, $handle, $actions) = @_;
129 13         17 print STDERR 'In handle connection ', scalar @$actions, "\n" if DEBUG;
130 13         25 my $action = shift @$actions;
131 13 100       79 unless (defined $action) {
132 3         5 print STDERR "closing connection\n" if DEBUG;
133 3         14 $handle->push_shutdown;
134 3         122 delete $self->{handles}->{$handle};
135 3         19 $self->{finished_cv}->end;
136 3         49 return;
137             }
138 10         40 my $method = shift @$action;
139 10         12 print STDERR "executing action: ", $method, "\n" if DEBUG;
140 10         46 $self->$method($handle, $actions, @$action);
141             }
142              
143              
144             sub send {
145 1     1 1 3 my ($self, $handle, $actions, $send, $desc) = @_;
146 1         2 print STDERR 'Sending: ', $send, ' ', $desc, "\n" if DEBUG;
147 1         2 print STDERR 'Sending ', length $send, " bytes\n" if DEBUG;
148 1         8 $handle->push_write($send);
149 1         134 $self->next_action($handle, $actions);
150             }
151              
152              
153             sub packsend {
154 2     2 1 4 my ($self, $handle, $actions, $data, $desc) = @_;
155 2         4 my $send = $data;
156 2         3 $send =~ s/\s+//g;
157 2         3 print STDERR 'Sending: ', $send, ' ', $desc, "\n" if DEBUG;
158 2         9 $send = pack 'H*', $send;
159 2         3 print STDERR 'Sending ', length $send, " bytes\n" if DEBUG;
160 2         7 $handle->push_write($send);
161 2         227 $self->next_action($handle, $actions);
162             }
163              
164              
165             sub recv {
166 1     1 1 3 my ($self, $handle, $actions, $recv, $desc) = @_;
167 1         2 print STDERR 'Waiting for ', $recv, ' ', $desc, "\n" if DEBUG;
168 1         2 my $len = length $recv;
169 1         2 print STDERR 'Waiting for ', $len, " bytes\n" if DEBUG;
170             $handle->push_read(chunk => $len,
171             sub {
172 1     1   149 my ($hdl, $data) = @_;
173 1         2 print STDERR "In receive handler\n" if DEBUG;
174 1         6 is($data, $recv,
175             '... correct message received by server - '.$desc);
176 1         459 $self->next_action($hdl, $actions);
177 1         15 1;
178 1         34 });
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 11 my ($self, $handle, $actions, $data, $desc) = @_;
206 4         7 my $recv = $data;
207 4         12 $recv =~ s/\s+//g;
208 4         8 my $expect = $recv;
209 4         16 print STDERR 'Waiting for ', $recv, ' ', $desc, "\n" if DEBUG;
210 4         25 my $len = .5*length $recv;
211 4         5 print STDERR 'Waiting for ', $len, " bytes\n" if DEBUG;
212             $handle->push_read(chunk => $len,
213             sub {
214 2     2   1596 my ($hdl, $data) = @_;
215 2         3 print STDERR "In receive handler\n" if DEBUG;
216 2         8 my $got = uc unpack 'H*', $data;
217 2         9 is($got, $expect,
218             '... correct message received by server - '.$desc);
219 2         828 $self->next_action($hdl, $actions);
220 2         4 1;
221 4         34 });
222             }
223              
224              
225             sub sleep {
226 1     1 1 4 my ($self, $handle, $actions, $interval, $desc) = @_;
227 1         2 print STDERR 'Sleeping for ', $interval, ' ', $desc, "\n" if DEBUG;
228 1         2 my $w;
229             $w = AnyEvent->timer(after => $interval,
230             cb => sub {
231 1     1   100309 $self->next_action($handle, $actions);
232 1         15 undef $w;
233 1         11 });
234             }
235              
236              
237             sub code {
238 1     1 1 3 my ($self, $handle, $actions, $code, $desc) = @_;
239 1         3 print STDERR 'Executing ', $code, ' for ', $desc, "\n" if DEBUG;
240 1         7 $code->($self, $handle, $desc);
241 1         682 $self->next_action($handle, $actions);
242             }
243              
244             1;
245              
246             __END__