line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!perl
|
2
|
|
|
|
|
|
|
#
|
3
|
|
|
|
|
|
|
# Documentation, copyright and license is at the end of this file.
|
4
|
|
|
|
|
|
|
#
|
5
|
|
|
|
|
|
|
package Test::Tech;
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
# use 5.001;
|
8
|
1
|
|
|
1
|
|
19413
|
use strict;
|
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
71
|
|
9
|
1
|
|
|
1
|
|
6
|
use warnings;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
62
|
|
10
|
1
|
|
|
1
|
|
6
|
use warnings::register;
|
|
1
|
|
|
|
|
18
|
|
|
1
|
|
|
|
|
470
|
|
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
1636
|
use Test (); # do not import the "Test" subroutines
|
|
1
|
|
|
|
|
6315
|
|
|
1
|
|
|
|
|
34
|
|
13
|
1
|
|
|
1
|
|
878
|
use Data::Secs2 1.22 qw(stringify);
|
|
1
|
|
|
|
|
44514
|
|
|
1
|
|
|
|
|
151
|
|
14
|
1
|
|
|
1
|
|
11
|
use Data::Str2Num 0.05;
|
|
1
|
|
|
|
|
18
|
|
|
1
|
|
|
|
|
35
|
|
15
|
1
|
|
|
1
|
|
5
|
use Data::Startup 0.03;
|
|
1
|
|
|
|
|
13
|
|
|
1
|
|
|
|
|
22
|
|
16
|
|
|
|
|
|
|
|
17
|
1
|
|
|
1
|
|
5
|
use vars qw($VERSION $DATE $FILE);
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
80
|
|
18
|
|
|
|
|
|
|
$VERSION = '1.26';
|
19
|
|
|
|
|
|
|
$DATE = '2004/05/20';
|
20
|
|
|
|
|
|
|
$FILE = __FILE__;
|
21
|
|
|
|
|
|
|
|
22
|
1
|
|
|
1
|
|
4
|
use vars qw(@ISA @EXPORT_OK);
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
346
|
|
23
|
|
|
|
|
|
|
require Exporter;
|
24
|
|
|
|
|
|
|
@ISA=('Exporter');
|
25
|
|
|
|
|
|
|
@EXPORT_OK = qw(demo finish is_skip ok ok_sub plan skip skip_sub
|
26
|
|
|
|
|
|
|
skip_tests stringify tech_config);
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
#######
|
29
|
|
|
|
|
|
|
# For subroutine interface keep all data hidden in a local hash of private object
|
30
|
|
|
|
|
|
|
#
|
31
|
|
|
|
|
|
|
my $tech_p = new Test::Tech;
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub new
|
34
|
|
|
|
|
|
|
{
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
####################
|
37
|
|
|
|
|
|
|
# $class is either a package name (scalar) or
|
38
|
|
|
|
|
|
|
# an object with a data pointer and a reference
|
39
|
|
|
|
|
|
|
# to a package name. A package name is also the
|
40
|
|
|
|
|
|
|
# name of a class
|
41
|
|
|
|
|
|
|
#
|
42
|
1
|
|
|
1
|
0
|
3
|
my ($class, @args) = @_;
|
43
|
1
|
50
|
|
|
|
6
|
$class = ref($class) if( ref($class) );
|
44
|
1
|
|
|
|
|
3
|
my $self = bless {}, $class;
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
######
|
47
|
|
|
|
|
|
|
# Make Test variables visible to tech_config
|
48
|
|
|
|
|
|
|
#
|
49
|
1
|
|
|
|
|
11
|
$self->{Test}->{ntest} = \$Test::ntest;
|
50
|
1
|
|
|
|
|
4
|
$self->{Test}->{TESTOUT} = \$Test::TESTOUT;
|
51
|
1
|
|
|
|
|
3
|
$self->{Test}->{TestLevel} = \$Test::TestLevel;
|
52
|
1
|
|
|
|
|
3
|
$self->{Test}->{ONFAIL} = \$Test::ONFAIL;
|
53
|
1
|
50
|
|
|
|
5
|
$self->{Test}->{TESTERR} = \$Test::TESTERR if defined $Test::TESTERR;
|
54
|
|
|
|
|
|
|
|
55
|
1
|
|
|
|
|
3
|
$self->{TestDefault}->{TESTOUT} = $Test::TESTOUT;
|
56
|
1
|
|
|
|
|
3
|
$self->{TestDefault}->{TestLevel} = $Test::TestLevel;
|
57
|
1
|
|
|
|
|
2
|
$self->{TestDefault}->{ONFAIL} = $Test::ONFAIL;
|
58
|
1
|
50
|
|
|
|
5
|
$self->{TestDefault}->{TESTERR} = $Test::TESTERR if defined $Test::TESTERR;
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
######
|
61
|
|
|
|
|
|
|
# Test::Tech object data
|
62
|
|
|
|
|
|
|
#
|
63
|
1
|
|
|
|
|
3
|
$self->{Skip_Tests} = 0;
|
64
|
1
|
|
|
|
|
3
|
$self->{test_name} = '';
|
65
|
1
|
|
|
|
|
2
|
$self->{passed} = [];
|
66
|
1
|
|
|
|
|
4
|
$self->{failed} = [];
|
67
|
1
|
|
|
|
|
1
|
$self->{skipped} = [];
|
68
|
1
|
|
|
|
|
3
|
$self->{missed} = [];
|
69
|
1
|
|
|
|
|
2
|
$self->{unplanned} = [];
|
70
|
1
|
|
|
|
|
2
|
$self->{last_test} = 0;
|
71
|
1
|
|
|
|
|
3
|
$self->{num_tests} = 0;
|
72
|
1
|
|
|
|
|
1
|
$self->{highest_test} = 0;
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
######
|
75
|
|
|
|
|
|
|
# Redirect Test:: output thru Test::Tech::Output handle
|
76
|
|
|
|
|
|
|
# unless been redirected and never restored!!
|
77
|
|
|
|
|
|
|
#
|
78
|
1
|
50
|
|
|
|
14
|
unless( \*TESTOUT eq $Test::TESTOUT ) {
|
79
|
1
|
|
|
|
|
2
|
$self->{test_out} = $Test::TESTOUT;
|
80
|
1
|
|
|
|
|
8
|
tie *TESTOUT, 'Test::Tech::Output', $Test::TESTOUT, $self;
|
81
|
1
|
|
|
|
|
3
|
$Test::TESTOUT = \*TESTOUT;
|
82
|
|
|
|
|
|
|
}
|
83
|
|
|
|
|
|
|
|
84
|
1
|
|
|
|
|
4
|
$self;
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
}
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
######
|
89
|
|
|
|
|
|
|
# Demo
|
90
|
|
|
|
|
|
|
#
|
91
|
|
|
|
|
|
|
sub demo
|
92
|
|
|
|
|
|
|
{
|
93
|
1
|
|
|
1
|
|
5
|
use Data::Dumper;
|
|
1
|
|
|
|
|
76
|
|
|
1
|
|
|
|
|
831
|
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
######
|
96
|
|
|
|
|
|
|
# This subroutine uses no object data; therefore,
|
97
|
|
|
|
|
|
|
# drop any class or object.
|
98
|
|
|
|
|
|
|
#
|
99
|
0
|
0
|
|
0
|
1
|
0
|
shift if UNIVERSAL::isa($_[0],__PACKAGE__);
|
100
|
|
|
|
|
|
|
|
101
|
0
|
|
|
|
|
0
|
my ($quoted_expression, @expression) = @_;
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
#######
|
104
|
|
|
|
|
|
|
# A demo trys to simulate someone typing expresssions
|
105
|
|
|
|
|
|
|
# at a console.
|
106
|
|
|
|
|
|
|
#
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
#########
|
109
|
|
|
|
|
|
|
# Print quoted expression so that see the non-executed
|
110
|
|
|
|
|
|
|
# expression. The extra space is so when pasted into
|
111
|
|
|
|
|
|
|
# a POD, the POD will process the line as code.
|
112
|
|
|
|
|
|
|
#
|
113
|
0
|
|
|
|
|
0
|
$quoted_expression =~ s/(\n+)/$1 /g;
|
114
|
0
|
|
|
|
|
0
|
print $Test::TESTOUT ' ' . $quoted_expression . "\n";
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
########
|
117
|
|
|
|
|
|
|
# @data is the result of the script executing the
|
118
|
|
|
|
|
|
|
# quoted expression.
|
119
|
|
|
|
|
|
|
#
|
120
|
|
|
|
|
|
|
# The demo output most likely will end up in a pod.
|
121
|
|
|
|
|
|
|
# The the process of running the generated script
|
122
|
|
|
|
|
|
|
# will execute the setup. Thus the input is the
|
123
|
|
|
|
|
|
|
# actual results. Putting a space in front of it
|
124
|
|
|
|
|
|
|
# tells the POD that it is code.
|
125
|
|
|
|
|
|
|
#
|
126
|
0
|
0
|
|
|
|
0
|
return unless @expression;
|
127
|
|
|
|
|
|
|
|
128
|
0
|
|
|
|
|
0
|
$Data::Dumper::Terse = 1;
|
129
|
0
|
|
|
|
|
0
|
my $data = Dumper(@expression);
|
130
|
0
|
|
|
|
|
0
|
$data =~ s/(\n+)/$1 #/g;
|
131
|
0
|
|
|
|
|
0
|
$data =~ s/\\\\/\\/g;
|
132
|
0
|
|
|
|
|
0
|
$data =~ s/\\'/'/g;
|
133
|
|
|
|
|
|
|
|
134
|
0
|
|
|
|
|
0
|
print $Test::TESTOUT "\n # " . $data . "\n" ;
|
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
}
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
#####
|
139
|
|
|
|
|
|
|
# Restore the Test:: moduel variable back to where they were when found
|
140
|
|
|
|
|
|
|
#
|
141
|
|
|
|
|
|
|
sub finish
|
142
|
|
|
|
|
|
|
{
|
143
|
0
|
0
|
|
0
|
1
|
0
|
$tech_p = Test::Tech->new() unless $tech_p;
|
144
|
0
|
0
|
|
|
|
0
|
my $self = UNIVERSAL::isa($_[0],__PACKAGE__) ? shift @_ : $tech_p;
|
145
|
0
|
0
|
|
|
|
0
|
$self = ref($self) ? $self : $tech_p;
|
146
|
|
|
|
|
|
|
|
147
|
0
|
0
|
|
|
|
0
|
return undef unless $Test::TESTOUT; # if IO::Handle object may be destroyed and undef
|
148
|
0
|
0
|
|
|
|
0
|
return undef unless $Test::planned;
|
149
|
|
|
|
|
|
|
|
150
|
0
|
|
|
|
|
0
|
my $missing = $self->{last_test} + 1;
|
151
|
0
|
|
|
|
|
0
|
$self->{test_name} = '';
|
152
|
0
|
|
|
|
|
0
|
while($missing <= $self->{num_tests}) {
|
153
|
0
|
0
|
|
|
|
0
|
$self->{Skip_Diag} = '' unless $self->{Skip_Diag};
|
154
|
0
|
|
|
|
|
0
|
print $Test::TESTOUT "not ok $missing Not Performed # missing $self->{Skip_Diag}\n";
|
155
|
0
|
0
|
|
|
|
0
|
if( 1.20 < $Test::VERSION ) {
|
156
|
0
|
|
|
|
|
0
|
print $Test::TESTERR "# Test $missing got: (Missing)\n";
|
157
|
0
|
|
|
|
|
0
|
print $Test::TESTERR "# Expected: (Missing)\n";
|
158
|
|
|
|
|
|
|
}
|
159
|
|
|
|
|
|
|
else {
|
160
|
0
|
|
|
|
|
0
|
print $Test::TESTOUT "# Test $missing got: (Missing)\n";
|
161
|
0
|
|
|
|
|
0
|
print $Test::TESTOUT "# Expected: (Missing)\n";
|
162
|
|
|
|
|
|
|
}
|
163
|
0
|
|
|
|
|
0
|
push @{$self->{missed}}, $missing++;
|
|
0
|
|
|
|
|
0
|
|
164
|
|
|
|
|
|
|
}
|
165
|
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
0
|
$Test::TESTOUT = $self->{TestDefault}->{TESTOUT};
|
167
|
0
|
|
|
|
|
0
|
$Test::TestLevel = $self->{TestDefault}->{TestLevel};
|
168
|
0
|
|
|
|
|
0
|
$Test::ONFAIL = $self->{TestDefault}->{ONFAIL};
|
169
|
0
|
0
|
|
|
|
0
|
$Test::TESTERR = $self->{TestDefault}->{TESTERR} if defined $Test::TESTERR;
|
170
|
|
|
|
|
|
|
|
171
|
0
|
0
|
|
|
|
0
|
if(@{$self->{unplanned}}) {
|
|
0
|
|
|
|
|
0
|
|
172
|
0
|
|
|
|
|
0
|
print $Test::TESTOUT '# Extra : ' . (join ' ', @{$self->{unplanned}}) . "\n";
|
|
0
|
|
|
|
|
0
|
|
173
|
|
|
|
|
|
|
}
|
174
|
0
|
0
|
|
|
|
0
|
if(@{$self->{missed}}) {
|
|
0
|
|
|
|
|
0
|
|
175
|
0
|
|
|
|
|
0
|
print $Test::TESTOUT '# Missing: ' . (join ' ', @{$self->{missed}}) . "\n";
|
|
0
|
|
|
|
|
0
|
|
176
|
|
|
|
|
|
|
}
|
177
|
0
|
0
|
|
|
|
0
|
if(@{$self->{skipped}}) {
|
|
0
|
|
|
|
|
0
|
|
178
|
0
|
|
|
|
|
0
|
print $Test::TESTOUT '# Skipped: ' . (join ' ', @{$self->{skipped}}) . "\n";
|
|
0
|
|
|
|
|
0
|
|
179
|
|
|
|
|
|
|
}
|
180
|
0
|
0
|
|
|
|
0
|
if(@{$self->{failed}}) {
|
|
0
|
|
|
|
|
0
|
|
181
|
0
|
|
|
|
|
0
|
print $Test::TESTOUT '# Failed : ' . (join ' ', @{$self->{failed}}) . "\n";
|
|
0
|
|
|
|
|
0
|
|
182
|
|
|
|
|
|
|
}
|
183
|
1
|
|
|
1
|
|
8
|
use integer;
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
6
|
|
184
|
|
|
|
|
|
|
|
185
|
0
|
0
|
|
|
|
0
|
my $total = $self->{num_tests} if $self->{num_tests};
|
186
|
0
|
0
|
0
|
|
|
0
|
$total = $self->{last_test} if $self->{last_test} && $self->{num_tests} < $self->{last_test};
|
187
|
0
|
|
|
|
|
0
|
$total -= @{$self->{skipped}};
|
|
0
|
|
|
|
|
0
|
|
188
|
|
|
|
|
|
|
|
189
|
0
|
|
|
|
|
0
|
my $passed = @{$self->{passed}};
|
|
0
|
|
|
|
|
0
|
|
190
|
0
|
0
|
|
|
|
0
|
print $Test::TESTOUT '# Passed : ' . "$passed/$total " . ((100*$passed)/$total) . "%\n" if $total;
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
######
|
193
|
|
|
|
|
|
|
# Only once per test run.
|
194
|
|
|
|
|
|
|
#
|
195
|
0
|
|
|
|
|
0
|
$Test::planned = 0;
|
196
|
|
|
|
|
|
|
|
197
|
0
|
0
|
|
|
|
0
|
return ($total,$self->{unplanned},$self->{missed},$self->{skipped},$self->{passed},$self->{failed})
|
198
|
|
|
|
|
|
|
if wantarray;
|
199
|
|
|
|
|
|
|
|
200
|
0
|
0
|
|
|
|
0
|
$passed ? 1 : 0;
|
201
|
|
|
|
|
|
|
}
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# *finish = &*Test::Tech::DESTORY; # DESTORY is alias for finish
|
204
|
|
|
|
|
|
|
sub DESTORY
|
205
|
|
|
|
|
|
|
{
|
206
|
0
|
|
|
0
|
0
|
0
|
finish( @_ );
|
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
}
|
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
######
|
212
|
|
|
|
|
|
|
#
|
213
|
|
|
|
|
|
|
#
|
214
|
|
|
|
|
|
|
sub is_skip
|
215
|
|
|
|
|
|
|
{
|
216
|
0
|
0
|
|
0
|
1
|
0
|
$tech_p = Test::Tech->new() unless $tech_p;
|
217
|
0
|
0
|
0
|
|
|
0
|
my $self = (UNIVERSAL::isa($_[0],__PACKAGE__) && ref($_[0])) ? shift @_ : $tech_p;
|
218
|
0
|
0
|
|
|
|
0
|
$self = ref($self) ? $self : $tech_p;
|
219
|
0
|
0
|
|
|
|
0
|
return ($self->{Skip_Tests}, $self->{Skip_Diag}) if wantarray;
|
220
|
0
|
|
|
|
|
0
|
$self->{Skip_Tests};
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
}
|
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
######
|
225
|
|
|
|
|
|
|
# Cover function for &Test::ok that adds capability to test
|
226
|
|
|
|
|
|
|
# complex data structures.
|
227
|
|
|
|
|
|
|
#
|
228
|
|
|
|
|
|
|
sub ok
|
229
|
|
|
|
|
|
|
{
|
230
|
0
|
|
|
0
|
1
|
0
|
$Test::TestLevel++;
|
231
|
0
|
|
|
|
|
0
|
my $results = ok_sub('',@_);
|
232
|
0
|
|
|
|
|
0
|
$Test::TestLevel--;
|
233
|
0
|
|
|
|
|
0
|
$results;
|
234
|
|
|
|
|
|
|
}
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
######
|
237
|
|
|
|
|
|
|
# Cover function for &Test::ok that adds capability to test
|
238
|
|
|
|
|
|
|
# complex data structures.
|
239
|
|
|
|
|
|
|
#
|
240
|
|
|
|
|
|
|
sub ok_sub
|
241
|
|
|
|
|
|
|
{
|
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
######
|
244
|
|
|
|
|
|
|
# If no object, use the default $tech_p object.
|
245
|
|
|
|
|
|
|
#
|
246
|
0
|
0
|
|
0
|
1
|
0
|
$tech_p = Test::Tech->new() unless $tech_p;
|
247
|
0
|
0
|
0
|
|
|
0
|
my $self = (UNIVERSAL::isa($_[0],__PACKAGE__) && ref($_[0])) ? shift @_ : $tech_p;
|
248
|
0
|
0
|
|
|
|
0
|
$self = ref($self) ? $self : $tech_p;
|
249
|
|
|
|
|
|
|
|
250
|
0
|
|
|
|
|
0
|
my ($diagnostic,$name) = ('','');
|
251
|
0
|
0
|
0
|
|
|
0
|
my $options = Data::Startup->new(pop @_) if (3 < @_) && ref($_[-1]);
|
252
|
|
|
|
|
|
|
|
253
|
0
|
0
|
|
|
|
0
|
$diagnostic = $options->{diagnostic} if defined $options->{diagnostic};
|
254
|
0
|
0
|
|
|
|
0
|
$name = $options->{name} if defined $options->{name};
|
255
|
|
|
|
|
|
|
|
256
|
0
|
|
|
|
|
0
|
my ($subroutine, $actual_result, $expected_result, $diagnostic_in, $name_in) = @_;
|
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
#########
|
259
|
|
|
|
|
|
|
# Fill in undefined inputs
|
260
|
|
|
|
|
|
|
#
|
261
|
0
|
0
|
|
|
|
0
|
$diagnostic = $diagnostic_in if defined $diagnostic_in;
|
262
|
0
|
0
|
|
|
|
0
|
$name = $name_in if defined $name_in;
|
263
|
0
|
0
|
|
|
|
0
|
$diagnostic = $name unless defined $diagnostic;
|
264
|
0
|
|
|
|
|
0
|
$self->{test_name} = $name; # used by tied handle Test::Tech::Output
|
265
|
|
|
|
|
|
|
|
266
|
0
|
0
|
|
|
|
0
|
if($self->{Skip_Tests}) { # skip rest of tests switch
|
267
|
0
|
|
|
|
|
0
|
&Test::skip( 1, '', '', $self->{Skip_Diag});
|
268
|
0
|
|
|
|
|
0
|
return 1;
|
269
|
|
|
|
|
|
|
}
|
270
|
|
|
|
|
|
|
|
271
|
0
|
|
|
|
|
0
|
my $str_actual_result = stringify($actual_result);
|
272
|
0
|
|
|
|
|
0
|
my $str_expected_result = stringify($expected_result);
|
273
|
0
|
|
|
|
|
0
|
foreach ($str_actual_result,$str_expected_result) {
|
274
|
0
|
0
|
|
|
|
0
|
if(ref($_)) {
|
275
|
0
|
|
|
|
|
0
|
$$_ =~ s/\n\n/\n# /g;
|
276
|
0
|
|
|
|
|
0
|
$$_ =~ s/\n([^#])/\n# $1/g;
|
277
|
0
|
|
|
|
|
0
|
$diagnostic = 'Test::Tech::stringify() broken.';
|
278
|
0
|
|
|
|
|
0
|
$self->{test_name} .= ' # ' . $diagnostic;
|
279
|
0
|
|
|
|
|
0
|
&Test::ok($$_,'',$diagnostic,$diagnostic);
|
280
|
0
|
|
|
|
|
0
|
return 0;
|
281
|
|
|
|
|
|
|
}
|
282
|
|
|
|
|
|
|
}
|
283
|
0
|
0
|
|
|
|
0
|
if($subroutine) {
|
284
|
0
|
0
|
|
|
|
0
|
$diagnostic .= "\n" unless substr($diagnostic,-1,1) eq "\n";
|
285
|
0
|
|
|
|
|
0
|
$str_actual_result =~ s/\n/\n /g;
|
286
|
0
|
|
|
|
|
0
|
$str_expected_result =~ s/\n/\n /g;
|
287
|
0
|
|
|
|
|
0
|
$diagnostic .=
|
288
|
|
|
|
|
|
|
" got: $str_actual_result\n" .
|
289
|
|
|
|
|
|
|
" expected: $str_expected_result\n";
|
290
|
0
|
|
|
|
|
0
|
$str_actual_result = &$subroutine($actual_result,$expected_result);
|
291
|
0
|
|
|
|
|
0
|
$str_expected_result = 1;
|
292
|
|
|
|
|
|
|
}
|
293
|
|
|
|
|
|
|
|
294
|
0
|
|
|
|
|
0
|
&Test::ok($str_actual_result, $str_expected_result, $diagnostic);
|
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
}
|
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
######
|
300
|
|
|
|
|
|
|
# Cover function for &Test::plan that sets the proper 'Test::TestLevel'
|
301
|
|
|
|
|
|
|
# and outputs some info on the current site
|
302
|
|
|
|
|
|
|
#
|
303
|
|
|
|
|
|
|
sub plan
|
304
|
|
|
|
|
|
|
{
|
305
|
|
|
|
|
|
|
######
|
306
|
|
|
|
|
|
|
# This subroutine uses no object data; therefore,
|
307
|
|
|
|
|
|
|
# drop any class or object.
|
308
|
|
|
|
|
|
|
#
|
309
|
1
|
50
|
|
1
|
1
|
97
|
$tech_p = Test::Tech->new() unless $tech_p;
|
310
|
1
|
50
|
33
|
|
|
12
|
my $self = (UNIVERSAL::isa($_[0],__PACKAGE__) && ref($_[0])) ? shift @_ : $tech_p;
|
311
|
1
|
50
|
|
|
|
5
|
$self = ref($self) ? $self : $tech_p;
|
312
|
|
|
|
|
|
|
|
313
|
1
|
|
|
|
|
5
|
&Test::plan( @_ );
|
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
###############
|
316
|
|
|
|
|
|
|
#
|
317
|
|
|
|
|
|
|
# Establish default for Test
|
318
|
|
|
|
|
|
|
#
|
319
|
|
|
|
|
|
|
# Test 1.24 resets global variables in plan which
|
320
|
|
|
|
|
|
|
# never happens in 1.15
|
321
|
|
|
|
|
|
|
#
|
322
|
1
|
|
|
|
|
8
|
$Test::TestLevel = 1;
|
323
|
|
|
|
|
|
|
|
324
|
1
|
|
|
|
|
35
|
my $loctime = localtime();
|
325
|
1
|
|
|
|
|
25
|
my $gmtime = gmtime();
|
326
|
|
|
|
|
|
|
|
327
|
1
|
|
|
|
|
3
|
my $perl = "$]";
|
328
|
1
|
50
|
33
|
|
|
8
|
if(defined(&Win32::BuildNumber) and defined &Win32::BuildNumber()) {
|
|
|
50
|
|
|
|
|
|
329
|
0
|
|
|
|
|
0
|
$perl .= " Win32 Build " . &Win32::BuildNumber();
|
330
|
|
|
|
|
|
|
}
|
331
|
|
|
|
|
|
|
elsif(defined $MacPerl::Version) {
|
332
|
0
|
|
|
|
|
0
|
$perl .= " MacPerl version " . $MacPerl::Version;
|
333
|
|
|
|
|
|
|
}
|
334
|
|
|
|
|
|
|
|
335
|
1
|
50
|
|
|
|
186
|
print $Test::TESTOUT <<"EOF" unless 1.20 < $Test::VERSION ;
|
336
|
|
|
|
|
|
|
# OS : $^O
|
337
|
|
|
|
|
|
|
# Perl : $perl
|
338
|
|
|
|
|
|
|
# Local Time : $loctime
|
339
|
|
|
|
|
|
|
# GMT Time : $gmtime
|
340
|
|
|
|
|
|
|
# Test : $Test::VERSION
|
341
|
|
|
|
|
|
|
EOF
|
342
|
|
|
|
|
|
|
|
343
|
1
|
|
|
|
|
11
|
print $Test::TESTOUT <<"EOF";
|
344
|
|
|
|
|
|
|
# Test::Tech : $VERSION
|
345
|
|
|
|
|
|
|
# Data::Secs2 : $Data::Secs2::VERSION
|
346
|
|
|
|
|
|
|
# Data::Startup : $Data::Startup::VERSION
|
347
|
|
|
|
|
|
|
# Data::Str2Num : $Data::Str2Num::VERSION
|
348
|
|
|
|
|
|
|
# Number of tests: $self->{num_tests}
|
349
|
|
|
|
|
|
|
# =cut
|
350
|
|
|
|
|
|
|
EOF
|
351
|
|
|
|
|
|
|
|
352
|
1
|
|
|
|
|
150
|
1
|
353
|
|
|
|
|
|
|
}
|
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
######
|
357
|
|
|
|
|
|
|
#
|
358
|
|
|
|
|
|
|
#
|
359
|
|
|
|
|
|
|
sub skip {
|
360
|
0
|
|
|
0
|
1
|
0
|
$Test::TestLevel++;
|
361
|
0
|
|
|
|
|
0
|
my $results = skip_sub( '', @_ );
|
362
|
0
|
|
|
|
|
0
|
$Test::TestLevel--;
|
363
|
0
|
|
|
|
|
0
|
$results;
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
};
|
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
######
|
369
|
|
|
|
|
|
|
#
|
370
|
|
|
|
|
|
|
#
|
371
|
|
|
|
|
|
|
sub skip_sub
|
372
|
|
|
|
|
|
|
{
|
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
######
|
375
|
|
|
|
|
|
|
# If no object, use the default $tech_p object.
|
376
|
|
|
|
|
|
|
#
|
377
|
0
|
0
|
|
0
|
0
|
0
|
$tech_p = Test::Tech->new() unless $tech_p;
|
378
|
0
|
0
|
0
|
|
|
0
|
my $self = (UNIVERSAL::isa($_[0],__PACKAGE__) && ref($_[0])) ? shift @_ : $tech_p;
|
379
|
0
|
0
|
|
|
|
0
|
$self = ref($self) ? $self : $tech_p;
|
380
|
|
|
|
|
|
|
|
381
|
0
|
|
|
|
|
0
|
my ($diagnostic,$name) = ('','');
|
382
|
0
|
0
|
0
|
|
|
0
|
my $options = Data::Startup->new(pop @_) if (4 < @_) && ref($_[-1]);
|
383
|
|
|
|
|
|
|
|
384
|
0
|
0
|
|
|
|
0
|
$diagnostic = $options->{diagnostic} if $options->{diagnostic};
|
385
|
0
|
0
|
|
|
|
0
|
$name = $options->{name} if $options->{name};
|
386
|
|
|
|
|
|
|
|
387
|
0
|
|
|
|
|
0
|
my ($subroutine, $mod, $actual_result, $expected_result, $diagnostic_in, $name_in) = @_;
|
388
|
|
|
|
|
|
|
|
389
|
0
|
0
|
|
|
|
0
|
$diagnostic = $diagnostic_in if defined $diagnostic_in;
|
390
|
0
|
0
|
|
|
|
0
|
$name = $name_in if defined $name_in;
|
391
|
0
|
0
|
|
|
|
0
|
$diagnostic = $name unless defined $diagnostic;
|
392
|
0
|
|
|
|
|
0
|
$self->{test_name} = $name; # used by tied handle Test::Tech::Output
|
393
|
|
|
|
|
|
|
|
394
|
0
|
0
|
|
|
|
0
|
if($self->{Skip_Tests}) { # skip rest of tests switch
|
395
|
0
|
|
|
|
|
0
|
&Test::skip( 1, '', '', $self->{Skip_Diag});
|
396
|
0
|
|
|
|
|
0
|
return 1;
|
397
|
|
|
|
|
|
|
}
|
398
|
|
|
|
|
|
|
|
399
|
0
|
|
|
|
|
0
|
my $str_actual_result = stringify($actual_result);
|
400
|
0
|
|
|
|
|
0
|
my $str_expected_result = stringify($expected_result);
|
401
|
0
|
|
|
|
|
0
|
foreach ($str_actual_result,$str_expected_result) {
|
402
|
0
|
0
|
|
|
|
0
|
if(ref($_)) {
|
403
|
0
|
|
|
|
|
0
|
$$_ =~ s/\n\n/\n# /g;
|
404
|
0
|
|
|
|
|
0
|
$$_ =~ s/\n([^#])/\n# $1/g;
|
405
|
0
|
|
|
|
|
0
|
$diagnostic = 'Test::Tech::stringify() broken.';
|
406
|
0
|
|
|
|
|
0
|
$self->{test_name} .= ' # ' . $diagnostic;
|
407
|
0
|
|
|
|
|
0
|
&Test::ok($$_,'',$diagnostic,$diagnostic);
|
408
|
0
|
|
|
|
|
0
|
return 0;
|
409
|
|
|
|
|
|
|
}
|
410
|
|
|
|
|
|
|
}
|
411
|
|
|
|
|
|
|
|
412
|
0
|
0
|
|
|
|
0
|
if($subroutine) {
|
413
|
0
|
0
|
|
|
|
0
|
$diagnostic .= "\n" unless substr($diagnostic,-1,1) eq "\n";
|
414
|
0
|
|
|
|
|
0
|
$str_actual_result =~ s/\n/\n /g;
|
415
|
0
|
|
|
|
|
0
|
$str_expected_result =~ s/\n/\n /g;
|
416
|
0
|
|
|
|
|
0
|
$diagnostic .=
|
417
|
|
|
|
|
|
|
" got: $str_actual_result\n" .
|
418
|
|
|
|
|
|
|
" expected: $str_expected_result\n";
|
419
|
0
|
|
|
|
|
0
|
$str_actual_result = &$subroutine($actual_result,$expected_result);
|
420
|
0
|
|
|
|
|
0
|
$str_expected_result = 1;
|
421
|
|
|
|
|
|
|
}
|
422
|
|
|
|
|
|
|
|
423
|
0
|
|
|
|
|
0
|
&Test::skip($mod, $str_actual_result, $str_expected_result, $diagnostic);
|
424
|
|
|
|
|
|
|
}
|
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
######
|
428
|
|
|
|
|
|
|
#
|
429
|
|
|
|
|
|
|
#
|
430
|
|
|
|
|
|
|
sub skip_tests
|
431
|
|
|
|
|
|
|
{
|
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
######
|
434
|
|
|
|
|
|
|
# If no object, use the default $tech_p object.
|
435
|
|
|
|
|
|
|
#
|
436
|
0
|
0
|
|
0
|
1
|
0
|
$tech_p = Test::Tech->new() unless $tech_p;
|
437
|
0
|
0
|
0
|
|
|
0
|
my $self = (UNIVERSAL::isa($_[0],__PACKAGE__) && ref($_[0])) ? shift @_ : $tech_p;
|
438
|
0
|
0
|
|
|
|
0
|
$self = ref($self) ? $self : $tech_p;
|
439
|
|
|
|
|
|
|
|
440
|
0
|
|
|
|
|
0
|
my ($value,$diagnostic) = @_;
|
441
|
0
|
|
|
|
|
0
|
my $result = $self->{Skip_Tests};
|
442
|
0
|
0
|
|
|
|
0
|
$value = 1 unless (defined $value);
|
443
|
0
|
|
|
|
|
0
|
$self->{Skip_Tests} = $value;
|
444
|
0
|
0
|
|
|
|
0
|
$diagnostic = 'Test not performed because of previous failure.' unless defined $diagnostic;
|
445
|
0
|
0
|
|
|
|
0
|
$self->{Skip_Diag} = $value ? $diagnostic : '';
|
446
|
0
|
|
|
|
|
0
|
$result;
|
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
}
|
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
#######
|
452
|
|
|
|
|
|
|
# This accesses the values in the %tech hash
|
453
|
|
|
|
|
|
|
#
|
454
|
|
|
|
|
|
|
# Use a dot notation for following down layers
|
455
|
|
|
|
|
|
|
# of hashes of hashes
|
456
|
|
|
|
|
|
|
#
|
457
|
|
|
|
|
|
|
sub tech_config
|
458
|
|
|
|
|
|
|
{
|
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
######
|
461
|
|
|
|
|
|
|
# If no object, use the default $tech_p object.
|
462
|
|
|
|
|
|
|
#
|
463
|
0
|
0
|
|
0
|
1
|
0
|
$tech_p = Test::Tech->new() unless $tech_p;
|
464
|
0
|
0
|
0
|
|
|
0
|
my $self = (UNIVERSAL::isa($_[0],__PACKAGE__) && ref($_[0])) ? shift @_ : $tech_p;
|
465
|
0
|
0
|
|
|
|
0
|
$self = ref($self) ? $self : $tech_p;
|
466
|
|
|
|
|
|
|
|
467
|
0
|
|
|
|
|
0
|
my ($key, $value) = @_;
|
468
|
0
|
|
|
|
|
0
|
my @keys = split /\./, $key;
|
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
#########
|
471
|
|
|
|
|
|
|
# Follow the hash with the current
|
472
|
|
|
|
|
|
|
# dot index until there are no more
|
473
|
|
|
|
|
|
|
# hashes. For success, the dot hash
|
474
|
|
|
|
|
|
|
# notation must match the structure.
|
475
|
|
|
|
|
|
|
#
|
476
|
0
|
|
|
|
|
0
|
my $key_p = $self;
|
477
|
0
|
|
|
|
|
0
|
while (@keys) {
|
478
|
|
|
|
|
|
|
|
479
|
0
|
|
|
|
|
0
|
$key = shift @keys;
|
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
######
|
482
|
|
|
|
|
|
|
# Do not allow creation of new configs
|
483
|
|
|
|
|
|
|
#
|
484
|
0
|
0
|
|
|
|
0
|
if( defined( $key_p->{$key}) ) {
|
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
########
|
487
|
|
|
|
|
|
|
# Follow the hash
|
488
|
|
|
|
|
|
|
#
|
489
|
0
|
0
|
|
|
|
0
|
if( ref($key_p->{$key}) eq 'HASH' ) {
|
490
|
0
|
|
|
|
|
0
|
$key_p = $key_p->{$key};
|
491
|
|
|
|
|
|
|
}
|
492
|
|
|
|
|
|
|
else {
|
493
|
0
|
0
|
|
|
|
0
|
if(@keys) {
|
494
|
0
|
|
|
|
|
0
|
warn( "More key levels than hashes.\n");
|
495
|
0
|
|
|
|
|
0
|
return undef;
|
496
|
|
|
|
|
|
|
}
|
497
|
0
|
|
|
|
|
0
|
last;
|
498
|
|
|
|
|
|
|
}
|
499
|
|
|
|
|
|
|
}
|
500
|
|
|
|
|
|
|
}
|
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
#########
|
504
|
|
|
|
|
|
|
# References to arrays and scalars in the config may
|
505
|
|
|
|
|
|
|
# be transparent.
|
506
|
|
|
|
|
|
|
#
|
507
|
0
|
|
|
|
|
0
|
my $current_value = $key_p->{$key};
|
508
|
0
|
0
|
|
|
|
0
|
if( ref($current_value) eq 'SCALAR') {
|
509
|
0
|
|
|
|
|
0
|
$current_value = $$current_value;
|
510
|
|
|
|
|
|
|
}
|
511
|
0
|
0
|
0
|
|
|
0
|
if (defined $value && $key ne 'ntest') {
|
512
|
0
|
0
|
|
|
|
0
|
if( ref($value) eq 'SCALAR' ) {
|
513
|
0
|
|
|
|
|
0
|
${$key_p->{$key}} = $$value;
|
|
0
|
|
|
|
|
0
|
|
514
|
|
|
|
|
|
|
}
|
515
|
|
|
|
|
|
|
else {
|
516
|
0
|
|
|
|
|
0
|
${$key_p->{$key}} = $value;
|
|
0
|
|
|
|
|
0
|
|
517
|
|
|
|
|
|
|
}
|
518
|
|
|
|
|
|
|
}
|
519
|
|
|
|
|
|
|
|
520
|
0
|
|
|
|
|
0
|
$current_value;
|
521
|
|
|
|
|
|
|
}
|
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
########
|
525
|
|
|
|
|
|
|
# Handle Tie to catch the Test module output
|
526
|
|
|
|
|
|
|
# so that it may be modified.
|
527
|
|
|
|
|
|
|
#
|
528
|
|
|
|
|
|
|
package Test::Tech::Output;
|
529
|
1
|
|
|
1
|
|
4696
|
use Tie::Handle;
|
|
1
|
|
|
|
|
4153
|
|
|
1
|
|
|
|
|
34
|
|
530
|
1
|
|
|
1
|
|
12
|
use vars qw(@ISA);
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1026
|
|
531
|
|
|
|
|
|
|
@ISA=('Tie::Handle');
|
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
#####
|
534
|
|
|
|
|
|
|
# Tie
|
535
|
|
|
|
|
|
|
#
|
536
|
|
|
|
|
|
|
sub TIEHANDLE
|
537
|
|
|
|
|
|
|
{
|
538
|
1
|
|
|
1
|
|
3
|
my($class, $test_handle, $tech) = @_;
|
539
|
1
|
50
|
|
|
|
4
|
$class = ref($class) if ref($class);
|
540
|
1
|
|
|
|
|
6
|
bless {test_out => $test_handle, tech => $tech}, $class;
|
541
|
|
|
|
|
|
|
}
|
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
#####
|
545
|
|
|
|
|
|
|
# Print out the test output
|
546
|
|
|
|
|
|
|
#
|
547
|
|
|
|
|
|
|
sub PRINT
|
548
|
|
|
|
|
|
|
{
|
549
|
5
|
|
|
5
|
|
4636
|
my $self = shift;
|
550
|
5
|
50
|
|
|
|
23
|
my $buf = join(defined $, ? $, : '',@_);
|
551
|
5
|
50
|
|
|
|
17
|
$buf .= $\ if defined $\;
|
552
|
5
|
|
|
|
|
21
|
my $test_name = $self->{tech}->{test_name};
|
553
|
5
|
|
|
|
|
8
|
my $skip_diag = $self->{tech}->{Skip_Diag};
|
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
#####
|
556
|
|
|
|
|
|
|
# Insert test name after ok or not ok
|
557
|
|
|
|
|
|
|
#
|
558
|
5
|
50
|
|
|
|
12
|
$buf =~ s/(ok \d+)/$1 - $test_name /g if($test_name);
|
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
######
|
561
|
|
|
|
|
|
|
# Insert skip diag after a skip comment
|
562
|
|
|
|
|
|
|
#
|
563
|
5
|
50
|
|
|
|
10
|
$buf =~ s/(# skip.*?)(\s*|\n)/$1 - $skip_diag$2/ig if $skip_diag;
|
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
#####
|
566
|
|
|
|
|
|
|
# Keep stats on what tests that pass, failed, skip, todo
|
567
|
|
|
|
|
|
|
#
|
568
|
5
|
|
|
|
|
220
|
$self->stats($buf);
|
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
#####
|
571
|
|
|
|
|
|
|
# Output the modified buffer
|
572
|
|
|
|
|
|
|
#
|
573
|
5
|
|
|
|
|
7
|
my $handle = $self->{test_out};
|
574
|
5
|
|
|
|
|
99
|
print $handle $buf;
|
575
|
|
|
|
|
|
|
}
|
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
#####
|
578
|
|
|
|
|
|
|
#
|
579
|
|
|
|
|
|
|
#
|
580
|
|
|
|
|
|
|
sub PRINTF
|
581
|
|
|
|
|
|
|
{
|
582
|
1
|
|
|
1
|
|
246
|
my $self = shift;
|
583
|
1
|
|
|
|
|
9
|
$self->PRINT (sprintf(shift,@_));
|
584
|
|
|
|
|
|
|
}
|
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
sub stats
|
587
|
|
|
|
|
|
|
{
|
588
|
5
|
|
|
5
|
|
9
|
my ($self,$buf) = @_;
|
589
|
|
|
|
|
|
|
#####
|
590
|
|
|
|
|
|
|
# Stats
|
591
|
5
|
|
|
|
|
7
|
my $tech = $self->{tech};
|
592
|
5
|
|
|
|
|
7
|
my $test_num;
|
593
|
5
|
50
|
|
|
|
23
|
if($buf =~ /^\s*(not ok|ok)\s*(\d+)/) {
|
594
|
0
|
|
|
|
|
0
|
$test_num = $2;
|
595
|
|
|
|
|
|
|
}
|
596
|
5
|
50
|
|
|
|
13
|
if($test_num) {
|
597
|
0
|
0
|
|
|
|
0
|
if( $tech->{num_tests} < $test_num) {
|
598
|
0
|
|
|
|
|
0
|
push @{$tech->{unplanned}},$test_num;
|
|
0
|
|
|
|
|
0
|
|
599
|
|
|
|
|
|
|
}
|
600
|
0
|
0
|
|
|
|
0
|
if($tech->{last_test} + 1 != $test_num) {
|
601
|
0
|
|
|
|
|
0
|
push @{$tech->{missing}},$test_num;
|
|
0
|
|
|
|
|
0
|
|
602
|
|
|
|
|
|
|
}
|
603
|
0
|
|
|
|
|
0
|
$tech->{last_test} = $test_num;
|
604
|
|
|
|
|
|
|
}
|
605
|
5
|
100
|
|
|
|
43
|
if($buf =~ /^\d+\.\.(\d+)/) {
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
606
|
1
|
|
|
|
|
7
|
$tech->{num_tests} = $1;
|
607
|
|
|
|
|
|
|
}
|
608
|
|
|
|
|
|
|
elsif ($buf =~ /^\s*ok\s*(\d+).*?\#\s*skip/i) {
|
609
|
0
|
|
|
|
|
|
push @{$tech->{skipped}},$1;
|
|
0
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
}
|
611
|
|
|
|
|
|
|
elsif ($buf =~ /^\s*not ok\s*(\d+)/i) {
|
612
|
0
|
|
|
|
|
|
push @{$tech->{failed}},$1;
|
|
0
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
}
|
614
|
|
|
|
|
|
|
elsif ($buf =~ /^\s*ok\s*(\d+)/i) {
|
615
|
0
|
|
|
|
|
|
push @{$tech->{passed}},$1;
|
|
0
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
}
|
617
|
|
|
|
|
|
|
}
|
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
1
|
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
__END__
|