File Coverage

blib/lib/WWW/Link/Tester.pm
Criterion Covered Total %
statement 73 81 90.1
branch 25 38 65.7
condition 2 6 33.3
subroutine 13 15 86.6
pod 2 9 22.2
total 115 149 77.1


line stmt bran cond sub pod time code
1             package WWW::Link::Tester;
2             $REVISION=q$Revision: 1.14 $ ; $VERSION = sprintf ( "%d.%02d", $REVISION =~ /(\d+).(\d+)/ );
3              
4             =head1 NAME
5              
6             WWW::Link::Tester - base class for link testers.
7              
8             =head1 SYNOPSIS
9              
10             use WWW::Link::Tester
11             $ua=create_a_user_agent();
12             my $tester = new WWW::Link::Tester, $ua;
13             $link=get_a_link_object();
14             $tester->test_link($link);
15              
16             =head1 DESCRIPTION
17              
18             This class acts as a base for constructing link testing classes. It
19             provides methods that are useful within those classes.
20              
21             =cut
22              
23 4     4   83440 use URI;
  4         9  
  4         126  
24 4     4   23 use Carp;
  4         8  
  4         317  
25 4     4   23 use Exporter;
  4         21  
  4         280  
26             @ISA=qw(Exporter);
27             @EXPORT=qw(RC_PROTOCOL_UNSUPPORTED MSG_PROTOCOL_UNSUPPORTED RC_REDIRECT_LIMIT_EXCEEDED MSG_REDIRECT_LIMIT_EXCEEDED);
28 4     4   23 use strict;
  4         28  
  4         160  
29 4     4   23 use warnings;
  4         7  
  4         152  
30 4     4   21 use HTTP::Status;
  4         6  
  4         5670  
31              
32             sub MSG_PROTOCOL_UNSUPPORTED () {"Unsupported protocol";}
33             sub RC_PROTOCOL_UNSUPPORTED () {498;}
34             sub MSG_REDIRECT_LIMIT_EXCEEDED () {"Too Many Redirects";}
35             sub RC_REDIRECT_LIMIT_EXCEEDED () {499;}
36              
37             sub new {
38 1     1 0 86 my $proto = shift;
39 1   33     9 my $class = ref($proto) || $proto;
40 1         2 my $self = {};
41 1         7 $self->{"user_agent"}=shift;
42 1         3 bless $self, $class;
43 1         4 $self->config();
44 1         2 return $self;
45             }
46              
47             sub test_link {
48 16     16 0 124 my $self=shift;
49 16         18 my $link=shift;
50 16         52 my ($response, @redirects) = $self->get_response($link);
51 16         58 $self->handle_response($link,$response,@redirects);
52             }
53              
54             sub get_response {
55 0     0 0 0 confess "get_response must be implemented in the child class";
56             }
57              
58             sub verbose {
59 0     0 0 0 my $self=shift;
60 0         0 my $verb=shift;
61 0 0       0 $self->{verbose} = $verb if defined $verb;
62 0         0 return $self->{verbose};
63             }
64              
65              
66             =head2 handle_response
67              
68             handle_response is normally just the same as apply response. The
69             extra level of indirection can be used where some responses aren't
70             meant to directly affect the link.
71              
72             =cut
73              
74             sub handle_response {
75 16     16 1 28 my $self=shift;
76 16         18 my $link=shift;
77 16         25 my $response=shift;
78 16         28 my @redirects=@_;
79 16         244 $self->apply_response($link, $response, @redirects);
80 16         27 my $now=time;
81 16         54 $link->store_response($response,$now, ref $self);
82             }
83              
84             =head2 apply_response
85              
86             We have a response which should be used to affect the state of the
87             link. This should only be called at the end of a chain of redirects,
88             not for each member in the chain.
89              
90             =cut
91              
92             sub apply_response {
93 46     46 1 85 my $self=shift;
94 46         55 my $link=shift;
95 46         46 my $response=shift;
96 46         89 my @redirects=@_;
97              
98 46         149 my $verbose=$self->{"verbose"};
99              
100 46         65 my $mode=$self->{mode};
101              
102 46 50       101 confess "response wasn't an object" unless ref $response;
103 46 50       127 confess "non numeric response code" . $response->code() unless
104             $response->code() =~ m/[1-9][0-9]+/;
105             CASE: {
106 46 100       497 robot_lockout($response) && do {
  46         107  
107 3 50       8 print STDERR "checking disallowed, signalling link\n"
108             if $::verbose;
109 3         14 $link->disallowed();
110 3         6 last;
111             };
112 43 100       617 unsupported($response) && do {
113 14 50       165 print STDERR "checking disallowed, signalling link\n"
114             if $::verbose;
115 14         52 $link->unsupported();
116 14         19 last;
117             };
118 29 100       76 $response->is_error() && do {
119 17 50       137 print STDERR "response was an error, signalling link\n"
120             if $::verbose;
121 17         88 $link->failed_test(); #someone should come look
122 17         22 last;
123             };
124 12 50       115 $response->is_success() && do {
125 12 50       90 print STDERR "response was success, signalling link\n"
126             if $::verbose;
127 12         40 $link->passed_test();
128 12         91 last;
129             };
130             #a redirect should eiter be terminiated with a success or should be
131             #treated as a failure if we don't find the end of a chain of
132             #redirects.
133 0 0       0 $response->is_redirect() &&
134             die "Redirects shouldn't get through to here\n";
135 0         0 $self->ambiguous_test($link);
136             }
137 46 100       253 @redirects ? $link->found_redirected() : $link->not_redirected();
138 46 100       160 $link->redirects( \@redirects ) if @redirects;
139             }
140              
141             sub config {
142 5     5 0 43 shift->{"max_redirects"}=15;
143             }
144              
145             sub robot_lockout {
146 46     46 0 51 my $response=shift;
147 46 100       109 $response->code() == RC_FORBIDDEN or return 0;
148 3         31 my $message = $response->message();
149             #FIXME; this is because the Complex tester looses this informaition!
150 3 100       29 defined $message or return 1;
151 2 50       163 $message=~ /robots\.txt/ and return 1;
152 0         0 return 0;
153             }
154              
155             sub unsupported {
156 43     43 0 51 my $response=shift;
157 43 100       109 $response->code() == RC_PROTOCOL_UNSUPPORTED
158             and return 1;
159              
160             #I'm not sure I like the following special case.
161              
162 29 50 33     336 $response->code == 400 and
163             $response-> message =~ m/Library does not allow method/
164             and return 1;
165              
166 29         266 return 0;
167             }
168              
169             1; #kEEp rEqUIrE HaPpY.