line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package TyeTest; |
2
|
3
|
|
|
3
|
|
10235
|
use strict; |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
128
|
|
3
|
|
|
|
|
|
|
|
4
|
3
|
|
|
3
|
|
1711
|
use Test qw< plan ok skip >; |
|
3
|
|
|
|
|
9555
|
|
|
3
|
|
|
|
|
241
|
|
5
|
3
|
|
|
3
|
|
21
|
use Carp qw< croak >; |
|
3
|
|
|
|
|
9
|
|
|
3
|
|
|
|
|
125
|
|
6
|
3
|
|
|
3
|
|
38
|
use vars qw< @EXPORT_OK >; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
206
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
BEGIN { |
9
|
3
|
|
|
3
|
|
13
|
@EXPORT_OK = qw< |
10
|
|
|
|
|
|
|
plan ok skip |
11
|
|
|
|
|
|
|
Okay True False |
12
|
|
|
|
|
|
|
Note Dump SkipIf |
13
|
|
|
|
|
|
|
Lives Dies Warns LinesLike |
14
|
|
|
|
|
|
|
>; |
15
|
3
|
|
|
|
|
12
|
require Exporter; |
16
|
3
|
|
|
|
|
5248
|
*import = \&Exporter::import; |
17
|
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
$| = 1; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
return 1; # Just subroutines below here. |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# Okay( $expect, codeToTest(), 'Description of test' ); |
25
|
|
|
|
|
|
|
# Okay( $boolean ); # But don't use it this way (much) |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub Okay($;$$) { |
28
|
30
|
|
|
30
|
0
|
726
|
my( $expect, $got, $desc ) = @_; |
29
|
30
|
|
|
|
|
45
|
local( $Test::TestLevel ) = 1 + $Test::TestLevel; |
30
|
30
|
50
|
|
|
|
71
|
return ok( $expect ) if 1 == @_; |
31
|
30
|
50
|
|
|
|
47
|
return ok( $got, $expect ) if ! $desc; |
32
|
30
|
|
|
|
|
93
|
return ok( $got, $expect, $desc ); |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# True( codeToTest(), 'Description of test' ); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub True($;$) { |
39
|
10
|
|
|
10
|
0
|
70
|
my( $got, $desc ) = @_; |
40
|
10
|
|
|
|
|
33
|
my $expect = qr/^([^0]|..)/s; |
41
|
10
|
50
|
|
|
|
43
|
$expect = $got # Pass test if got a 'true' value. |
42
|
|
|
|
|
|
|
if $got; |
43
|
10
|
|
|
|
|
27
|
local( $Test::TestLevel ) = 1 + $Test::TestLevel; |
44
|
10
|
|
|
|
|
20
|
return Okay( $expect, $got, $desc ); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# False( codeToTest(), 'Description of test' ); |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub False($;$) { |
51
|
4
|
|
|
4
|
0
|
21
|
my( $got, $desc ) = @_; |
52
|
4
|
|
|
|
|
24
|
my $expect = qr/^0?\z/; # Explain what we expected. |
53
|
4
|
100
|
|
|
|
14
|
$expect = $got # Pass test if got 0, '', or undef()... |
54
|
|
|
|
|
|
|
if ! $got; # (any 'false' value). |
55
|
4
|
|
|
|
|
13
|
local( $Test::TestLevel ) = 1 + $Test::TestLevel; |
56
|
4
|
|
|
|
|
77
|
return Okay( $expect, $got, $desc ); |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# Note( $string, ... ); |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub Note { |
63
|
|
|
|
|
|
|
# Note: Ignores trailing newlines per string |
64
|
8
|
|
|
8
|
0
|
1234
|
for my $line ( map { split /\n/, $_ } @_ ) { |
|
8
|
|
|
|
|
47
|
|
65
|
8
|
|
|
|
|
75
|
print "#$line\n"; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# Dump( $data, ... ); |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub Dump { |
73
|
0
|
|
|
0
|
0
|
0
|
require Data::Dumper; |
74
|
0
|
0
|
|
|
|
0
|
my $dd = Data::Dumper->new( |
75
|
|
|
|
|
|
|
1 == @_ ? [@_] : [[@_]], |
76
|
|
|
|
|
|
|
); |
77
|
0
|
|
|
|
|
0
|
$dd->Indent(1)->Useqq(1)->Terse(1)->Sortkeys(1); |
78
|
0
|
|
|
|
|
0
|
Note( $dd->Dump() ); |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
# SkipIf( $skipReason, $expect, sub { codeToMaybeTest() }, 'Description of test' ); |
83
|
|
|
|
|
|
|
# SkipIf( |
84
|
|
|
|
|
|
|
# ! Okay( $expect1, codeToTest(), 'Description of first test' ), |
85
|
|
|
|
|
|
|
# $expect2, sub { codeToTestIfFirstTestPasses() }, 'Description of 2nd test', |
86
|
|
|
|
|
|
|
# ) |
87
|
|
|
|
|
|
|
# |
88
|
|
|
|
|
|
|
# my $skip = $ENV{TESTSERVER} ? '' : 'TESTSERVER not set in environment'; |
89
|
|
|
|
|
|
|
# SkipIf( $skip, sub { codeThatNeedsTestServer() }, 'Description of test' ); |
90
|
|
|
|
|
|
|
# |
91
|
|
|
|
|
|
|
# Give $skipReason as a false value to have the test run (not skipped). |
92
|
|
|
|
|
|
|
# A $skipReason of '1' becomes "Prior test failed" |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub SkipIf($;$$$) { |
95
|
4
|
|
|
4
|
0
|
5
|
my( $skip, $expect, $sub, $desc ) = @_; |
96
|
4
|
50
|
33
|
|
|
23
|
croak( "Can't not skip a non-test" ) |
97
|
|
|
|
|
|
|
if ! $skip && @_ <= 1; |
98
|
4
|
50
|
33
|
|
|
8
|
$skip = 'Prior test failed' |
99
|
|
|
|
|
|
|
if $skip && '1' eq $skip; |
100
|
4
|
|
|
|
|
20
|
local( $Test::TestLevel ) = 1 + $Test::TestLevel; |
101
|
4
|
50
|
|
|
|
7
|
return skip( $skip ) if 1 == @_; |
102
|
4
|
50
|
|
|
|
12
|
return skip( $skip, $expect ) if 2 == @_; |
103
|
4
|
50
|
|
|
|
10
|
return skip( $skip, $sub, $expect ) if 3 == @_; |
104
|
4
|
|
|
|
|
14
|
return skip( $skip, $sub, $expect, $desc ); |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# Lives( $stringOfPerlCodeToTest, 'Description of test' ); |
109
|
|
|
|
|
|
|
# Lives( \&subToCallThatMightDie, 'Description of test' ); |
110
|
|
|
|
|
|
|
# Lives( sub { ... }, 'Description of test' ); |
111
|
|
|
|
|
|
|
# |
112
|
|
|
|
|
|
|
# "Should not die:\n" gets prepended to the description. |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub Lives { |
115
|
0
|
|
|
0
|
0
|
0
|
my( $code, $desc ) = @_; |
116
|
|
|
|
|
|
|
|
117
|
0
|
|
|
|
|
0
|
my( $pkg, $file, $line ) = caller( $Test::TestLevel ); |
118
|
0
|
|
|
|
|
0
|
local( $Test::TestLevel ) = 1 + $Test::TestLevel; |
119
|
|
|
|
|
|
|
|
120
|
0
|
0
|
|
|
|
0
|
if( ref $code ) { |
121
|
0
|
0
|
|
|
|
0
|
if( ! $desc ) { |
122
|
0
|
|
|
|
|
0
|
( $desc ) = $file =~ m{([^/]+)$}; |
123
|
0
|
|
0
|
|
|
0
|
$desc ||= $file; |
124
|
0
|
|
|
|
|
0
|
$desc .= " line $line"; |
125
|
|
|
|
|
|
|
} |
126
|
0
|
|
|
|
|
0
|
return Okay( 1, eval { $code->(); 1 }, "Should not die: $desc\nError: $@" ); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
127
|
|
|
|
|
|
|
} |
128
|
0
|
|
0
|
|
|
0
|
$desc &&= " $desc"; |
129
|
0
|
|
0
|
|
|
0
|
$desc ||= "\n$code"; |
130
|
0
|
|
|
|
|
0
|
my $eval = join "\n", |
131
|
|
|
|
|
|
|
"package $pkg;", |
132
|
|
|
|
|
|
|
qq<#line $line "$file">, |
133
|
|
|
|
|
|
|
"# your code:", |
134
|
|
|
|
|
|
|
$code, |
135
|
|
|
|
|
|
|
";1\n"; |
136
|
0
|
|
|
|
|
0
|
return Okay( 1, eval $eval, "Should not die:$desc\nError: $@" ); |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
# Dies( 'Test desc', $stringOfPerlCodeToTest, qr/expected error/, qr/.../... ) |
141
|
|
|
|
|
|
|
# Dies( 'Test desc', \&subThatShouldDie, qr/expected error/, qr/.../... ) |
142
|
|
|
|
|
|
|
# Dies( 'Test desc', sub { ... }, qr/expected error/, qr/.../... ) |
143
|
|
|
|
|
|
|
# |
144
|
|
|
|
|
|
|
# Counts as 1+@regexes when counting what to tell plan(). |
145
|
|
|
|
|
|
|
# Description defaults to the code if it is a string. |
146
|
|
|
|
|
|
|
# Prepends "Should die:" then "Error from:" or "Error $n from:" to desc. |
147
|
|
|
|
|
|
|
# If you give a string instead of a regex, then index() ignoring case is done. |
148
|
|
|
|
|
|
|
# Format your code as follows if you want accurate display of line numbers: |
149
|
|
|
|
|
|
|
# Dies( 'Test desc', |
150
|
|
|
|
|
|
|
# $code, |
151
|
|
|
|
|
|
|
# qr/test/, |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub Dies { |
154
|
3
|
|
|
3
|
0
|
44
|
my( $desc, $code, @omens ) = @_; |
155
|
|
|
|
|
|
|
|
156
|
3
|
|
|
|
|
10
|
my( $pkg, $file, $line ) = caller( $Test::TestLevel ); |
157
|
3
|
|
|
|
|
7
|
local( $Test::TestLevel ) = 1 + $Test::TestLevel; |
158
|
|
|
|
|
|
|
|
159
|
3
|
|
|
|
|
2
|
my $skip; |
160
|
3
|
|
33
|
|
|
13
|
$desc &&= " $desc"; |
161
|
3
|
50
|
|
|
|
5
|
if( ref $code ) { |
162
|
3
|
|
|
|
|
3
|
--$line; |
163
|
3
|
50
|
|
|
|
5
|
if( ! $desc ) { |
164
|
0
|
|
|
|
|
0
|
( $desc ) = $file =~ m{([^/]+)$}; |
165
|
0
|
|
0
|
|
|
0
|
$desc ||= $file; |
166
|
0
|
|
|
|
|
0
|
$desc .= " line $line"; |
167
|
|
|
|
|
|
|
} |
168
|
3
|
|
|
|
|
4
|
$skip = ! Okay( undef, eval { $code->(); 1 }, "Should die: $desc" ); |
|
3
|
|
|
|
|
5
|
|
|
0
|
|
|
|
|
0
|
|
169
|
|
|
|
|
|
|
} else { |
170
|
0
|
0
|
0
|
|
|
0
|
$desc ||= "\n" . join '', $code, $code =~ /\n$/ ? '' : "\n"; |
171
|
0
|
|
|
|
|
0
|
my $eval = join "\n", |
172
|
|
|
|
|
|
|
"package $pkg;", |
173
|
|
|
|
|
|
|
qq<#line $line "$file">, |
174
|
|
|
|
|
|
|
"# your code:", |
175
|
|
|
|
|
|
|
$code, |
176
|
|
|
|
|
|
|
";1\n"; |
177
|
0
|
|
|
|
|
0
|
$skip = ! Okay( undef, eval $eval, "Should die:$desc" ), |
178
|
|
|
|
|
|
|
} |
179
|
3
|
|
|
|
|
170
|
my $got = $@; |
180
|
3
|
100
|
|
|
|
10
|
my $idx = 1 == @omens ? '' : 1; |
181
|
3
|
100
|
|
|
|
6
|
my $sp = $idx ? ' ' : ''; |
182
|
3
|
|
|
|
|
4
|
my $fail = $skip; |
183
|
3
|
|
|
|
|
6
|
for my $omen ( @omens ) { |
184
|
4
|
50
|
|
|
|
11
|
$omen = $omen->() |
185
|
|
|
|
|
|
|
if 'CODE' eq ref $omen; |
186
|
4
|
50
|
|
|
|
403
|
$omen = qr/\Q$omen/i |
187
|
|
|
|
|
|
|
if ! ref $omen; |
188
|
4
|
50
|
|
|
|
18
|
$fail = 1 |
189
|
|
|
|
|
|
|
if ! SkipIf( $skip, $omen, $got, "Error$sp$idx from:$desc" ); |
190
|
4
|
|
|
|
|
201
|
$idx++; |
191
|
|
|
|
|
|
|
} |
192
|
3
|
|
|
|
|
8
|
return ! $fail; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
# Warns( 'Test desc', \&subThatShouldNotWarn ) |
197
|
|
|
|
|
|
|
# Warns( 'Test desc', \&subThatShouldWarn, qr/expected error/, qr/.../... ) |
198
|
|
|
|
|
|
|
# Warns( 'Test desc', sub {...}, qr/expected error/, qr/.../... ) |
199
|
|
|
|
|
|
|
# Warns( 'Desc', sub {...}, [ qr/first/, ... ], [ qr/2nd/ ], ... ) |
200
|
|
|
|
|
|
|
# |
201
|
|
|
|
|
|
|
# Counts as 1+@regexes tests when counting what to tell plan(). |
202
|
|
|
|
|
|
|
# Giving no regexes actually asserts that no warnings are generated (1 test). |
203
|
|
|
|
|
|
|
# Giving 1 or more array refs means you expect a precise number of warnings |
204
|
|
|
|
|
|
|
# and the first array of regexes is tested against the 1st warning, etc. |
205
|
|
|
|
|
|
|
# Else, don't use array refs and each regex must match at least one warning. |
206
|
|
|
|
|
|
|
# If you give a string instead of a regex, then index() ignoring case is done. |
207
|
|
|
|
|
|
|
# Various strings get prepended to the test description. |
208
|
|
|
|
|
|
|
# Description defaults to a file and line number. |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
sub Warns { |
211
|
2
|
|
|
2
|
0
|
82
|
my( $desc, $sub, @omens ) = @_; |
212
|
2
|
50
|
|
|
|
8
|
if( ! $desc ) { |
213
|
0
|
|
|
|
|
0
|
my( $pkg, $file, $line ) = caller( $Test::TestLevel ); |
214
|
0
|
|
|
|
|
0
|
++$line; |
215
|
0
|
|
|
|
|
0
|
( $desc ) = $file =~ m{([^/]+)$}; |
216
|
0
|
|
0
|
|
|
0
|
$desc ||= $file; |
217
|
0
|
|
|
|
|
0
|
$desc .= " line $line"; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# Collect any warnings from running the code: |
221
|
2
|
|
|
|
|
4
|
my @warns; |
222
|
|
|
|
|
|
|
{ |
223
|
2
|
|
|
2
|
|
4
|
local( $SIG{__WARN__} ) = sub { push @warns, $_[0] }; |
|
2
|
|
|
|
|
14
|
|
|
2
|
|
|
|
|
8
|
|
224
|
2
|
|
|
|
|
6
|
$sub->(); |
225
|
|
|
|
|
|
|
} |
226
|
2
|
|
|
|
|
4
|
local( $Test::TestLevel ) = 1 + $Test::TestLevel; |
227
|
2
|
|
|
|
|
8
|
return LinesLike( $desc, 'warning', \@warns, @omens ); |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
sub LinesLike { |
232
|
2
|
|
|
2
|
0
|
6
|
my( $desc, $what, $lines_av, @omens ) = @_; |
233
|
2
|
50
|
|
|
|
6
|
if( ! $desc ) { |
234
|
0
|
|
|
|
|
0
|
my( $pkg, $file, $line ) = caller( $Test::TestLevel ); |
235
|
0
|
|
|
|
|
0
|
++$line; |
236
|
0
|
|
|
|
|
0
|
( $desc ) = $file =~ m{([^/]+)$}; |
237
|
0
|
|
0
|
|
|
0
|
$desc ||= $file; |
238
|
0
|
|
|
|
|
0
|
$desc .= " line $line"; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
2
|
|
|
|
|
4
|
local( $Test::TestLevel ) = 1 + $Test::TestLevel; |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# We expected no lines: |
244
|
2
|
50
|
|
|
|
8
|
if( ! @omens ) { |
245
|
0
|
|
|
|
|
0
|
$desc = "No $what from: $desc"; |
246
|
0
|
0
|
|
|
|
0
|
$desc .= "\n$lines_av->[0]" |
247
|
|
|
|
|
|
|
if @$lines_av; |
248
|
0
|
|
|
|
|
0
|
return Okay( 0, 0+@$lines_av, $desc ); |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
2
|
|
|
|
|
2
|
my $fail; |
252
|
2
|
50
|
|
|
|
8
|
if( "ARRAY" eq ref $omens[0] ) { |
253
|
|
|
|
|
|
|
# We expected a specific list of lines: |
254
|
0
|
|
|
|
|
0
|
$fail = ! Okay( 0+@omens, 0+@$lines_av, "\u$what(s) from: $desc" ); |
255
|
0
|
0
|
|
|
|
0
|
if( ! $fail ) { # Got expected number, so test each: |
256
|
0
|
|
|
|
|
0
|
for my $i ( 1 .. @omens ) { |
257
|
0
|
|
|
|
|
0
|
my $line = $lines_av->[$i-1]; |
258
|
0
|
|
|
|
|
0
|
for my $omen ( @{ $omens[$i-1] } ) { |
|
0
|
|
|
|
|
0
|
|
259
|
0
|
0
|
|
|
|
0
|
$omen = qr/\Q$omen/i |
260
|
|
|
|
|
|
|
if ! ref $omen; |
261
|
0
|
|
|
|
|
0
|
$fail += ! Okay( $omen, $line, "\u$what $i from: $desc" ); |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
} |
264
|
0
|
|
|
|
|
0
|
return ! $fail; |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
# Got unexpected number; fall back to just checking each omen: |
267
|
0
|
|
|
|
|
0
|
@omens = map @$_, @omens; |
268
|
|
|
|
|
|
|
} else { |
269
|
|
|
|
|
|
|
# We expected at least one line: |
270
|
2
|
|
|
|
|
14
|
$fail = ! Okay( |
271
|
|
|
|
|
|
|
1, 0+!!@$lines_av, |
272
|
|
|
|
|
|
|
join( ' ', "Got", 0+@$lines_av, "$what(s) from: $desc" ), |
273
|
|
|
|
|
|
|
); |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
|
276
|
2
|
50
|
|
|
|
166
|
if( ! @$lines_av ) { |
277
|
|
|
|
|
|
|
skip( "Expected $what; got none; $_" ) |
278
|
0
|
|
|
|
|
0
|
for @omens; |
279
|
0
|
|
|
|
|
0
|
return 0; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
s/\n?$/\n/ |
283
|
2
|
|
|
|
|
26
|
for @$lines_av; |
284
|
2
|
|
|
|
|
4
|
my $all = join '', @$lines_av; |
285
|
2
|
50
|
|
|
|
8
|
my $s = 1 == @$lines_av ? '' : 's'; |
286
|
2
|
|
|
|
|
4
|
for my $omen ( @omens ) { |
287
|
4
|
100
|
|
|
|
156
|
$omen = qr/\Q$omen/i |
288
|
|
|
|
|
|
|
if ! ref $omen; |
289
|
4
|
|
|
|
|
26
|
$fail += ! Okay( $omen, $all, "\u$what$s from: $desc" ); |
290
|
|
|
|
|
|
|
} |
291
|
2
|
|
|
|
|
98
|
return ! $fail; |
292
|
|
|
|
|
|
|
} |