File Coverage

blib/lib/Test2/Event.pm
Criterion Covered Total %
statement 189 200 94.5
branch 87 106 82.0
condition 39 48 81.2
subroutine 39 41 95.1
pod 20 23 86.9
total 374 418 89.4


line stmt bran cond sub pod time code
1             package Test2::Event;
2 246     246   2123 use strict;
  246         484  
  246         7137  
3 246     246   1249 use warnings;
  246         918  
  246         10738  
4              
5             our $VERSION = '1.302180';
6              
7 246     246   1555 use Scalar::Util qw/blessed reftype/;
  246         549  
  246         14461  
8 246     246   1644 use Carp qw/croak/;
  246         519  
  246         13727  
9              
10 246     246   1743 use Test2::Util::HashBase qw/trace -amnesty uuid -_eid -hubs/;
  246         724  
  246         1711  
11 246     246   2214 use Test2::Util::ExternalMeta qw/meta get_meta set_meta delete_meta/;
  246         567  
  246         15844  
12 246     246   7148 use Test2::Util qw/pkg_to_file gen_uid/;
  246         643  
  246         11373  
13              
14 246     246   101531 use Test2::EventFacet::About();
  246         5043  
  246         7102  
15 246     246   96455 use Test2::EventFacet::Amnesty();
  246         675  
  246         4761  
16 246     246   96440 use Test2::EventFacet::Assert();
  246         703  
  246         4982  
17 246     246   98213 use Test2::EventFacet::Control();
  246         662  
  246         4931  
18 246     246   96993 use Test2::EventFacet::Error();
  246         651  
  246         4877  
19 246     246   97121 use Test2::EventFacet::Info();
  246         632  
  246         4722  
20 246     246   98117 use Test2::EventFacet::Meta();
  246         630  
  246         4821  
21 246     246   98769 use Test2::EventFacet::Parent();
  246         683  
  246         5061  
22 246     246   99116 use Test2::EventFacet::Plan();
  246         631  
  246         4788  
23 246     246   1913 use Test2::EventFacet::Trace();
  246         475  
  246         3256  
24 246     246   96934 use Test2::EventFacet::Hub();
  246         679  
  246         460946  
