xref: /openbsd-src/gnu/usr.bin/perl/cpan/Test-Simple/lib/Test2/Event.pm (revision 5486feefcc8cb79b19e014ab332cc5dfd05b3b33)
15759b3d2Safresh1package Test2::Event;
25759b3d2Safresh1use strict;
35759b3d2Safresh1use warnings;
45759b3d2Safresh1
5*5486feefSafresh1our $VERSION = '1.302199';
65759b3d2Safresh1
75759b3d2Safresh1use Scalar::Util qw/blessed reftype/;
85759b3d2Safresh1use Carp qw/croak/;
95759b3d2Safresh1
10f3efcd01Safresh1use Test2::Util::HashBase qw/trace -amnesty uuid -_eid -hubs/;
115759b3d2Safresh1use Test2::Util::ExternalMeta qw/meta get_meta set_meta delete_meta/;
12f3efcd01Safresh1use Test2::Util qw/pkg_to_file gen_uid/;
135759b3d2Safresh1
145759b3d2Safresh1use Test2::EventFacet::About();
155759b3d2Safresh1use Test2::EventFacet::Amnesty();
165759b3d2Safresh1use Test2::EventFacet::Assert();
175759b3d2Safresh1use Test2::EventFacet::Control();
185759b3d2Safresh1use Test2::EventFacet::Error();
195759b3d2Safresh1use Test2::EventFacet::Info();
205759b3d2Safresh1use Test2::EventFacet::Meta();
215759b3d2Safresh1use Test2::EventFacet::Parent();
225759b3d2Safresh1use Test2::EventFacet::Plan();
235759b3d2Safresh1use Test2::EventFacet::Trace();
245759b3d2Safresh1use Test2::EventFacet::Hub();
255759b3d2Safresh1
265759b3d2Safresh1# Legacy tools will expect this to be loaded now
275759b3d2Safresh1require Test2::Util::Trace;
285759b3d2Safresh1
295759b3d2Safresh1my %LOADED_FACETS = (
305759b3d2Safresh1    'about'   => 'Test2::EventFacet::About',
315759b3d2Safresh1    'amnesty' => 'Test2::EventFacet::Amnesty',
325759b3d2Safresh1    'assert'  => 'Test2::EventFacet::Assert',
335759b3d2Safresh1    'control' => 'Test2::EventFacet::Control',
345759b3d2Safresh1    'errors'  => 'Test2::EventFacet::Error',
355759b3d2Safresh1    'info'    => 'Test2::EventFacet::Info',
365759b3d2Safresh1    'meta'    => 'Test2::EventFacet::Meta',
375759b3d2Safresh1    'parent'  => 'Test2::EventFacet::Parent',
385759b3d2Safresh1    'plan'    => 'Test2::EventFacet::Plan',
395759b3d2Safresh1    'trace'   => 'Test2::EventFacet::Trace',
405759b3d2Safresh1    'hubs'    => 'Test2::EventFacet::Hub',
415759b3d2Safresh1);
425759b3d2Safresh1
435759b3d2Safresh1sub FACET_TYPES { sort values %LOADED_FACETS }
445759b3d2Safresh1
455759b3d2Safresh1sub load_facet {
465759b3d2Safresh1    my $class = shift;
475759b3d2Safresh1    my ($facet) = @_;
485759b3d2Safresh1
495759b3d2Safresh1    return $LOADED_FACETS{$facet} if exists $LOADED_FACETS{$facet};
505759b3d2Safresh1
515759b3d2Safresh1    my @check = ($facet);
525759b3d2Safresh1    if ('s' eq substr($facet, -1, 1)) {
535759b3d2Safresh1        push @check => substr($facet, 0, -1);
545759b3d2Safresh1    }
555759b3d2Safresh1    else {
565759b3d2Safresh1        push @check => $facet . 's';
575759b3d2Safresh1    }
585759b3d2Safresh1
595759b3d2Safresh1    my $found;
605759b3d2Safresh1    for my $check (@check) {
615759b3d2Safresh1        my $mod  = "Test2::EventFacet::" . ucfirst($facet);
625759b3d2Safresh1        my $file = pkg_to_file($mod);
635759b3d2Safresh1        next unless eval { require $file; 1 };
645759b3d2Safresh1        $found = $mod;
655759b3d2Safresh1        last;
665759b3d2Safresh1    }
675759b3d2Safresh1
685759b3d2Safresh1    return undef unless $found;
695759b3d2Safresh1    $LOADED_FACETS{$facet} = $found;
705759b3d2Safresh1}
715759b3d2Safresh1
725759b3d2Safresh1sub causes_fail      { 0 }
735759b3d2Safresh1sub increments_count { 0 }
745759b3d2Safresh1sub diagnostics      { 0 }
755759b3d2Safresh1sub no_display       { 0 }
765759b3d2Safresh1sub subtest_id       { undef }
775759b3d2Safresh1
785759b3d2Safresh1sub callback { }
795759b3d2Safresh1
805759b3d2Safresh1sub terminate { () }
815759b3d2Safresh1sub global    { () }
825759b3d2Safresh1sub sets_plan { () }
835759b3d2Safresh1
845759b3d2Safresh1sub summary { ref($_[0]) }
855759b3d2Safresh1
865759b3d2Safresh1sub related {
875759b3d2Safresh1    my $self = shift;
885759b3d2Safresh1    my ($event) = @_;
895759b3d2Safresh1
905759b3d2Safresh1    my $tracea = $self->trace  or return undef;
915759b3d2Safresh1    my $traceb = $event->trace or return undef;
925759b3d2Safresh1
935759b3d2Safresh1    my $uuida = $tracea->uuid;
945759b3d2Safresh1    my $uuidb = $traceb->uuid;
955759b3d2Safresh1    if ($uuida && $uuidb) {
965759b3d2Safresh1        return 1 if $uuida eq $uuidb;
975759b3d2Safresh1        return 0;
985759b3d2Safresh1    }
995759b3d2Safresh1
1005759b3d2Safresh1    my $siga = $tracea->signature or return undef;
1015759b3d2Safresh1    my $sigb = $traceb->signature or return undef;
1025759b3d2Safresh1
1035759b3d2Safresh1    return 1 if $siga eq $sigb;
1045759b3d2Safresh1    return 0;
1055759b3d2Safresh1}
1065759b3d2Safresh1
1075759b3d2Safresh1sub add_hub {
1085759b3d2Safresh1    my $self = shift;
1095759b3d2Safresh1    unshift @{$self->{+HUBS}} => @_;
1105759b3d2Safresh1}
1115759b3d2Safresh1
1125759b3d2Safresh1sub add_amnesty {
1135759b3d2Safresh1    my $self = shift;
1145759b3d2Safresh1
1155759b3d2Safresh1    for my $am (@_) {
1165759b3d2Safresh1        $am = {%$am} if ref($am) ne 'ARRAY';
1175759b3d2Safresh1        $am = Test2::EventFacet::Amnesty->new($am);
1185759b3d2Safresh1
1195759b3d2Safresh1        push @{$self->{+AMNESTY}} => $am;
1205759b3d2Safresh1    }
1215759b3d2Safresh1}
1225759b3d2Safresh1
123f3efcd01Safresh1sub eid { $_[0]->{+_EID} ||= gen_uid() }
124f3efcd01Safresh1
1255759b3d2Safresh1sub common_facet_data {
1265759b3d2Safresh1    my $self = shift;
1275759b3d2Safresh1
1285759b3d2Safresh1    my %out;
1295759b3d2Safresh1
1305759b3d2Safresh1    $out{about} = {package => ref($self) || undef};
1315759b3d2Safresh1    if (my $uuid = $self->uuid) {
1325759b3d2Safresh1        $out{about}->{uuid} = $uuid;
1335759b3d2Safresh1    }
1345759b3d2Safresh1
135f3efcd01Safresh1    $out{about}->{eid} = $self->{+_EID} || $self->eid;
136f3efcd01Safresh1
1375759b3d2Safresh1    if (my $trace = $self->trace) {
1385759b3d2Safresh1        $out{trace} = { %$trace };
1395759b3d2Safresh1    }
1405759b3d2Safresh1
1415759b3d2Safresh1    if (my $hubs = $self->hubs) {
1425759b3d2Safresh1        $out{hubs} = $hubs;
1435759b3d2Safresh1    }
1445759b3d2Safresh1
1455759b3d2Safresh1    $out{amnesty} = [map {{ %{$_} }} @{$self->{+AMNESTY}}]
1465759b3d2Safresh1        if $self->{+AMNESTY};
1475759b3d2Safresh1
1485759b3d2Safresh1    if (my $meta = $self->meta_facet_data) {
1495759b3d2Safresh1        $out{meta} = $meta;
1505759b3d2Safresh1    }
1515759b3d2Safresh1
1525759b3d2Safresh1    return \%out;
1535759b3d2Safresh1}
1545759b3d2Safresh1
1555759b3d2Safresh1sub meta_facet_data {
1565759b3d2Safresh1    my $self = shift;
1575759b3d2Safresh1
1585759b3d2Safresh1    my $key = Test2::Util::ExternalMeta::META_KEY();
1595759b3d2Safresh1
1605759b3d2Safresh1    my $hash = $self->{$key} or return undef;
1615759b3d2Safresh1    return {%$hash};
1625759b3d2Safresh1}
1635759b3d2Safresh1
1645759b3d2Safresh1sub facet_data {
1655759b3d2Safresh1    my $self = shift;
1665759b3d2Safresh1
1675759b3d2Safresh1    my $out = $self->common_facet_data;
1685759b3d2Safresh1
1695759b3d2Safresh1    $out->{about}->{details}    = $self->summary    || undef;
1705759b3d2Safresh1    $out->{about}->{no_display} = $self->no_display || undef;
1715759b3d2Safresh1
1725759b3d2Safresh1    # Might be undef, we want to preserve that
1735759b3d2Safresh1    my $terminate = $self->terminate;
1745759b3d2Safresh1    $out->{control} = {
1755759b3d2Safresh1        global    => $self->global    || 0,
1765759b3d2Safresh1        terminate => $terminate,
1775759b3d2Safresh1        has_callback => $self->can('callback') == \&callback ? 0 : 1,
1785759b3d2Safresh1    };
1795759b3d2Safresh1
1805759b3d2Safresh1    $out->{assert} = {
1815759b3d2Safresh1        no_debug => 1,                     # Legacy behavior
1825759b3d2Safresh1        pass     => $self->causes_fail ? 0 : 1,
1835759b3d2Safresh1        details  => $self->summary,
1845759b3d2Safresh1    } if $self->increments_count;
1855759b3d2Safresh1
1865759b3d2Safresh1    $out->{parent} = {hid => $self->subtest_id} if $self->subtest_id;
1875759b3d2Safresh1
1885759b3d2Safresh1    if (my @plan = $self->sets_plan) {
1895759b3d2Safresh1        $out->{plan} = {};
1905759b3d2Safresh1
1915759b3d2Safresh1        $out->{plan}->{count}   = $plan[0] if defined $plan[0];
1925759b3d2Safresh1        $out->{plan}->{details} = $plan[2] if defined $plan[2];
1935759b3d2Safresh1
1945759b3d2Safresh1        if ($plan[1]) {
1955759b3d2Safresh1            $out->{plan}->{skip} = 1 if $plan[1] eq 'SKIP';
1965759b3d2Safresh1            $out->{plan}->{none} = 1 if $plan[1] eq 'NO PLAN';
1975759b3d2Safresh1        }
1985759b3d2Safresh1
1995759b3d2Safresh1        $out->{control}->{terminate} ||= 0 if $out->{plan}->{skip};
2005759b3d2Safresh1    }
2015759b3d2Safresh1
2025759b3d2Safresh1    if ($self->causes_fail && !$out->{assert}) {
2035759b3d2Safresh1        $out->{errors} = [
2045759b3d2Safresh1            {
2055759b3d2Safresh1                tag     => 'FAIL',
2065759b3d2Safresh1                fail    => 1,
2075759b3d2Safresh1                details => $self->summary,
2085759b3d2Safresh1            }
2095759b3d2Safresh1        ];
2105759b3d2Safresh1    }
2115759b3d2Safresh1
2125759b3d2Safresh1    my %IGNORE = (trace => 1, about => 1, control => 1);
2135759b3d2Safresh1    my $do_info = !grep { !$IGNORE{$_} } keys %$out;
2145759b3d2Safresh1
2155759b3d2Safresh1    if ($do_info && !$self->no_display && $self->diagnostics) {
2165759b3d2Safresh1        $out->{info} = [
2175759b3d2Safresh1            {
2185759b3d2Safresh1                tag     => 'DIAG',
2195759b3d2Safresh1                debug   => 1,
2205759b3d2Safresh1                details => $self->summary,
2215759b3d2Safresh1            }
2225759b3d2Safresh1        ];
2235759b3d2Safresh1    }
2245759b3d2Safresh1
2255759b3d2Safresh1    return $out;
2265759b3d2Safresh1}
2275759b3d2Safresh1
2285759b3d2Safresh1sub facets {
2295759b3d2Safresh1    my $self = shift;
2305759b3d2Safresh1    my %out;
2315759b3d2Safresh1
2325759b3d2Safresh1    my $data = $self->facet_data;
2335759b3d2Safresh1    my @errors = $self->validate_facet_data($data);
2345759b3d2Safresh1    die join "\n" => @errors if @errors;
2355759b3d2Safresh1
2365759b3d2Safresh1    for my $facet (keys %$data) {
2375759b3d2Safresh1        my $class = $self->load_facet($facet);
2385759b3d2Safresh1        my $val = $data->{$facet};
2395759b3d2Safresh1
2405759b3d2Safresh1        unless($class) {
2415759b3d2Safresh1            $out{$facet} = $val;
2425759b3d2Safresh1            next;
2435759b3d2Safresh1        }
2445759b3d2Safresh1
2455759b3d2Safresh1        my $is_list = reftype($val) eq 'ARRAY' ? 1 : 0;
2465759b3d2Safresh1        if ($is_list) {
2475759b3d2Safresh1            $out{$facet} = [map { $class->new($_) } @$val];
2485759b3d2Safresh1        }
2495759b3d2Safresh1        else {
2505759b3d2Safresh1            $out{$facet} = $class->new($val);
2515759b3d2Safresh1        }
2525759b3d2Safresh1    }
2535759b3d2Safresh1
2545759b3d2Safresh1    return \%out;
2555759b3d2Safresh1}
2565759b3d2Safresh1
2575759b3d2Safresh1sub validate_facet_data {
2585759b3d2Safresh1    my $class_or_self = shift;
2595759b3d2Safresh1    my ($f, %params);
2605759b3d2Safresh1
2615759b3d2Safresh1    $f = shift if @_ && (reftype($_[0]) || '') eq 'HASH';
2625759b3d2Safresh1    %params = @_;
2635759b3d2Safresh1
2645759b3d2Safresh1    $f ||= $class_or_self->facet_data if blessed($class_or_self);
2655759b3d2Safresh1    croak "No facet data" unless $f;
2665759b3d2Safresh1
2675759b3d2Safresh1    my @errors;
2685759b3d2Safresh1
2695759b3d2Safresh1    for my $k (sort keys %$f) {
2705759b3d2Safresh1        my $fclass = $class_or_self->load_facet($k);
2715759b3d2Safresh1
2725759b3d2Safresh1        push @errors => "Could not find a facet class for facet '$k'"
2735759b3d2Safresh1            if $params{require_facet_class} && !$fclass;
2745759b3d2Safresh1
2755759b3d2Safresh1        next unless $fclass;
2765759b3d2Safresh1
2775759b3d2Safresh1        my $v = $f->{$k};
2785759b3d2Safresh1        next unless defined($v); # undef is always fine
2795759b3d2Safresh1
2805759b3d2Safresh1        my $is_list = $fclass->is_list();
2815759b3d2Safresh1        my $got_list = reftype($v) eq 'ARRAY' ? 1 : 0;
2825759b3d2Safresh1
2835759b3d2Safresh1        push @errors => "Facet '$k' should be a list, but got a single item ($v)"
2845759b3d2Safresh1            if $is_list && !$got_list;
2855759b3d2Safresh1
2865759b3d2Safresh1        push @errors => "Facet '$k' should not be a list, but got a a list ($v)"
2875759b3d2Safresh1            if $got_list && !$is_list;
2885759b3d2Safresh1    }
2895759b3d2Safresh1
2905759b3d2Safresh1    return @errors;
2915759b3d2Safresh1}
2925759b3d2Safresh1
2935759b3d2Safresh1sub nested {
2945759b3d2Safresh1    my $self = shift;
2955759b3d2Safresh1
2965759b3d2Safresh1    Carp::cluck("Use of Test2::Event->nested() is deprecated, use Test2::Event->trace->nested instead")
2975759b3d2Safresh1        if $ENV{AUTHOR_TESTING};
2985759b3d2Safresh1
2995759b3d2Safresh1    if (my $hubs = $self->{+HUBS}) {
3005759b3d2Safresh1        return $hubs->[0]->{nested} if @$hubs;
3015759b3d2Safresh1    }
3025759b3d2Safresh1
3035759b3d2Safresh1    my $trace = $self->{+TRACE} or return undef;
3045759b3d2Safresh1    return $trace->{nested};
3055759b3d2Safresh1}
3065759b3d2Safresh1
3075759b3d2Safresh1sub in_subtest {
3085759b3d2Safresh1    my $self = shift;
3095759b3d2Safresh1
3105759b3d2Safresh1    Carp::cluck("Use of Test2::Event->in_subtest() is deprecated, use Test2::Event->trace->hid instead")
3115759b3d2Safresh1        if $ENV{AUTHOR_TESTING};
3125759b3d2Safresh1
3135759b3d2Safresh1    my $hubs = $self->{+HUBS};
3145759b3d2Safresh1    if ($hubs && @$hubs) {
3155759b3d2Safresh1        return undef unless $hubs->[0]->{nested};
3165759b3d2Safresh1        return $hubs->[0]->{hid}
3175759b3d2Safresh1    }
3185759b3d2Safresh1
3195759b3d2Safresh1    my $trace = $self->{+TRACE} or return undef;
3205759b3d2Safresh1    return undef unless $trace->{nested};
3215759b3d2Safresh1    return $trace->{hid};
3225759b3d2Safresh1}
3235759b3d2Safresh1
3245759b3d2Safresh11;
3255759b3d2Safresh1
3265759b3d2Safresh1__END__
3275759b3d2Safresh1
3285759b3d2Safresh1=pod
3295759b3d2Safresh1
3305759b3d2Safresh1=encoding UTF-8
3315759b3d2Safresh1
3325759b3d2Safresh1=head1 NAME
3335759b3d2Safresh1
3345759b3d2Safresh1Test2::Event - Base class for events
3355759b3d2Safresh1
3365759b3d2Safresh1=head1 DESCRIPTION
3375759b3d2Safresh1
3385759b3d2Safresh1Base class for all event objects that get passed through
3395759b3d2Safresh1L<Test2>.
3405759b3d2Safresh1
3415759b3d2Safresh1=head1 SYNOPSIS
3425759b3d2Safresh1
3435759b3d2Safresh1    package Test2::Event::MyEvent;
3445759b3d2Safresh1    use strict;
3455759b3d2Safresh1    use warnings;
3465759b3d2Safresh1
3475759b3d2Safresh1    # This will make our class an event subclass (required)
3485759b3d2Safresh1    use base 'Test2::Event';
3495759b3d2Safresh1
3505759b3d2Safresh1    # Add some accessors (optional)
3515759b3d2Safresh1    # You are not obligated to use HashBase, you can use any object tool you
3525759b3d2Safresh1    # want, or roll your own accessors.
3535759b3d2Safresh1    use Test2::Util::HashBase qw/foo bar baz/;
3545759b3d2Safresh1
3555759b3d2Safresh1    # Use this if you want the legacy API to be written for you, for this to
3565759b3d2Safresh1    # work you will need to implement a facet_data() method.
3575759b3d2Safresh1    use Test2::Util::Facets2Legacy;
3585759b3d2Safresh1
3595759b3d2Safresh1    # Chance to initialize some defaults
3605759b3d2Safresh1    sub init {
3615759b3d2Safresh1        my $self = shift;
3625759b3d2Safresh1        # no other args in @_
3635759b3d2Safresh1
3645759b3d2Safresh1        $self->set_foo('xxx') unless defined $self->foo;
3655759b3d2Safresh1
3665759b3d2Safresh1        ...
3675759b3d2Safresh1    }
3685759b3d2Safresh1
3695759b3d2Safresh1    # This is the new way for events to convey data to the Test2 system
3705759b3d2Safresh1    sub facet_data {
3715759b3d2Safresh1        my $self = shift;
3725759b3d2Safresh1
3735759b3d2Safresh1        # Get common facets such as 'about', 'trace' 'amnesty', and 'meta'
3745759b3d2Safresh1        my $facet_data = $self->common_facet_data();
3755759b3d2Safresh1
3765759b3d2Safresh1        # Are you making an assertion?
3775759b3d2Safresh1        $facet_data->{assert} = {pass => 1, details => 'my assertion'};
3785759b3d2Safresh1        ...
3795759b3d2Safresh1
3805759b3d2Safresh1        return $facet_data;
3815759b3d2Safresh1    }
3825759b3d2Safresh1
3835759b3d2Safresh1    1;
3845759b3d2Safresh1
3855759b3d2Safresh1=head1 METHODS
3865759b3d2Safresh1
3875759b3d2Safresh1=head2 GENERAL
3885759b3d2Safresh1
3895759b3d2Safresh1=over 4
3905759b3d2Safresh1
3915759b3d2Safresh1=item $trace = $e->trace
3925759b3d2Safresh1
3935759b3d2Safresh1Get a snapshot of the L<Test2::EventFacet::Trace> as it was when this event was
3945759b3d2Safresh1generated
3955759b3d2Safresh1
3965759b3d2Safresh1=item $bool_or_undef = $e->related($e2)
3975759b3d2Safresh1
3985759b3d2Safresh1Check if 2 events are related. In this case related means their traces share a
3995759b3d2Safresh1signature meaning they were created with the same context (or at the very least
4005759b3d2Safresh1by contexts which share an id, which is the same thing unless someone is doing
4015759b3d2Safresh1something very bad).
4025759b3d2Safresh1
4035759b3d2Safresh1This can be used to reliably link multiple events created by the same tool. For
4045759b3d2Safresh1instance a failing test like C<ok(0, "fail"> will generate 2 events, one being
4055759b3d2Safresh1a L<Test2::Event::Ok>, the other being a L<Test2::Event::Diag>, both of these
4065759b3d2Safresh1events are related having been created under the same context and by the same
4075759b3d2Safresh1initial tool (though multiple tools may have been nested under the initial
4085759b3d2Safresh1one).
4095759b3d2Safresh1
4105759b3d2Safresh1This will return C<undef> if the relationship cannot be checked, which happens
4115759b3d2Safresh1if either event has an incomplete or missing trace. This will return C<0> if
4125759b3d2Safresh1the traces are complete, but do not match. C<1> will be returned if there is a
4135759b3d2Safresh1match.
4145759b3d2Safresh1
4155759b3d2Safresh1=item $e->add_amnesty({tag => $TAG, details => $DETAILS});
4165759b3d2Safresh1
4175759b3d2Safresh1This can be used to add amnesty to this event. Amnesty only effects failing
4185759b3d2Safresh1assertions in most cases, but some formatters may display them for passing
4195759b3d2Safresh1assertions, or even non-assertions as well.
4205759b3d2Safresh1
4215759b3d2Safresh1Amnesty will prevent a failed assertion from causing the overall test to fail.
4225759b3d2Safresh1In other words it marks a failure as expected and allowed.
4235759b3d2Safresh1
4245759b3d2Safresh1B<Note:> This is how 'TODO' is implemented under the hood. TODO is essentially
4255759b3d2Safresh1amnesty with the 'TODO' tag. The details are the reason for the TODO.
4265759b3d2Safresh1
4275759b3d2Safresh1=item $uuid = $e->uuid
4285759b3d2Safresh1
4295759b3d2Safresh1If UUID tagging is enabled (See L<Test::API>) then any event that has made its
4305759b3d2Safresh1way through a hub will be tagged with a UUID. A newly created event will not
4315759b3d2Safresh1yet be tagged in most cases.
4325759b3d2Safresh1
4335759b3d2Safresh1=item $class = $e->load_facet($name)
4345759b3d2Safresh1
4355759b3d2Safresh1This method is used to load a facet by name (or key). It will attempt to load
4365759b3d2Safresh1the facet class, if it succeeds it will return the class it loaded. If it fails
4375759b3d2Safresh1it will return C<undef>. This caches the result at the class level so that
4385759b3d2Safresh1future calls will be faster.
4395759b3d2Safresh1
4405759b3d2Safresh1The C<$name> variable should be the key used to access the facet in a facets
4415759b3d2Safresh1hashref. For instance the assertion facet has the key 'assert', the information
4425759b3d2Safresh1facet has the 'info' key, and the error facet has the key 'errors'. You may
4435759b3d2Safresh1include or omit the 's' at the end of the name, the method is smart enough to
4445759b3d2Safresh1try both the 's' and no-'s' forms, it will check what you provided first, and
4455759b3d2Safresh1if that is not found it will add or strip the 's and try again.
4465759b3d2Safresh1
4475759b3d2Safresh1=item @classes = $e->FACET_TYPES()
4485759b3d2Safresh1
4495759b3d2Safresh1=item @classes = Test2::Event->FACET_TYPES()
4505759b3d2Safresh1
4515759b3d2Safresh1This returns a list of all facets that have been loaded using the
4525759b3d2Safresh1C<load_facet()> method. This will not return any classes that have not been
4535759b3d2Safresh1loaded, or have been loaded directly without a call to C<load_facet()>.
4545759b3d2Safresh1
4555759b3d2Safresh1B<Note:> The core facet types are automatically loaded and populated in this
4565759b3d2Safresh1list.
4575759b3d2Safresh1
4585759b3d2Safresh1=back
4595759b3d2Safresh1
4605759b3d2Safresh1=head2 NEW API
4615759b3d2Safresh1
4625759b3d2Safresh1=over 4
4635759b3d2Safresh1
4645759b3d2Safresh1=item $hashref = $e->common_facet_data();
4655759b3d2Safresh1
4665759b3d2Safresh1This can be used by subclasses to generate a starting facet data hashref. This
4675759b3d2Safresh1will populate the hashref with the trace, meta, amnesty, and about facets.
4685759b3d2Safresh1These facets are nearly always produced the same way for all events.
4695759b3d2Safresh1
4705759b3d2Safresh1=item $hashref = $e->facet_data()
4715759b3d2Safresh1
4725759b3d2Safresh1If you do not override this then the default implementation will attempt to
4735759b3d2Safresh1generate facets from the legacy API. This generation is limited only to what
4745759b3d2Safresh1the legacy API can provide. It is recommended that you override this method and
4755759b3d2Safresh1write out explicit facet data.
4765759b3d2Safresh1
4775759b3d2Safresh1=item $hashref = $e->facets()
4785759b3d2Safresh1
4795759b3d2Safresh1This takes the hashref from C<facet_data()> and blesses each facet into the
4805759b3d2Safresh1proper C<Test2::EventFacet::*> subclass. If no class can be found for any given
4815759b3d2Safresh1facet it will be passed along unchanged.
4825759b3d2Safresh1
4835759b3d2Safresh1=item @errors = $e->validate_facet_data();
4845759b3d2Safresh1
4855759b3d2Safresh1=item @errors = $e->validate_facet_data(%params);
4865759b3d2Safresh1
4875759b3d2Safresh1=item @errors = $e->validate_facet_data(\%facets, %params);
4885759b3d2Safresh1
4895759b3d2Safresh1=item @errors = Test2::Event->validate_facet_data(%params);
4905759b3d2Safresh1
4915759b3d2Safresh1=item @errors = Test2::Event->validate_facet_data(\%facets, %params);
4925759b3d2Safresh1
4935759b3d2Safresh1This method will validate facet data and return a list of errors. If no errors
4945759b3d2Safresh1are found this will return an empty list.
4955759b3d2Safresh1
4965759b3d2Safresh1This can be called as an object method with no arguments, in which case the
4975759b3d2Safresh1C<facet_data()> method will be called to get the facet data to be validated.
4985759b3d2Safresh1
4995759b3d2Safresh1When used as an object method the C<\%facet_data> argument may be omitted.
5005759b3d2Safresh1
5015759b3d2Safresh1When used as a class method the C<\%facet_data> argument is required.
5025759b3d2Safresh1
5035759b3d2Safresh1Remaining arguments will be slurped into a C<%params> hash.
5045759b3d2Safresh1
5055759b3d2Safresh1Currently only 1 parameter is defined:
5065759b3d2Safresh1
5075759b3d2Safresh1=over 4
5085759b3d2Safresh1
5095759b3d2Safresh1=item require_facet_class => $BOOL
5105759b3d2Safresh1
5115759b3d2Safresh1When set to true (default is false) this will reject any facets where a facet
5125759b3d2Safresh1class cannot be found. Normally facets without classes are assumed to be custom
5135759b3d2Safresh1and are ignored.
5145759b3d2Safresh1
5155759b3d2Safresh1=back
5165759b3d2Safresh1
5175759b3d2Safresh1=back
5185759b3d2Safresh1
5195759b3d2Safresh1=head3 WHAT ARE FACETS?
5205759b3d2Safresh1
5215759b3d2Safresh1Facets are how events convey their purpose to the Test2 internals and
5225759b3d2Safresh1formatters. An event without facets will have no intentional effect on the
5235759b3d2Safresh1overall test state, and will not be displayed at all by most formatters, except
5245759b3d2Safresh1perhaps to say that an event of an unknown type was seen.
5255759b3d2Safresh1
5265759b3d2Safresh1Facets are produced by the C<facet_data()> subroutine, which you should
5275759b3d2Safresh1nearly-always override. C<facet_data()> is expected to return a hashref where
5285759b3d2Safresh1each key is the facet type, and the value is either a hashref with the data for
529de8cc8edSafresh1that facet, or an array of hashrefs. Some facets must be defined as single
5305759b3d2Safresh1hashrefs, some must be defined as an array of hashrefs, No facets allow both.
5315759b3d2Safresh1
5325759b3d2Safresh1C<facet_data()> B<MUST NOT> bless the data it returns, the main hashref, and
533de8cc8edSafresh1nested facet hashrefs B<MUST> be bare, though items contained within each
5345759b3d2Safresh1facet may be blessed. The data returned by this method B<should> also be copies
5355759b3d2Safresh1of the internal data in order to prevent accidental state modification.
5365759b3d2Safresh1
5375759b3d2Safresh1C<facets()> takes the data from C<facet_data()> and blesses it into the
5385759b3d2Safresh1C<Test2::EventFacet::*> packages. This is rarely used however, the EventFacet
5395759b3d2Safresh1packages are primarily for convenience and documentation. The EventFacet
5405759b3d2Safresh1classes are not used at all internally, instead the raw data is used.
5415759b3d2Safresh1
5425759b3d2Safresh1Here is a list of facet types by package. The packages are not used internally,
5435759b3d2Safresh1but are where the documentation for each type is kept.
5445759b3d2Safresh1
5455759b3d2Safresh1B<Note:> Every single facet type has the C<'details'> field. This field is
5465759b3d2Safresh1always intended for human consumption, and when provided, should explain the
5475759b3d2Safresh1'why' for the facet. All other fields are facet specific.
5485759b3d2Safresh1
5495759b3d2Safresh1=over 4
5505759b3d2Safresh1
5515759b3d2Safresh1=item about => {...}
5525759b3d2Safresh1
5535759b3d2Safresh1L<Test2::EventFacet::About>
5545759b3d2Safresh1
5555759b3d2Safresh1This contains information about the event itself such as the event package
5565759b3d2Safresh1name. The C<details> field for this facet is an overall summary of the event.
5575759b3d2Safresh1
5585759b3d2Safresh1=item assert => {...}
5595759b3d2Safresh1
5605759b3d2Safresh1L<Test2::EventFacet::Assert>
5615759b3d2Safresh1
5625759b3d2Safresh1This facet is used if an assertion was made. The C<details> field of this facet
5635759b3d2Safresh1is the description of the assertion.
5645759b3d2Safresh1
5655759b3d2Safresh1=item control => {...}
5665759b3d2Safresh1
5675759b3d2Safresh1L<Test2::EventFacet::Control>
5685759b3d2Safresh1
5695759b3d2Safresh1This facet is used to tell the L<Test2::Event::Hub> about special actions the
5705759b3d2Safresh1event causes. Things like halting all testing, terminating the current test,
5715759b3d2Safresh1etc. In this facet the C<details> field explains why any special action was
5725759b3d2Safresh1taken.
5735759b3d2Safresh1
5745759b3d2Safresh1B<Note:> This is how bail-out is implemented.
5755759b3d2Safresh1
5765759b3d2Safresh1=item meta => {...}
5775759b3d2Safresh1
5785759b3d2Safresh1L<Test2::EventFacet::Meta>
5795759b3d2Safresh1
5805759b3d2Safresh1The meta facet contains all the meta-data attached to the event. In this case
5815759b3d2Safresh1the C<details> field has no special meaning, but may be present if something
5825759b3d2Safresh1sets the 'details' meta-key on the event.
5835759b3d2Safresh1
5845759b3d2Safresh1=item parent => {...}
5855759b3d2Safresh1
5865759b3d2Safresh1L<Test2::EventFacet::Parent>
5875759b3d2Safresh1
5885759b3d2Safresh1This facet contains nested events and similar details for subtests. In this
5895759b3d2Safresh1facet the C<details> field will typically be the name of the subtest.
5905759b3d2Safresh1
5915759b3d2Safresh1=item plan => {...}
5925759b3d2Safresh1
5935759b3d2Safresh1L<Test2::EventFacet::Plan>
5945759b3d2Safresh1
5955759b3d2Safresh1This facet tells the system that a plan has been set. The C<details> field of
5965759b3d2Safresh1this is usually left empty, but when present explains why the plan is what it
5975759b3d2Safresh1is, this is most useful if the plan is to skip-all.
5985759b3d2Safresh1
5995759b3d2Safresh1=item trace => {...}
6005759b3d2Safresh1
6015759b3d2Safresh1L<Test2::EventFacet::Trace>
6025759b3d2Safresh1
6035759b3d2Safresh1This facet contains information related to when and where the event was
6045759b3d2Safresh1generated. This is how the test file and line number of a failure is known.
6055759b3d2Safresh1This facet can also help you to tell if tests are related.
6065759b3d2Safresh1
6075759b3d2Safresh1In this facet the C<details> field overrides the "failed at test_file.t line
6085759b3d2Safresh142." message provided on assertion failure.
6095759b3d2Safresh1
6105759b3d2Safresh1=item amnesty => [{...}, ...]
6115759b3d2Safresh1
6125759b3d2Safresh1L<Test2::EventFacet::Amnesty>
6135759b3d2Safresh1
6145759b3d2Safresh1The amnesty facet is a list instead of a single item, this is important as
6155759b3d2Safresh1amnesty can come from multiple places at once.
6165759b3d2Safresh1
6175759b3d2Safresh1For each instance of amnesty the C<details> field explains why amnesty was
6185759b3d2Safresh1granted.
6195759b3d2Safresh1
6205759b3d2Safresh1B<Note:> Outside of formatters amnesty only acts to forgive a failing
6215759b3d2Safresh1assertion.
6225759b3d2Safresh1
6235759b3d2Safresh1=item errors => [{...}, ...]
6245759b3d2Safresh1
6255759b3d2Safresh1L<Test2::EventFacet::Error>
6265759b3d2Safresh1
6275759b3d2Safresh1The errors facet is a list instead of a single item, any number of errors can
6285759b3d2Safresh1be listed. In this facet C<details> describes the error, or may contain the raw
6295759b3d2Safresh1error message itself (such as an exception). In perl exception may be blessed
6305759b3d2Safresh1objects, as such the raw data for this facet may contain nested items which are
6315759b3d2Safresh1blessed.
6325759b3d2Safresh1
6335759b3d2Safresh1Not all errors are considered fatal, there is a C<fail> field that must be set
6345759b3d2Safresh1for an error to cause the test to fail.
6355759b3d2Safresh1
6365759b3d2Safresh1B<Note:> This facet is unique in that the field name is 'errors' while the
6375759b3d2Safresh1package is 'Error'. This is because this is the only facet type that is both a
6385759b3d2Safresh1list, and has a name where the plural is not the same as the singular. This may
6395759b3d2Safresh1cause some confusion, but I feel it will be less confusing than the
6405759b3d2Safresh1alternative.
6415759b3d2Safresh1
6425759b3d2Safresh1=item info => [{...}, ...]
6435759b3d2Safresh1
6445759b3d2Safresh1L<Test2::EventFacet::Info>
6455759b3d2Safresh1
6465759b3d2Safresh1The 'info' facet is a list instead of a single item, any quantity of extra
6475759b3d2Safresh1information can be attached to an event. Some information may be critical
6485759b3d2Safresh1diagnostics, others may be simply commentary in nature, this is determined by
6495759b3d2Safresh1the C<debug> flag.
6505759b3d2Safresh1
6515759b3d2Safresh1For this facet the C<details> flag is the info itself. This info may be a
6525759b3d2Safresh1string, or it may be a data structure to display. This is one of the few facet
6535759b3d2Safresh1types that may contain blessed items.
6545759b3d2Safresh1
6555759b3d2Safresh1=back
6565759b3d2Safresh1
6575759b3d2Safresh1=head2 LEGACY API
6585759b3d2Safresh1
6595759b3d2Safresh1=over 4
6605759b3d2Safresh1
6615759b3d2Safresh1=item $bool = $e->causes_fail
6625759b3d2Safresh1
6635759b3d2Safresh1Returns true if this event should result in a test failure. In general this
6645759b3d2Safresh1should be false.
6655759b3d2Safresh1
6665759b3d2Safresh1=item $bool = $e->increments_count
6675759b3d2Safresh1
6685759b3d2Safresh1Should be true if this event should result in a test count increment.
6695759b3d2Safresh1
6705759b3d2Safresh1=item $e->callback($hub)
6715759b3d2Safresh1
6725759b3d2Safresh1If your event needs to have extra effects on the L<Test2::Hub> you can override
6735759b3d2Safresh1this method.
6745759b3d2Safresh1
6755759b3d2Safresh1This is called B<BEFORE> your event is passed to the formatter.
6765759b3d2Safresh1
6775759b3d2Safresh1=item $num = $e->nested
6785759b3d2Safresh1
6795759b3d2Safresh1If this event is nested inside of other events, this should be the depth of
6805759b3d2Safresh1nesting. (This is mainly for subtests)
6815759b3d2Safresh1
6825759b3d2Safresh1=item $bool = $e->global
6835759b3d2Safresh1
6845759b3d2Safresh1Set this to true if your event is global, that is ALL threads and processes
6855759b3d2Safresh1should see it no matter when or where it is generated. This is not a common
6865759b3d2Safresh1thing to want, it is used by bail-out and skip_all to end testing.
6875759b3d2Safresh1
6885759b3d2Safresh1=item $code = $e->terminate
6895759b3d2Safresh1
6905759b3d2Safresh1This is called B<AFTER> your event has been passed to the formatter. This
6915759b3d2Safresh1should normally return undef, only change this if your event should cause the
6925759b3d2Safresh1test to exit immediately.
6935759b3d2Safresh1
6945759b3d2Safresh1If you want this event to cause the test to exit you should return the exit
6955759b3d2Safresh1code here. Exit code of 0 means exit success, any other integer means exit with
6965759b3d2Safresh1failure.
6975759b3d2Safresh1
6985759b3d2Safresh1This is used by L<Test2::Event::Plan> to exit 0 when the plan is
6995759b3d2Safresh1'skip_all'. This is also used by L<Test2::Event:Bail> to force the test
7005759b3d2Safresh1to exit with a failure.
7015759b3d2Safresh1
7025759b3d2Safresh1This is called after the event has been sent to the formatter in order to
7035759b3d2Safresh1ensure the event is seen and understood.
7045759b3d2Safresh1
7055759b3d2Safresh1=item $msg = $e->summary
7065759b3d2Safresh1
7075759b3d2Safresh1This is intended to be a human readable summary of the event. This should
7085759b3d2Safresh1ideally only be one line long, but you can use multiple lines if necessary. This
7095759b3d2Safresh1is intended for human consumption. You do not need to make it easy for machines
7105759b3d2Safresh1to understand.
7115759b3d2Safresh1
7125759b3d2Safresh1The default is to simply return the event package name.
7135759b3d2Safresh1
7145759b3d2Safresh1=item ($count, $directive, $reason) = $e->sets_plan()
7155759b3d2Safresh1
7165759b3d2Safresh1Check if this event sets the testing plan. It will return an empty list if it
7175759b3d2Safresh1does not. If it does set the plan it will return a list of 1 to 3 items in
7185759b3d2Safresh1order: Expected Test Count, Test Directive, Reason for directive.
7195759b3d2Safresh1
7205759b3d2Safresh1=item $bool = $e->diagnostics
7215759b3d2Safresh1
7225759b3d2Safresh1True if the event contains diagnostics info. This is useful because a
7235759b3d2Safresh1non-verbose harness may choose to hide events that are not in this category.
7245759b3d2Safresh1Some formatters may choose to send these to STDERR instead of STDOUT to ensure
7255759b3d2Safresh1they are seen.
7265759b3d2Safresh1
7275759b3d2Safresh1=item $bool = $e->no_display
7285759b3d2Safresh1
7295759b3d2Safresh1False by default. This will return true on events that should not be displayed
7305759b3d2Safresh1by formatters.
7315759b3d2Safresh1
7325759b3d2Safresh1=item $id = $e->in_subtest
7335759b3d2Safresh1
7345759b3d2Safresh1If the event is inside a subtest this should have the subtest ID.
7355759b3d2Safresh1
7365759b3d2Safresh1=item $id = $e->subtest_id
7375759b3d2Safresh1
7385759b3d2Safresh1If the event is a final subtest event, this should contain the subtest ID.
7395759b3d2Safresh1
7405759b3d2Safresh1=back
7415759b3d2Safresh1
7425759b3d2Safresh1=head1 THIRD PARTY META-DATA
7435759b3d2Safresh1
7445759b3d2Safresh1This object consumes L<Test2::Util::ExternalMeta> which provides a consistent
7455759b3d2Safresh1way for you to attach meta-data to instances of this class. This is useful for
7465759b3d2Safresh1tools, plugins, and other extensions.
7475759b3d2Safresh1
7485759b3d2Safresh1=head1 SOURCE
7495759b3d2Safresh1
7505759b3d2Safresh1The source code repository for Test2 can be found at
751*5486feefSafresh1L<https://github.com/Test-More/test-more/>.
7525759b3d2Safresh1
7535759b3d2Safresh1=head1 MAINTAINERS
7545759b3d2Safresh1
7555759b3d2Safresh1=over 4
7565759b3d2Safresh1
7575759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt>
7585759b3d2Safresh1
7595759b3d2Safresh1=back
7605759b3d2Safresh1
7615759b3d2Safresh1=head1 AUTHORS
7625759b3d2Safresh1
7635759b3d2Safresh1=over 4
7645759b3d2Safresh1
7655759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt>
7665759b3d2Safresh1
7675759b3d2Safresh1=back
7685759b3d2Safresh1
7695759b3d2Safresh1=head1 COPYRIGHT
7705759b3d2Safresh1
771256a93a4Safresh1Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>.
7725759b3d2Safresh1
7735759b3d2Safresh1This program is free software; you can redistribute it and/or
7745759b3d2Safresh1modify it under the same terms as Perl itself.
7755759b3d2Safresh1
776*5486feefSafresh1See L<https://dev.perl.org/licenses/>
7775759b3d2Safresh1
7785759b3d2Safresh1=cut
779