line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test2::Hub; |
2
|
246
|
|
|
246
|
|
3958
|
use strict; |
|
246
|
|
|
|
|
500
|
|
|
246
|
|
|
|
|
7888
|
|
3
|
246
|
|
|
246
|
|
1641
|
use warnings; |
|
246
|
|
|
|
|
461
|
|
|
246
|
|
|
|
|
11108
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
our $VERSION = '1.302182'; |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
|
8
|
246
|
|
|
246
|
|
1455
|
use Carp qw/carp croak confess/; |
|
246
|
|
|
|
|
520
|
|
|
246
|
|
|
|
|
15686
|
|
9
|
246
|
|
|
246
|
|
2094
|
use Test2::Util qw/get_tid gen_uid/; |
|
246
|
|
|
|
|
574
|
|
|
246
|
|
|
|
|
13326
|
|
10
|
|
|
|
|
|
|
|
11
|
246
|
|
|
246
|
|
1665
|
use Scalar::Util qw/weaken/; |
|
246
|
|
|
|
|
496
|
|
|
246
|
|
|
|
|
12518
|
|
12
|
246
|
|
|
246
|
|
1594
|
use List::Util qw/first/; |
|
246
|
|
|
|
|
637
|
|
|
246
|
|
|
|
|
28338
|
|
13
|
|
|
|
|
|
|
|
14
|
246
|
|
|
246
|
|
102059
|
use Test2::Util::ExternalMeta qw/meta get_meta set_meta delete_meta/; |
|
246
|
|
|
|
|
598
|
|
|
246
|
|
|
|
|
19809
|
|
15
|
246
|
|
|
|
|
1513
|
use Test2::Util::HashBase qw{ |
16
|
|
|
|
|
|
|
pid tid hid ipc |
17
|
|
|
|
|
|
|
nested buffered |
18
|
|
|
|
|
|
|
no_ending |
19
|
|
|
|
|
|
|
_filters |
20
|
|
|
|
|
|
|
_pre_filters |
21
|
|
|
|
|
|
|
_listeners |
22
|
|
|
|
|
|
|
_follow_ups |
23
|
|
|
|
|
|
|
_formatter |
24
|
|
|
|
|
|
|
_context_acquire |
25
|
|
|
|
|
|
|
_context_init |
26
|
|
|
|
|
|
|
_context_release |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
uuid |
29
|
|
|
|
|
|
|
active |
30
|
|
|
|
|
|
|
count |
31
|
|
|
|
|
|
|
failed |
32
|
|
|
|
|
|
|
ended |
33
|
|
|
|
|
|
|
bailed_out |
34
|
|
|
|
|
|
|
_passing |
35
|
|
|
|
|
|
|
_plan |
36
|
|
|
|
|
|
|
skip_reason |
37
|
246
|
|
|
246
|
|
2098
|
}; |
|
246
|
|
|
|
|
479
|
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
my $UUID_VIA; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub init { |
42
|
729
|
|
|
729
|
0
|
1545
|
my $self = shift; |
43
|
|
|
|
|
|
|
|
44
|
729
|
|
|
|
|
3497
|
$self->{+PID} = $$; |
45
|
729
|
|
|
|
|
1960
|
$self->{+TID} = get_tid(); |
46
|
729
|
|
|
|
|
4025
|
$self->{+HID} = gen_uid(); |
47
|
|
|
|
|
|
|
|
48
|
729
|
|
66
|
|
|
3683
|
$UUID_VIA ||= Test2::API::_add_uuid_via_ref(); |
49
|
729
|
100
|
|
|
|
2313
|
$self->{+UUID} = ${$UUID_VIA}->('hub') if $$UUID_VIA; |
|
4
|
|
|
|
|
10
|
|
50
|
|
|
|
|
|
|
|
51
|
729
|
100
|
|
|
|
2895
|
$self->{+NESTED} = 0 unless defined $self->{+NESTED}; |
52
|
729
|
100
|
|
|
|
2527
|
$self->{+BUFFERED} = 0 unless defined $self->{+BUFFERED}; |
53
|
|
|
|
|
|
|
|
54
|
729
|
|
|
|
|
1806
|
$self->{+COUNT} = 0; |
55
|
729
|
|
|
|
|
1628
|
$self->{+FAILED} = 0; |
56
|
729
|
|
|
|
|
2142
|
$self->{+_PASSING} = 1; |
57
|
|
|
|
|
|
|
|
58
|
729
|
100
|
|
|
|
2373
|
if (my $formatter = delete $self->{formatter}) { |
59
|
52
|
|
|
|
|
218
|
$self->format($formatter); |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
729
|
100
|
|
|
|
2807
|
if (my $ipc = $self->{+IPC}) { |
63
|
15
|
|
|
|
|
63
|
$ipc->add_hub($self->{+HID}); |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
235
|
|
|
235
|
0
|
2845
|
sub is_subtest { 0 } |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub _tb_reset { |
70
|
55
|
|
|
55
|
|
164
|
my $self = shift; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# Nothing to do |
73
|
55
|
100
|
66
|
|
|
503
|
return if $self->{+PID} == $$ && $self->{+TID} == get_tid(); |
74
|
|
|
|
|
|
|
|
75
|
1
|
|
|
|
|
32
|
$self->{+PID} = $$; |
76
|
1
|
|
|
|
|
22
|
$self->{+TID} = get_tid(); |
77
|
1
|
|
|
|
|
25
|
$self->{+HID} = gen_uid(); |
78
|
|
|
|
|
|
|
|
79
|
1
|
50
|
|
|
|
32
|
if (my $ipc = $self->{+IPC}) { |
80
|
0
|
|
|
|
|
0
|
$ipc->add_hub($self->{+HID}); |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub reset_state { |
85
|
58
|
|
|
58
|
1
|
169
|
my $self = shift; |
86
|
|
|
|
|
|
|
|
87
|
58
|
|
|
|
|
160
|
$self->{+COUNT} = 0; |
88
|
58
|
|
|
|
|
133
|
$self->{+FAILED} = 0; |
89
|
58
|
|
|
|
|
177
|
$self->{+_PASSING} = 1; |
90
|
|
|
|
|
|
|
|
91
|
58
|
|
|
|
|
151
|
delete $self->{+_PLAN}; |
92
|
58
|
|
|
|
|
121
|
delete $self->{+ENDED}; |
93
|
58
|
|
|
|
|
114
|
delete $self->{+BAILED_OUT}; |
94
|
58
|
|
|
|
|
150
|
delete $self->{+SKIP_REASON}; |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub inherit { |
98
|
292
|
|
|
292
|
0
|
551
|
my $self = shift; |
99
|
292
|
|
|
|
|
632
|
my ($from, %params) = @_; |
100
|
|
|
|
|
|
|
|
101
|
292
|
|
50
|
|
|
1540
|
$self->{+NESTED} ||= 0; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
$self->{+_FORMATTER} = $from->{+_FORMATTER} |
104
|
292
|
100
|
66
|
|
|
1558
|
unless $self->{+_FORMATTER} || exists($params{formatter}); |
105
|
|
|
|
|
|
|
|
106
|
292
|
100
|
66
|
|
|
1097
|
if ($from->{+IPC} && !$self->{+IPC} && !exists($params{ipc})) { |
|
|
|
100
|
|
|
|
|
107
|
24
|
|
|
|
|
55
|
my $ipc = $from->{+IPC}; |
108
|
24
|
|
|
|
|
55
|
$self->{+IPC} = $ipc; |
109
|
24
|
|
|
|
|
103
|
$ipc->add_hub($self->{+HID}); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
292
|
100
|
|
|
|
907
|
if (my $ls = $from->{+_LISTENERS}) { |
113
|
53
|
|
|
|
|
91
|
push @{$self->{+_LISTENERS}} => grep { $_->{inherit} } @$ls; |
|
53
|
|
|
|
|
229
|
|
|
55
|
|
|
|
|
200
|
|
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
292
|
100
|
|
|
|
803
|
if (my $pfs = $from->{+_PRE_FILTERS}) { |
117
|
173
|
|
|
|
|
251
|
push @{$self->{+_PRE_FILTERS}} => grep { $_->{inherit} } @$pfs; |
|
173
|
|
|
|
|
519
|
|
|
253
|
|
|
|
|
665
|
|
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
292
|
100
|
|
|
|
1150
|
if (my $fs = $from->{+_FILTERS}) { |
121
|
12
|
|
|
|
|
21
|
push @{$self->{+_FILTERS}} => grep { $_->{inherit} } @$fs; |
|
12
|
|
|
|
|
48
|
|
|
6
|
|
|
|
|
30
|
|
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub format { |
126
|
3485
|
|
|
3485
|
1
|
6068
|
my $self = shift; |
127
|
|
|
|
|
|
|
|
128
|
3485
|
|
|
|
|
5972
|
my $old = $self->{+_FORMATTER}; |
129
|
3485
|
100
|
|
|
|
8405
|
($self->{+_FORMATTER}) = @_ if @_; |
130
|
|
|
|
|
|
|
|
131
|
3485
|
|
|
|
|
9984
|
return $old; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub is_local { |
135
|
127
|
|
|
127
|
0
|
256
|
my $self = shift; |
136
|
|
|
|
|
|
|
return $$ == $self->{+PID} |
137
|
127
|
|
66
|
|
|
1081
|
&& get_tid() == $self->{+TID}; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
sub listen { |
141
|
343
|
|
|
343
|
1
|
644
|
my $self = shift; |
142
|
343
|
|
|
|
|
836
|
my ($sub, %params) = @_; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
carp "Useless addition of a listener in a child process or thread!" |
145
|
343
|
50
|
33
|
|
|
1973
|
if $$ != $self->{+PID} || get_tid() != $self->{+TID}; |
146
|
|
|
|
|
|
|
|
147
|
343
|
100
|
66
|
|
|
2017
|
croak "listen only takes coderefs for arguments, got '$sub'" |
148
|
|
|
|
|
|
|
unless ref $sub && ref $sub eq 'CODE'; |
149
|
|
|
|
|
|
|
|
150
|
342
|
|
|
|
|
586
|
push @{$self->{+_LISTENERS}} => { %params, code => $sub }; |
|
342
|
|
|
|
|
1492
|
|
151
|
|
|
|
|
|
|
|
152
|
342
|
|
|
|
|
915
|
$sub; # Intentional return. |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub unlisten { |
156
|
1
|
|
|
1
|
1
|
8
|
my $self = shift; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
carp "Useless removal of a listener in a child process or thread!" |
159
|
1
|
50
|
33
|
|
|
23
|
if $$ != $self->{+PID} || get_tid() != $self->{+TID}; |
160
|
|
|
|
|
|
|
|
161
|
1
|
|
|
|
|
5
|
my %subs = map {$_ => $_} @_; |
|
1
|
|
|
|
|
10
|
|
162
|
|
|
|
|
|
|
|
163
|
1
|
|
|
|
|
4
|
@{$self->{+_LISTENERS}} = grep { !$subs{$_->{code}} } @{$self->{+_LISTENERS}}; |
|
1
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
8
|
|
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub filter { |
167
|
11
|
|
|
11
|
1
|
77
|
my $self = shift; |
168
|
11
|
|
|
|
|
51
|
my ($sub, %params) = @_; |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
carp "Useless addition of a filter in a child process or thread!" |
171
|
11
|
50
|
33
|
|
|
115
|
if $$ != $self->{+PID} || get_tid() != $self->{+TID}; |
172
|
|
|
|
|
|
|
|
173
|
11
|
100
|
66
|
|
|
192
|
croak "filter only takes coderefs for arguments, got '$sub'" |
174
|
|
|
|
|
|
|
unless ref $sub && ref $sub eq 'CODE'; |
175
|
|
|
|
|
|
|
|
176
|
10
|
|
|
|
|
18
|
push @{$self->{+_FILTERS}} => { %params, code => $sub }; |
|
10
|
|
|
|
|
67
|
|
177
|
|
|
|
|
|
|
|
178
|
10
|
|
|
|
|
52
|
$sub; # Intentional Return |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub unfilter { |
182
|
2
|
|
|
2
|
1
|
13
|
my $self = shift; |
183
|
|
|
|
|
|
|
carp "Useless removal of a filter in a child process or thread!" |
184
|
2
|
50
|
33
|
|
|
30
|
if $$ != $self->{+PID} || get_tid() != $self->{+TID}; |
185
|
2
|
|
|
|
|
11
|
my %subs = map {$_ => $_} @_; |
|
2
|
|
|
|
|
15
|
|
186
|
2
|
|
|
|
|
8
|
@{$self->{+_FILTERS}} = grep { !$subs{$_->{code}} } @{$self->{+_FILTERS}}; |
|
2
|
|
|
|
|
15
|
|
|
3
|
|
|
|
|
21
|
|
|
2
|
|
|
|
|
12
|
|
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub pre_filter { |
190
|
482
|
|
|
482
|
1
|
1258
|
my $self = shift; |
191
|
482
|
|
|
|
|
1729
|
my ($sub, %params) = @_; |
192
|
|
|
|
|
|
|
|
193
|
482
|
100
|
66
|
|
|
3110
|
croak "pre_filter only takes coderefs for arguments, got '$sub'" |
194
|
|
|
|
|
|
|
unless ref $sub && ref $sub eq 'CODE'; |
195
|
|
|
|
|
|
|
|
196
|
481
|
|
|
|
|
1065
|
push @{$self->{+_PRE_FILTERS}} => { %params, code => $sub }; |
|
481
|
|
|
|
|
2776
|
|
197
|
|
|
|
|
|
|
|
198
|
481
|
|
|
|
|
2059
|
$sub; # Intentional Return |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub pre_unfilter { |
202
|
93
|
|
|
93
|
1
|
167
|
my $self = shift; |
203
|
93
|
|
|
|
|
229
|
my %subs = map {$_ => $_} @_; |
|
93
|
|
|
|
|
421
|
|
204
|
93
|
|
|
|
|
171
|
@{$self->{+_PRE_FILTERS}} = grep { !$subs{$_->{code}} } @{$self->{+_PRE_FILTERS}}; |
|
93
|
|
|
|
|
364
|
|
|
211
|
|
|
|
|
589
|
|
|
93
|
|
|
|
|
218
|
|
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
sub follow_up { |
208
|
4
|
|
|
4
|
0
|
32
|
my $self = shift; |
209
|
4
|
|
|
|
|
10
|
my ($sub) = @_; |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
carp "Useless addition of a follow-up in a child process or thread!" |
212
|
4
|
50
|
33
|
|
|
22
|
if $$ != $self->{+PID} || get_tid() != $self->{+TID}; |
213
|
|
|
|
|
|
|
|
214
|
4
|
100
|
66
|
|
|
386
|
croak "follow_up only takes coderefs for arguments, got '$sub'" |
215
|
|
|
|
|
|
|
unless ref $sub && ref $sub eq 'CODE'; |
216
|
|
|
|
|
|
|
|
217
|
2
|
|
|
|
|
4
|
push @{$self->{+_FOLLOW_UPS}} => $sub; |
|
2
|
|
|
|
|
10
|
|
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
*add_context_aquire = \&add_context_acquire; |
221
|
|
|
|
|
|
|
sub add_context_acquire { |
222
|
1
|
|
|
1
|
1
|
9
|
my $self = shift; |
223
|
1
|
|
|
|
|
2
|
my ($sub) = @_; |
224
|
|
|
|
|
|
|
|
225
|
1
|
50
|
33
|
|
|
6
|
croak "add_context_acquire only takes coderefs for arguments, got '$sub'" |
226
|
|
|
|
|
|
|
unless ref $sub && ref $sub eq 'CODE'; |
227
|
|
|
|
|
|
|
|
228
|
1
|
|
|
|
|
2
|
push @{$self->{+_CONTEXT_ACQUIRE}} => $sub; |
|
1
|
|
|
|
|
15
|
|
229
|
|
|
|
|
|
|
|
230
|
1
|
|
|
|
|
5
|
$sub; # Intentional return. |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
*remove_context_aquire = \&remove_context_acquire; |
234
|
|
|
|
|
|
|
sub remove_context_acquire { |
235
|
1
|
|
|
1
|
1
|
6
|
my $self = shift; |
236
|
1
|
|
|
|
|
2
|
my %subs = map {$_ => $_} @_; |
|
1
|
|
|
|
|
5
|
|
237
|
1
|
|
|
|
|
2
|
@{$self->{+_CONTEXT_ACQUIRE}} = grep { !$subs{$_} == $_ } @{$self->{+_CONTEXT_ACQUIRE}}; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
4
|
|
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub add_context_init { |
241
|
1
|
|
|
1
|
1
|
11
|
my $self = shift; |
242
|
1
|
|
|
|
|
3
|
my ($sub) = @_; |
243
|
|
|
|
|
|
|
|
244
|
1
|
50
|
33
|
|
|
8
|
croak "add_context_init only takes coderefs for arguments, got '$sub'" |
245
|
|
|
|
|
|
|
unless ref $sub && ref $sub eq 'CODE'; |
246
|
|
|
|
|
|
|
|
247
|
1
|
|
|
|
|
3
|
push @{$self->{+_CONTEXT_INIT}} => $sub; |
|
1
|
|
|
|
|
4
|
|
248
|
|
|
|
|
|
|
|
249
|
1
|
|
|
|
|
4
|
$sub; # Intentional return. |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub remove_context_init { |
253
|
1
|
|
|
1
|
1
|
10
|
my $self = shift; |
254
|
1
|
|
|
|
|
17
|
my %subs = map {$_ => $_} @_; |
|
1
|
|
|
|
|
6
|
|
255
|
1
|
|
|
|
|
3
|
@{$self->{+_CONTEXT_INIT}} = grep { !$subs{$_} == $_ } @{$self->{+_CONTEXT_INIT}}; |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
4
|
|
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub add_context_release { |
259
|
1
|
|
|
1
|
1
|
8
|
my $self = shift; |
260
|
1
|
|
|
|
|
3
|
my ($sub) = @_; |
261
|
|
|
|
|
|
|
|
262
|
1
|
50
|
33
|
|
|
5
|
croak "add_context_release only takes coderefs for arguments, got '$sub'" |
263
|
|
|
|
|
|
|
unless ref $sub && ref $sub eq 'CODE'; |
264
|
|
|
|
|
|
|
|
265
|
1
|
|
|
|
|
3
|
push @{$self->{+_CONTEXT_RELEASE}} => $sub; |
|
1
|
|
|
|
|
3
|
|
266
|
|
|
|
|
|
|
|
267
|
1
|
|
|
|
|
3
|
$sub; # Intentional return. |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
sub remove_context_release { |
271
|
1
|
|
|
1
|
1
|
6
|
my $self = shift; |
272
|
1
|
|
|
|
|
3
|
my %subs = map {$_ => $_} @_; |
|
1
|
|
|
|
|
4
|
|
273
|
1
|
|
|
|
|
3
|
@{$self->{+_CONTEXT_RELEASE}} = grep { !$subs{$_} == $_ } @{$self->{+_CONTEXT_RELEASE}}; |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub send { |
277
|
6019
|
|
|
6019
|
1
|
12088
|
my $self = shift; |
278
|
6019
|
|
|
|
|
10852
|
my ($e) = @_; |
279
|
|
|
|
|
|
|
|
280
|
6019
|
|
|
|
|
26309
|
$e->eid; |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
$e->add_hub( |
283
|
|
|
|
|
|
|
{ |
284
|
|
|
|
|
|
|
details => ref($self), |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
buffered => $self->{+BUFFERED}, |
287
|
|
|
|
|
|
|
hid => $self->{+HID}, |
288
|
|
|
|
|
|
|
nested => $self->{+NESTED}, |
289
|
|
|
|
|
|
|
pid => $self->{+PID}, |
290
|
|
|
|
|
|
|
tid => $self->{+TID}, |
291
|
|
|
|
|
|
|
uuid => $self->{+UUID}, |
292
|
|
|
|
|
|
|
|
293
|
6019
|
100
|
|
|
|
61155
|
ipc => $self->{+IPC} ? 1 : 0, |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
); |
296
|
|
|
|
|
|
|
|
297
|
6019
|
100
|
|
|
|
15542
|
$e->set_uuid(${$UUID_VIA}->('event')) if $$UUID_VIA; |
|
43
|
|
|
|
|
98
|
|
298
|
|
|
|
|
|
|
|
299
|
6019
|
100
|
|
|
|
14006
|
if ($self->{+_PRE_FILTERS}) { |
300
|
3798
|
|
|
|
|
5298
|
for (@{$self->{+_PRE_FILTERS}}) { |
|
3798
|
|
|
|
|
8718
|
|
301
|
5279
|
|
|
|
|
16849
|
$e = $_->{code}->($self, $e); |
302
|
5279
|
100
|
|
|
|
13483
|
return unless $e; |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
6016
|
|
100
|
|
|
21214
|
my $ipc = $self->{+IPC} || return $self->process($e); |
307
|
|
|
|
|
|
|
|
308
|
692
|
100
|
|
|
|
2432
|
if($e->global) { |
309
|
1
|
|
|
|
|
7
|
$ipc->send($self->{+HID}, $e, 'GLOBAL'); |
310
|
1
|
|
|
|
|
6
|
return $self->process($e); |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
return $ipc->send($self->{+HID}, $e) |
314
|
691
|
100
|
66
|
|
|
3449
|
if $$ != $self->{+PID} || get_tid() != $self->{+TID}; |
315
|
|
|
|
|
|
|
|
316
|
681
|
|
|
|
|
1795
|
$self->process($e); |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub process { |
320
|
6074
|
|
|
6074
|
1
|
9849
|
my $self = shift; |
321
|
6074
|
|
|
|
|
11421
|
my ($e) = @_; |
322
|
|
|
|
|
|
|
|
323
|
6074
|
100
|
|
|
|
13086
|
if ($self->{+_FILTERS}) { |
324
|
18
|
|
|
|
|
31
|
for (@{$self->{+_FILTERS}}) { |
|
18
|
|
|
|
|
58
|
|
325
|
17
|
|
|
|
|
70
|
$e = $_->{code}->($self, $e); |
326
|
17
|
100
|
|
|
|
146
|
return unless $e; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# Optimize the most common case |
331
|
6065
|
|
|
|
|
12221
|
my $type = ref($e); |
332
|
6065
|
100
|
100
|
|
|
24862
|
if ($type eq 'Test2::Event::Pass' || ($type eq 'Test2::Event::Ok' && $e->{pass})) { |
|
|
|
100
|
|
|
|
|
333
|
3573
|
|
|
|
|
6892
|
my $count = ++($self->{+COUNT}); |
334
|
3573
|
100
|
|
|
|
19162
|
$self->{+_FORMATTER}->write($e, $count) if $self->{+_FORMATTER}; |
335
|
|
|
|
|
|
|
|
336
|
3573
|
100
|
|
|
|
10251
|
if ($self->{+_LISTENERS}) { |
337
|
826
|
|
|
|
|
1299
|
$_->{code}->($self, $e, $count) for @{$self->{+_LISTENERS}}; |
|
826
|
|
|
|
|
3439
|
|
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
3573
|
|
|
|
|
11099
|
return $e; |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
2492
|
|
|
|
|
8076
|
my $f = $e->facet_data; |
344
|
|
|
|
|
|
|
|
345
|
2492
|
|
|
|
|
4309
|
my $fail = 0; |
346
|
2492
|
100
|
100
|
|
|
8277
|
$fail = 1 if $f->{assert} && !$f->{assert}->{pass}; |
347
|
2492
|
100
|
100
|
|
|
6468
|
$fail = 1 if $f->{errors} && grep { $_->{fail} } @{$f->{errors}}; |
|
8
|
|
|
|
|
29
|
|
|
6
|
|
|
|
|
19
|
|
348
|
2492
|
100
|
|
|
|
5499
|
$fail = 0 if $f->{amnesty}; |
349
|
|
|
|
|
|
|
|
350
|
2492
|
100
|
|
|
|
5571
|
$self->{+COUNT}++ if $f->{assert}; |
351
|
2492
|
100
|
100
|
|
|
6024
|
$self->{+FAILED}++ if $fail && $f->{assert}; |
352
|
2492
|
100
|
|
|
|
5246
|
$self->{+_PASSING} = 0 if $fail; |
353
|
|
|
|
|
|
|
|
354
|
2492
|
100
|
|
|
|
6270
|
my $code = $f->{control} ? $f->{control}->{terminate} : undef; |
355
|
2492
|
|
|
|
|
4146
|
my $count = $self->{+COUNT}; |
356
|
|
|
|
|
|
|
|
357
|
2492
|
100
|
|
|
|
5853
|
if (my $plan = $f->{plan}) { |
358
|
550
|
100
|
|
|
|
2688
|
if ($plan->{skip}) { |
|
|
100
|
|
|
|
|
|
359
|
24
|
|
|
|
|
132
|
$self->plan('SKIP'); |
360
|
24
|
|
100
|
|
|
205
|
$self->set_skip_reason($plan->{details} || 1); |
361
|
24
|
|
50
|
|
|
160
|
$code ||= 0; |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
elsif ($plan->{none}) { |
364
|
1
|
|
|
|
|
5
|
$self->plan('NO PLAN'); |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
else { |
367
|
525
|
|
|
|
|
2254
|
$self->plan($plan->{count}); |
368
|
|
|
|
|
|
|
} |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
|
371
|
2492
|
50
|
66
|
|
|
8037
|
$e->callback($self) if $f->{control} && $f->{control}->{has_callback}; |
372
|
|
|
|
|
|
|
|
373
|
2492
|
100
|
|
|
|
12133
|
$self->{+_FORMATTER}->write($e, $count, $f) if $self->{+_FORMATTER}; |
374
|
|
|
|
|
|
|
|
375
|
2492
|
100
|
|
|
|
7002
|
if ($self->{+_LISTENERS}) { |
376
|
773
|
|
|
|
|
1394
|
$_->{code}->($self, $e, $count, $f) for @{$self->{+_LISTENERS}}; |
|
773
|
|
|
|
|
3275
|
|
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
2492
|
100
|
100
|
|
|
10893
|
if ($f->{control} && $f->{control}->{halt}) { |
380
|
11
|
|
100
|
|
|
44
|
$code ||= 255; |
381
|
11
|
|
|
|
|
61
|
$self->set_bailed_out($e); |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
|
384
|
2492
|
100
|
|
|
|
5922
|
if (defined $code) { |
385
|
35
|
100
|
|
|
|
400
|
$self->{+_FORMATTER}->terminate($e, $f) if $self->{+_FORMATTER}; |
386
|
35
|
|
|
|
|
181
|
$self->terminate($code, $e, $f); |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
2462
|
|
|
|
|
24987
|
return $e; |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
sub terminate { |
393
|
15
|
|
|
15
|
0
|
44
|
my $self = shift; |
394
|
15
|
|
|
|
|
43
|
my ($code) = @_; |
395
|
15
|
|
|
|
|
270
|
exit($code); |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub cull { |
399
|
1223
|
|
|
1223
|
1
|
2404
|
my $self = shift; |
400
|
|
|
|
|
|
|
|
401
|
1223
|
|
100
|
|
|
3674
|
my $ipc = $self->{+IPC} || return; |
402
|
744
|
100
|
66
|
|
|
3629
|
return if $self->{+PID} != $$ || $self->{+TID} != get_tid(); |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# No need to do IPC checks on culled events |
405
|
737
|
|
|
|
|
2533
|
$self->process($_) for $ipc->cull($self->{+HID}); |
406
|
|
|
|
|
|
|
} |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
sub finalize { |
409
|
469
|
|
|
469
|
0
|
1166
|
my $self = shift; |
410
|
469
|
|
|
|
|
1235
|
my ($trace, $do_plan) = @_; |
411
|
|
|
|
|
|
|
|
412
|
469
|
|
|
|
|
2248
|
$self->cull(); |
413
|
|
|
|
|
|
|
|
414
|
469
|
|
|
|
|
1173
|
my $plan = $self->{+_PLAN}; |
415
|
469
|
|
|
|
|
1247
|
my $count = $self->{+COUNT}; |
416
|
469
|
|
|
|
|
1152
|
my $failed = $self->{+FAILED}; |
417
|
469
|
|
|
|
|
993
|
my $active = $self->{+ACTIVE}; |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
# return if NOTHING was done. |
420
|
469
|
100
|
66
|
|
|
4068
|
unless ($active || $do_plan || defined($plan) || $count || $failed) { |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
421
|
12
|
50
|
|
|
|
118
|
$self->{+_FORMATTER}->finalize($plan, $count, $failed, 0, $self->is_subtest) if $self->{+_FORMATTER}; |
422
|
12
|
|
|
|
|
37
|
return; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
457
|
100
|
|
|
|
1788
|
unless ($self->{+ENDED}) { |
426
|
454
|
100
|
|
|
|
1646
|
if ($self->{+_FOLLOW_UPS}) { |
427
|
2
|
|
|
|
|
4
|
$_->($trace, $self) for reverse @{$self->{+_FOLLOW_UPS}}; |
|
2
|
|
|
|
|
12
|
|
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
# These need to be refreshed now |
431
|
454
|
|
|
|
|
1210
|
$plan = $self->{+_PLAN}; |
432
|
454
|
|
|
|
|
1006
|
$count = $self->{+COUNT}; |
433
|
454
|
|
|
|
|
928
|
$failed = $self->{+FAILED}; |
434
|
|
|
|
|
|
|
|
435
|
454
|
100
|
100
|
|
|
4070
|
if (($plan && $plan eq 'NO PLAN') || ($do_plan && !$plan)) { |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
436
|
313
|
|
|
|
|
2590
|
$self->send( |
437
|
|
|
|
|
|
|
Test2::Event::Plan->new( |
438
|
|
|
|
|
|
|
trace => $trace, |
439
|
|
|
|
|
|
|
max => $count, |
440
|
|
|
|
|
|
|
) |
441
|
|
|
|
|
|
|
); |
442
|
|
|
|
|
|
|
} |
443
|
454
|
|
|
|
|
2071
|
$plan = $self->{+_PLAN}; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
457
|
|
|
|
|
2183
|
my $frame = $trace->frame; |
447
|
457
|
100
|
|
|
|
1665
|
if($self->{+ENDED}) { |
448
|
3
|
|
|
|
|
8
|
my (undef, $ffile, $fline) = @{$self->{+ENDED}}; |
|
3
|
|
|
|
|
12
|
|
449
|
3
|
|
|
|
|
11
|
my (undef, $sfile, $sline) = @$frame; |
450
|
|
|
|
|
|
|
|
451
|
3
|
|
|
|
|
27
|
die <<" EOT" |
452
|
|
|
|
|
|
|
Test already ended! |
453
|
|
|
|
|
|
|
First End: $ffile line $fline |
454
|
|
|
|
|
|
|
Second End: $sfile line $sline |
455
|
|
|
|
|
|
|
EOT |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
|
458
|
454
|
|
|
|
|
1371
|
$self->{+ENDED} = $frame; |
459
|
454
|
|
|
|
|
1882
|
my $pass = $self->is_passing(); # Generate the final boolean. |
460
|
|
|
|
|
|
|
|
461
|
454
|
100
|
|
|
|
2718
|
$self->{+_FORMATTER}->finalize($plan, $count, $failed, $pass, $self->is_subtest) if $self->{+_FORMATTER}; |
462
|
|
|
|
|
|
|
|
463
|
454
|
|
|
|
|
1424
|
return $pass; |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
sub is_passing { |
467
|
2198
|
|
|
2198
|
1
|
4021
|
my $self = shift; |
468
|
|
|
|
|
|
|
|
469
|
2198
|
100
|
|
|
|
5035
|
($self->{+_PASSING}) = @_ if @_; |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
# If we already failed just return 0. |
472
|
2198
|
100
|
|
|
|
5797
|
my $pass = $self->{+_PASSING} or return 0; |
473
|
1773
|
100
|
|
|
|
4005
|
return $self->{+_PASSING} = 0 if $self->{+FAILED}; |
474
|
|
|
|
|
|
|
|
475
|
1766
|
|
|
|
|
2918
|
my $count = $self->{+COUNT}; |
476
|
1766
|
|
|
|
|
2781
|
my $ended = $self->{+ENDED}; |
477
|
1766
|
|
|
|
|
2905
|
my $plan = $self->{+_PLAN}; |
478
|
|
|
|
|
|
|
|
479
|
1766
|
100
|
100
|
|
|
6310
|
return $pass if !$count && $plan && $plan =~ m/^SKIP$/; |
|
|
|
100
|
|
|
|
|
480
|
|
|
|
|
|
|
|
481
|
1725
|
100
|
100
|
|
|
7122
|
return $self->{+_PASSING} = 0 |
|
|
|
100
|
|
|
|
|
482
|
|
|
|
|
|
|
if $ended && (!$count || !$plan); |
483
|
|
|
|
|
|
|
|
484
|
1696
|
100
|
100
|
|
|
10465
|
return $pass unless $plan && $plan =~ m/^\d+$/; |
485
|
|
|
|
|
|
|
|
486
|
1550
|
100
|
|
|
|
3675
|
if ($ended) { |
487
|
872
|
100
|
|
|
|
2292
|
return $self->{+_PASSING} = 0 if $count != $plan; |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
else { |
490
|
678
|
100
|
|
|
|
1255
|
return $self->{+_PASSING} = 0 if $count > $plan; |
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
|
493
|
1546
|
|
|
|
|
5118
|
return $pass; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
sub plan { |
497
|
1967
|
|
|
1967
|
1
|
3638
|
my $self = shift; |
498
|
|
|
|
|
|
|
|
499
|
1967
|
100
|
|
|
|
7603
|
return $self->{+_PLAN} unless @_; |
500
|
|
|
|
|
|
|
|
501
|
582
|
|
|
|
|
1584
|
my ($plan) = @_; |
502
|
|
|
|
|
|
|
|
503
|
582
|
50
|
|
|
|
1767
|
confess "You cannot unset the plan" |
504
|
|
|
|
|
|
|
unless defined $plan; |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
confess "You cannot change the plan" |
507
|
582
|
100
|
100
|
|
|
2716
|
if $self->{+_PLAN} && $self->{+_PLAN} !~ m/^NO PLAN$/; |
508
|
|
|
|
|
|
|
|
509
|
581
|
100
|
|
|
|
4401
|
confess "'$plan' is not a valid plan! Plan must be an integer greater than 0, 'NO PLAN', or 'SKIP'" |
510
|
|
|
|
|
|
|
unless $plan =~ m/^(\d+|NO PLAN|SKIP)$/; |
511
|
|
|
|
|
|
|
|
512
|
580
|
|
|
|
|
1945
|
$self->{+_PLAN} = $plan; |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
sub check_plan { |
516
|
124
|
|
|
124
|
1
|
260
|
my $self = shift; |
517
|
|
|
|
|
|
|
|
518
|
124
|
50
|
|
|
|
363
|
return undef unless $self->{+ENDED}; |
519
|
124
|
|
100
|
|
|
361
|
my $plan = $self->{+_PLAN} || return undef; |
520
|
|
|
|
|
|
|
|
521
|
115
|
50
|
|
|
|
633
|
return 1 if $plan !~ m/^\d+$/; |
522
|
|
|
|
|
|
|
|
523
|
115
|
100
|
|
|
|
512
|
return 1 if $plan == $self->{+COUNT}; |
524
|
1
|
|
|
|
|
4
|
return 0; |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
sub DESTROY { |
528
|
465
|
|
|
465
|
|
1891
|
my $self = shift; |
529
|
465
|
|
100
|
|
|
15462
|
my $ipc = $self->{+IPC} || return; |
530
|
51
|
100
|
|
|
|
312
|
return unless $$ == $self->{+PID}; |
531
|
50
|
50
|
|
|
|
153
|
return unless get_tid() == $self->{+TID}; |
532
|
50
|
|
|
|
|
269
|
$ipc->drop_hub($self->{+HID}); |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
1; |
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
__END__ |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
=pod |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
=encoding UTF-8 |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
=head1 NAME |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
Test2::Hub - The conduit through which all events flow. |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
=head1 SYNOPSIS |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
use Test2::Hub; |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
my $hub = Test2::Hub->new(); |
552
|
|
|
|
|
|
|
$hub->send(...); |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
=head1 DESCRIPTION |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
The hub is the place where all events get processed and handed off to the |
557
|
|
|
|
|
|
|
formatter. The hub also tracks test state, and provides several hooks into the |
558
|
|
|
|
|
|
|
event pipeline. |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
=head1 COMMON TASKS |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
=head2 SENDING EVENTS |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
$hub->send($event) |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
The C<send()> method is used to issue an event to the hub. This method will |
567
|
|
|
|
|
|
|
handle thread/fork sync, filters, listeners, TAP output, etc. |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
=head2 ALTERING OR REMOVING EVENTS |
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
You can use either C<filter()> or C<pre_filter()>, depending on your |
572
|
|
|
|
|
|
|
needs. Both have identical syntax, so only C<filter()> is shown here. |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
$hub->filter(sub { |
575
|
|
|
|
|
|
|
my ($hub, $event) = @_; |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
my $action = get_action($event); |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
# No action should be taken |
580
|
|
|
|
|
|
|
return $event if $action eq 'none'; |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
# You want your filter to remove the event |
583
|
|
|
|
|
|
|
return undef if $action eq 'delete'; |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
if ($action eq 'do_it') { |
586
|
|
|
|
|
|
|
my $new_event = copy_event($event); |
587
|
|
|
|
|
|
|
... Change your copy of the event ... |
588
|
|
|
|
|
|
|
return $new_event; |
589
|
|
|
|
|
|
|
} |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
die "Should not happen"; |
592
|
|
|
|
|
|
|
}); |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
By default, filters are not inherited by child hubs. That means if you start a |
595
|
|
|
|
|
|
|
subtest, the subtest will not inherit the filter. You can change this behavior |
596
|
|
|
|
|
|
|
with the C<inherit> parameter: |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
$hub->filter(sub { ... }, inherit => 1); |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
=head2 LISTENING FOR EVENTS |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
$hub->listen(sub { |
603
|
|
|
|
|
|
|
my ($hub, $event, $number) = @_; |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
... do whatever you want with the event ... |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
# return is ignored |
608
|
|
|
|
|
|
|
}); |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
By default listeners are not inherited by child hubs. That means if you start a |
611
|
|
|
|
|
|
|
subtest, the subtest will not inherit the listener. You can change this behavior |
612
|
|
|
|
|
|
|
with the C<inherit> parameter: |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
$hub->listen(sub { ... }, inherit => 1); |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
=head2 POST-TEST BEHAVIORS |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
$hub->follow_up(sub { |
620
|
|
|
|
|
|
|
my ($trace, $hub) = @_; |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
... do whatever you need to ... |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
# Return is ignored |
625
|
|
|
|
|
|
|
}); |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
follow_up subs are called only once, either when done_testing is called, or in |
628
|
|
|
|
|
|
|
an END block. |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
=head2 SETTING THE FORMATTER |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
By default an instance of L<Test2::Formatter::TAP> is created and used. |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
my $old = $hub->format(My::Formatter->new); |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
Setting the formatter will REPLACE any existing formatter. You may set the |
637
|
|
|
|
|
|
|
formatter to undef to prevent output. The old formatter will be returned if one |
638
|
|
|
|
|
|
|
was already set. Only one formatter is allowed at a time. |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
=head1 METHODS |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
=over 4 |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
=item $hub->send($event) |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
This is where all events enter the hub for processing. |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
=item $hub->process($event) |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
This is called by send after it does any IPC handling. You can use this to |
651
|
|
|
|
|
|
|
bypass the IPC process, but in general you should avoid using this. |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
=item $old = $hub->format($formatter) |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
Replace the existing formatter instance with a new one. Formatters must be |
656
|
|
|
|
|
|
|
objects that implement a C<< $formatter->write($event) >> method. |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
=item $sub = $hub->listen(sub { ... }, %optional_params) |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
You can use this to record all events AFTER they have been sent to the |
661
|
|
|
|
|
|
|
formatter. No changes made here will be meaningful, except possibly to other |
662
|
|
|
|
|
|
|
listeners. |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
$hub->listen(sub { |
665
|
|
|
|
|
|
|
my ($hub, $event, $number) = @_; |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
... do whatever you want with the event ... |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
# return is ignored |
670
|
|
|
|
|
|
|
}); |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
Normally listeners are not inherited by child hubs such as subtests. You can |
673
|
|
|
|
|
|
|
add the C<< inherit => 1 >> parameter to allow a listener to be inherited. |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
=item $hub->unlisten($sub) |
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
You can use this to remove a listen callback. You must pass in the coderef |
678
|
|
|
|
|
|
|
returned by the C<listen()> method. |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
=item $sub = $hub->filter(sub { ... }, %optional_params) |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
=item $sub = $hub->pre_filter(sub { ... }, %optional_params) |
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
These can be used to add filters. Filters can modify, replace, or remove events |
685
|
|
|
|
|
|
|
before anything else can see them. |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
$hub->filter( |
688
|
|
|
|
|
|
|
sub { |
689
|
|
|
|
|
|
|
my ($hub, $event) = @_; |
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
return $event; # No Changes |
692
|
|
|
|
|
|
|
return; # Remove the event |
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
# Or you can modify an event before returning it. |
695
|
|
|
|
|
|
|
$event->modify; |
696
|
|
|
|
|
|
|
return $event; |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
); |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
If you are not using threads, forking, or IPC then the only difference between |
701
|
|
|
|
|
|
|
a C<filter> and a C<pre_filter> is that C<pre_filter> subs run first. When you |
702
|
|
|
|
|
|
|
are using threads, forking, or IPC, pre_filters happen to events before they |
703
|
|
|
|
|
|
|
are sent to their destination proc/thread, ordinary filters happen only in the |
704
|
|
|
|
|
|
|
destination hub/thread. |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
You cannot add a regular filter to a hub if the hub was created in another |
707
|
|
|
|
|
|
|
process or thread. You can always add a pre_filter. |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
=item $hub->unfilter($sub) |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
=item $hub->pre_unfilter($sub) |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
These can be used to remove filters and pre_filters. The C<$sub> argument is |
714
|
|
|
|
|
|
|
the reference returned by C<filter()> or C<pre_filter()>. |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
=item $hub->follow_op(sub { ... }) |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
Use this to add behaviors that are called just before the hub is finalized. The |
719
|
|
|
|
|
|
|
only argument to your codeblock will be a L<Test2::EventFacet::Trace> instance. |
720
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
$hub->follow_up(sub { |
722
|
|
|
|
|
|
|
my ($trace, $hub) = @_; |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
... do whatever you need to ... |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
# Return is ignored |
727
|
|
|
|
|
|
|
}); |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
follow_up subs are called only once, ether when done_testing is called, or in |
730
|
|
|
|
|
|
|
an END block. |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
=item $sub = $hub->add_context_acquire(sub { ... }); |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
Add a callback that will be called every time someone tries to acquire a |
735
|
|
|
|
|
|
|
context. It gets a single argument, a reference of the hash of parameters |
736
|
|
|
|
|
|
|
being used the construct the context. This is your chance to change the |
737
|
|
|
|
|
|
|
parameters by directly altering the hash. |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
test2_add_callback_context_acquire(sub { |
740
|
|
|
|
|
|
|
my $params = shift; |
741
|
|
|
|
|
|
|
$params->{level}++; |
742
|
|
|
|
|
|
|
}); |
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
This is a very scary API function. Please do not use this unless you need to. |
745
|
|
|
|
|
|
|
This is here for L<Test::Builder> and backwards compatibility. This has you |
746
|
|
|
|
|
|
|
directly manipulate the hash instead of returning a new one for performance |
747
|
|
|
|
|
|
|
reasons. |
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
B<Note> Using this hook could have a huge performance impact. |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
The coderef you provide is returned and can be used to remove the hook later. |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
=item $hub->remove_context_acquire($sub); |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
This can be used to remove a context acquire hook. |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
=item $sub = $hub->add_context_init(sub { ... }); |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
This allows you to add callbacks that will trigger every time a new context is |
760
|
|
|
|
|
|
|
created for the hub. The only argument to the sub will be the |
761
|
|
|
|
|
|
|
L<Test2::API::Context> instance that was created. |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
B<Note> Using this hook could have a huge performance impact. |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
The coderef you provide is returned and can be used to remove the hook later. |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
=item $hub->remove_context_init($sub); |
768
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
This can be used to remove a context init hook. |
770
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
=item $sub = $hub->add_context_release(sub { ... }); |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
This allows you to add callbacks that will trigger every time a context for |
774
|
|
|
|
|
|
|
this hub is released. The only argument to the sub will be the |
775
|
|
|
|
|
|
|
L<Test2::API::Context> instance that was released. These will run in reverse |
776
|
|
|
|
|
|
|
order. |
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
B<Note> Using this hook could have a huge performance impact. |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
The coderef you provide is returned and can be used to remove the hook later. |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
=item $hub->remove_context_release($sub); |
783
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
This can be used to remove a context release hook. |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
=item $hub->cull() |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
Cull any IPC events (and process them). |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
=item $pid = $hub->pid() |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
Get the process id under which the hub was created. |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
=item $tid = $hub->tid() |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
Get the thread id under which the hub was created. |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
=item $hud = $hub->hid() |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
Get the identifier string of the hub. |
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
=item $uuid = $hub->uuid() |
803
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
If UUID tagging is enabled (see L<Test2::API>) then the hub will have a UUID. |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
=item $ipc = $hub->ipc() |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
Get the IPC object used by the hub. |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
=item $hub->set_no_ending($bool) |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
=item $bool = $hub->no_ending |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
This can be used to disable auto-ending behavior for a hub. The auto-ending |
815
|
|
|
|
|
|
|
behavior is triggered by an end block and is used to cull IPC events, and |
816
|
|
|
|
|
|
|
output the final plan if the plan was 'NO PLAN'. |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
=item $bool = $hub->active |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
=item $hub->set_active($bool) |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
These are used to get/set the 'active' attribute. When true this attribute will |
823
|
|
|
|
|
|
|
force C<< hub->finalize() >> to take action even if there is no plan, and no |
824
|
|
|
|
|
|
|
tests have been run. This flag is useful for plugins that add follow-up |
825
|
|
|
|
|
|
|
behaviors that need to run even if no events are seen. |
826
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
=back |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
=head2 STATE METHODS |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
=over 4 |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
=item $hub->reset_state() |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
Reset all state to the start. This sets the test count to 0, clears the plan, |
836
|
|
|
|
|
|
|
removes the failures, etc. |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
=item $num = $hub->count |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
Get the number of tests that have been run. |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
=item $num = $hub->failed |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
Get the number of failures (Not all failures come from a test fail, so this |
845
|
|
|
|
|
|
|
number can be larger than the count). |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
=item $bool = $hub->ended |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
True if the testing has ended. This MAY return the stack frame of the tool that |
850
|
|
|
|
|
|
|
ended the test, but that is not guaranteed. |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
=item $bool = $hub->is_passing |
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
=item $hub->is_passing($bool) |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
Check if the overall test run is a failure. Can also be used to set the |
857
|
|
|
|
|
|
|
pass/fail status. |
858
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
=item $hub->plan($plan) |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
=item $plan = $hub->plan |
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
Get or set the plan. The plan must be an integer larger than 0, the string |
864
|
|
|
|
|
|
|
'NO PLAN', or the string 'SKIP'. |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
=item $bool = $hub->check_plan |
867
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
Check if the plan and counts match, but only if the tests have ended. If tests |
869
|
|
|
|
|
|
|
have not ended this will return undef, otherwise it will be a true/false. |
870
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
=back |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
=head1 THIRD PARTY META-DATA |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
This object consumes L<Test2::Util::ExternalMeta> which provides a consistent |
876
|
|
|
|
|
|
|
way for you to attach meta-data to instances of this class. This is useful for |
877
|
|
|
|
|
|
|
tools, plugins, and other extensions. |
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
=head1 SOURCE |
880
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
The source code repository for Test2 can be found at |
882
|
|
|
|
|
|
|
F<http://github.com/Test-More/test-more/>. |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
=head1 MAINTAINERS |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
=over 4 |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
=item Chad Granum E<lt>exodist@cpan.orgE<gt> |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
=back |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
=head1 AUTHORS |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
=over 4 |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
=item Chad Granum E<lt>exodist@cpan.orgE<gt> |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
=back |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
=head1 COPYRIGHT |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>. |
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or |
905
|
|
|
|
|
|
|
modify it under the same terms as Perl itself. |
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
See F<http://dev.perl.org/licenses/> |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
=cut |