line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package WWW::Webrobot::TestplanRunner; |
2
|
1
|
|
|
1
|
|
21216
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
40
|
|
3
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
205
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# Author: Stefan Trcek |
6
|
|
|
|
|
|
|
# Copyright(c) 2004-2006 ABAS Software AG |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
565
|
use WWW::Webrobot::UserAgentConnection; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
43
|
|
10
|
1
|
|
|
1
|
|
1951
|
use WWW::Webrobot::Print::Null; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
32
|
|
11
|
1
|
|
|
1
|
|
5
|
use WWW::Webrobot::AssertConstant; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
27
|
|
12
|
1
|
|
|
1
|
|
6
|
use WWW::Webrobot::Attributes qw(sym_tbl failed_assertions); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
8
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
my $ASSERT_TRUE = WWW::Webrobot::AssertConstant->new(0, ["0 always true"]); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 NAME |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
WWW::Webrobot::TestplanRunner - runs a testplan |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
WWW::Webrobot::TestplanRunner -> new() -> run($test_plan, $cfg); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head1 DESCRIPTION |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
This module configures Webrobot with $cfg, |
28
|
|
|
|
|
|
|
reads a testplan and executes this plan. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head1 METHODS |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=over |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=item $wr = WWW::Webrobot::TestplanRunner -> new(); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
Construct an object. |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=cut |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub new { |
42
|
0
|
|
|
0
|
1
|
0
|
my $class = shift; |
43
|
0
|
|
0
|
|
|
0
|
my $self = bless({}, ref($class) || $class); |
44
|
0
|
|
|
|
|
0
|
return $self; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=item WWW::Webrobot::TestplanRunner -> run($testplan, $cfg); |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=over |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=item $testplan |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
Read in the testplan (reference to list). |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=item $cfg |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
[optional] Read the configuration (reference to list). |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=back |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=cut |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub run { |
65
|
0
|
|
|
0
|
1
|
0
|
my ($self, $testplan, $cfg, $sym_tbl) = @_; |
66
|
|
|
|
|
|
|
|
67
|
0
|
|
|
|
|
0
|
$self -> {cfg} = $cfg; |
68
|
0
|
|
|
|
|
0
|
$self -> {_sym_tbl} = $sym_tbl; |
69
|
0
|
|
|
|
|
0
|
$self -> {_ua_list} = {}; |
70
|
0
|
|
|
|
|
0
|
$self -> {_defined} = []; |
71
|
0
|
|
|
|
|
0
|
$self -> {_failed_assertions} = 0; |
72
|
|
|
|
|
|
|
my $max_errors = $cfg->{max_errors} ? sub { |
73
|
0
|
|
|
0
|
|
0
|
my ($fail) = @_; |
74
|
0
|
0
|
|
|
|
0
|
$self->{_failed_assertions}++ if $fail; |
75
|
0
|
|
|
|
|
0
|
$self->{_failed_assertions} >= $cfg->{max_errors}; |
76
|
0
|
0
|
|
0
|
|
0
|
} : sub {0}; |
|
0
|
|
|
|
|
0
|
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# treat testplan |
79
|
0
|
|
0
|
|
|
0
|
my $out = $cfg -> {output} || WWW::Webrobot::Print::Null -> new(); |
80
|
0
|
|
|
|
|
0
|
$_ -> global_start() foreach (@$out); |
81
|
0
|
|
|
|
|
0
|
my $exit_status = 0; |
82
|
0
|
|
|
|
|
0
|
my @global_assert_xml = (); |
83
|
|
|
|
|
|
|
ENTRY: |
84
|
0
|
|
|
|
|
0
|
foreach my $entry (@$testplan) { |
85
|
|
|
|
|
|
|
# assertion |
86
|
0
|
|
|
|
|
0
|
my @a_xml = (); |
87
|
0
|
0
|
|
|
|
0
|
if (defined $entry->{global_assert_xml}) { # defining a global assertion |
88
|
0
|
0
|
|
|
|
0
|
@global_assert_xml = () if $entry->{mode} eq "new"; |
89
|
0
|
|
|
|
|
0
|
push @global_assert_xml, clone_me($entry->{global_assert_xml}); |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
else { |
92
|
0
|
0
|
|
|
|
0
|
push @a_xml, clone_me($entry->{assert_xml}) if defined $entry->{assert_xml}; |
93
|
0
|
|
|
|
|
0
|
push @a_xml, clone_me($_) foreach (@global_assert_xml); |
94
|
|
|
|
|
|
|
} |
95
|
0
|
|
|
|
|
0
|
$entry->{assert_xml} = \@a_xml; |
96
|
0
|
|
|
|
|
0
|
$sym_tbl -> evaluate($entry); # substitute variables |
97
|
|
|
|
|
|
|
|
98
|
0
|
|
|
|
|
0
|
my @a = (); |
99
|
0
|
0
|
|
|
|
0
|
if (defined $entry->{global_assert_xml}) { |
100
|
0
|
|
|
|
|
0
|
push @a, $ASSERT_TRUE; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
else { |
103
|
0
|
|
|
|
|
0
|
foreach (@{$entry->{assert_xml}}) { |
|
0
|
|
|
|
|
0
|
|
104
|
0
|
|
|
|
|
0
|
push @a, parse_assertion($_); |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
} |
107
|
0
|
|
|
|
|
0
|
$entry->{assert} = \@a; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# recursion |
110
|
0
|
0
|
|
|
|
0
|
if (defined (my $xml = $entry->{recurse_xml})) { |
111
|
0
|
|
|
|
|
0
|
$entry->{recurse} = get_plugin($xml->[0], $xml->[1]); |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
0
|
my $user = $self -> _get_ua_connection($cfg, $entry -> {useragent}); |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# get url in testplan |
117
|
0
|
|
|
|
|
0
|
$_ -> item_pre($entry) foreach (@$out); |
118
|
0
|
|
|
|
|
0
|
my ($r_plan, $fail_plan, $fail_plan_str) = $user -> treat_single_url($entry, $sym_tbl); |
119
|
0
|
|
|
|
|
0
|
$entry->{fail} = $fail_plan; |
120
|
0
|
|
|
|
|
0
|
$entry->{fail_str} = $fail_plan_str; |
121
|
0
|
|
|
|
|
0
|
$_ -> item_post($r_plan, $entry, $fail_plan) foreach (@$out); |
122
|
0
|
0
|
|
|
|
0
|
last ENTRY if $max_errors->($fail_plan); |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# do recursion |
125
|
0
|
|
|
|
|
0
|
my $fail_all = $fail_plan; |
126
|
0
|
0
|
|
|
|
0
|
if (defined(my $recurse = $entry -> {recurse})) { |
127
|
0
|
|
|
|
|
0
|
$user -> ua() -> set_redirect_ok($recurse); |
128
|
0
|
|
|
|
|
0
|
my ($newurl, $caller_pages) = $recurse -> next($r_plan); |
129
|
0
|
|
|
|
|
0
|
while ($newurl) { |
130
|
0
|
|
|
|
|
0
|
my $entry_recurse = { |
131
|
|
|
|
|
|
|
method => "GET", |
132
|
|
|
|
|
|
|
url => $newurl, |
133
|
|
|
|
|
|
|
description => $entry->{description}, |
134
|
|
|
|
|
|
|
assert => $entry->{assert}, |
135
|
|
|
|
|
|
|
global_assert => $entry->{global_assert}, |
136
|
|
|
|
|
|
|
http_header => $entry->{http_header}, |
137
|
|
|
|
|
|
|
caller_pages => $caller_pages, |
138
|
|
|
|
|
|
|
is_recursive => 1, |
139
|
|
|
|
|
|
|
}; |
140
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
0
|
$_ -> item_pre($entry_recurse) foreach (@$out); |
142
|
0
|
|
|
|
|
0
|
my ($r, $fail, $fail_str) = $user -> treat_single_url($entry_recurse, $sym_tbl); |
143
|
0
|
|
|
|
|
0
|
$entry_recurse->{fail} = $fail; |
144
|
0
|
|
|
|
|
0
|
$entry_recurse->{fail_str} = $fail_str; |
145
|
0
|
|
|
|
|
0
|
$_ -> item_post($r, $entry_recurse, $fail) foreach (@$out); |
146
|
0
|
0
|
|
|
|
0
|
last ENTRY if $max_errors->($fail); |
147
|
|
|
|
|
|
|
|
148
|
0
|
0
|
|
|
|
0
|
$fail_all = 1 if $fail; |
149
|
0
|
|
|
|
|
0
|
($newurl, $caller_pages) = $recurse -> next($r); |
150
|
0
|
0
|
|
|
|
0
|
save_memory($r) if WWW::Webrobot::Global->save_memory(); |
151
|
|
|
|
|
|
|
} |
152
|
0
|
|
|
|
|
0
|
$user -> ua() -> set_redirect_ok(undef); |
153
|
|
|
|
|
|
|
} |
154
|
0
|
|
|
|
|
0
|
$entry -> {result} = $r_plan; |
155
|
0
|
|
|
|
|
0
|
$entry -> {fail} = $fail_all; |
156
|
0
|
|
|
|
|
0
|
$entry -> {fail_str} = $fail_plan_str; |
157
|
0
|
0
|
|
|
|
0
|
$exit_status = 1 if $fail_all; |
158
|
0
|
0
|
|
|
|
0
|
save_memory($r_plan) if WWW::Webrobot::Global->save_memory(); |
159
|
|
|
|
|
|
|
} |
160
|
0
|
|
|
|
|
0
|
$_ -> global_end() foreach (@$out); |
161
|
0
|
|
|
|
|
0
|
return $exit_status; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub clone_me { |
166
|
12
|
|
|
12
|
0
|
4057
|
my ($tree) = @_; |
167
|
12
|
|
|
|
|
36
|
SWITCH: foreach (ref $tree) { |
168
|
12
|
100
|
|
|
|
47
|
/^ARRAY$/ and do { |
169
|
9
|
|
|
|
|
22
|
my @array = ( @$tree ); |
170
|
9
|
|
|
|
|
14
|
foreach my $elem (@array) { |
171
|
26
|
100
|
|
|
|
73
|
$elem = clone_me($elem) if ref $elem; |
172
|
|
|
|
|
|
|
} |
173
|
9
|
|
|
|
|
47
|
return \@array; |
174
|
|
|
|
|
|
|
}; |
175
|
3
|
50
|
|
|
|
16
|
/^HASH$/ and do { |
176
|
3
|
|
|
|
|
5
|
my %hash = (); |
177
|
3
|
|
|
|
|
16
|
while (my ($key,$value) = each %$tree) { |
178
|
8
|
100
|
|
|
|
60
|
$hash{$key} = ref $value ? clone_me($value) : $value; |
179
|
|
|
|
|
|
|
} |
180
|
3
|
|
|
|
|
20
|
return \%hash; |
181
|
|
|
|
|
|
|
}; |
182
|
0
|
|
|
|
|
|
return undef; |
183
|
|
|
|
|
|
|
}; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
sub parse_assertion { |
188
|
0
|
|
|
0
|
0
|
|
my ($assert_xml) = @_; |
189
|
0
|
0
|
|
|
|
|
return undef if ! defined $assert_xml; |
190
|
0
|
|
|
|
|
|
my $name = $assert_xml->[0]; |
191
|
0
|
0
|
|
|
|
|
if ($name =~ /^[A-Z][^.]*\./) { |
192
|
0
|
|
|
|
|
|
return get_plugin($assert_xml->[0], $assert_xml->[1]); |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
else { |
195
|
0
|
|
|
|
|
|
return get_plugin('WWW.Webrobot.Assert', [{}, @$assert_xml]); |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# SAVE MEMORY: delete _content and _content_xhtml of response |
201
|
|
|
|
|
|
|
sub save_memory { |
202
|
0
|
|
|
0
|
0
|
|
my ($req) = @_; |
203
|
0
|
|
|
|
|
|
while (defined $req) { # for all subrequests |
204
|
0
|
|
|
|
|
|
undef $req->{_content}; |
205
|
0
|
|
|
|
|
|
undef $req->{_content_xhtml}; |
206
|
0
|
|
|
|
|
|
$req = $req -> {_previous}; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub get_plugin { |
212
|
0
|
|
|
0
|
0
|
|
my ($tag, $content) = @_; |
213
|
0
|
|
|
|
|
|
$tag =~ s/\./::/g; |
214
|
|
|
|
|
|
|
# ??? delete ', 0' in following line |
215
|
0
|
|
|
|
|
|
my $ret = eval "require $tag; $tag -> new(\$content, 0);"; |
216
|
0
|
0
|
|
|
|
|
die "Can't use lib $tag: $@" if $@; |
217
|
0
|
|
|
|
|
|
return $ret; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# get useragent - create one if nonexistent |
222
|
|
|
|
|
|
|
sub _get_ua_connection { |
223
|
0
|
|
|
0
|
|
|
my ($self, $cfg, $user) = @_; |
224
|
0
|
0
|
|
|
|
|
if (!exists $self->{_ua_list}->{$user}) { |
225
|
0
|
|
|
|
|
|
$self->{_ua_list}->{$user} = |
226
|
|
|
|
|
|
|
WWW::Webrobot::UserAgentConnection -> new($cfg, user => $user); |
227
|
|
|
|
|
|
|
} |
228
|
0
|
|
|
|
|
|
return $self->{_ua_list}->{$user}; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=item $conn -> sym_tbl |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
Get the symbol table, see L. |
235
|
|
|
|
|
|
|
Symbols are defined within a config file or within a test plan. |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=back |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=head1 SEE ALSO |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=over |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=item L |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
is a frontend for this class |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=back |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=cut |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
1; |