25              
26             # Legacy tools will expect this to be loaded now
27             require Test2::Util::Trace;
28              
29             my %LOADED_FACETS = (
30             'about' => 'Test2::EventFacet::About',
31             'amnesty' => 'Test2::EventFacet::Amnesty',
32             'assert' => 'Test2::EventFacet::Assert',
33             'control' => 'Test2::EventFacet::Control',
34             'errors' => 'Test2::EventFacet::Error',
35             'info' => 'Test2::EventFacet::Info',
36             'meta' => 'Test2::EventFacet::Meta',
37             'parent' => 'Test2::EventFacet::Parent',
38             'plan' => 'Test2::EventFacet::Plan',
39             'trace' => 'Test2::EventFacet::Trace',
40             'hubs' => 'Test2::EventFacet::Hub',
41             );
42              
43 0     0 1 0 sub FACET_TYPES { sort values %LOADED_FACETS }
44              
45             sub load_facet {
46 242     242 1 354 my $class = shift;
47 242         385 my ($facet) = @_;
48              
49 242 100       607 return $LOADED_FACETS{$facet} if exists $LOADED_FACETS{$facet};
50              
51 6         14 my @check = ($facet);
52 6 50       17 if ('s' eq substr($facet, -1, 1)) {
53 0         0 push @check => substr($facet, 0, -1);
54             }
55             else {
56 6         17 push @check => $facet . 's';
57             }
58              
59 6         10 my $found;
60 6         11 for my $check (@check) {
61 12         44 my $mod = "Test2::EventFacet::" . ucfirst($facet);
62 12         38 my $file = pkg_to_file($mod);
63 12 50       22 next unless eval { require $file; 1 };
  12         1810  
  0         0  
64 0         0 $found = $mod;
65 0         0 last;
66             }
67              
68 6 50       32 return undef unless $found;
69 0         0 $LOADED_FACETS{$facet} = $found;
70             }
71              
72 13     13 1 40 sub causes_fail { 0 }
73 14     14 1 39 sub increments_count { 0 }
74 1     1 1 5 sub diagnostics { 0 }
75 13     13 1 85 sub no_display { 0 }
76 31     31 1 67 sub subtest_id { undef }
77              
78       0 1   sub callback { }
79              
80 929     929 1 5319 sub terminate { () }
81 95     95 1 406 sub global { () }
82 13     13 1 35 sub sets_plan { () }
83              
84 46     46 1 206 sub summary { ref($_[0]) }
85              
86             sub related {
87 9     9 1 49 my $self = shift;
88 9         18 my ($event) = @_;
89              
90 9 100       27 my $tracea = $self->trace or return undef;
91 8 50       19 my $traceb = $event->trace or return undef;
92              
93 8         21 my $uuida = $tracea->uuid;
94 8         17 my $uuidb = $traceb->uuid;
95 8 100 66     27 if ($uuida && $uuidb) {
96 2 100       9 return 1 if $uuida eq $uuidb;
97 1         5 return 0;
98             }
99              
100 6 100       132 my $siga = $tracea->signature or return undef;
101 4 50       15 my $sigb = $traceb->signature or return undef;
102              
103 4 100       28 return 1 if $siga eq $sigb;
104 2         12 return 0;
105             }
106              
107             sub add_hub {
108 6015     6015 0 9999 my $self = shift;
109 6015         8914 unshift @{$self->{+HUBS}} => @_;
  6015         21705  
110             }
111              
112             sub add_amnesty {
113 308     308 1 478 my $self = shift;
114              
115 308         593 for my $am (@_) {
116 308 50       1482 $am = {%$am} if ref($am) ne 'ARRAY';
117 308         1081 $am = Test2::EventFacet::Amnesty->new($am);
118              
119 308         468 push @{$self->{+AMNESTY}} => $am;
  308         1008  
120             }
121             }
122              
123 7222   66 7222 0 33095 sub eid { $_[0]->{+_EID} ||= gen_uid() }
124              
125             sub common_facet_data {
126 6556     6556 1 9422 my $self = shift;
127              
128 6556         9298 my %out;
129              
130 6556   50     22132 $out{about} = {package => ref($self) || undef};
131 6556 100       18471 if (my $uuid = $self->uuid) {
132 16         30 $out{about}->{uuid} = $uuid;
133             }
134              
135 6556   66     18428 $out{about}->{eid} = $self->{+_EID} || $self->eid;
136              
137 6556 100       15839 if (my $trace = $self->trace) {
138 6543         41291 $out{trace} = { %$trace };
139             }
140              
141 6556 100       20273 if (my $hubs = $self->hubs) {
142 5350         8771 $out{hubs} = $hubs;
143             }
144              
145 504         664 $out{amnesty} = [map {{ %{$_} }} @{$self->{+AMNESTY}}]
  504         2045  
  355         763  
146 6556 100       13856 if $self->{+AMNESTY};
147              
148 6556 100       13917 if (my $meta = $self->meta_facet_data) {
149 984         1761 $out{meta} = $meta;
150             }
151              
152 6556         15992 return \%out;
153             }
154              
155             sub meta_facet_data {
156 6801     6801 0 10115 my $self = shift;
157              
158 6801         10625 my $key = Test2::Util::ExternalMeta::META_KEY();
159              
160 6801 100       20825 my $hash = $self->{$key} or return undef;
161 985         3571 return {%$hash};
162             }
163              
164             sub facet_data {
165 32     32 1 59 my $self = shift;
166              
167 32         98 my $out = $self->common_facet_data;
168              
169 32   50     92 $out->{about}->{details} = $self->summary || undef;
170 32   100     83 $out->{about}->{no_display} = $self->no_display || undef;
171              
172             # Might be undef, we want to preserve that
173 32         99 my $terminate = $self->terminate;
174             $out->{control} = {
175 32 100 100     83 global => $self->global || 0,
176             terminate => $terminate,
177             has_callback => $self->can('callback') == \&callback ? 0 : 1,
178             };
179              
180             $out->{assert} = {
181 32 100       108 no_debug => 1, # Legacy behavior
    100          
182             pass => $self->causes_fail ? 0 : 1,
183             details => $self->summary,
184             } if $self->increments_count;
185              
186 32 100       98 $out->{parent} = {hid => $self->subtest_id} if $self->subtest_id;
187              
188 32 100       84 if (my @plan = $self->sets_plan) {
189 4         10 $out->{plan} = {};
190              
191 4 50       15 $out->{plan}->{count} = $plan[0] if defined $plan[0];
192 4 100       11 $out->{plan}->{details} = $plan[2] if defined $plan[2];
193              
194 4 100       11 if ($plan[1]) {
195 3 100       9 $out->{plan}->{skip} = 1 if $plan[1] eq 'SKIP';
196 3 100       10 $out->{plan}->{none} = 1 if $plan[1] eq 'NO PLAN';
197             }
198              
199 4 100 50     14 $out->{control}->{terminate} ||= 0 if $out->{plan}->{skip};
200             }
201              
202 32 100 100     109 if ($self->causes_fail && !$out->{assert}) {
203             $out->{errors} = [
204             {
205 1         9 tag => 'FAIL',
206             fail => 1,
207             details => $self->summary,
208             }
209             ];
210             }
211              
212 31         105 my %IGNORE = (trace => 1, about => 1, control => 1);
213 31         109 my $do_info = !grep { !$IGNORE{$_} } keys %$out;
  126         253  
214              
215 31 100 100     110 if ($do_info && !$self->no_display && $self->diagnostics) {
      100        
216             $out->{info} = [
217             {
218 2         10 tag => 'DIAG',
219             debug => 1,
220             details => $self->summary,
221             }
222             ];
223             }
224              
225 31         162 return $out;
226             }
227              
228             sub facets {
229 23     23 1 97 my $self = shift;
230 23         37 my %out;
231              
232 23         77 my $data = $self->facet_data;
233 23         93 my @errors = $self->validate_facet_data($data);
234 23 50       71 die join "\n" => @errors if @errors;
235              
236 23         67 for my $facet (keys %$data) {
237 112         218 my $class = $self->load_facet($facet);
238 112         270 my $val = $data->{$facet};
239              
240 112 50       212 unless($class) {
241 0         0 $out{$facet} = $val;
242 0         0 next;
243             }
244              
245 112 100       268 my $is_list = reftype($val) eq 'ARRAY' ? 1 : 0;
246 112 100       200 if ($is_list) {
247 34         65 $out{$facet} = [map { $class->new($_) } @$val];
  40         131  
248             }
249             else {
250 78         292 $out{$facet} = $class->new($val);
251             }
252             }
253              
254 23         242 return \%out;
255             }
256              
257             sub validate_facet_data {
258 29     29 1 71 my $class_or_self = shift;
259 29         49 my ($f, %params);
260              
261 29 100 100     202 $f = shift if @_ && (reftype($_[0]) || '') eq 'HASH';
      100        
262 29         64 %params = @_;
263              
264 29 100 66     134 $f ||= $class_or_self->facet_data if blessed($class_or_self);
265 29 50       76 croak "No facet data" unless $f;
266              
267 29         44 my @errors;
268              
269 29         174 for my $k (sort keys %$f) {
270 130         297 my $fclass = $class_or_self->load_facet($k);
271              
272             push @errors => "Could not find a facet class for facet '$k'"
273 130 100 100     300 if $params{require_facet_class} && !$fclass;
274              
275 130 100       238 next unless $fclass;
276              
277 124         174 my $v = $f->{$k};
278 124 50       214 next unless defined($v); # undef is always fine
279              
280 124         623 my $is_list = $fclass->is_list();
281 124 100       307 my $got_list = reftype($v) eq 'ARRAY' ? 1 : 0;
282              
283 124 100 100     346 push @errors => "Facet '$k' should be a list, but got a single item ($v)"
284             if $is_list && !$got_list;
285              
286 124 100 100     348 push @errors => "Facet '$k' should not be a list, but got a a list ($v)"
287             if $got_list && !$is_list;
288             }
289              
290 29         131 return @errors;
291             }
292              
293             sub nested {
294 2     2 1 27 my $self = shift;
295              
296             Carp::cluck("Use of Test2::Event->nested() is deprecated, use Test2::Event->trace->nested instead")
297 2 100       217 if $ENV{AUTHOR_TESTING};
298              
299 2 50       9 if (my $hubs = $self->{+HUBS}) {
300 0 0       0 return $hubs->[0]->{nested} if @$hubs;
301             }
302              
303 2 50       9 my $trace = $self->{+TRACE} or return undef;
304 2         10 return $trace->{nested};
305             }
306              
307             sub in_subtest {
308 2     2 1 5 my $self = shift;
309              
310             Carp::cluck("Use of Test2::Event->in_subtest() is deprecated, use Test2::Event->trace->hid instead")
311 2 100       104 if $ENV{AUTHOR_TESTING};
312              
313 2         5 my $hubs = $self->{+HUBS};
314 2 50 33     10 if ($hubs && @$hubs) {
315 0 0       0 return undef unless $hubs->[0]->{nested};
316             return $hubs->[0]->{hid}
317 0         0 }
318              
319 2 50       8 my $trace = $self->{+TRACE} or return undef;
320 2 100       7 return undef unless $trace->{nested};
321 1         6 return $trace->{hid};
322             }
323              
324             1;
325              
326             __END__