line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::Given::Check; |
2
|
41
|
|
|
41
|
|
198
|
use strict; |
|
41
|
|
|
|
|
63
|
|
|
41
|
|
|
|
|
1226
|
|
3
|
41
|
|
|
41
|
|
185
|
use warnings; |
|
41
|
|
|
|
|
69
|
|
|
41
|
|
|
|
|
853
|
|
4
|
|
|
|
|
|
|
|
5
|
41
|
|
|
41
|
|
204
|
use B::Deparse (); |
|
41
|
|
|
|
|
64
|
|
|
41
|
|
|
|
|
49438
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
sub new { |
8
|
225
|
|
|
225
|
0
|
320
|
my ($class, $sub) = @_; |
9
|
225
|
|
|
|
|
530
|
my $self = { |
10
|
|
|
|
|
|
|
sub => $sub, |
11
|
|
|
|
|
|
|
}; |
12
|
225
|
|
|
|
|
954
|
bless $self, $class; |
13
|
|
|
|
|
|
|
} |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub execute { |
16
|
308
|
|
|
308
|
0
|
423
|
my ($self, $exceptions) = @_; |
17
|
308
|
100
|
|
|
|
1812
|
return 1 if !$self->{sub}; |
18
|
|
|
|
|
|
|
|
19
|
304
|
|
|
|
|
498
|
my $rv = eval { |
20
|
304
|
|
|
|
|
1387
|
$self->{sub}->($exceptions); |
21
|
|
|
|
|
|
|
}; |
22
|
304
|
100
|
|
|
|
6575
|
if ($@) { |
23
|
20
|
|
|
|
|
735
|
warn $@; |
24
|
20
|
|
|
|
|
54
|
$rv = ''; |
25
|
|
|
|
|
|
|
} |
26
|
304
|
|
|
|
|
6511
|
return $rv; |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
our $deparser = B::Deparse->new('-l'); |
30
|
|
|
|
|
|
|
sub _decompile { |
31
|
195
|
|
|
195
|
|
337
|
my ($self) = @_; |
32
|
195
|
100
|
|
|
|
701
|
unless ( exists $self->{code} ) { |
33
|
135
|
|
|
|
|
200418
|
my @code = split( /\n/, $deparser->coderef2text($self->{sub}) ); |
34
|
135
|
50
|
|
|
|
1205
|
@code = (@code > 1) ? @code[1..$#code-1] : (); |
35
|
135
|
|
|
|
|
647
|
$self->{code} = \@code; |
36
|
|
|
|
|
|
|
} |
37
|
195
|
|
|
|
|
569
|
return $self->{code}; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub name { |
41
|
133
|
|
|
133
|
0
|
268
|
my ($self) = @_; |
42
|
133
|
100
|
|
|
|
437
|
return '' if !$self->{sub}; |
43
|
|
|
|
|
|
|
|
44
|
129
|
|
|
|
|
202
|
my @code = grep { !/^ *(?:package|use|no|#line) / } @{ $self->_decompile() }; |
|
549
|
|
|
|
|
2090
|
|
|
129
|
|
|
|
|
558
|
|
45
|
129
|
|
|
|
|
696
|
my ($line) = _clean_code( $code[$#code] ); |
46
|
129
|
|
|
|
|
559
|
$line =~ s/;$//; |
47
|
129
|
|
|
|
|
1061
|
return $line; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub message { |
51
|
66
|
|
|
66
|
0
|
97
|
my ($self) = @_; |
52
|
66
|
50
|
|
|
|
207
|
return '' if !$self->{sub}; |
53
|
|
|
|
|
|
|
|
54
|
66
|
|
|
|
|
107
|
my @lines = @{ $self->_decompile() }; |
|
66
|
|
|
|
|
157
|
|
55
|
66
|
|
|
|
|
125
|
my @code = _clean_code(grep { !/^ *(?:package|use|no|#line) / } @lines); |
|
296
|
|
|
|
|
1053
|
|
56
|
66
|
|
|
|
|
109
|
my ($line_number) = grep { /^ *#line / } @lines; |
|
296
|
|
|
|
|
670
|
|
57
|
|
|
|
|
|
|
|
58
|
66
|
|
|
|
|
188
|
my $msg = $self->type() . ": $line_number\n " . join("\n ", @code); |
59
|
|
|
|
|
|
|
|
60
|
66
|
100
|
|
|
|
218
|
if ( my ($left, $cmp, $right) = _split_expression( $code[$#code] ) ) { |
61
|
48
|
|
|
|
|
83
|
my @package = grep { /^ *package / } @lines; |
|
216
|
|
|
|
|
408
|
|
62
|
48
|
100
|
|
|
|
139
|
@package = 'package main;' unless @package; |
63
|
|
|
|
|
|
|
|
64
|
48
|
|
|
|
|
70
|
my @use = grep { /^ *(?:use|no) / } @lines; |
|
216
|
|
|
|
|
618
|
|
65
|
48
|
|
|
|
|
96
|
push @use, "no warnings 'all';"; |
66
|
|
|
|
|
|
|
|
67
|
48
|
|
|
|
|
111
|
my $left_value = _eval_in_context(@package, @use, $left); |
68
|
48
|
|
|
|
|
110
|
my $right_value = _eval_in_context(@package, @use, $right); |
69
|
|
|
|
|
|
|
|
70
|
48
|
100
|
66
|
|
|
341
|
unless ($left_value =~ /
|
71
|
40
|
|
|
|
|
270
|
$msg .= "\n $left_value\t<- $left\n $right_value\t<- $right"; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
} |
74
|
66
|
|
|
|
|
465
|
return $msg; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub _split_expression { |
78
|
66
|
|
|
66
|
|
692
|
return $_[0] =~ /^\s*(?:return\s+)?(.*) ([!=<>]=|[<>]|<=>|eq|ne|cmp|[lg][te]|[!=]~) (.*?)\s*;?$/; |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub _eval_in_context { |
82
|
96
|
|
|
96
|
|
7405
|
my $result = eval( join("\n", @_) ); |
|
8
|
|
|
8
|
|
60
|
|
|
8
|
|
|
8
|
|
13
|
|
|
8
|
|
|
8
|
|
311
|
|
|
8
|
|
|
8
|
|
42
|
|
|
8
|
|
|
8
|
|
12
|
|
|
8
|
|
|
8
|
|
292
|
|
|
8
|
|
|
8
|
|
36
|
|
|
8
|
|
|
8
|
|
11
|
|
|
8
|
|
|
8
|
|
373
|
|
|
8
|
|
|
8
|
|
41
|
|
|
8
|
|
|
8
|
|
14
|
|
|
8
|
|
|
8
|
|
185
|
|
|
8
|
|
|
8
|
|
39
|
|
|
8
|
|
|
8
|
|
14
|
|
|
8
|
|
|
8
|
|
257
|
|
|
8
|
|
|
8
|
|
36
|
|
|
8
|
|
|
8
|
|
11
|
|
|
8
|
|
|
8
|
|
283
|
|
|
8
|
|
|
8
|
|
53
|
|
|
8
|
|
|
8
|
|
15
|
|
|
8
|
|
|
8
|
|
265
|
|
|
8
|
|
|
8
|
|
40
|
|
|
8
|
|
|
8
|
|
15
|
|
|
8
|
|
|
8
|
|
299
|
|
|
8
|
|
|
8
|
|
37
|
|
|
8
|
|
|
8
|
|
15
|
|
|
8
|
|
|
8
|
|
348
|
|
|
8
|
|
|
8
|
|
41
|
|
|
8
|
|
|
8
|
|
16
|
|
|
8
|
|
|
8
|
|
196
|
|
|
8
|
|
|
8
|
|
36
|
|
|
8
|
|
|
8
|
|
16
|
|
|
8
|
|
|
8
|
|
272
|
|
|
8
|
|
|
8
|
|
37
|
|
|
8
|
|
|
8
|
|
15
|
|
|
8
|
|
|
8
|
|
241
|
|
|
8
|
|
|
|
|
46
|
|
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
228
|
|
|
8
|
|
|
|
|
37
|
|
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
227
|
|
|
8
|
|
|
|
|
36
|
|
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
197
|
|
|
8
|
|
|
|
|
35
|
|
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
187
|
|
|
8
|
|
|
|
|
37
|
|
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
192
|
|
|
8
|
|
|
|
|
41
|
|
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
275
|
|
|
8
|
|
|
|
|
45
|
|
|
8
|
|
|
|
|
17
|
|
|
8
|
|
|
|
|
192
|
|
|
8
|
|
|
|
|
33
|
|
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
237
|
|
|
8
|
|
|
|
|
34
|
|
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
300
|
|
|
8
|
|
|
|
|
37
|
|
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
148
|
|
|
8
|
|
|
|
|
31
|
|
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
215
|
|
|
8
|
|
|
|
|
29
|
|
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
207
|
|
|
8
|
|
|
|
|
46
|
|
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
268
|
|
|
8
|
|
|
|
|
39
|
|
|
8
|
|
|
|
|
10
|
|
|
8
|
|
|
|
|
276
|
|
|
8
|
|
|
|
|
45
|
|
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
203
|
|
|
8
|
|
|
|
|
42
|
|
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
204
|
|
|
8
|
|
|
|
|
37
|
|
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
208
|
|
|
8
|
|
|
|
|
36
|
|
|
8
|
|
|
|
|
71
|
|
|
8
|
|
|
|
|
165
|
|
|
8
|
|
|
|
|
47
|
|
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
202
|
|
|
8
|
|
|
|
|
35
|
|
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
276
|
|
|
8
|
|
|
|
|
36
|
|
|
8
|
|
|
|
|
43
|
|
|
8
|
|
|
|
|
269
|
|
|
8
|
|
|
|
|
38
|
|
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
169
|
|
|
8
|
|
|
|
|
37
|
|
|
8
|
|
|
|
|
10
|
|
|
8
|
|
|
|
|
242
|
|
|
8
|
|
|
|
|
38
|
|
|
8
|
|
|
|
|
24
|
|
|
8
|
|
|
|
|
177
|
|
83
|
|
|
|
|
|
|
|
84
|
96
|
100
|
|
|
|
304
|
if ($@) { |
85
|
24
|
|
|
|
|
43
|
$result = $@; |
86
|
24
|
|
|
|
|
55
|
$result =~ s/ at \(eval \d+\) line \d+.*\n?//; |
87
|
24
|
|
|
|
|
65
|
$result = ""; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
96
|
100
|
|
|
|
190
|
$result = '' unless defined $result; |
91
|
96
|
|
|
|
|
187
|
return $result; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# convert $$var to $var-> |
95
|
|
|
|
|
|
|
sub _clean_code { |
96
|
195
|
|
|
|
|
1407
|
map { |
97
|
195
|
|
|
195
|
|
329
|
s/\$(\$.*?)([\{\[])/$1->$2/g; |
98
|
195
|
|
|
|
|
883
|
s/^ //; |
99
|
195
|
|
|
|
|
636
|
$_; |
100
|
|
|
|
|
|
|
} @_; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
package Test::Given::Invariant; |
104
|
41
|
|
|
41
|
|
34845
|
use parent 'Test::Given::Check'; |
|
41
|
|
|
|
|
13139
|
|
|
41
|
|
|
|
|
207
|
|
105
|
5
|
|
|
5
|
|
26
|
sub type { 'Invariant' } |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
package Test::Given::Then; |
108
|
41
|
|
|
41
|
|
3564
|
use parent 'Test::Given::Check'; |
|
41
|
|
|
|
|
85
|
|
|
41
|
|
|
|
|
204
|
|
109
|
59
|
|
|
59
|
|
249
|
sub type { 'Then' } |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
package Test::Given::And; |
112
|
41
|
|
|
41
|
|
2477
|
use parent 'Test::Given::Check'; |
|
41
|
|
|
|
|
77
|
|
|
41
|
|
|
|
|
149
|
|
113
|
2
|
|
|
2
|
|
10
|
sub type { 'And' } |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
package Test::Given::Test; |
116
|
|
|
|
|
|
|
|
117
|
41
|
|
|
41
|
|
26649
|
use Test::Given::Builder; |
|
41
|
|
|
|
|
134
|
|
|
41
|
|
|
|
|
423
|
|
118
|
|
|
|
|
|
|
my $TEST_CLASS = 'Test::Given::Builder'; |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub new { |
121
|
137
|
|
|
137
|
|
235
|
my ($class, $sub) = @_; |
122
|
137
|
|
|
|
|
872
|
my $self = { |
123
|
|
|
|
|
|
|
checks => [ Test::Given::Then->new($sub) ], |
124
|
|
|
|
|
|
|
}; |
125
|
137
|
|
|
|
|
709
|
bless $self, $class; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
sub add_check { |
128
|
52
|
|
|
52
|
|
88
|
my ($self) = shift; |
129
|
52
|
|
|
|
|
64
|
push @{ $self->{checks} }, Test::Given::And->new(@_); |
|
52
|
|
|
|
|
275
|
|
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
sub execute { |
132
|
135
|
|
|
135
|
|
339
|
my ($self, $context) = @_; |
133
|
135
|
|
|
|
|
571
|
$context->reset(); |
134
|
135
|
|
|
|
|
1586
|
$context->apply_givens(); |
135
|
133
|
|
|
|
|
723
|
$context->apply_whens(); |
136
|
133
|
|
|
|
|
499
|
my $exceptions = $context->exceptions(); |
137
|
133
|
|
|
|
|
249
|
my @failed = grep { not $_->execute($exceptions) } @{ $self->{checks} }; |
|
185
|
|
|
|
|
1344
|
|
|
133
|
|
|
|
|
572
|
|
138
|
133
|
|
|
|
|
605
|
push @failed, $context->apply_invariants($exceptions); |
139
|
133
|
|
|
|
|
258
|
my $passed = not @failed; |
140
|
133
|
|
|
|
|
533
|
ok($passed, name($self->{checks})); |
141
|
133
|
100
|
|
|
|
547
|
diag(message(\@failed)) unless $passed; |
142
|
133
|
|
|
|
|
8455
|
return $passed; |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub name { |
146
|
133
|
|
|
133
|
|
226
|
my ($checks) = @_; |
147
|
133
|
|
|
|
|
660
|
return $checks->[0]->name(); |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub message { |
151
|
66
|
|
|
66
|
|
107
|
my ($failed) = @_; |
152
|
66
|
|
|
|
|
139
|
return join("\n\n", map { $_->message() } @$failed); |
|
66
|
|
|
|
|
276
|
|
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
1; |