File Coverage

inc/Test/HTTP/LocalServer.pm
Criterion Covered Total %
statement 62 73 84.9
branch 8 18 44.4
condition 1 2 50.0
subroutine 15 17 88.2
pod 5 5 100.0
total 91 115 79.1


line stmt bran cond sub pod time code
1             package Test::HTTP::LocalServer;
2              
3             # start a fake webserver, fork, and connect to ourselves
4 7     7   2675 use strict;
  7         13  
  7         160  
5 7     7   2093 use LWP::Simple;
  7         86458  
  7         49  
6 7     7   4418 use FindBin;
  7         5729  
  7         325  
7 7     7   68 use File::Spec;
  7         12  
  7         99  
8 7     7   4101 use File::Temp;
  7         59018  
  7         412  
9 7     7   2360 use URI::URL qw();
  7         15629  
  7         132  
10 7     7   35 use Carp qw(carp croak);
  7         10  
  7         284  
11              
12 7     7   30 use vars qw($VERSION);
  7         9  
  7         3647  
13             $VERSION = '0.53';
14              
15             =head1 SYNOPSIS
16              
17             use LWP::Simple qw(get);
18             my $server = Test::HTTP::LocalServer->spawn;
19              
20             ok get $server->url, "Retrieve " . $server->url;
21              
22             $server->stop;
23              
24             =head1 METHODS
25              
26             =head2 Cspawn %ARGS>
27              
28             This spawns a new HTTP server. The server will stay running until
29             $server->stop
30             is called.
31              
32             Valid arguments are :
33              
34             =over 4
35              
36             =item *
37              
38             C<< html => >> scalar containing the page to be served
39              
40             =item *
41              
42             C<< file => >> filename containing the page to be served
43              
44             =item *
45              
46             C<< debug => 1 >> to make the spawned server output debug information
47              
48             =item *
49              
50             C<< eval => >> string that will get evaluated per request in the server
51              
52             Try to avoid characters that are special to the shell, especially quotes.
53             A good idea for a slow server would be
54              
55             eval => sleep+10
56              
57             =back
58              
59             All served HTML will have the first %s replaced by the current location.
60              
61             The following entries will be removed from C<%ENV>:
62              
63             HTTP_PROXY
64             http_proxy
65             CGI_HTTP_PROXY
66              
67             =cut
68              
69             sub spawn {
70 7     7 1 29052 my ($class,%args) = @_;
71 7         19 my $self = { %args };
72 7         12 bless $self,$class;
73              
74             local $ENV{TEST_HTTP_VERBOSE} = 1
75 7 50       21 if (delete $args{debug});
76              
77 7         53 delete @ENV{qw(HTTP_PROXY http_proxy CGI_HTTP_PROXY)};
78              
79 7         49 $self->{delete} = [];
80 7 50       18 if (my $html = delete $args{html}) {
81             # write the html to a temp file
82 0         0 my ($fh,$tempfile) = File::Temp::tempfile();
83 0         0 binmode $fh;
84 0 0       0 print $fh $html
85             or die "Couldn't write tempfile $tempfile : $!";
86 0         0 close $fh;
87 0         0 push @{$self->{delete}},$tempfile;
  0         0  
88 0         0 $args{file} = $tempfile;
89             };
90 7         22 my ($fh,$logfile) = File::Temp::tempfile();
91 7         3065 close $fh;
92 7         13 push @{$self->{delete}},$logfile;
  7         20  
93 7         13 $self->{logfile} = $logfile;
94 7   50     38 my $web_page = delete $args{file} || "";
95              
96 7         99 my $server_file = File::Spec->catfile( $FindBin::Bin,File::Spec->updir,'inc','Test','HTTP','log-server' );
97 7         15 my @opts;
98             push @opts, "-e" => qq{"} . delete($args{ eval }) . qq{"}
99 7 100       20 if $args{ eval };
100              
101 7 50       16457 open my $server, qq'$^X "$server_file" "$web_page" "$logfile" @opts|'
102             or croak "Couldn't spawn local server $server_file : $!";
103 7         723308 my $url = <$server>;
104 7         102 chomp $url;
105 7 50       133 die "Couldn't read back local server url"
106             unless $url;
107              
108 7         98 $self->{_fh} = $server;
109 7         459 $self->{_server_url} = URI::URL->new($url);
110              
111 7         51129 $self;
112             };
113              
114             =head2 C<< $server->port >>
115              
116             This returns the port of the current server. As new instances
117             will most likely run under a different port, this is convenient
118             if you need to compare results from two runs.
119              
120             =cut
121              
122             sub port {
123 0 0   0 1 0 carp __PACKAGE__ . "::port called without a server" unless $_[0]->{_server_url};
124             $_[0]->{_server_url}->port
125 0         0 };
126              
127             =head2 C<< $server->url >>
128              
129             This returns the url where you can contact the server. This url
130             is valid until the C<$server> goes out of scope or you call
131             $server->stop;
132              
133             =cut
134              
135             sub url {
136             $_[0]->{_server_url}->abs
137 7     7 1 94 };
138              
139             =head2 C<< $server->stop >>
140              
141             This stops the server process by requesting a special
142             url.
143              
144             =cut
145              
146             sub stop {
147 7     7 1 24733 get( $_[0]->{_server_url} . "quit_server" );
148             undef $_[0]->{_server_url}
149 7         2879 };
150              
151             =head2 C<< $server->get_log >>
152              
153             This returns the
154             output of the server process. This output will be a list of
155             all requests made to the server concatenated together
156             as a string.
157              
158             =cut
159              
160             sub get_log {
161 0     0 1 0 my ($self) = @_;
162 0         0 return get( $self->{_server_url} . "get_server_log" );
163             };
164              
165             sub DESTROY {
166 7 50   7   139 $_[0]->stop if $_[0]->{_server_url};
167 7         16 for my $file (@{$_[0]->{delete}}) {
  7         53  
168 7 50       6976399 unlink $file or warn "Couldn't remove tempfile $file : $!\n";
169             };
170             };
171              
172             =head1 URLs implemented by the server
173              
174             =head2 302 redirect C<< $server->redirect($target) >>
175              
176             This URL will issue a redirect to C<$target>. No special care is taken
177             towards URL-decoding C<$target> as not to complicate the server code.
178             You need to be wary about issuing requests with escaped URL parameters.
179              
180             =head2 404 error C<< $server->error_notfound($target) >>
181              
182             This URL will response with status code 404.
183              
184             =head2 Error in response content C<< $server->error_after_headers >>
185              
186             This URL will send headers for a successfull response but will close the
187             socket with an error after 2 blocks of 16 spaces have been sent.
188              
189             =head2 Chunked response C<< $server->chunked >>
190              
191             This URL will return 5 blocks of 16 spaces at a rate of one block per second
192             in a chunked response.
193              
194             =head2 Other URLs
195              
196             All other URLs will echo back the cookies and query parameters.
197              
198             =cut
199              
200 7     7   41 use vars qw(%urls);
  7         10  
  7         451  
201             %urls = (
202             'redirect' => 'redirect/%s',
203             'error_notfound' => 'error/notfound/%s',
204             'error_after_headers' => 'error/after_headers',
205             'chunked' => 'chunks',
206             'referer' => 'referer',
207             'multiline_header' => 'multiline_header',
208             );
209             for (keys %urls) {
210 7     7   36 no strict 'refs';
  7         8  
  7         598  
211             my $name = $_;
212             *{ $name } = sub {
213 4     4   42 my $self = shift;
214 4         32 $self->url . sprintf $urls{ $name }, @_;
215             };
216             };
217              
218             =head1 EXPORT
219              
220             None by default.
221              
222             =head1 COPYRIGHT AND LICENSE
223              
224             This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
225              
226             Copyright (C) 2003-2011 Max Maischein
227              
228             =head1 AUTHOR
229              
230             Max Maischein, Ecorion@cpan.orgE
231              
232             Please contact me if you find bugs or otherwise improve the module. More tests are also very welcome !
233              
234             =head1 SEE ALSO
235              
236             L,L,L
237              
238             =cut
239              
240             1;