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