xref: /openbsd-src/gnu/usr.bin/perl/cpan/Test-Simple/lib/Test2/API/InterceptResult/Event.pm (revision 5486feefcc8cb79b19e014ab332cc5dfd05b3b33)
1256a93a4Safresh1package Test2::API::InterceptResult::Event;
2256a93a4Safresh1use strict;
3256a93a4Safresh1use warnings;
4256a93a4Safresh1
5*5486feefSafresh1our $VERSION = '1.302199';
6256a93a4Safresh1
7256a93a4Safresh1use List::Util   qw/first/;
8256a93a4Safresh1use Test2::Util  qw/pkg_to_file/;
9256a93a4Safresh1use Scalar::Util qw/reftype blessed/;
10256a93a4Safresh1
11256a93a4Safresh1use Storable qw/dclone/;
12256a93a4Safresh1use Carp     qw/confess croak/;
13256a93a4Safresh1
14256a93a4Safresh1use Test2::API::InterceptResult::Facet;
15256a93a4Safresh1use Test2::API::InterceptResult::Hub;
16256a93a4Safresh1
17256a93a4Safresh1use Test2::Util::HashBase qw{
18256a93a4Safresh1    +causes_failure
19256a93a4Safresh1    <facet_data
20256a93a4Safresh1    <result_class
21256a93a4Safresh1};
22256a93a4Safresh1
23256a93a4Safresh1my %FACETS;
24256a93a4Safresh1BEGIN {
25256a93a4Safresh1    local $@;
26256a93a4Safresh1    local *plugins;
27256a93a4Safresh1    if (eval { require Module::Pluggable; 1 }) {
28256a93a4Safresh1        Module::Pluggable->import(
29256a93a4Safresh1            # We will replace the sub later
30256a93a4Safresh1            require          => 1,
31256a93a4Safresh1            on_require_error => sub { 1 },
32256a93a4Safresh1            search_path      => ['Test2::EventFacet'],
33256a93a4Safresh1            max_depth        => 3,
34256a93a4Safresh1            min_depth        => 3,
35256a93a4Safresh1        );
36256a93a4Safresh1
37256a93a4Safresh1        for my $facet_type (__PACKAGE__->plugins) {
38256a93a4Safresh1            my ($key, $list);
39256a93a4Safresh1            eval {
40256a93a4Safresh1                $key  = $facet_type->facet_key;
41256a93a4Safresh1                $list = $facet_type->is_list;
42256a93a4Safresh1            };
43256a93a4Safresh1            next unless $key && defined($list);
44256a93a4Safresh1
45256a93a4Safresh1            $FACETS{$key} = {list => $list, class => $facet_type, loaded => 1};
46256a93a4Safresh1        }
47256a93a4Safresh1    }
48256a93a4Safresh1
49256a93a4Safresh1    $FACETS{__GENERIC__} = {class => 'Test2::API::InterceptResult::Facet', loaded => 1};
50256a93a4Safresh1}
51256a93a4Safresh1
52256a93a4Safresh1sub facet_map { \%FACETS }
53256a93a4Safresh1
54256a93a4Safresh1sub facet_info {
55256a93a4Safresh1    my $facet = pop;
56256a93a4Safresh1
57256a93a4Safresh1    return $FACETS{$facet} if exists $FACETS{$facet};
58256a93a4Safresh1
59256a93a4Safresh1    my $mname = ucfirst(lc($facet));
60256a93a4Safresh1    $mname =~ s/s$//;
61256a93a4Safresh1
62256a93a4Safresh1    for my $name ($mname, "${mname}s") {
63256a93a4Safresh1        my $file  = "Test2/EventFacet/$name.pm";
64256a93a4Safresh1        my $class = "Test2::EventFacet::$name";
65256a93a4Safresh1
66256a93a4Safresh1        local $@;
67256a93a4Safresh1        my $ok = eval {
68256a93a4Safresh1            require $file;
69256a93a4Safresh1
70256a93a4Safresh1            my $key = $class->facet_key;
71256a93a4Safresh1            my $list = $class->is_list;
72256a93a4Safresh1
73256a93a4Safresh1            $FACETS{$key} = {list => $list, class => $class, loaded => 1};
74256a93a4Safresh1            $FACETS{$facet} = $FACETS{$key} if $facet ne $key;
75256a93a4Safresh1
76256a93a4Safresh1            1;
77256a93a4Safresh1        };
78256a93a4Safresh1
79256a93a4Safresh1        return $FACETS{$facet} if $ok && $FACETS{$facet};
80256a93a4Safresh1    }
81256a93a4Safresh1
82256a93a4Safresh1    return $FACETS{$facet} = $FACETS{__GENERIC__};
83256a93a4Safresh1}
84256a93a4Safresh1
85256a93a4Safresh1sub init {
86256a93a4Safresh1    my $self = shift;
87256a93a4Safresh1
88256a93a4Safresh1    my $rc = $self->{+RESULT_CLASS} ||= 'Test2::API::InterceptResult';
89256a93a4Safresh1    my $rc_file = pkg_to_file($rc);
90256a93a4Safresh1    require($rc_file) unless $INC{$rc_file};
91256a93a4Safresh1
92256a93a4Safresh1    my $fd = $self->{+FACET_DATA} ||= {};
93256a93a4Safresh1
94256a93a4Safresh1    for my $facet (keys %$fd) {
95256a93a4Safresh1        my $finfo = $self->facet_info($facet);
96256a93a4Safresh1        my $is_list = $finfo->{list};
97256a93a4Safresh1        next unless defined $is_list;
98256a93a4Safresh1
99256a93a4Safresh1        my $type = reftype($fd->{$facet});
100256a93a4Safresh1
101256a93a4Safresh1        if ($is_list) {
102256a93a4Safresh1            confess "Facet '$facet' is a list facet, but got '$type' instead of an arrayref"
103256a93a4Safresh1                unless $type eq 'ARRAY';
104256a93a4Safresh1
105256a93a4Safresh1            for my $item (@{$fd->{$facet}}) {
106256a93a4Safresh1                my $itype = reftype($item);
107256a93a4Safresh1                next if $itype eq 'HASH';
108256a93a4Safresh1
109256a93a4Safresh1                confess "Got item type '$itype' in list-facet '$facet', all items must be hashrefs";
110256a93a4Safresh1            }
111256a93a4Safresh1        }
112256a93a4Safresh1        else {
113256a93a4Safresh1            confess "Facet '$facet' is an only-one facet, but got '$type' instead of a hashref"
114256a93a4Safresh1                unless $type eq 'HASH';
115256a93a4Safresh1        }
116256a93a4Safresh1    }
117256a93a4Safresh1}
118256a93a4Safresh1
119256a93a4Safresh1sub clone {
120256a93a4Safresh1    my $self = shift;
121256a93a4Safresh1    my $class = blessed($self);
122256a93a4Safresh1
123256a93a4Safresh1    my %data = %$self;
124256a93a4Safresh1
125256a93a4Safresh1    $data{+FACET_DATA} = dclone($data{+FACET_DATA});
126256a93a4Safresh1
127256a93a4Safresh1    return bless(\%data, $class);
128256a93a4Safresh1}
129256a93a4Safresh1
130256a93a4Safresh1sub _facet_class {
131256a93a4Safresh1    my $self = shift;
132256a93a4Safresh1    my ($name) = @_;
133256a93a4Safresh1
134256a93a4Safresh1    my $spec  = $self->facet_info($name);
135256a93a4Safresh1    my $class = $spec->{class};
136256a93a4Safresh1    unless ($spec->{loaded}) {
137256a93a4Safresh1        my $file = pkg_to_file($class);
138256a93a4Safresh1        require $file unless $INC{$file};
139256a93a4Safresh1        $spec->{loaded} = 1;
140256a93a4Safresh1    }
141256a93a4Safresh1
142256a93a4Safresh1    return $class;
143256a93a4Safresh1}
144256a93a4Safresh1
145256a93a4Safresh1sub the_facet {
146256a93a4Safresh1    my $self = shift;
147256a93a4Safresh1    my ($name) = @_;
148256a93a4Safresh1
149256a93a4Safresh1    return undef unless defined $self->{+FACET_DATA}->{$name};
150256a93a4Safresh1
151256a93a4Safresh1    my $data = $self->{+FACET_DATA}->{$name};
152256a93a4Safresh1
153256a93a4Safresh1    my $type = reftype($data) or confess "Facet '$name' has a value that is not a reference, this should not happen";
154256a93a4Safresh1
155256a93a4Safresh1    return $self->_facet_class($name)->new(%{dclone($data)})
156256a93a4Safresh1        if $type eq 'HASH';
157256a93a4Safresh1
158256a93a4Safresh1    if ($type eq 'ARRAY') {
159256a93a4Safresh1        return undef unless @$data;
160256a93a4Safresh1        croak "'the_facet' called for facet '$name', but '$name' has '" . @$data . "' items" if @$data != 1;
161256a93a4Safresh1        return $self->_facet_class($name)->new(%{dclone($data->[0])});
162256a93a4Safresh1    }
163256a93a4Safresh1
164256a93a4Safresh1    die "Invalid facet data type: $type";
165256a93a4Safresh1}
166256a93a4Safresh1
167256a93a4Safresh1sub facet {
168256a93a4Safresh1    my $self = shift;
169256a93a4Safresh1    my ($name) = @_;
170256a93a4Safresh1
171256a93a4Safresh1    return () unless exists $self->{+FACET_DATA}->{$name};
172256a93a4Safresh1
173256a93a4Safresh1    my $data = $self->{+FACET_DATA}->{$name};
174256a93a4Safresh1
175256a93a4Safresh1    my $type = reftype($data) or confess "Facet '$name' has a value that is not a reference, this should not happen";
176256a93a4Safresh1
177256a93a4Safresh1    my @out;
178256a93a4Safresh1    @out = ($data)  if $type eq 'HASH';
179256a93a4Safresh1    @out = (@$data) if $type eq 'ARRAY';
180256a93a4Safresh1
181256a93a4Safresh1    my $class = $self->_facet_class($name);
182256a93a4Safresh1
183256a93a4Safresh1    return map { $class->new(%{dclone($_)}) } @out;
184256a93a4Safresh1}
185256a93a4Safresh1
186256a93a4Safresh1sub causes_failure {
187256a93a4Safresh1    my $self = shift;
188256a93a4Safresh1
189256a93a4Safresh1    return $self->{+CAUSES_FAILURE}
190256a93a4Safresh1        if exists $self->{+CAUSES_FAILURE};
191256a93a4Safresh1
192256a93a4Safresh1    my $hub = Test2::API::InterceptResult::Hub->new();
193256a93a4Safresh1    $hub->process($self);
194256a93a4Safresh1
195256a93a4Safresh1    return $self->{+CAUSES_FAILURE} = ($hub->is_passing ? 0 : 1);
196256a93a4Safresh1}
197256a93a4Safresh1
198256a93a4Safresh1sub causes_fail { shift->causes_failure }
199256a93a4Safresh1
200256a93a4Safresh1sub trace         { $_[0]->facet('trace') }
201256a93a4Safresh1sub the_trace     { $_[0]->the_facet('trace') }
202256a93a4Safresh1sub frame         { my $t = $_[0]->the_trace or return undef; $t->{frame}   || undef }
203256a93a4Safresh1sub trace_details { my $t = $_[0]->the_trace or return undef; $t->{details} || undef }
204*5486feefSafresh1sub trace_stamp   { my $f = $_[0]->the_trace or return undef; $f->{stamp}   || undef }
205256a93a4Safresh1sub trace_package { my $f = $_[0]->frame     or return undef; $f->[0]       || undef }
206256a93a4Safresh1sub trace_file    { my $f = $_[0]->frame     or return undef; $f->[1]       || undef }
207256a93a4Safresh1sub trace_line    { my $f = $_[0]->frame     or return undef; $f->[2]       || undef }
208256a93a4Safresh1sub trace_subname { my $f = $_[0]->frame     or return undef; $f->[3]       || undef }
209256a93a4Safresh1sub trace_tool    { my $f = $_[0]->frame     or return undef; $f->[3]       || undef }
210256a93a4Safresh1
211256a93a4Safresh1sub trace_signature { my $t = $_[0]->the_trace or return undef; Test2::EventFacet::Trace::signature($t) || undef }
212256a93a4Safresh1
213256a93a4Safresh1sub brief {
214256a93a4Safresh1    my $self = shift;
215256a93a4Safresh1
216256a93a4Safresh1    my @try = qw{
217256a93a4Safresh1        bailout_brief
218256a93a4Safresh1        error_brief
219256a93a4Safresh1        assert_brief
220256a93a4Safresh1        plan_brief
221256a93a4Safresh1    };
222256a93a4Safresh1
223256a93a4Safresh1    for my $meth (@try) {
224256a93a4Safresh1        my $got = $self->$meth or next;
225256a93a4Safresh1        return $got;
226256a93a4Safresh1    }
227256a93a4Safresh1
228256a93a4Safresh1    return;
229256a93a4Safresh1}
230256a93a4Safresh1
231256a93a4Safresh1sub flatten {
232256a93a4Safresh1    my $self = shift;
233256a93a4Safresh1    my %params = @_;
234256a93a4Safresh1
235256a93a4Safresh1    my $todo = {%{$self->{+FACET_DATA}}};
236256a93a4Safresh1    delete $todo->{hubs};
237256a93a4Safresh1    delete $todo->{meta};
238256a93a4Safresh1    delete $todo->{trace};
239256a93a4Safresh1
240256a93a4Safresh1    my $out = $self->summary;
241256a93a4Safresh1    delete $out->{brief};
242256a93a4Safresh1    delete $out->{facets};
243256a93a4Safresh1    delete $out->{trace_tool};
244256a93a4Safresh1    delete $out->{trace_details} unless defined($out->{trace_details});
245256a93a4Safresh1
246256a93a4Safresh1    for my $tagged (grep { my $finfo = $self->facet_info($_); $finfo->{list} && $finfo->{class}->can('tag') } keys %FACETS, keys %$todo) {
247256a93a4Safresh1        my $set = delete $todo->{$tagged} or next;
248256a93a4Safresh1
249256a93a4Safresh1        my $fd = $self->{+FACET_DATA};
250256a93a4Safresh1        my $has_assert = $self->has_assert;
251256a93a4Safresh1        my $has_parent = $self->has_subtest;
252256a93a4Safresh1        my $has_fatal_error = $self->has_errors && grep { $_->{fail} } $self->errors;
253256a93a4Safresh1
254256a93a4Safresh1        next if $tagged eq 'amnesty' && !($has_assert || $has_parent || $has_fatal_error);
255256a93a4Safresh1
256256a93a4Safresh1        for my $item (@$set) {
257256a93a4Safresh1            push @{$out->{lc($item->{tag})}} => $item->{fail} ? "FATAL: $item->{details}" : $item->{details};
258256a93a4Safresh1        }
259256a93a4Safresh1    }
260256a93a4Safresh1
261256a93a4Safresh1    if (my $assert = delete $todo->{assert}) {
262256a93a4Safresh1        $out->{pass} = $assert->{pass};
263256a93a4Safresh1        $out->{name} = $assert->{details};
264256a93a4Safresh1    }
265256a93a4Safresh1
266256a93a4Safresh1    if (my $parent = delete $todo->{parent}) {
267256a93a4Safresh1        delete $out->{subtest}->{bailed_out}  unless defined $out->{subtest}->{bailed_out};
268256a93a4Safresh1        delete $out->{subtest}->{skip_reason} unless defined $out->{subtest}->{skip_reason};
269256a93a4Safresh1
270256a93a4Safresh1        if (my $res = $self->subtest_result) {
271256a93a4Safresh1            my $state = $res->state;
272256a93a4Safresh1            delete $state->{$_} for grep { !defined($state->{$_}) } keys %$state;
273256a93a4Safresh1            $out->{subtest} = $state;
274256a93a4Safresh1            $out->{subevents} = $res->flatten(%params)
275256a93a4Safresh1                if $params{include_subevents};
276256a93a4Safresh1        }
277256a93a4Safresh1    }
278256a93a4Safresh1
279256a93a4Safresh1    if (my $control = delete $todo->{control}) {
280256a93a4Safresh1        if ($control->{halt}) {
281256a93a4Safresh1            $out->{bailed_out} = $control->{details} || 1;
282256a93a4Safresh1        }
283256a93a4Safresh1        elsif(defined $control->{details}) {
284256a93a4Safresh1            $out->{control} = $control->{details};
285256a93a4Safresh1        }
286256a93a4Safresh1    }
287256a93a4Safresh1
288256a93a4Safresh1    if (my $plan = delete $todo->{plan}) {
289256a93a4Safresh1        $out->{plan} = $self->plan_brief;
290256a93a4Safresh1        $out->{plan} =~ s/^PLAN\s*//;
291256a93a4Safresh1    }
292256a93a4Safresh1
293256a93a4Safresh1    for my $other (keys %$todo) {
294256a93a4Safresh1        my $data = $todo->{$other} or next;
295256a93a4Safresh1
296256a93a4Safresh1        if (reftype($data) eq 'ARRAY') {
297256a93a4Safresh1            if (!$out->{$other} || reftype($out->{$other}) eq 'ARRAY') {
298256a93a4Safresh1                for my $item (@$data) {
299256a93a4Safresh1                    push @{$out->{$other}} => $item->{details} if defined $item->{details};
300256a93a4Safresh1                }
301256a93a4Safresh1            }
302256a93a4Safresh1        }
303256a93a4Safresh1        else {
304256a93a4Safresh1            $out->{$other} = $data->{details} if defined($data->{details}) && !defined($out->{$other});
305256a93a4Safresh1        }
306256a93a4Safresh1    }
307256a93a4Safresh1
308256a93a4Safresh1    if (my $fields = $params{fields}) {
309256a93a4Safresh1        $out = { map {exists($out->{$_}) ? ($_ => $out->{$_}) : ()} @$fields };
310256a93a4Safresh1    }
311256a93a4Safresh1
312256a93a4Safresh1    if (my $remove = $params{remove}) {
313256a93a4Safresh1        delete $out->{$_} for @$remove;
314256a93a4Safresh1    }
315256a93a4Safresh1
316256a93a4Safresh1    return $out;
317256a93a4Safresh1}
318256a93a4Safresh1
319256a93a4Safresh1sub summary {
320256a93a4Safresh1    my $self = shift;
321256a93a4Safresh1    my %params = @_;
322256a93a4Safresh1
323256a93a4Safresh1    my $out = {
324256a93a4Safresh1        brief => $self->brief || '',
325256a93a4Safresh1
326256a93a4Safresh1        causes_failure => $self->causes_failure,
327256a93a4Safresh1
328256a93a4Safresh1        trace_line    => $self->trace_line,
329256a93a4Safresh1        trace_file    => $self->trace_file,
330256a93a4Safresh1        trace_tool    => $self->trace_subname,
331256a93a4Safresh1        trace_details => $self->trace_details,
332256a93a4Safresh1
333256a93a4Safresh1        facets => [ sort keys(%{$self->{+FACET_DATA}}) ],
334256a93a4Safresh1    };
335256a93a4Safresh1
336256a93a4Safresh1    if (my $fields = $params{fields}) {
337256a93a4Safresh1        $out = { map {exists($out->{$_}) ? ($_ => $out->{$_}) : ()} @$fields };
338256a93a4Safresh1    }
339256a93a4Safresh1
340256a93a4Safresh1    if (my $remove = $params{remove}) {
341256a93a4Safresh1        delete $out->{$_} for @$remove;
342256a93a4Safresh1    }
343256a93a4Safresh1
344256a93a4Safresh1    return $out;
345256a93a4Safresh1}
346256a93a4Safresh1
347256a93a4Safresh1sub has_assert { $_[0]->{+FACET_DATA}->{assert} ? 1 : 0 }
348256a93a4Safresh1sub the_assert { $_[0]->the_facet('assert') }
349256a93a4Safresh1sub assert     { $_[0]->facet('assert') }
350256a93a4Safresh1
351256a93a4Safresh1sub assert_brief {
352256a93a4Safresh1    my $self = shift;
353256a93a4Safresh1
354256a93a4Safresh1    my $fd = $self->{+FACET_DATA};
355256a93a4Safresh1    my $as = $fd->{assert} or return;
356256a93a4Safresh1    my $am = $fd->{amnesty};
357256a93a4Safresh1
358256a93a4Safresh1    my $out = $as->{pass} ? "PASS" : "FAIL";
359256a93a4Safresh1    $out .= " with amnesty" if $am;
360256a93a4Safresh1    return $out;
361256a93a4Safresh1}
362256a93a4Safresh1
363256a93a4Safresh1sub has_subtest { $_[0]->{+FACET_DATA}->{parent} ? 1 : 0 }
364256a93a4Safresh1sub the_subtest { $_[0]->the_facet('parent') }
365256a93a4Safresh1sub subtest     { $_[0]->facet('parent') }
366256a93a4Safresh1
367256a93a4Safresh1sub subtest_result {
368256a93a4Safresh1    my $self = shift;
369256a93a4Safresh1
370256a93a4Safresh1    my $parent = $self->{+FACET_DATA}->{parent} or return;
371256a93a4Safresh1    my $children = $parent->{children} || [];
372256a93a4Safresh1
373256a93a4Safresh1    $children = $self->{+RESULT_CLASS}->new(@$children)->upgrade
374256a93a4Safresh1        unless blessed($children) && $children->isa($self->{+RESULT_CLASS});
375256a93a4Safresh1
376256a93a4Safresh1    return $children;
377256a93a4Safresh1}
378256a93a4Safresh1
379256a93a4Safresh1sub has_bailout { $_[0]->bailout ? 1 : 0 }
380256a93a4Safresh1sub the_bailout { my ($b) = $_[0]->bailout; $b }
381256a93a4Safresh1
382256a93a4Safresh1sub bailout {
383256a93a4Safresh1    my $self = shift;
384256a93a4Safresh1    my $control = $self->{+FACET_DATA}->{control} or return;
385256a93a4Safresh1    return $control if $control->{halt};
386256a93a4Safresh1    return;
387256a93a4Safresh1}
388256a93a4Safresh1
389256a93a4Safresh1sub bailout_brief {
390256a93a4Safresh1    my $self = shift;
391256a93a4Safresh1    my $bo = $self->bailout or return;
392256a93a4Safresh1
393256a93a4Safresh1    my $reason = $bo->{details} or return "BAILED OUT";
394256a93a4Safresh1    return "BAILED OUT: $reason";
395256a93a4Safresh1}
396256a93a4Safresh1
397256a93a4Safresh1sub bailout_reason {
398256a93a4Safresh1    my $self = shift;
399256a93a4Safresh1    my $bo = $self->bailout or return;
400256a93a4Safresh1    return $bo->{details} || '';
401256a93a4Safresh1}
402256a93a4Safresh1
403256a93a4Safresh1sub has_plan { $_[0]->{+FACET_DATA}->{plan} ? 1 : 0 }
404256a93a4Safresh1sub the_plan { $_[0]->the_facet('plan') }
405256a93a4Safresh1sub plan     { $_[0]->facet('plan') }
406256a93a4Safresh1
407256a93a4Safresh1sub plan_brief {
408256a93a4Safresh1    my $self = shift;
409256a93a4Safresh1
410256a93a4Safresh1    my $plan = $self->{+FACET_DATA}->{plan} or return;
411256a93a4Safresh1
412256a93a4Safresh1    my $base = $self->_plan_brief($plan);
413256a93a4Safresh1
414256a93a4Safresh1    my $reason = $plan->{details} or return $base;
415256a93a4Safresh1    return "$base: $reason";
416256a93a4Safresh1}
417256a93a4Safresh1
418256a93a4Safresh1sub _plan_brief {
419256a93a4Safresh1    my $self = shift;
420256a93a4Safresh1    my ($plan) = @_;
421256a93a4Safresh1
422256a93a4Safresh1    return 'NO PLAN' if $plan->{none};
423256a93a4Safresh1    return "SKIP ALL" if $plan->{skip} || !$plan->{count};
424256a93a4Safresh1    return "PLAN $plan->{count}";
425256a93a4Safresh1}
426256a93a4Safresh1
427256a93a4Safresh1sub has_amnesty     { $_[0]->{+FACET_DATA}->{amnesty} ? 1 : 0 }
428256a93a4Safresh1sub the_amnesty     { $_[0]->the_facet('amnesty') }
429256a93a4Safresh1sub amnesty         { $_[0]->facet('amnesty') }
430256a93a4Safresh1sub amnesty_reasons { map { $_->{details} } $_[0]->amnesty }
431256a93a4Safresh1
432256a93a4Safresh1sub has_todos    { &first(sub { uc($_->{tag}) eq 'TODO' }, $_[0]->amnesty) ? 1 : 0 }
433256a93a4Safresh1sub todos        {       grep { uc($_->{tag}) eq 'TODO' }  $_[0]->amnesty          }
434256a93a4Safresh1sub todo_reasons {       map  { $_->{details} || 'TODO' }  $_[0]->todos            }
435256a93a4Safresh1
436256a93a4Safresh1sub has_skips    { &first(sub { uc($_->{tag}) eq 'SKIP' }, $_[0]->amnesty) ? 1 : 0 }
437256a93a4Safresh1sub skips        {       grep { uc($_->{tag}) eq 'SKIP' }  $_[0]->amnesty          }
438256a93a4Safresh1sub skip_reasons {       map  { $_->{details} || 'SKIP' }  $_[0]->skips            }
439256a93a4Safresh1
440256a93a4Safresh1my %TODO_OR_SKIP = (SKIP => 1, TODO => 1);
441256a93a4Safresh1sub has_other_amnesty     { &first( sub { !$TODO_OR_SKIP{uc($_->{tag})}            }, $_[0]->amnesty) ? 1 : 0 }
442256a93a4Safresh1sub other_amnesty         {        grep { !$TODO_OR_SKIP{uc($_->{tag})}            }  $_[0]->amnesty          }
443256a93a4Safresh1sub other_amnesty_reasons {        map  { $_->{details} ||  $_->{tag} || 'AMNESTY' }  $_[0]->other_amnesty    }
444256a93a4Safresh1
445256a93a4Safresh1sub has_errors     { $_[0]->{+FACET_DATA}->{errors} ? 1 : 0 }
446256a93a4Safresh1sub the_errors     { $_[0]->the_facet('errors') }
447256a93a4Safresh1sub errors         { $_[0]->facet('errors') }
448256a93a4Safresh1sub error_messages { map { $_->{details} || $_->{tag} || 'ERROR' } $_[0]->errors }
449256a93a4Safresh1
450256a93a4Safresh1sub error_brief {
451256a93a4Safresh1    my $self = shift;
452256a93a4Safresh1
453256a93a4Safresh1    my $errors = $self->{+FACET_DATA}->{errors} or return;
454256a93a4Safresh1
455256a93a4Safresh1    my $base = @$errors > 1 ? "ERRORS" : "ERROR";
456256a93a4Safresh1
457256a93a4Safresh1    return $base unless @$errors;
458256a93a4Safresh1
459256a93a4Safresh1    my ($msg, @extra) = split /[\n\r]+/, $errors->[0]->{details};
460256a93a4Safresh1
461256a93a4Safresh1    my $out = "$base: $msg";
462256a93a4Safresh1
463256a93a4Safresh1    $out .= " [...]" if @extra || @$errors > 1;
464256a93a4Safresh1
465256a93a4Safresh1    return $out;
466256a93a4Safresh1}
467256a93a4Safresh1
468256a93a4Safresh1sub has_info      { $_[0]->{+FACET_DATA}->{info} ? 1 : 0 }
469256a93a4Safresh1sub the_info      { $_[0]->the_facet('info') }
470256a93a4Safresh1sub info          { $_[0]->facet('info') }
471256a93a4Safresh1sub info_messages { map { $_->{details} } $_[0]->info }
472256a93a4Safresh1
473256a93a4Safresh1sub has_diags { &first(sub { uc($_->{tag}) eq 'DIAG' }, $_[0]->info) ? 1 : 0 }
474256a93a4Safresh1sub diags         {   grep { uc($_->{tag}) eq 'DIAG' }  $_[0]->info          }
475256a93a4Safresh1sub diag_messages {   map  { $_->{details} || 'DIAG' }  $_[0]->diags         }
476256a93a4Safresh1
477256a93a4Safresh1sub has_notes { &first(sub { uc($_->{tag}) eq 'NOTE' }, $_[0]->info) ? 1 : 0 }
478256a93a4Safresh1sub notes         {   grep { uc($_->{tag}) eq 'NOTE' }  $_[0]->info          }
479256a93a4Safresh1sub note_messages {   map  { $_->{details} || 'NOTE' }  $_[0]->notes         }
480256a93a4Safresh1
481256a93a4Safresh1my %NOTE_OR_DIAG = (NOTE => 1, DIAG => 1);
482256a93a4Safresh1sub has_other_info { &first(sub { !$NOTE_OR_DIAG{uc($_->{tag})}         }, $_[0]->info) ? 1 : 0 }
483256a93a4Safresh1sub other_info          {  grep { !$NOTE_OR_DIAG{uc($_->{tag})}         }  $_[0]->info          }
484256a93a4Safresh1sub other_info_messages {  map  { $_->{details} ||  $_->{tag} || 'INFO' }  $_[0]->other_info    }
485256a93a4Safresh1
486256a93a4Safresh11;
487256a93a4Safresh1
488256a93a4Safresh1__END__
489256a93a4Safresh1
490256a93a4Safresh1=pod
491256a93a4Safresh1
492256a93a4Safresh1=encoding UTF-8
493256a93a4Safresh1
494256a93a4Safresh1=head1 NAME
495256a93a4Safresh1
496256a93a4Safresh1Test2::API::InterceptResult::Event - Representation of an event for use in
497256a93a4Safresh1testing other test tools.
498256a93a4Safresh1
499256a93a4Safresh1=head1 DESCRIPTION
500256a93a4Safresh1
501256a93a4Safresh1C<intercept { ... }> from L<Test2::API> returns an instance of
502256a93a4Safresh1L<Test2::API::InterceptResult> which is a blessed arrayref of
503256a93a4Safresh1L<Test2::API::InterceptResult::Event> objects.
504256a93a4Safresh1
505256a93a4Safresh1This POD documents the methods of these events, which are mainly provided for
506256a93a4Safresh1you to use when testing your test tools.
507256a93a4Safresh1
508256a93a4Safresh1=head1 SYNOPSIS
509256a93a4Safresh1
510256a93a4Safresh1    use Test2::V0;
511256a93a4Safresh1    use Test2::API qw/intercept/;
512256a93a4Safresh1
513256a93a4Safresh1    my $events = intercept {
514256a93a4Safresh1        ok(1, "A passing assertion");
515256a93a4Safresh1        plan(1);
516256a93a4Safresh1    };
517256a93a4Safresh1
518256a93a4Safresh1    # This will convert all events into instances of
519256a93a4Safresh1    # Test2::API::InterceptResult::Event. Until we do this they are the
520256a93a4Safresh1    # original Test::Event::* instances
521256a93a4Safresh1    $events->upgrade(in_place => 1);
522256a93a4Safresh1
523256a93a4Safresh1    # Now we can get individual events in this form
524256a93a4Safresh1    my $assert = $events->[0];
525256a93a4Safresh1    my $plan   = $events->[1];
526256a93a4Safresh1
527256a93a4Safresh1    # Or we can operate on all events at once:
528256a93a4Safresh1    my $flattened = $events->flatten;
529256a93a4Safresh1    is(
530256a93a4Safresh1        $flattened,
531256a93a4Safresh1        [
532256a93a4Safresh1          {
533256a93a4Safresh1            causes_failure => 0,
534256a93a4Safresh1
535256a93a4Safresh1            name => 'A passing assertion',
536256a93a4Safresh1            pass => 1,
537256a93a4Safresh1
538256a93a4Safresh1            trace_file => 'xxx.t',
539256a93a4Safresh1            trace_line => 5,
540256a93a4Safresh1          },
541256a93a4Safresh1          {
542256a93a4Safresh1            causes_failure => 0,
543256a93a4Safresh1
544256a93a4Safresh1            plan => 1,
545256a93a4Safresh1
546256a93a4Safresh1            trace_file => 'xxx.t',
547256a93a4Safresh1            trace_line => 6,
548256a93a4Safresh1          },
549256a93a4Safresh1        ],
550256a93a4Safresh1        "Flattened both events and returned an arrayref of the results
551256a93a4Safresh1    );
552256a93a4Safresh1
553256a93a4Safresh1=head1 METHODS
554256a93a4Safresh1
555256a93a4Safresh1=head2 !!! IMPORTANT NOTES ON DESIGN !!!
556256a93a4Safresh1
557256a93a4Safresh1Please pay attention to what these return, many return a scalar when
558256a93a4Safresh1applicable or an empty list when not (as opposed to undef). Many also always
559256a93a4Safresh1return a list of 0 or more items. Some always return a scalar. Note that none
560256a93a4Safresh1of the methods care about context, their behavior is consistent regardless of
561256a93a4Safresh1scalar, list, or void context.
562256a93a4Safresh1
563256a93a4Safresh1This was done because this class was specifically designed to be used in a list
564256a93a4Safresh1and generate more lists in bulk operations. Sometimes in a map you want nothing
565256a93a4Safresh1to show up for the event, and you do not want an undef in its place. In general
566256a93a4Safresh1single event instances are not going to be used alone, though that is allowed.
567256a93a4Safresh1
568256a93a4Safresh1As a general rule any method prefixed with C<the_> implies the event should
569256a93a4Safresh1have exactly 1 of the specified item, and and exception will be thrown if there
570256a93a4Safresh1are 0, or more than 1 of the item.
571256a93a4Safresh1
572256a93a4Safresh1=head2 ATTRIBUTES
573256a93a4Safresh1
574256a93a4Safresh1=over 4
575256a93a4Safresh1
576256a93a4Safresh1=item $hashref = $event->facet_data
577256a93a4Safresh1
578256a93a4Safresh1This will return the facet data hashref, which is all Test2 cares about for any
579256a93a4Safresh1given event.
580256a93a4Safresh1
581256a93a4Safresh1=item $class = $event->result_class
582256a93a4Safresh1
583256a93a4Safresh1This is normally L<Test2::API::InterceptResult>. This is set at construction so
584256a93a4Safresh1that subtest results can be turned into instances of it on demand.
585256a93a4Safresh1
586256a93a4Safresh1=back
587256a93a4Safresh1
588256a93a4Safresh1=head2 DUPLICATION
589256a93a4Safresh1
590256a93a4Safresh1=over 4
591256a93a4Safresh1
592256a93a4Safresh1=item $copy = $event->clone
593256a93a4Safresh1
594256a93a4Safresh1Create a deep copy of the event. Modifying either event will not effect the
595256a93a4Safresh1other.
596256a93a4Safresh1
597256a93a4Safresh1=back
598256a93a4Safresh1
599256a93a4Safresh1=head2 CONDENSED MULTI-FACET DATA
600256a93a4Safresh1
601256a93a4Safresh1=over 4
602256a93a4Safresh1
603256a93a4Safresh1=item $bool = $event->causes_failure
604256a93a4Safresh1
605256a93a4Safresh1=item $bool = $event->causes_fail
606256a93a4Safresh1
607256a93a4Safresh1These are both aliases of the same functionality.
608256a93a4Safresh1
609256a93a4Safresh1This will always return either a true value, or a false value. This never
610256a93a4Safresh1returns a list.
611256a93a4Safresh1
612256a93a4Safresh1This method may be relatively slow (still super fast) because it determines
613256a93a4Safresh1pass or fail by creating an instance of L<Test2::Hub> and asking it to process
614256a93a4Safresh1the event, and then asks the hub for its pass/fail state. This is slower than
615*5486feefSafresh1building in logic to do the check, but it is more reliable as it will always
616256a93a4Safresh1tell you what the hub thinks, so the logic will never be out of date relative
617256a93a4Safresh1to the Test2 logic that actually cares.
618256a93a4Safresh1
619256a93a4Safresh1=item STRING_OR_EMPTY_LIST = $event->brief
620256a93a4Safresh1
621256a93a4Safresh1Not all events have a brief, some events are not rendered by the formatter,
622256a93a4Safresh1others have no "brief" data worth seeing. When this is the case an empty list
623256a93a4Safresh1is returned. This is done intentionally so it can be used in a map operation
624256a93a4Safresh1without having C<undef> being included in the result.
625256a93a4Safresh1
626256a93a4Safresh1When a brief can be generated it is always a single 1-line string, and is
627256a93a4Safresh1returned as-is, not in a list.
628256a93a4Safresh1
629256a93a4Safresh1Possible briefs:
630256a93a4Safresh1
631256a93a4Safresh1    # From control facets
632256a93a4Safresh1    "BAILED OUT"
633256a93a4Safresh1    "BAILED OUT: $why"
634256a93a4Safresh1
635256a93a4Safresh1    # From error facets
636256a93a4Safresh1    "ERROR"
637256a93a4Safresh1    "ERROR: $message"
638256a93a4Safresh1    "ERROR: $partial_message [...]"
639256a93a4Safresh1    "ERRORS: $first_error_message [...]"
640256a93a4Safresh1
641256a93a4Safresh1    # From assert facets
642256a93a4Safresh1    "PASS"
643256a93a4Safresh1    "FAIL"
644256a93a4Safresh1    "PASS with amnesty"
645256a93a4Safresh1    "FAIL with amnesty"
646256a93a4Safresh1
647256a93a4Safresh1    # From plan facets
648256a93a4Safresh1    "PLAN $count"
649256a93a4Safresh1    "NO PLAN"
650256a93a4Safresh1    "SKIP ALL"
651256a93a4Safresh1    "SKIP ALL: $why"
652256a93a4Safresh1
653256a93a4Safresh1Note that only the first applicable brief is returned. This is essnetially a
654256a93a4Safresh1poor-mans TAP that only includes facets that could (but not necessarily do)
655256a93a4Safresh1cause a failure.
656256a93a4Safresh1
657256a93a4Safresh1=item $hashref = $event->flatten
658256a93a4Safresh1
659256a93a4Safresh1=item $hashref = $event->flatten(include_subevents => 1)
660256a93a4Safresh1
661256a93a4Safresh1This ALWAYS returns a hashref. This puts all the most useful data for the most
662256a93a4Safresh1interesting facets into a single hashref for easy validation.
663256a93a4Safresh1
664256a93a4Safresh1If there are no meaningful facets this will return an empty hashref.
665256a93a4Safresh1
666256a93a4Safresh1If given the 'include_subevents' parameter it will also include subtest data:
667256a93a4Safresh1
668256a93a4Safresh1Here is a list of EVERY possible field. If a field is not applicable it will
669256a93a4Safresh1not be present.
670256a93a4Safresh1
671256a93a4Safresh1=over 4
672256a93a4Safresh1
673256a93a4Safresh1=item always present
674256a93a4Safresh1
675256a93a4Safresh1        causes_failure => 1,    # Always present
676256a93a4Safresh1
677256a93a4Safresh1=item Present if the event has a trace facet
678256a93a4Safresh1
679256a93a4Safresh1        trace_line    => 42,
680256a93a4Safresh1        trace_file    => 'Foo/Bar.pm',
681256a93a4Safresh1        trace_details => 'Extra trace details',    # usually not present
682256a93a4Safresh1
683256a93a4Safresh1=item If an assertion is present
684256a93a4Safresh1
685256a93a4Safresh1        pass => 0,
686256a93a4Safresh1        name => "1 + 1 = 2, so math works",
687256a93a4Safresh1
688256a93a4Safresh1=item If a plan is present:
689256a93a4Safresh1
690256a93a4Safresh1        plan => $count_or_SKIP_ALL_or_NO_PLAN,
691256a93a4Safresh1
692256a93a4Safresh1=item If amnesty facets are present
693256a93a4Safresh1
694256a93a4Safresh1You get an array for each type that is present.
695256a93a4Safresh1
696256a93a4Safresh1        todo => [    # Yes you could be under multiple todos, this will list them all.
697256a93a4Safresh1            "I will fix this later",
698256a93a4Safresh1            "I promise to fix these",
699256a93a4Safresh1        ],
700256a93a4Safresh1
701256a93a4Safresh1        skip => ["This will format the main drive, do not run"],
702256a93a4Safresh1
703256a93a4Safresh1        ... => ["Other amnesty"]
704256a93a4Safresh1
705256a93a4Safresh1=item If Info (note/diag) facets are present
706256a93a4Safresh1
707256a93a4Safresh1You get an arrayref for any that are present, the key is not defined if they are not present.
708256a93a4Safresh1
709256a93a4Safresh1        diag => [
710256a93a4Safresh1            "Test failed at Foo/Bar.pm line 42",
711256a93a4Safresh1            "You forgot to tie your boots",
712256a93a4Safresh1        ],
713256a93a4Safresh1
714256a93a4Safresh1        note => ["Your boots are red"],
715256a93a4Safresh1
716256a93a4Safresh1        ...  => ["Other info"],
717256a93a4Safresh1
718256a93a4Safresh1=item If error facets are present
719256a93a4Safresh1
720256a93a4Safresh1Always an arrayref
721256a93a4Safresh1
722256a93a4Safresh1        error => [
723256a93a4Safresh1            "non fatal error (does not cause test failure, just an FYI",
724256a93a4Safresh1            "FATAL: This is a fatal error (causes failure)",
725256a93a4Safresh1        ],
726256a93a4Safresh1
727256a93a4Safresh1        # Errors can have alternative tags, but in practice are always 'error',
728256a93a4Safresh1        # listing this for completeness.
729256a93a4Safresh1        ... => [ ... ]
730256a93a4Safresh1
731256a93a4Safresh1=item Present if the event is a subtest
732256a93a4Safresh1
733256a93a4Safresh1        subtest => {
734256a93a4Safresh1            count      => 2,    # Number of assertions made
735256a93a4Safresh1            failed     => 1,    # Number of test failures seen
736256a93a4Safresh1            is_passing => 0,    # Boolean, true if the test would be passing
737256a93a4Safresh1                                # after the events are processed.
738256a93a4Safresh1
739256a93a4Safresh1            plan         => 2,  # Plan, either a number, undef, 'SKIP', or 'NO PLAN'
740256a93a4Safresh1            follows_plan => 1,  # True if there is a plan and it was followed.
741256a93a4Safresh1                                # False if the plan and assertions did not
742256a93a4Safresh1                                # match, undef if no plan was present in the
743256a93a4Safresh1                                # event list.
744256a93a4Safresh1
745256a93a4Safresh1            bailed_out => "foo",    # if there was a bail-out in the
746256a93a4Safresh1                                    # events in this will be a string explaining
747256a93a4Safresh1                                    # why there was a bailout, if no reason was
748256a93a4Safresh1                                    # given this will simply be set to true (1).
749256a93a4Safresh1
750256a93a4Safresh1            skip_reason => "foo",   # If there was a skip_all this will give the
751256a93a4Safresh1                                    # reason.
752256a93a4Safresh1        },
753256a93a4Safresh1
754256a93a4Safresh1if C<< (include_subtest => 1) >> was provided as a parameter then the following
755256a93a4Safresh1will be included. This is the result of turning all subtest child events into
756256a93a4Safresh1an L<Test2::API::InterceptResult> instance and calling the C<flatten> method on
757256a93a4Safresh1it.
758256a93a4Safresh1
759256a93a4Safresh1        subevents => Test2::API::InterceptResult->new(@child_events)->flatten(...),
760256a93a4Safresh1
761256a93a4Safresh1=item If a bail-out is being requested
762256a93a4Safresh1
763256a93a4Safresh1If no reason was given this will be set to 1.
764256a93a4Safresh1
765256a93a4Safresh1        bailed_out => "reason",
766256a93a4Safresh1
767256a93a4Safresh1=back
768256a93a4Safresh1
769256a93a4Safresh1=item $hashref = $event->summary()
770256a93a4Safresh1
771256a93a4Safresh1This returns a limited summary. See C<flatten()>, which is usually a better
772256a93a4Safresh1option.
773256a93a4Safresh1
774256a93a4Safresh1    {
775256a93a4Safresh1        brief => $event->brief || '',
776256a93a4Safresh1
777256a93a4Safresh1        causes_failure => $event->causes_failure,
778256a93a4Safresh1
779256a93a4Safresh1        trace_line    => $event->trace_line,
780256a93a4Safresh1        trace_file    => $event->trace_file,
781256a93a4Safresh1        trace_tool    => $event->trace_subname,
782256a93a4Safresh1        trace_details => $event->trace_details,
783256a93a4Safresh1
784256a93a4Safresh1        facets => [ sort keys(%{$event->{+FACET_DATA}}) ],
785256a93a4Safresh1    }
786256a93a4Safresh1
787256a93a4Safresh1=back
788256a93a4Safresh1
789256a93a4Safresh1=head2 DIRECT ARBITRARY FACET ACCESS
790256a93a4Safresh1
791256a93a4Safresh1=over 4
792256a93a4Safresh1
793256a93a4Safresh1=item @list_of_facets = $event->facet($name)
794256a93a4Safresh1
795256a93a4Safresh1This always returns a list of 0 or more items. This fetches the facet instances
796256a93a4Safresh1from the event. For facets like 'assert' this will always return 0 or 1
797256a93a4Safresh1item. For events like 'info' (diags, notes) this will return 0 or more
798256a93a4Safresh1instances, once for each instance of the facet.
799256a93a4Safresh1
800256a93a4Safresh1These will be blessed into the proper L<Test2::EventFacet> subclass. If no
801256a93a4Safresh1subclass can be found it will be blessed as an
802256a93a4Safresh1L<Test2::API::InterceptResult::Facet> generic facet class.
803256a93a4Safresh1
804256a93a4Safresh1=item $undef_or_facet = $event->the_facet($name)
805256a93a4Safresh1
806256a93a4Safresh1If you know you will have exactly 1 instance of a facet you can call this.
807256a93a4Safresh1
808256a93a4Safresh1If you are correct and there is exactly one instance of the facet it will
809256a93a4Safresh1always return the hashref.
810256a93a4Safresh1
811*5486feefSafresh1If there are 0 instances of the facet this will return undef, not an empty
812256a93a4Safresh1list.
813256a93a4Safresh1
814256a93a4Safresh1If there are more than 1 instance this will throw an exception because your
815256a93a4Safresh1assumption was incorrect.
816256a93a4Safresh1
817256a93a4Safresh1=back
818256a93a4Safresh1
819256a93a4Safresh1=head2 TRACE FACET
820256a93a4Safresh1
821256a93a4Safresh1=over 4
822256a93a4Safresh1
823256a93a4Safresh1=item @list_of_facets = $event->trace
824256a93a4Safresh1
825256a93a4Safresh1TODO
826256a93a4Safresh1
827256a93a4Safresh1=item $undef_or_hashref = $event->the_trace
828256a93a4Safresh1
829256a93a4Safresh1This returns the trace hashref, or undef if it is not present.
830256a93a4Safresh1
831256a93a4Safresh1=item $undef_or_arrayref = $event->frame
832256a93a4Safresh1
833256a93a4Safresh1If a trace is present, and has a caller frame, this will be an arrayref:
834256a93a4Safresh1
835256a93a4Safresh1    [$package, $file, $line, $subname]
836256a93a4Safresh1
837256a93a4Safresh1If the trace is not present, or has no caller frame this will return undef.
838256a93a4Safresh1
839256a93a4Safresh1=item $undef_or_string = $event->trace_details
840256a93a4Safresh1
841256a93a4Safresh1This is usually undef, but occasionally has a string that overrides the
842256a93a4Safresh1file/line number debugging a trace usually provides on test failure.
843256a93a4Safresh1
844256a93a4Safresh1=item $undef_or_string = $event->trace_package
845256a93a4Safresh1
846256a93a4Safresh1Same as C<(caller())[0]>, the first element of the trace frame.
847256a93a4Safresh1
848256a93a4Safresh1Will be undef if not present.
849256a93a4Safresh1
850256a93a4Safresh1=item $undef_or_string = $event->trace_file
851256a93a4Safresh1
852256a93a4Safresh1Same as C<(caller())[1]>, the second element of the trace frame.
853256a93a4Safresh1
854256a93a4Safresh1Will be undef if not present.
855256a93a4Safresh1
856256a93a4Safresh1=item $undef_or_integer = $event->trace_line
857256a93a4Safresh1
858256a93a4Safresh1Same as C<(caller())[2]>, the third element of the trace frame.
859256a93a4Safresh1
860256a93a4Safresh1Will be undef if not present.
861256a93a4Safresh1
862256a93a4Safresh1=item $undef_or_string = $event->trace_subname
863256a93a4Safresh1
864256a93a4Safresh1=item $undef_or_string = $event->trace_tool
865256a93a4Safresh1
866256a93a4Safresh1Aliases for the same thing
867256a93a4Safresh1
868256a93a4Safresh1Same as C<(caller($level))[4]>, the fourth element of the trace frame.
869256a93a4Safresh1
870256a93a4Safresh1Will be undef if not present.
871256a93a4Safresh1
872256a93a4Safresh1=item $undef_or_string = $event->trace_signature
873256a93a4Safresh1
874256a93a4Safresh1A string that is a unique signature for the trace. If a single context
875256a93a4Safresh1generates multiple events they will all have the same signature. This can be
876*5486feefSafresh1used to tie assertions and diagnostics sent as separate events together after
877256a93a4Safresh1the fact.
878256a93a4Safresh1
879256a93a4Safresh1=back
880256a93a4Safresh1
881256a93a4Safresh1=head2 ASSERT FACET
882256a93a4Safresh1
883256a93a4Safresh1=over 4
884256a93a4Safresh1
885256a93a4Safresh1=item $bool = $event->has_assert
886256a93a4Safresh1
887256a93a4Safresh1Returns true if the event has an assert facet, false if it does not.
888256a93a4Safresh1
889256a93a4Safresh1=item $undef_or_hashref = $event->the_assert
890256a93a4Safresh1
891256a93a4Safresh1Returns the assert facet if present, undef if it is not.
892256a93a4Safresh1
893256a93a4Safresh1=item @list_of_facets = $event->assert
894256a93a4Safresh1
895256a93a4Safresh1TODO
896256a93a4Safresh1
897256a93a4Safresh1=item EMPTY_LIST_OR_STRING = $event->assert_brief
898256a93a4Safresh1
899256a93a4Safresh1Returns a string giving a brief of the assertion if an assertion is present.
900256a93a4Safresh1Returns an empty list if no assertion is present.
901256a93a4Safresh1
902256a93a4Safresh1=back
903256a93a4Safresh1
904256a93a4Safresh1=head2 SUBTESTS (PARENT FACET)
905256a93a4Safresh1
906256a93a4Safresh1=over 4
907256a93a4Safresh1
908256a93a4Safresh1=item $bool = $event->has_subtest
909256a93a4Safresh1
910256a93a4Safresh1True if a subetest is present in this event.
911256a93a4Safresh1
912256a93a4Safresh1=item $undef_or_hashref = $event->the_subtest
913256a93a4Safresh1
914256a93a4Safresh1Get the one subtest if present, otherwise undef.
915256a93a4Safresh1
916256a93a4Safresh1=item @list_of_facets = $event->subtest
917256a93a4Safresh1
918256a93a4Safresh1TODO
919256a93a4Safresh1
920256a93a4Safresh1=item EMPTY_LIST_OR_OBJECT = $event->subtest_result
921256a93a4Safresh1
922256a93a4Safresh1Returns an empty list if there is no subtest.
923256a93a4Safresh1
924256a93a4Safresh1Get an instance of L<Test2::API::InterceptResult> representing the subtest.
925256a93a4Safresh1
926256a93a4Safresh1=back
927256a93a4Safresh1
928256a93a4Safresh1=head2 CONTROL FACET (BAILOUT, ENCODING)
929256a93a4Safresh1
930256a93a4Safresh1=over 4
931256a93a4Safresh1
932256a93a4Safresh1=item $bool = $event->has_bailout
933256a93a4Safresh1
934256a93a4Safresh1True if there was a bailout
935256a93a4Safresh1
936256a93a4Safresh1=item $undef_hashref = $event->the_bailout
937256a93a4Safresh1
938256a93a4Safresh1Return the control facet if it requested a bailout.
939256a93a4Safresh1
940256a93a4Safresh1=item EMPTY_LIST_OR_HASHREF = $event->bailout
941256a93a4Safresh1
942256a93a4Safresh1Get a list of 0 or 1 hashrefs. The hashref will be the control facet if a
943256a93a4Safresh1bail-out was requested.
944256a93a4Safresh1
945256a93a4Safresh1=item EMPTY_LIST_OR_STRING = $event->bailout_brief
946256a93a4Safresh1
947256a93a4Safresh1Get the brief of the balout if present.
948256a93a4Safresh1
949256a93a4Safresh1=item EMPTY_LIST_OR_STRING = $event->bailout_reason
950256a93a4Safresh1
951256a93a4Safresh1Get the reason for the bailout, an empty string if no reason was provided, or
952256a93a4Safresh1an empty list if there was no bailout.
953256a93a4Safresh1
954256a93a4Safresh1=back
955256a93a4Safresh1
956256a93a4Safresh1=head2 PLAN FACET
957256a93a4Safresh1
958256a93a4Safresh1TODO
959256a93a4Safresh1
960256a93a4Safresh1=over 4
961256a93a4Safresh1
962256a93a4Safresh1=item $bool = $event->has_plan
963256a93a4Safresh1
964256a93a4Safresh1=item $undef_or_hashref = $event->the_plan
965256a93a4Safresh1
966256a93a4Safresh1=item @list_if_hashrefs = $event->plan
967256a93a4Safresh1
968256a93a4Safresh1=item EMPTY_LIST_OR_STRING $event->plan_brief
969256a93a4Safresh1
970256a93a4Safresh1=back
971256a93a4Safresh1
972256a93a4Safresh1=head2 AMNESTY FACET (TODO AND SKIP)
973256a93a4Safresh1
974256a93a4Safresh1TODO
975256a93a4Safresh1
976256a93a4Safresh1=over 4
977256a93a4Safresh1
978256a93a4Safresh1=item $event->has_amnesty
979256a93a4Safresh1
980256a93a4Safresh1=item $event->the_amnesty
981256a93a4Safresh1
982256a93a4Safresh1=item $event->amnesty
983256a93a4Safresh1
984256a93a4Safresh1=item $event->amnesty_reasons
985256a93a4Safresh1
986256a93a4Safresh1=item $event->has_todos
987256a93a4Safresh1
988256a93a4Safresh1=item $event->todos
989256a93a4Safresh1
990256a93a4Safresh1=item $event->todo_reasons
991256a93a4Safresh1
992256a93a4Safresh1=item $event->has_skips
993256a93a4Safresh1
994256a93a4Safresh1=item $event->skips
995256a93a4Safresh1
996256a93a4Safresh1=item $event->skip_reasons
997256a93a4Safresh1
998256a93a4Safresh1=item $event->has_other_amnesty
999256a93a4Safresh1
1000256a93a4Safresh1=item $event->other_amnesty
1001256a93a4Safresh1
1002256a93a4Safresh1=item $event->other_amnesty_reasons
1003256a93a4Safresh1
1004256a93a4Safresh1=back
1005256a93a4Safresh1
1006256a93a4Safresh1=head2 ERROR FACET (CAPTURED EXCEPTIONS)
1007256a93a4Safresh1
1008256a93a4Safresh1TODO
1009256a93a4Safresh1
1010256a93a4Safresh1=over 4
1011256a93a4Safresh1
1012256a93a4Safresh1=item $event->has_errors
1013256a93a4Safresh1
1014256a93a4Safresh1=item $event->the_errors
1015256a93a4Safresh1
1016256a93a4Safresh1=item $event->errors
1017256a93a4Safresh1
1018256a93a4Safresh1=item $event->error_messages
1019256a93a4Safresh1
1020256a93a4Safresh1=item $event->error_brief
1021256a93a4Safresh1
1022256a93a4Safresh1=back
1023256a93a4Safresh1
1024256a93a4Safresh1=head2 INFO FACET (DIAG, NOTE)
1025256a93a4Safresh1
1026256a93a4Safresh1TODO
1027256a93a4Safresh1
1028256a93a4Safresh1=over 4
1029256a93a4Safresh1
1030256a93a4Safresh1=item $event->has_info
1031256a93a4Safresh1
1032256a93a4Safresh1=item $event->the_info
1033256a93a4Safresh1
1034256a93a4Safresh1=item $event->info
1035256a93a4Safresh1
1036256a93a4Safresh1=item $event->info_messages
1037256a93a4Safresh1
1038256a93a4Safresh1=item $event->has_diags
1039256a93a4Safresh1
1040256a93a4Safresh1=item $event->diags
1041256a93a4Safresh1
1042256a93a4Safresh1=item $event->diag_messages
1043256a93a4Safresh1
1044256a93a4Safresh1=item $event->has_notes
1045256a93a4Safresh1
1046256a93a4Safresh1=item $event->notes
1047256a93a4Safresh1
1048256a93a4Safresh1=item $event->note_messages
1049256a93a4Safresh1
1050256a93a4Safresh1=item $event->has_other_info
1051256a93a4Safresh1
1052256a93a4Safresh1=item $event->other_info
1053256a93a4Safresh1
1054256a93a4Safresh1=item $event->other_info_messages
1055256a93a4Safresh1
1056256a93a4Safresh1=back
1057256a93a4Safresh1
1058256a93a4Safresh1=head1 SOURCE
1059256a93a4Safresh1
1060256a93a4Safresh1The source code repository for Test2 can be found at
1061*5486feefSafresh1L<https://github.com/Test-More/test-more/>.
1062256a93a4Safresh1
1063256a93a4Safresh1=head1 MAINTAINERS
1064256a93a4Safresh1
1065256a93a4Safresh1=over 4
1066256a93a4Safresh1
1067256a93a4Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt>
1068256a93a4Safresh1
1069256a93a4Safresh1=back
1070256a93a4Safresh1
1071256a93a4Safresh1=head1 AUTHORS
1072256a93a4Safresh1
1073256a93a4Safresh1=over 4
1074256a93a4Safresh1
1075256a93a4Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt>
1076256a93a4Safresh1
1077256a93a4Safresh1=back
1078256a93a4Safresh1
1079256a93a4Safresh1=head1 COPYRIGHT
1080256a93a4Safresh1
1081256a93a4Safresh1Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>.
1082256a93a4Safresh1
1083256a93a4Safresh1This program is free software; you can redistribute it and/or
1084256a93a4Safresh1modify it under the same terms as Perl itself.
1085256a93a4Safresh1
1086*5486feefSafresh1See L<https://dev.perl.org/licenses/>
1087256a93a4Safresh1
1088256a93a4Safresh1=cut
1089