xref: /openbsd-src/gnu/usr.bin/perl/cpan/Test-Simple/lib/Test2/API/Context.pm (revision 5486feefcc8cb79b19e014ab332cc5dfd05b3b33)
1package Test2::API::Context;
2use strict;
3use warnings;
4
5our $VERSION = '1.302199';
6
7
8use Carp qw/confess croak/;
9use Scalar::Util qw/weaken blessed/;
10use Test2::Util qw/get_tid try pkg_to_file get_tid/;
11
12use Test2::EventFacet::Trace();
13use Test2::API();
14
15# Preload some key event types
16my %LOADED = (
17    map {
18        my $pkg  = "Test2::Event::$_";
19        my $file = "Test2/Event/$_.pm";
20        require $file unless $INC{$file};
21        ( $pkg => $pkg, $_ => $pkg )
22    } qw/Ok Diag Note Plan Bail Exception Waiting Skip Subtest Pass Fail V2/
23);
24
25use Test2::Util::ExternalMeta qw/meta get_meta set_meta delete_meta/;
26use Test2::Util::HashBase qw{
27    stack hub trace _on_release _depth _is_canon _is_spawn _aborted
28    errno eval_error child_error thrown
29};
30
31# Private, not package vars
32# It is safe to cache these.
33my $ON_RELEASE = Test2::API::_context_release_callbacks_ref();
34my $CONTEXTS   = Test2::API::_contexts_ref();
35
36sub init {
37    my $self = shift;
38
39    confess "The 'trace' attribute is required"
40        unless $self->{+TRACE};
41
42    confess "The 'hub' attribute is required"
43        unless $self->{+HUB};
44
45    $self->{+_DEPTH} = 0 unless defined $self->{+_DEPTH};
46
47    $self->{+ERRNO}       = $! unless exists $self->{+ERRNO};
48    $self->{+EVAL_ERROR}  = $@ unless exists $self->{+EVAL_ERROR};
49    $self->{+CHILD_ERROR} = $? unless exists $self->{+CHILD_ERROR};
50}
51
52sub snapshot { bless {%{$_[0]}, _is_canon => undef, _is_spawn => undef, _aborted => undef}, __PACKAGE__ }
53
54sub restore_error_vars {
55    my $self = shift;
56    ($!, $@, $?) = @$self{+ERRNO, +EVAL_ERROR, +CHILD_ERROR};
57}
58
59sub DESTROY {
60    return unless $_[0]->{+_IS_CANON} || $_[0]->{+_IS_SPAWN};
61    return if $_[0]->{+_ABORTED} && ${$_[0]->{+_ABORTED}};
62    my ($self) = @_;
63
64    my $hub = $self->{+HUB};
65    my $hid = $hub->{hid};
66
67    # Do not show the warning if it looks like an exception has been thrown, or
68    # if the context is not local to this process or thread.
69    {
70        # Sometimes $@ is uninitialized, not a problem in this case so do not
71        # show the warning about using eq.
72        no warnings 'uninitialized';
73        if($self->{+EVAL_ERROR} eq $@ && $hub->is_local) {
74            require Carp;
75            my $mess = Carp::longmess("Context destroyed");
76            my $frame = $self->{+_IS_SPAWN} || $self->{+TRACE}->frame;
77            warn <<"            EOT";
78A context appears to have been destroyed without first calling release().
79Based on \$@ it does not look like an exception was thrown (this is not always
80a reliable test)
81
82This is a problem because the global error variables (\$!, \$@, and \$?) will
83not be restored. In addition some release callbacks will not work properly from
84inside a DESTROY method.
85
86Here are the context creation details, just in case a tool forgot to call
87release():
88  File: $frame->[1]
89  Line: $frame->[2]
90  Tool: $frame->[3]
91
92Here is a trace to the code that caused the context to be destroyed, this could
93be an exit(), a goto, or simply the end of a scope:
94$mess
95
96Cleaning up the CONTEXT stack...
97            EOT
98        }
99    }
100
101    return if $self->{+_IS_SPAWN};
102
103    # Remove the key itself to avoid a slow memory leak
104    delete $CONTEXTS->{$hid};
105    $self->{+_IS_CANON} = undef;
106
107    if (my $cbk = $self->{+_ON_RELEASE}) {
108        $_->($self) for reverse @$cbk;
109    }
110    if (my $hcbk = $hub->{_context_release}) {
111        $_->($self) for reverse @$hcbk;
112    }
113    $_->($self) for reverse @$ON_RELEASE;
114}
115
116# release exists to implement behaviors like die-on-fail. In die-on-fail you
117# want to die after a failure, but only after diagnostics have been reported.
118# The ideal time for the die to happen is when the context is released.
119# Unfortunately die does not work in a DESTROY block.
120sub release {
121    my ($self) = @_;
122
123    ($!, $@, $?) = @$self{+ERRNO, +EVAL_ERROR, +CHILD_ERROR} and return if $self->{+THROWN};
124
125    ($!, $@, $?) = @$self{+ERRNO, +EVAL_ERROR, +CHILD_ERROR} and return $self->{+_IS_SPAWN} = undef
126        if $self->{+_IS_SPAWN};
127
128    croak "release() should not be called on context that is neither canon nor a child"
129        unless $self->{+_IS_CANON};
130
131    my $hub = $self->{+HUB};
132    my $hid = $hub->{hid};
133
134    croak "context thinks it is canon, but it is not"
135        unless $CONTEXTS->{$hid} && $CONTEXTS->{$hid} == $self;
136
137    # Remove the key itself to avoid a slow memory leak
138    $self->{+_IS_CANON} = undef;
139    delete $CONTEXTS->{$hid};
140
141    if (my $cbk = $self->{+_ON_RELEASE}) {
142        $_->($self) for reverse @$cbk;
143    }
144    if (my $hcbk = $hub->{_context_release}) {
145        $_->($self) for reverse @$hcbk;
146    }
147    $_->($self) for reverse @$ON_RELEASE;
148
149    # Do this last so that nothing else changes them.
150    # If one of the hooks dies then these do not get restored, this is
151    # intentional
152    ($!, $@, $?) = @$self{+ERRNO, +EVAL_ERROR, +CHILD_ERROR};
153
154    return;
155}
156
157sub do_in_context {
158    my $self = shift;
159    my ($sub, @args) = @_;
160
161    # We need to update the pid/tid and error vars.
162    my $clone = $self->snapshot;
163    @$clone{+ERRNO, +EVAL_ERROR, +CHILD_ERROR} = ($!, $@, $?);
164    $clone->{+TRACE} = $clone->{+TRACE}->snapshot(pid => $$, tid => get_tid());
165
166    my $hub = $clone->{+HUB};
167    my $hid = $hub->hid;
168
169    my $old = $CONTEXTS->{$hid};
170
171    $clone->{+_IS_CANON} = 1;
172    $CONTEXTS->{$hid} = $clone;
173    weaken($CONTEXTS->{$hid});
174    my ($ok, $err) = &try($sub, @args);
175    my ($rok, $rerr) = try { $clone->release };
176    delete $clone->{+_IS_CANON};
177
178    if ($old) {
179        $CONTEXTS->{$hid} = $old;
180        weaken($CONTEXTS->{$hid});
181    }
182    else {
183        delete $CONTEXTS->{$hid};
184    }
185
186    die $err  unless $ok;
187    die $rerr unless $rok;
188}
189
190sub done_testing {
191    my $self = shift;
192    $self->hub->finalize($self->trace, 1);
193    return;
194}
195
196sub throw {
197    my ($self, $msg) = @_;
198    $self->{+THROWN} = 1;
199    ${$self->{+_ABORTED}}++ if $self->{+_ABORTED};
200    $self->release if $self->{+_IS_CANON} || $self->{+_IS_SPAWN};
201    $self->trace->throw($msg);
202}
203
204sub alert {
205    my ($self, $msg) = @_;
206    $self->trace->alert($msg);
207}
208
209sub send_ev2_and_release {
210    my $self = shift;
211    my $out  = $self->send_ev2(@_);
212    $self->release;
213    return $out;
214}
215
216sub send_ev2 {
217    my $self = shift;
218
219    my $e;
220    {
221        local $Carp::CarpLevel = $Carp::CarpLevel + 1;
222        $e = Test2::Event::V2->new(
223            trace => $self->{+TRACE}->snapshot,
224            @_,
225        );
226    }
227
228    if ($self->{+_ABORTED}) {
229        my $f = $e->facet_data;
230        ${$self->{+_ABORTED}}++ if $f->{control}->{halt} || defined($f->{control}->{terminate}) || defined($e->terminate);
231    }
232    $self->{+HUB}->send($e);
233}
234
235sub build_ev2 {
236    my $self = shift;
237
238    local $Carp::CarpLevel = $Carp::CarpLevel + 1;
239    Test2::Event::V2->new(
240        trace => $self->{+TRACE}->snapshot,
241        @_,
242    );
243}
244
245sub send_event_and_release {
246    my $self = shift;
247    my $out = $self->send_event(@_);
248    $self->release;
249    return $out;
250}
251
252sub send_event {
253    my $self  = shift;
254    my $event = shift;
255    my %args  = @_;
256
257    my $pkg = $LOADED{$event} || $self->_parse_event($event);
258
259    my $e;
260    {
261        local $Carp::CarpLevel = $Carp::CarpLevel + 1;
262        $e = $pkg->new(
263            trace => $self->{+TRACE}->snapshot,
264            %args,
265        );
266    }
267
268    if ($self->{+_ABORTED}) {
269        my $f = $e->facet_data;
270        ${$self->{+_ABORTED}}++ if $f->{control}->{halt} || defined($f->{control}->{terminate}) || defined($e->terminate);
271    }
272    $self->{+HUB}->send($e);
273}
274
275sub build_event {
276    my $self  = shift;
277    my $event = shift;
278    my %args  = @_;
279
280    my $pkg = $LOADED{$event} || $self->_parse_event($event);
281
282    local $Carp::CarpLevel = $Carp::CarpLevel + 1;
283    $pkg->new(
284        trace => $self->{+TRACE}->snapshot,
285        %args,
286    );
287}
288
289sub pass {
290    my $self = shift;
291    my ($name) = @_;
292
293    my $e = bless(
294        {
295            trace => bless({%{$self->{+TRACE}}}, 'Test2::EventFacet::Trace'),
296            name  => $name,
297        },
298        "Test2::Event::Pass"
299    );
300
301    $self->{+HUB}->send($e);
302    return $e;
303}
304
305sub pass_and_release {
306    my $self = shift;
307    my ($name) = @_;
308
309    my $e = bless(
310        {
311            trace => bless({%{$self->{+TRACE}}}, 'Test2::EventFacet::Trace'),
312            name  => $name,
313        },
314        "Test2::Event::Pass"
315    );
316
317    $self->{+HUB}->send($e);
318    $self->release;
319    return 1;
320}
321
322sub fail {
323    my $self = shift;
324    my ($name, @diag) = @_;
325
326    my $e = bless(
327        {
328            trace => bless({%{$self->{+TRACE}}}, 'Test2::EventFacet::Trace'),
329            name  => $name,
330        },
331        "Test2::Event::Fail"
332    );
333
334    for my $msg (@diag) {
335        if (ref($msg) eq 'Test2::EventFacet::Info::Table') {
336            $e->add_info({tag => 'DIAG', debug => 1, $msg->info_args});
337        }
338        else {
339            $e->add_info({tag => 'DIAG', debug => 1, details => $msg});
340        }
341    }
342
343    $self->{+HUB}->send($e);
344    return $e;
345}
346
347sub fail_and_release {
348    my $self = shift;
349    my ($name, @diag) = @_;
350
351    my $e = bless(
352        {
353            trace => bless({%{$self->{+TRACE}}}, 'Test2::EventFacet::Trace'),
354            name  => $name,
355        },
356        "Test2::Event::Fail"
357    );
358
359    for my $msg (@diag) {
360        if (ref($msg) eq 'Test2::EventFacet::Info::Table') {
361            $e->add_info({tag => 'DIAG', debug => 1, $msg->info_args});
362        }
363        else {
364            $e->add_info({tag => 'DIAG', debug => 1, details => $msg});
365        }
366    }
367
368    $self->{+HUB}->send($e);
369    $self->release;
370    return 0;
371}
372
373sub ok {
374    my $self = shift;
375    my ($pass, $name, $on_fail) = @_;
376
377    my $hub = $self->{+HUB};
378
379    my $e = bless {
380        trace => bless( {%{$self->{+TRACE}}}, 'Test2::EventFacet::Trace'),
381        pass  => $pass,
382        name  => $name,
383    }, 'Test2::Event::Ok';
384    $e->init;
385
386    $hub->send($e);
387    return $e if $pass;
388
389    $self->failure_diag($e);
390
391    if ($on_fail && @$on_fail) {
392        $self->diag($_) for @$on_fail;
393    }
394
395    return $e;
396}
397
398sub failure_diag {
399    my $self = shift;
400    my ($e) = @_;
401
402    # Figure out the debug info, this is typically the file name and line
403    # number, but can also be a custom message. If no trace object is provided
404    # then we have nothing useful to display.
405    my $name  = $e->name;
406    my $trace = $e->trace;
407    my $debug = $trace ? $trace->debug : "[No trace info available]";
408
409    # Create the initial diagnostics. If the test has a name we put the debug
410    # info on a second line, this behavior is inherited from Test::Builder.
411    my $msg = defined($name)
412        ? qq[Failed test '$name'\n$debug.\n]
413        : qq[Failed test $debug.\n];
414
415    $self->diag($msg);
416}
417
418sub skip {
419    my $self = shift;
420    my ($name, $reason, @extra) = @_;
421    $self->send_event(
422        'Skip',
423        name => $name,
424        reason => $reason,
425        pass => 1,
426        @extra,
427    );
428}
429
430sub note {
431    my $self = shift;
432    my ($message) = @_;
433    $self->send_event('Note', message => $message);
434}
435
436sub diag {
437    my $self = shift;
438    my ($message) = @_;
439    $self->send_event(
440        'Diag',
441        message => $message,
442    );
443}
444
445sub plan {
446    my ($self, $max, $directive, $reason) = @_;
447    $self->send_event('Plan', max => $max, directive => $directive, reason => $reason);
448}
449
450sub bail {
451    my ($self, $reason) = @_;
452    $self->send_event('Bail', reason => $reason);
453}
454
455sub _parse_event {
456    my $self = shift;
457    my $event = shift;
458
459    my $pkg;
460    if ($event =~ m/^\+(.*)/) {
461        $pkg = $1;
462    }
463    else {
464        $pkg = "Test2::Event::$event";
465    }
466
467    unless ($LOADED{$pkg}) {
468        my $file = pkg_to_file($pkg);
469        my ($ok, $err) = try { require $file };
470        $self->throw("Could not load event module '$pkg': $err")
471            unless $ok;
472
473        $LOADED{$pkg} = $pkg;
474    }
475
476    confess "'$pkg' is not a subclass of 'Test2::Event'"
477        unless $pkg->isa('Test2::Event');
478
479    $LOADED{$event} = $pkg;
480
481    return $pkg;
482}
483
4841;
485
486__END__
487
488=pod
489
490=encoding UTF-8
491
492=head1 NAME
493
494Test2::API::Context - Object to represent a testing context.
495
496=head1 DESCRIPTION
497
498The context object is the primary interface for authors of testing tools
499written with L<Test2>. The context object represents the context in
500which a test takes place (File and Line Number), and provides a quick way to
501generate events from that context. The context object also takes care of
502sending events to the correct L<Test2::Hub> instance.
503
504=head1 SYNOPSIS
505
506In general you will not be creating contexts directly. To obtain a context you
507should always use C<context()> which is exported by the L<Test2::API> module.
508
509    use Test2::API qw/context/;
510
511    sub my_ok {
512        my ($bool, $name) = @_;
513        my $ctx = context();
514
515        if ($bool) {
516            $ctx->pass($name);
517        }
518        else {
519            $ctx->fail($name);
520        }
521
522        $ctx->release; # You MUST do this!
523        return $bool;
524    }
525
526Context objects make it easy to wrap other tools that also use context. Once
527you grab a context, any tool you call before releasing your context will
528inherit it:
529
530    sub wrapper {
531        my ($bool, $name) = @_;
532        my $ctx = context();
533        $ctx->diag("wrapping my_ok");
534
535        my $out = my_ok($bool, $name);
536        $ctx->release; # You MUST do this!
537        return $out;
538    }
539
540=head1 CRITICAL DETAILS
541
542=over 4
543
544=item you MUST always use the context() sub from Test2::API
545
546Creating your own context via C<< Test2::API::Context->new() >> will almost never
547produce a desirable result. Use C<context()> which is exported by L<Test2::API>.
548
549There are a handful of cases where a tool author may want to create a new
550context by hand, which is why the C<new> method exists. Unless you really know
551what you are doing you should avoid this.
552
553=item You MUST always release the context when done with it
554
555Releasing the context tells the system you are done with it. This gives it a
556chance to run any necessary callbacks or cleanup tasks. If you forget to
557release the context it will try to detect the problem and warn you about it.
558
559=item You MUST NOT pass context objects around
560
561When you obtain a context object it is made specifically for your tool and any
562tools nested within. If you pass a context around you run the risk of polluting
563other tools with incorrect context information.
564
565If you are certain that you want a different tool to use the same context you
566may pass it a snapshot. C<< $ctx->snapshot >> will give you a shallow clone of
567the context that is safe to pass around or store.
568
569=item You MUST NOT store or cache a context for later
570
571As long as a context exists for a given hub, all tools that try to get a
572context will get the existing instance. If you try to store the context you
573will pollute other tools with incorrect context information.
574
575If you are certain that you want to save the context for later, you can use a
576snapshot. C<< $ctx->snapshot >> will give you a shallow clone of the context
577that is safe to pass around or store.
578
579C<context()> has some mechanisms to protect you if you do cause a context to
580persist beyond the scope in which it was obtained. In practice you should not
581rely on these protections, and they are fairly noisy with warnings.
582
583=item You SHOULD obtain your context as soon as possible in a given tool
584
585You never know what tools you call from within your own tool will need a
586context. Obtaining the context early ensures that nested tools can find the
587context you want them to find.
588
589=back
590
591=head1 METHODS
592
593=over 4
594
595=item $ctx->done_testing;
596
597Note that testing is finished. If no plan has been set this will generate a
598Plan event.
599
600=item $clone = $ctx->snapshot()
601
602This will return a shallow clone of the context. The shallow clone is safe to
603store for later.
604
605=item $ctx->release()
606
607This will release the context. This runs cleanup tasks, and several important
608hooks. It will also restore C<$!>, C<$?>, and C<$@> to what they were when the
609context was created.
610
611B<Note:> If a context is acquired more than once an internal refcount is kept.
612C<release()> decrements the ref count, none of the other actions of
613C<release()> will occur unless the refcount hits 0. This means only the last
614call to C<release()> will reset C<$?>, C<$!>, C<$@>, and run the cleanup tasks.
615
616=item $ctx->throw($message)
617
618This will throw an exception reporting to the file and line number of the
619context. This will also release the context for you.
620
621=item $ctx->alert($message)
622
623This will issue a warning from the file and line number of the context.
624
625=item $stack = $ctx->stack()
626
627This will return the L<Test2::API::Stack> instance the context used to find
628the current hub.
629
630=item $hub = $ctx->hub()
631
632This will return the L<Test2::Hub> instance the context recognizes as the
633current one to which all events should be sent.
634
635=item $dbg = $ctx->trace()
636
637This will return the L<Test2::EventFacet::Trace> instance used by the context.
638
639=item $ctx->do_in_context(\&code, @args);
640
641Sometimes you have a context that is not current, and you want things to use it
642as the current one. In these cases you can call
643C<< $ctx->do_in_context(sub { ... }) >>. The codeblock will be run, and
644anything inside of it that looks for a context will find the one on which the
645method was called.
646
647This B<DOES NOT> affect context on other hubs, only the hub used by the context
648will be affected.
649
650    my $ctx = ...;
651    $ctx->do_in_context(sub {
652        my $ctx = context(); # returns the $ctx the sub is called on
653    });
654
655B<Note:> The context will actually be cloned, the clone will be used instead of
656the original. This allows the thread id, process id, and error variables to be correct without
657modifying the original context.
658
659=item $ctx->restore_error_vars()
660
661This will set C<$!>, C<$?>, and C<$@> to what they were when the context was
662created. There is no localization or anything done here, calling this method
663will actually set these vars.
664
665=item $! = $ctx->errno()
666
667The (numeric) value of C<$!> when the context was created.
668
669=item $? = $ctx->child_error()
670
671The value of C<$?> when the context was created.
672
673=item $@ = $ctx->eval_error()
674
675The value of C<$@> when the context was created.
676
677=back
678
679=head2 EVENT PRODUCTION METHODS
680
681B<Which one do I use?>
682
683The C<pass*> and C<fail*> are optimal if they meet your situation, using one of
684them will always be the most optimal. That said they are optimal by eliminating
685many features.
686
687Method such as C<ok>, and C<note> are shortcuts for generating common 1-task
688events based on the old API, however they are forward compatible, and easy to
689use. If these meet your needs then go ahead and use them, but please check back
690often for alternatives that may be added.
691
692If you want to generate new style events, events that do many things at once,
693then you want the C<*ev2*> methods. These let you directly specify which facets
694you wish to use.
695
696=over 4
697
698=item $event = $ctx->pass()
699
700=item $event = $ctx->pass($name)
701
702This will send and return an L<Test2::Event::Pass> event. You may optionally
703provide a C<$name> for the assertion.
704
705The L<Test2::Event::Pass> is a specially crafted and optimized event, using
706this will help the performance of passing tests.
707
708=item $true = $ctx->pass_and_release()
709
710=item $true = $ctx->pass_and_release($name)
711
712This is a combination of C<pass()> and C<release()>. You can use this if you do
713not plan to do anything with the context after sending the event. This helps
714write more clear and compact code.
715
716    sub shorthand {
717        my ($bool, $name) = @_;
718        my $ctx = context();
719        return $ctx->pass_and_release($name) if $bool;
720
721        ... Handle a failure ...
722    }
723
724    sub longform {
725        my ($bool, $name) = @_;
726        my $ctx = context();
727
728        if ($bool) {
729            $ctx->pass($name);
730            $ctx->release;
731            return 1;
732        }
733
734        ... Handle a failure ...
735    }
736
737=item my $event = $ctx->fail()
738
739=item my $event = $ctx->fail($name)
740
741=item my $event = $ctx->fail($name, @diagnostics)
742
743This lets you send an L<Test2::Event::Fail> event. You may optionally provide a
744C<$name> and C<@diagnostics> messages.
745
746Diagnostics messages can be simple strings, data structures, or instances of
747L<Test2::EventFacet::Info::Table> (which are converted inline into the
748L<Test2::EventFacet::Info> structure).
749
750=item my $false = $ctx->fail_and_release()
751
752=item my $false = $ctx->fail_and_release($name)
753
754=item my $false = $ctx->fail_and_release($name, @diagnostics)
755
756This is a combination of C<fail()> and C<release()>. This can be used to write
757clearer and shorter code.
758
759    sub shorthand {
760        my ($bool, $name) = @_;
761        my $ctx = context();
762        return $ctx->fail_and_release($name) unless $bool;
763
764        ... Handle a success ...
765    }
766
767    sub longform {
768        my ($bool, $name) = @_;
769        my $ctx = context();
770
771        unless ($bool) {
772            $ctx->pass($name);
773            $ctx->release;
774            return 1;
775        }
776
777        ... Handle a success ...
778    }
779
780
781=item $event = $ctx->ok($bool, $name)
782
783=item $event = $ctx->ok($bool, $name, \@on_fail)
784
785B<NOTE:> Use of this method is discouraged in favor of C<pass()> and C<fail()>
786which produce L<Test2::Event::Pass> and L<Test2::Event::Fail> events. These
787newer event types are faster and less crufty.
788
789This will create an L<Test2::Event::Ok> object for you. If C<$bool> is false
790then an L<Test2::Event::Diag> event will be sent as well with details about the
791failure. If you do not want automatic diagnostics you should use the
792C<send_event()> method directly.
793
794The third argument C<\@on_fail>) is an optional set of diagnostics to be sent in
795the event of a test failure. Unlike with C<fail()> these diagnostics must be
796plain strings, data structures are not supported.
797
798=item $event = $ctx->note($message)
799
800Send an L<Test2::Event::Note>. This event prints a message to STDOUT.
801
802=item $event = $ctx->diag($message)
803
804Send an L<Test2::Event::Diag>. This event prints a message to STDERR.
805
806=item $event = $ctx->plan($max)
807
808=item $event = $ctx->plan(0, 'SKIP', $reason)
809
810This can be used to send an L<Test2::Event::Plan> event. This event
811usually takes either a number of tests you expect to run. Optionally you can
812set the expected count to 0 and give the 'SKIP' directive with a reason to
813cause all tests to be skipped.
814
815=item $event = $ctx->skip($name, $reason);
816
817Send an L<Test2::Event::Skip> event.
818
819=item $event = $ctx->bail($reason)
820
821This sends an L<Test2::Event::Bail> event. This event will completely
822terminate all testing.
823
824=item $event = $ctx->send_ev2(%facets)
825
826This lets you build and send a V2 event directly from facets. The event is
827returned after it is sent.
828
829This example sends a single assertion, a note (comment for stdout in
830Test::Builder talk) and sets the plan to 1.
831
832    my $event = $ctx->send_event(
833        plan   => {count => 1},
834        assert => {pass  => 1, details => "A passing assert"},
835        info => [{tag => 'NOTE', details => "This is a note"}],
836    );
837
838=item $event = $ctx->build_e2(%facets)
839
840This is the same as C<send_ev2()>, except it builds and returns the event
841without sending it.
842
843=item $event = $ctx->send_ev2_and_release($Type, %parameters)
844
845This is a combination of C<send_ev2()> and C<release()>.
846
847    sub shorthand {
848        my $ctx = context();
849        return $ctx->send_ev2_and_release(assert => {pass => 1, details => 'foo'});
850    }
851
852    sub longform {
853        my $ctx = context();
854        my $event = $ctx->send_ev2(assert => {pass => 1, details => 'foo'});
855        $ctx->release;
856        return $event;
857    }
858
859=item $event = $ctx->send_event($Type, %parameters)
860
861B<It is better to use send_ev2() in new code.>
862
863This lets you build and send an event of any type. The C<$Type> argument should
864be the event package name with C<Test2::Event::> left off, or a fully
865qualified package name prefixed with a '+'. The event is returned after it is
866sent.
867
868    my $event = $ctx->send_event('Ok', ...);
869
870or
871
872    my $event = $ctx->send_event('+Test2::Event::Ok', ...);
873
874=item $event = $ctx->build_event($Type, %parameters)
875
876B<It is better to use build_ev2() in new code.>
877
878This is the same as C<send_event()>, except it builds and returns the event
879without sending it.
880
881=item $event = $ctx->send_event_and_release($Type, %parameters)
882
883B<It is better to use send_ev2_and_release() in new code.>
884
885This is a combination of C<send_event()> and C<release()>.
886
887    sub shorthand {
888        my $ctx = context();
889        return $ctx->send_event_and_release(Pass => { name => 'foo' });
890    }
891
892    sub longform {
893        my $ctx = context();
894        my $event = $ctx->send_event(Pass => { name => 'foo' });
895        $ctx->release;
896        return $event;
897    }
898
899=back
900
901=head1 HOOKS
902
903There are 2 types of hooks, init hooks, and release hooks. As the names
904suggest, these hooks are triggered when contexts are created or released.
905
906=head2 INIT HOOKS
907
908These are called whenever a context is initialized. That means when a new
909instance is created. These hooks are B<NOT> called every time something
910requests a context, just when a new one is created.
911
912=head3 GLOBAL
913
914This is how you add a global init callback. Global callbacks happen for every
915context for any hub or stack.
916
917    Test2::API::test2_add_callback_context_init(sub {
918        my $ctx = shift;
919        ...
920    });
921
922=head3 PER HUB
923
924This is how you add an init callback for all contexts created for a given hub.
925These callbacks will not run for other hubs.
926
927    $hub->add_context_init(sub {
928        my $ctx = shift;
929        ...
930    });
931
932=head3 PER CONTEXT
933
934This is how you specify an init hook that will only run if your call to
935C<context()> generates a new context. The callback will be ignored if
936C<context()> is returning an existing context.
937
938    my $ctx = context(on_init => sub {
939        my $ctx = shift;
940        ...
941    });
942
943=head2 RELEASE HOOKS
944
945These are called whenever a context is released. That means when the last
946reference to the instance is about to be destroyed. These hooks are B<NOT>
947called every time C<< $ctx->release >> is called.
948
949=head3 GLOBAL
950
951This is how you add a global release callback. Global callbacks happen for every
952context for any hub or stack.
953
954    Test2::API::test2_add_callback_context_release(sub {
955        my $ctx = shift;
956        ...
957    });
958
959=head3 PER HUB
960
961This is how you add a release callback for all contexts created for a given
962hub. These callbacks will not run for other hubs.
963
964    $hub->add_context_release(sub {
965        my $ctx = shift;
966        ...
967    });
968
969=head3 PER CONTEXT
970
971This is how you add release callbacks directly to a context. The callback will
972B<ALWAYS> be added to the context that gets returned, it does not matter if a
973new one is generated, or if an existing one is returned.
974
975    my $ctx = context(on_release => sub {
976        my $ctx = shift;
977        ...
978    });
979
980=head1 THIRD PARTY META-DATA
981
982This object consumes L<Test2::Util::ExternalMeta> which provides a consistent
983way for you to attach meta-data to instances of this class. This is useful for
984tools, plugins, and other extensions.
985
986=head1 SOURCE
987
988The source code repository for Test2 can be found at
989L<https://github.com/Test-More/test-more/>.
990
991=head1 MAINTAINERS
992
993=over 4
994
995=item Chad Granum E<lt>exodist@cpan.orgE<gt>
996
997=back
998
999=head1 AUTHORS
1000
1001=over 4
1002
1003=item Chad Granum E<lt>exodist@cpan.orgE<gt>
1004
1005=item Kent Fredric E<lt>kentnl@cpan.orgE<gt>
1006
1007=back
1008
1009=head1 COPYRIGHT
1010
1011Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>.
1012
1013This program is free software; you can redistribute it and/or
1014modify it under the same terms as Perl itself.
1015
1016See L<https://dev.perl.org/licenses/>
1017
1018=cut
1019