xref: /openbsd-src/gnu/usr.bin/perl/cpan/Test-Simple/lib/Test2/API.pm (revision 5486feefcc8cb79b19e014ab332cc5dfd05b3b33)
15759b3d2Safresh1package Test2::API;
25759b3d2Safresh1use strict;
35759b3d2Safresh1use warnings;
45759b3d2Safresh1
5256a93a4Safresh1use Time::HiRes qw/time/;
65759b3d2Safresh1use Test2::Util qw/USE_THREADS/;
75759b3d2Safresh1
85759b3d2Safresh1BEGIN {
95759b3d2Safresh1    $ENV{TEST_ACTIVE} ||= 1;
105759b3d2Safresh1    $ENV{TEST2_ACTIVE} = 1;
115759b3d2Safresh1}
125759b3d2Safresh1
13*5486feefSafresh1our $VERSION = '1.302199';
145759b3d2Safresh1
155759b3d2Safresh1
165759b3d2Safresh1my $INST;
175759b3d2Safresh1my $ENDING = 0;
18de8cc8edSafresh1sub test2_unset_is_end { $ENDING = 0 }
195759b3d2Safresh1sub test2_get_is_end { $ENDING }
205759b3d2Safresh1
21de8cc8edSafresh1sub test2_set_is_end {
22de8cc8edSafresh1    my $before = $ENDING;
23de8cc8edSafresh1    ($ENDING) = @_ ? @_ : (1);
24de8cc8edSafresh1
25de8cc8edSafresh1    # Only send the event in a transition from false to true
26de8cc8edSafresh1    return if $before;
27de8cc8edSafresh1    return unless $ENDING;
28de8cc8edSafresh1
29de8cc8edSafresh1    return unless $INST;
30de8cc8edSafresh1    my $stack = $INST->stack or return;
31de8cc8edSafresh1    my $root = $stack->root or return;
32de8cc8edSafresh1
33de8cc8edSafresh1    return unless $root->count;
34de8cc8edSafresh1
35de8cc8edSafresh1    return unless $$ == $INST->pid;
36de8cc8edSafresh1    return unless get_tid() == $INST->tid;
37de8cc8edSafresh1
38de8cc8edSafresh1    my $trace = Test2::EventFacet::Trace->new(
39de8cc8edSafresh1        frame  => [__PACKAGE__, __FILE__, __LINE__, __PACKAGE__ . '::test2_set_is_end'],
40de8cc8edSafresh1    );
41de8cc8edSafresh1    my $ctx = Test2::API::Context->new(
42de8cc8edSafresh1        trace => $trace,
43de8cc8edSafresh1        hub   => $root,
44de8cc8edSafresh1    );
45de8cc8edSafresh1
46de8cc8edSafresh1    $ctx->send_ev2(control => { phase => 'END', details => 'Transition to END phase' });
47de8cc8edSafresh1
48de8cc8edSafresh1    1;
49de8cc8edSafresh1}
50de8cc8edSafresh1
515759b3d2Safresh1use Test2::API::Instance(\$INST);
525759b3d2Safresh1
535759b3d2Safresh1# Set the exit status
545759b3d2Safresh1END {
555759b3d2Safresh1    test2_set_is_end(); # See gh #16
565759b3d2Safresh1    $INST->set_exit();
575759b3d2Safresh1}
585759b3d2Safresh1
595759b3d2Safresh1sub CLONE {
605759b3d2Safresh1    my $init = test2_init_done();
615759b3d2Safresh1    my $load = test2_load_done();
625759b3d2Safresh1
635759b3d2Safresh1    return if $init && $load;
645759b3d2Safresh1
655759b3d2Safresh1    require Carp;
665759b3d2Safresh1    Carp::croak "Test2 must be fully loaded before you start a new thread!\n";
675759b3d2Safresh1}
685759b3d2Safresh1
695759b3d2Safresh1# See gh #16
705759b3d2Safresh1{
715759b3d2Safresh1    no warnings;
725759b3d2Safresh1    INIT { eval 'END { test2_set_is_end() }; 1' or die $@ }
735759b3d2Safresh1}
745759b3d2Safresh1
755759b3d2Safresh1BEGIN {
765759b3d2Safresh1    no warnings 'once';
775759b3d2Safresh1    if($] ge '5.014' || $ENV{T2_CHECK_DEPTH} || $Test2::API::DO_DEPTH_CHECK) {
785759b3d2Safresh1        *DO_DEPTH_CHECK = sub() { 1 };
795759b3d2Safresh1    }
805759b3d2Safresh1    else {
815759b3d2Safresh1        *DO_DEPTH_CHECK = sub() { 0 };
825759b3d2Safresh1    }
835759b3d2Safresh1}
845759b3d2Safresh1
855759b3d2Safresh1use Test2::EventFacet::Trace();
865759b3d2Safresh1use Test2::Util::Trace(); # Legacy
875759b3d2Safresh1
885759b3d2Safresh1use Test2::Hub::Subtest();
895759b3d2Safresh1use Test2::Hub::Interceptor();
905759b3d2Safresh1use Test2::Hub::Interceptor::Terminator();
915759b3d2Safresh1
925759b3d2Safresh1use Test2::Event::Ok();
935759b3d2Safresh1use Test2::Event::Diag();
945759b3d2Safresh1use Test2::Event::Note();
955759b3d2Safresh1use Test2::Event::Plan();
965759b3d2Safresh1use Test2::Event::Bail();
975759b3d2Safresh1use Test2::Event::Exception();
985759b3d2Safresh1use Test2::Event::Waiting();
995759b3d2Safresh1use Test2::Event::Skip();
1005759b3d2Safresh1use Test2::Event::Subtest();
1015759b3d2Safresh1
1025759b3d2Safresh1use Carp qw/carp croak confess/;
1035759b3d2Safresh1use Scalar::Util qw/blessed weaken/;
104f3efcd01Safresh1use Test2::Util qw/get_tid clone_io pkg_to_file gen_uid/;
1055759b3d2Safresh1
1065759b3d2Safresh1our @EXPORT_OK = qw{
1075759b3d2Safresh1    context release
1085759b3d2Safresh1    context_do
1095759b3d2Safresh1    no_context
1105759b3d2Safresh1    intercept intercept_deep
1115759b3d2Safresh1    run_subtest
1125759b3d2Safresh1
1135759b3d2Safresh1    test2_init_done
1145759b3d2Safresh1    test2_load_done
1155759b3d2Safresh1    test2_load
1165759b3d2Safresh1    test2_start_preload
1175759b3d2Safresh1    test2_stop_preload
1185759b3d2Safresh1    test2_in_preload
119de8cc8edSafresh1    test2_is_testing_done
1205759b3d2Safresh1
1215759b3d2Safresh1    test2_set_is_end
122de8cc8edSafresh1    test2_unset_is_end
1235759b3d2Safresh1    test2_get_is_end
1245759b3d2Safresh1
1255759b3d2Safresh1    test2_pid
1265759b3d2Safresh1    test2_tid
1275759b3d2Safresh1    test2_stack
1285759b3d2Safresh1    test2_no_wait
1295759b3d2Safresh1    test2_ipc_wait_enable
1305759b3d2Safresh1    test2_ipc_wait_disable
1315759b3d2Safresh1    test2_ipc_wait_enabled
1325759b3d2Safresh1
1335759b3d2Safresh1    test2_add_uuid_via
1345759b3d2Safresh1
135f3efcd01Safresh1    test2_add_callback_testing_done
136f3efcd01Safresh1
1375759b3d2Safresh1    test2_add_callback_context_aquire
1385759b3d2Safresh1    test2_add_callback_context_acquire
1395759b3d2Safresh1    test2_add_callback_context_init
1405759b3d2Safresh1    test2_add_callback_context_release
1415759b3d2Safresh1    test2_add_callback_exit
1425759b3d2Safresh1    test2_add_callback_post_load
1435759b3d2Safresh1    test2_add_callback_pre_subtest
1445759b3d2Safresh1    test2_list_context_aquire_callbacks
1455759b3d2Safresh1    test2_list_context_acquire_callbacks
1465759b3d2Safresh1    test2_list_context_init_callbacks
1475759b3d2Safresh1    test2_list_context_release_callbacks
1485759b3d2Safresh1    test2_list_exit_callbacks
1495759b3d2Safresh1    test2_list_post_load_callbacks
1505759b3d2Safresh1    test2_list_pre_subtest_callbacks
1515759b3d2Safresh1
1525759b3d2Safresh1    test2_ipc
1535759b3d2Safresh1    test2_has_ipc
1545759b3d2Safresh1    test2_ipc_disable
1555759b3d2Safresh1    test2_ipc_disabled
1565759b3d2Safresh1    test2_ipc_drivers
1575759b3d2Safresh1    test2_ipc_add_driver
1585759b3d2Safresh1    test2_ipc_polling
1595759b3d2Safresh1    test2_ipc_disable_polling
1605759b3d2Safresh1    test2_ipc_enable_polling
1615759b3d2Safresh1    test2_ipc_get_pending
1625759b3d2Safresh1    test2_ipc_set_pending
1635759b3d2Safresh1    test2_ipc_get_timeout
1645759b3d2Safresh1    test2_ipc_set_timeout
1655759b3d2Safresh1
1665759b3d2Safresh1    test2_formatter
1675759b3d2Safresh1    test2_formatters
1685759b3d2Safresh1    test2_formatter_add
1695759b3d2Safresh1    test2_formatter_set
1705759b3d2Safresh1
1715759b3d2Safresh1    test2_stdout
1725759b3d2Safresh1    test2_stderr
1735759b3d2Safresh1    test2_reset_io
174*5486feefSafresh1
175*5486feefSafresh1    test2_enable_trace_stamps
176*5486feefSafresh1    test2_disable_trace_stamps
177*5486feefSafresh1    test2_trace_stamps_enabled
1785759b3d2Safresh1};
1795759b3d2Safresh1BEGIN { require Exporter; our @ISA = qw(Exporter) }
1805759b3d2Safresh1
1815759b3d2Safresh1my $STACK       = $INST->stack;
1825759b3d2Safresh1my $CONTEXTS    = $INST->contexts;
1835759b3d2Safresh1my $INIT_CBS    = $INST->context_init_callbacks;
1845759b3d2Safresh1my $ACQUIRE_CBS = $INST->context_acquire_callbacks;
1855759b3d2Safresh1
1865759b3d2Safresh1my $STDOUT = clone_io(\*STDOUT);
1875759b3d2Safresh1my $STDERR = clone_io(\*STDERR);
1885759b3d2Safresh1sub test2_stdout { $STDOUT ||= clone_io(\*STDOUT) }
1895759b3d2Safresh1sub test2_stderr { $STDERR ||= clone_io(\*STDERR) }
1905759b3d2Safresh1
1915759b3d2Safresh1sub test2_post_preload_reset {
1925759b3d2Safresh1    test2_reset_io();
1935759b3d2Safresh1    $INST->post_preload_reset;
1945759b3d2Safresh1}
1955759b3d2Safresh1
1965759b3d2Safresh1sub test2_reset_io {
1975759b3d2Safresh1    $STDOUT = clone_io(\*STDOUT);
1985759b3d2Safresh1    $STDERR = clone_io(\*STDERR);
1995759b3d2Safresh1}
2005759b3d2Safresh1
2015759b3d2Safresh1sub test2_init_done { $INST->finalized }
2025759b3d2Safresh1sub test2_load_done { $INST->loaded }
2035759b3d2Safresh1
2045759b3d2Safresh1sub test2_load          { $INST->load }
2055759b3d2Safresh1sub test2_start_preload { $ENV{T2_IN_PRELOAD} = 1; $INST->start_preload }
2065759b3d2Safresh1sub test2_stop_preload  { $ENV{T2_IN_PRELOAD} = 0; $INST->stop_preload }
2075759b3d2Safresh1sub test2_in_preload    { $INST->preload }
2085759b3d2Safresh1
2095759b3d2Safresh1sub test2_pid              { $INST->pid }
2105759b3d2Safresh1sub test2_tid              { $INST->tid }
2115759b3d2Safresh1sub test2_stack            { $INST->stack }
2125759b3d2Safresh1sub test2_ipc_wait_enable  { $INST->set_no_wait(0) }
2135759b3d2Safresh1sub test2_ipc_wait_disable { $INST->set_no_wait(1) }
2145759b3d2Safresh1sub test2_ipc_wait_enabled { !$INST->no_wait }
2155759b3d2Safresh1
216*5486feefSafresh1sub test2_enable_trace_stamps  { $INST->test2_enable_trace_stamps }
217*5486feefSafresh1sub test2_disable_trace_stamps { $INST->test2_disable_trace_stamps }
218*5486feefSafresh1sub test2_trace_stamps_enabled { $INST->test2_trace_stamps_enabled }
219*5486feefSafresh1
220de8cc8edSafresh1sub test2_is_testing_done {
221de8cc8edSafresh1    # No instance? VERY DONE!
222de8cc8edSafresh1    return 1 unless $INST;
223de8cc8edSafresh1
224de8cc8edSafresh1    # No stack? tests must be done, it is created pretty early
225de8cc8edSafresh1    my $stack = $INST->stack or return 1;
226de8cc8edSafresh1
227de8cc8edSafresh1    # Nothing on the stack, no root hub yet, likely have not started testing
228de8cc8edSafresh1    return 0 unless @$stack;
229de8cc8edSafresh1
230de8cc8edSafresh1    # Stack has a slot for the root hub (see above) but it is undefined, likely
231de8cc8edSafresh1    # garbage collected, test is done
232de8cc8edSafresh1    my $root_hub = $stack->[0] or return 1;
233de8cc8edSafresh1
234de8cc8edSafresh1    # If the root hub is ended than testing is done.
235de8cc8edSafresh1    return 1 if $root_hub->ended;
236de8cc8edSafresh1
237de8cc8edSafresh1    # Looks like we are still testing!
238de8cc8edSafresh1    return 0;
239de8cc8edSafresh1}
240de8cc8edSafresh1
2415759b3d2Safresh1sub test2_no_wait {
2425759b3d2Safresh1    $INST->set_no_wait(@_) if @_;
2435759b3d2Safresh1    $INST->no_wait;
2445759b3d2Safresh1}
2455759b3d2Safresh1
246f3efcd01Safresh1sub test2_add_callback_testing_done {
247f3efcd01Safresh1    my $cb = shift;
248f3efcd01Safresh1
249f3efcd01Safresh1    test2_add_callback_post_load(sub {
250f3efcd01Safresh1        my $stack = test2_stack();
251*5486feefSafresh1        $stack->top; # Ensure we have a hub
252f3efcd01Safresh1        my ($hub) = Test2::API::test2_stack->all;
253f3efcd01Safresh1
254f3efcd01Safresh1        $hub->set_active(1);
255f3efcd01Safresh1
256f3efcd01Safresh1        $hub->follow_up($cb);
257f3efcd01Safresh1    });
258f3efcd01Safresh1
259f3efcd01Safresh1    return;
260f3efcd01Safresh1}
261f3efcd01Safresh1
2625759b3d2Safresh1sub test2_add_callback_context_acquire   { $INST->add_context_acquire_callback(@_) }
2635759b3d2Safresh1sub test2_add_callback_context_aquire    { $INST->add_context_acquire_callback(@_) }
2645759b3d2Safresh1sub test2_add_callback_context_init      { $INST->add_context_init_callback(@_) }
2655759b3d2Safresh1sub test2_add_callback_context_release   { $INST->add_context_release_callback(@_) }
2665759b3d2Safresh1sub test2_add_callback_exit              { $INST->add_exit_callback(@_) }
2675759b3d2Safresh1sub test2_add_callback_post_load         { $INST->add_post_load_callback(@_) }
2685759b3d2Safresh1sub test2_add_callback_pre_subtest       { $INST->add_pre_subtest_callback(@_) }
2695759b3d2Safresh1sub test2_list_context_aquire_callbacks  { @{$INST->context_acquire_callbacks} }
2705759b3d2Safresh1sub test2_list_context_acquire_callbacks { @{$INST->context_acquire_callbacks} }
2715759b3d2Safresh1sub test2_list_context_init_callbacks    { @{$INST->context_init_callbacks} }
2725759b3d2Safresh1sub test2_list_context_release_callbacks { @{$INST->context_release_callbacks} }
2735759b3d2Safresh1sub test2_list_exit_callbacks            { @{$INST->exit_callbacks} }
2745759b3d2Safresh1sub test2_list_post_load_callbacks       { @{$INST->post_load_callbacks} }
2755759b3d2Safresh1sub test2_list_pre_subtest_callbacks     { @{$INST->pre_subtest_callbacks} }
2765759b3d2Safresh1
2775759b3d2Safresh1sub test2_add_uuid_via {
2785759b3d2Safresh1    $INST->set_add_uuid_via(@_) if @_;
2795759b3d2Safresh1    $INST->add_uuid_via();
2805759b3d2Safresh1}
2815759b3d2Safresh1
2825759b3d2Safresh1sub test2_ipc                 { $INST->ipc }
2835759b3d2Safresh1sub test2_has_ipc             { $INST->has_ipc }
2845759b3d2Safresh1sub test2_ipc_disable         { $INST->ipc_disable }
2855759b3d2Safresh1sub test2_ipc_disabled        { $INST->ipc_disabled }
2865759b3d2Safresh1sub test2_ipc_add_driver      { $INST->add_ipc_driver(@_) }
2875759b3d2Safresh1sub test2_ipc_drivers         { @{$INST->ipc_drivers} }
2885759b3d2Safresh1sub test2_ipc_polling         { $INST->ipc_polling }
2895759b3d2Safresh1sub test2_ipc_enable_polling  { $INST->enable_ipc_polling }
2905759b3d2Safresh1sub test2_ipc_disable_polling { $INST->disable_ipc_polling }
2915759b3d2Safresh1sub test2_ipc_get_pending     { $INST->get_ipc_pending }
2925759b3d2Safresh1sub test2_ipc_set_pending     { $INST->set_ipc_pending(@_) }
2935759b3d2Safresh1sub test2_ipc_set_timeout     { $INST->set_ipc_timeout(@_) }
2945759b3d2Safresh1sub test2_ipc_get_timeout     { $INST->ipc_timeout() }
295f3efcd01Safresh1sub test2_ipc_enable_shm      { 0 }
2965759b3d2Safresh1
2975759b3d2Safresh1sub test2_formatter     {
2985759b3d2Safresh1    if ($ENV{T2_FORMATTER} && $ENV{T2_FORMATTER} =~ m/^(\+)?(.*)$/) {
2995759b3d2Safresh1        my $formatter = $1 ? $2 : "Test2::Formatter::$2";
3005759b3d2Safresh1        my $file = pkg_to_file($formatter);
3015759b3d2Safresh1        require $file;
3025759b3d2Safresh1        return $formatter;
3035759b3d2Safresh1    }
3045759b3d2Safresh1
3055759b3d2Safresh1    return $INST->formatter;
3065759b3d2Safresh1}
3075759b3d2Safresh1
3085759b3d2Safresh1sub test2_formatters    { @{$INST->formatters} }
3095759b3d2Safresh1sub test2_formatter_add { $INST->add_formatter(@_) }
3105759b3d2Safresh1sub test2_formatter_set {
3115759b3d2Safresh1    my ($formatter) = @_;
3125759b3d2Safresh1    croak "No formatter specified" unless $formatter;
3135759b3d2Safresh1    croak "Global Formatter already set" if $INST->formatter_set;
3145759b3d2Safresh1    $INST->set_formatter($formatter);
3155759b3d2Safresh1}
3165759b3d2Safresh1
3175759b3d2Safresh1# Private, for use in Test2::API::Context
3185759b3d2Safresh1sub _contexts_ref                  { $INST->contexts }
3195759b3d2Safresh1sub _context_acquire_callbacks_ref { $INST->context_acquire_callbacks }
3205759b3d2Safresh1sub _context_init_callbacks_ref    { $INST->context_init_callbacks }
3215759b3d2Safresh1sub _context_release_callbacks_ref { $INST->context_release_callbacks }
3225759b3d2Safresh1sub _add_uuid_via_ref              { \($INST->{Test2::API::Instance::ADD_UUID_VIA()}) }
3235759b3d2Safresh1
3245759b3d2Safresh1# Private, for use in Test2::IPC
3255759b3d2Safresh1sub _set_ipc { $INST->set_ipc(@_) }
3265759b3d2Safresh1
3275759b3d2Safresh1sub context_do(&;@) {
3285759b3d2Safresh1    my $code = shift;
3295759b3d2Safresh1    my @args = @_;
3305759b3d2Safresh1
3315759b3d2Safresh1    my $ctx = context(level => 1);
3325759b3d2Safresh1
3335759b3d2Safresh1    my $want = wantarray;
3345759b3d2Safresh1
3355759b3d2Safresh1    my @out;
3365759b3d2Safresh1    my $ok = eval {
3375759b3d2Safresh1        $want          ? @out    = $code->($ctx, @args) :
3385759b3d2Safresh1        defined($want) ? $out[0] = $code->($ctx, @args) :
3395759b3d2Safresh1                                   $code->($ctx, @args) ;
3405759b3d2Safresh1        1;
3415759b3d2Safresh1    };
3425759b3d2Safresh1    my $err = $@;
3435759b3d2Safresh1
3445759b3d2Safresh1    $ctx->release;
3455759b3d2Safresh1
3465759b3d2Safresh1    die $err unless $ok;
3475759b3d2Safresh1
3485759b3d2Safresh1    return @out    if $want;
3495759b3d2Safresh1    return $out[0] if defined $want;
3505759b3d2Safresh1    return;
3515759b3d2Safresh1}
3525759b3d2Safresh1
3535759b3d2Safresh1sub no_context(&;$) {
3545759b3d2Safresh1    my ($code, $hid) = @_;
3555759b3d2Safresh1    $hid ||= $STACK->top->hid;
3565759b3d2Safresh1
3575759b3d2Safresh1    my $ctx = $CONTEXTS->{$hid};
3585759b3d2Safresh1    delete $CONTEXTS->{$hid};
3595759b3d2Safresh1    my $ok = eval { $code->(); 1 };
3605759b3d2Safresh1    my $err = $@;
3615759b3d2Safresh1
3625759b3d2Safresh1    $CONTEXTS->{$hid} = $ctx;
3635759b3d2Safresh1    weaken($CONTEXTS->{$hid});
3645759b3d2Safresh1
3655759b3d2Safresh1    die $err unless $ok;
3665759b3d2Safresh1
3675759b3d2Safresh1    return;
3685759b3d2Safresh1};
3695759b3d2Safresh1
3705759b3d2Safresh1my $UUID_VIA = _add_uuid_via_ref();
3715759b3d2Safresh1sub context {
3725759b3d2Safresh1    # We need to grab these before anything else to ensure they are not
3735759b3d2Safresh1    # changed.
3745759b3d2Safresh1    my ($errno, $eval_error, $child_error, $extended_error) = (0 + $!, $@, $?, $^E);
3755759b3d2Safresh1
3765759b3d2Safresh1    my %params = (level => 0, wrapped => 0, @_);
3775759b3d2Safresh1
3785759b3d2Safresh1    # If something is getting a context then the sync system needs to be
3795759b3d2Safresh1    # considered loaded...
3805759b3d2Safresh1    $INST->load unless $INST->{loaded};
3815759b3d2Safresh1
3825759b3d2Safresh1    croak "context() called, but return value is ignored"
3835759b3d2Safresh1        unless defined wantarray;
3845759b3d2Safresh1
3855759b3d2Safresh1    my $stack   = $params{stack} || $STACK;
3865759b3d2Safresh1    my $hub     = $params{hub}   || (@$stack ? $stack->[-1] : $stack->top);
387de8cc8edSafresh1
388de8cc8edSafresh1    # Catch an edge case where we try to get context after the root hub has
389de8cc8edSafresh1    # been garbage collected resulting in a stack that has a single undef
390de8cc8edSafresh1    # hub
391*5486feefSafresh1    if (!($hub && $hub->{hid}) && !exists($params{hub}) && @$stack) {
392*5486feefSafresh1        my $msg;
393*5486feefSafresh1
394*5486feefSafresh1        if ($hub && !$hub->{hid}) {
395*5486feefSafresh1            $msg = Carp::longmess("$hub has no hid! (did you attempt a testing event after done_testing?). You may be relying on a tool or plugin that was based off an old Test2 that did not require hids.");
396*5486feefSafresh1        }
397*5486feefSafresh1        else {
398*5486feefSafresh1            $msg = Carp::longmess("Attempt to get Test2 context after testing has completed (did you attempt a testing event after done_testing?)");
399*5486feefSafresh1        }
400de8cc8edSafresh1
401de8cc8edSafresh1        # The error message is usually masked by the global destruction, so we have to print to STDER
402de8cc8edSafresh1        print STDERR $msg;
403de8cc8edSafresh1
404de8cc8edSafresh1        # Make sure this is a failure, we are probably already in END, so set $? to change the exit code
405de8cc8edSafresh1        $? = 1;
406de8cc8edSafresh1
407de8cc8edSafresh1        # Now we actually die to interrupt the program flow and avoid undefined his warnings
408de8cc8edSafresh1        die $msg;
409de8cc8edSafresh1    }
410de8cc8edSafresh1
4115759b3d2Safresh1    my $hid     = $hub->{hid};
4125759b3d2Safresh1    my $current = $CONTEXTS->{$hid};
4135759b3d2Safresh1
4145759b3d2Safresh1    $_->(\%params) for @$ACQUIRE_CBS;
4155759b3d2Safresh1    map $_->(\%params), @{$hub->{_context_acquire}} if $hub->{_context_acquire};
4165759b3d2Safresh1
4175759b3d2Safresh1    # This is for https://github.com/Test-More/test-more/issues/16
4185759b3d2Safresh1    # and https://rt.perl.org/Public/Bug/Display.html?id=127774
4195759b3d2Safresh1    my $phase = ${^GLOBAL_PHASE} || 'NA';
4205759b3d2Safresh1    my $end_phase = $ENDING || $phase eq 'END' || $phase eq 'DESTRUCT';
4215759b3d2Safresh1
4225759b3d2Safresh1    my $level = 1 + $params{level};
423256a93a4Safresh1    my ($pkg, $file, $line, $sub, @other) = $end_phase ? caller(0) : caller($level);
4245759b3d2Safresh1    unless ($pkg || $end_phase) {
4255759b3d2Safresh1        confess "Could not find context at depth $level" unless $params{fudge};
426256a93a4Safresh1        ($pkg, $file, $line, $sub, @other) = caller(--$level) while ($level >= 0 && !$pkg);
4275759b3d2Safresh1    }
4285759b3d2Safresh1
4295759b3d2Safresh1    my $depth = $level;
4305759b3d2Safresh1    $depth++ while DO_DEPTH_CHECK && !$end_phase && (!$current || $depth <= $current->{_depth} + $params{wrapped}) && caller($depth + 1);
4315759b3d2Safresh1    $depth -= $params{wrapped};
4325759b3d2Safresh1    my $depth_ok = !DO_DEPTH_CHECK || $end_phase || !$current || $current->{_depth} < $depth;
4335759b3d2Safresh1
4345759b3d2Safresh1    if ($current && $params{on_release} && $depth_ok) {
4355759b3d2Safresh1        $current->{_on_release} ||= [];
4365759b3d2Safresh1        push @{$current->{_on_release}} => $params{on_release};
4375759b3d2Safresh1    }
4385759b3d2Safresh1
4395759b3d2Safresh1    # I know this is ugly....
4405759b3d2Safresh1    ($!, $@, $?, $^E) = ($errno, $eval_error, $child_error, $extended_error) and return bless(
4415759b3d2Safresh1        {
4425759b3d2Safresh1            %$current,
4435759b3d2Safresh1            _is_canon   => undef,
4445759b3d2Safresh1            errno       => $errno,
4455759b3d2Safresh1            eval_error  => $eval_error,
4465759b3d2Safresh1            child_error => $child_error,
4475759b3d2Safresh1            _is_spawn   => [$pkg, $file, $line, $sub],
4485759b3d2Safresh1        },
4495759b3d2Safresh1        'Test2::API::Context'
4505759b3d2Safresh1    ) if $current && $depth_ok;
4515759b3d2Safresh1
4525759b3d2Safresh1    # Handle error condition of bad level
4535759b3d2Safresh1    if ($current) {
4545759b3d2Safresh1        unless (${$current->{_aborted}}) {
4555759b3d2Safresh1            _canon_error($current, [$pkg, $file, $line, $sub, $depth])
4565759b3d2Safresh1                unless $current->{_is_canon};
4575759b3d2Safresh1
4585759b3d2Safresh1            _depth_error($current, [$pkg, $file, $line, $sub, $depth])
4595759b3d2Safresh1                unless $depth_ok;
4605759b3d2Safresh1        }
4615759b3d2Safresh1
4625759b3d2Safresh1        $current->release if $current->{_is_canon};
4635759b3d2Safresh1
4645759b3d2Safresh1        delete $CONTEXTS->{$hid};
4655759b3d2Safresh1    }
4665759b3d2Safresh1
4675759b3d2Safresh1    # Directly bless the object here, calling new is a noticeable performance
4685759b3d2Safresh1    # hit with how often this needs to be called.
4695759b3d2Safresh1    my $trace = bless(
4705759b3d2Safresh1        {
4715759b3d2Safresh1            frame  => [$pkg, $file, $line, $sub],
4725759b3d2Safresh1            pid    => $$,
4735759b3d2Safresh1            tid    => get_tid(),
474f3efcd01Safresh1            cid    => gen_uid(),
4755759b3d2Safresh1            hid    => $hid,
4765759b3d2Safresh1            nested => $hub->{nested},
4775759b3d2Safresh1            buffered => $hub->{buffered},
4785759b3d2Safresh1
479256a93a4Safresh1            full_caller => [$pkg, $file, $line, $sub, @other],
480256a93a4Safresh1
481*5486feefSafresh1            $INST->{trace_stamps} ? (stamp => time()) : (),
482*5486feefSafresh1
4835759b3d2Safresh1            $$UUID_VIA ? (
4845759b3d2Safresh1                huuid => $hub->{uuid},
4855759b3d2Safresh1                uuid  => ${$UUID_VIA}->('context'),
4865759b3d2Safresh1            ) : (),
4875759b3d2Safresh1        },
4885759b3d2Safresh1        'Test2::EventFacet::Trace'
4895759b3d2Safresh1    );
4905759b3d2Safresh1
4915759b3d2Safresh1    # Directly bless the object here, calling new is a noticeable performance
4925759b3d2Safresh1    # hit with how often this needs to be called.
4935759b3d2Safresh1    my $aborted = 0;
4945759b3d2Safresh1    $current = bless(
4955759b3d2Safresh1        {
4965759b3d2Safresh1            _aborted     => \$aborted,
4975759b3d2Safresh1            stack        => $stack,
4985759b3d2Safresh1            hub          => $hub,
4995759b3d2Safresh1            trace        => $trace,
5005759b3d2Safresh1            _is_canon    => 1,
5015759b3d2Safresh1            _depth       => $depth,
5025759b3d2Safresh1            errno        => $errno,
5035759b3d2Safresh1            eval_error   => $eval_error,
5045759b3d2Safresh1            child_error  => $child_error,
5055759b3d2Safresh1            $params{on_release} ? (_on_release => [$params{on_release}]) : (),
5065759b3d2Safresh1        },
5075759b3d2Safresh1        'Test2::API::Context'
5085759b3d2Safresh1    );
5095759b3d2Safresh1
5105759b3d2Safresh1    $CONTEXTS->{$hid} = $current;
5115759b3d2Safresh1    weaken($CONTEXTS->{$hid});
5125759b3d2Safresh1
5135759b3d2Safresh1    $_->($current) for @$INIT_CBS;
5145759b3d2Safresh1    map $_->($current), @{$hub->{_context_init}} if $hub->{_context_init};
5155759b3d2Safresh1
5165759b3d2Safresh1    $params{on_init}->($current) if $params{on_init};
5175759b3d2Safresh1
5185759b3d2Safresh1    ($!, $@, $?, $^E) = ($errno, $eval_error, $child_error, $extended_error);
5195759b3d2Safresh1
5205759b3d2Safresh1    return $current;
5215759b3d2Safresh1}
5225759b3d2Safresh1
5235759b3d2Safresh1sub _depth_error {
5245759b3d2Safresh1    _existing_error(@_, <<"    EOT");
5255759b3d2Safresh1context() was called to retrieve an existing context, however the existing
5265759b3d2Safresh1context was created in a stack frame at the same, or deeper level. This usually
5275759b3d2Safresh1means that a tool failed to release the context when it was finished.
5285759b3d2Safresh1    EOT
5295759b3d2Safresh1}
5305759b3d2Safresh1
5315759b3d2Safresh1sub _canon_error {
5325759b3d2Safresh1    _existing_error(@_, <<"    EOT");
5335759b3d2Safresh1context() was called to retrieve an existing context, however the existing
5345759b3d2Safresh1context has an invalid internal state (!_canon_count). This should not normally
5355759b3d2Safresh1happen unless something is mucking about with internals...
5365759b3d2Safresh1    EOT
5375759b3d2Safresh1}
5385759b3d2Safresh1
5395759b3d2Safresh1sub _existing_error {
5405759b3d2Safresh1    my ($ctx, $details, $msg) = @_;
5415759b3d2Safresh1    my ($pkg, $file, $line, $sub, $depth) = @$details;
5425759b3d2Safresh1
5435759b3d2Safresh1    my $oldframe = $ctx->{trace}->frame;
5445759b3d2Safresh1    my $olddepth = $ctx->{_depth};
5455759b3d2Safresh1
5465759b3d2Safresh1    # Older versions of Carp do not export longmess() function, so it needs to be called with package name
5475759b3d2Safresh1    my $mess = Carp::longmess();
5485759b3d2Safresh1
5495759b3d2Safresh1    warn <<"    EOT";
5505759b3d2Safresh1$msg
5515759b3d2Safresh1Old context details:
5525759b3d2Safresh1   File: $oldframe->[1]
5535759b3d2Safresh1   Line: $oldframe->[2]
5545759b3d2Safresh1   Tool: $oldframe->[3]
5555759b3d2Safresh1  Depth: $olddepth
5565759b3d2Safresh1
5575759b3d2Safresh1New context details:
5585759b3d2Safresh1   File: $file
5595759b3d2Safresh1   Line: $line
5605759b3d2Safresh1   Tool: $sub
5615759b3d2Safresh1  Depth: $depth
5625759b3d2Safresh1
5635759b3d2Safresh1Trace: $mess
5645759b3d2Safresh1
5655759b3d2Safresh1Removing the old context and creating a new one...
5665759b3d2Safresh1    EOT
5675759b3d2Safresh1}
5685759b3d2Safresh1
5695759b3d2Safresh1sub release($;$) {
5705759b3d2Safresh1    $_[0]->release;
5715759b3d2Safresh1    return $_[1];
5725759b3d2Safresh1}
5735759b3d2Safresh1
5745759b3d2Safresh1sub intercept(&) {
5755759b3d2Safresh1    my $code = shift;
5765759b3d2Safresh1    my $ctx = context();
5775759b3d2Safresh1
5785759b3d2Safresh1    my $events = _intercept($code, deep => 0);
5795759b3d2Safresh1
5805759b3d2Safresh1    $ctx->release;
5815759b3d2Safresh1
5825759b3d2Safresh1    return $events;
5835759b3d2Safresh1}
5845759b3d2Safresh1
5855759b3d2Safresh1sub intercept_deep(&) {
5865759b3d2Safresh1    my $code = shift;
5875759b3d2Safresh1    my $ctx = context();
5885759b3d2Safresh1
5895759b3d2Safresh1    my $events = _intercept($code, deep => 1);
5905759b3d2Safresh1
5915759b3d2Safresh1    $ctx->release;
5925759b3d2Safresh1
5935759b3d2Safresh1    return $events;
5945759b3d2Safresh1}
5955759b3d2Safresh1
5965759b3d2Safresh1sub _intercept {
5975759b3d2Safresh1    my $code = shift;
5985759b3d2Safresh1    my %params = @_;
5995759b3d2Safresh1    my $ctx = context();
6005759b3d2Safresh1
6015759b3d2Safresh1    my $ipc;
6025759b3d2Safresh1    if (my $global_ipc = test2_ipc()) {
6035759b3d2Safresh1        my $driver = blessed($global_ipc);
6045759b3d2Safresh1        $ipc = $driver->new;
6055759b3d2Safresh1    }
6065759b3d2Safresh1
6075759b3d2Safresh1    my $hub = Test2::Hub::Interceptor->new(
6085759b3d2Safresh1        ipc => $ipc,
6095759b3d2Safresh1        no_ending => 1,
6105759b3d2Safresh1    );
6115759b3d2Safresh1
6125759b3d2Safresh1    my @events;
6135759b3d2Safresh1    $hub->listen(sub { push @events => $_[1] }, inherit => $params{deep});
6145759b3d2Safresh1
6155759b3d2Safresh1    $ctx->stack->top; # Make sure there is a top hub before we begin.
6165759b3d2Safresh1    $ctx->stack->push($hub);
6175759b3d2Safresh1
618256a93a4Safresh1    my $trace = $ctx->trace;
619256a93a4Safresh1    my $state = {};
620256a93a4Safresh1    $hub->clean_inherited(trace => $trace, state => $state);
621256a93a4Safresh1
6225759b3d2Safresh1    my ($ok, $err) = (1, undef);
6235759b3d2Safresh1    T2_SUBTEST_WRAPPER: {
6245759b3d2Safresh1        # Do not use 'try' cause it localizes __DIE__
6255759b3d2Safresh1        $ok = eval { $code->(hub => $hub, context => $ctx->snapshot); 1 };
6265759b3d2Safresh1        $err = $@;
6275759b3d2Safresh1
6285759b3d2Safresh1        # They might have done 'BEGIN { skip_all => "whatever" }'
6295759b3d2Safresh1        if (!$ok && $err =~ m/Label not found for "last T2_SUBTEST_WRAPPER"/ || (blessed($err) && $err->isa('Test2::Hub::Interceptor::Terminator'))) {
6305759b3d2Safresh1            $ok  = 1;
6315759b3d2Safresh1            $err = undef;
6325759b3d2Safresh1        }
6335759b3d2Safresh1    }
6345759b3d2Safresh1
6355759b3d2Safresh1    $hub->cull;
6365759b3d2Safresh1    $ctx->stack->pop($hub);
6375759b3d2Safresh1
638256a93a4Safresh1    $hub->restore_inherited(trace => $trace, state => $state);
639256a93a4Safresh1
6405759b3d2Safresh1    $ctx->release;
6415759b3d2Safresh1
6425759b3d2Safresh1    die $err unless $ok;
6435759b3d2Safresh1
6445759b3d2Safresh1    $hub->finalize($trace, 1)
6455759b3d2Safresh1        if $ok
6465759b3d2Safresh1        && !$hub->no_ending
6475759b3d2Safresh1        && !$hub->ended;
6485759b3d2Safresh1
649256a93a4Safresh1    require Test2::API::InterceptResult;
650256a93a4Safresh1    return Test2::API::InterceptResult->new_from_ref(\@events);
6515759b3d2Safresh1}
6525759b3d2Safresh1
6535759b3d2Safresh1sub run_subtest {
6545759b3d2Safresh1    my ($name, $code, $params, @args) = @_;
6555759b3d2Safresh1
6565759b3d2Safresh1    $_->($name,$code,@args)
6575759b3d2Safresh1        for Test2::API::test2_list_pre_subtest_callbacks();
6585759b3d2Safresh1
6595759b3d2Safresh1    $params = {buffered => $params} unless ref $params;
6605759b3d2Safresh1    my $inherit_trace = delete $params->{inherit_trace};
6615759b3d2Safresh1
6625759b3d2Safresh1    my $ctx = context();
6635759b3d2Safresh1
6645759b3d2Safresh1    my $parent = $ctx->hub;
6655759b3d2Safresh1
6665759b3d2Safresh1    # If a parent is buffered then the child must be as well.
6675759b3d2Safresh1    my $buffered = $params->{buffered} || $parent->{buffered};
6685759b3d2Safresh1
6695759b3d2Safresh1    $ctx->note($name) unless $buffered;
6705759b3d2Safresh1
6715759b3d2Safresh1    my $stack = $ctx->stack || $STACK;
6725759b3d2Safresh1    my $hub = $stack->new_hub(
6735759b3d2Safresh1        class => 'Test2::Hub::Subtest',
6745759b3d2Safresh1        %$params,
6755759b3d2Safresh1        buffered => $buffered,
6765759b3d2Safresh1    );
6775759b3d2Safresh1
6785759b3d2Safresh1    my @events;
6795759b3d2Safresh1    $hub->listen(sub { push @events => $_[1] });
6805759b3d2Safresh1
6815759b3d2Safresh1    if ($buffered) {
6825759b3d2Safresh1        if (my $format = $hub->format) {
6835759b3d2Safresh1            my $hide = $format->can('hide_buffered') ? $format->hide_buffered : 1;
6845759b3d2Safresh1            $hub->format(undef) if $hide;
6855759b3d2Safresh1        }
6865759b3d2Safresh1    }
6875759b3d2Safresh1
6885759b3d2Safresh1    if ($inherit_trace) {
6895759b3d2Safresh1        my $orig = $code;
6905759b3d2Safresh1        $code = sub {
6915759b3d2Safresh1            my $base_trace = $ctx->trace;
6925759b3d2Safresh1            my $trace = $base_trace->snapshot(nested => 1 + $base_trace->nested);
6935759b3d2Safresh1            my $st_ctx = Test2::API::Context->new(
6945759b3d2Safresh1                trace  => $trace,
6955759b3d2Safresh1                hub    => $hub,
6965759b3d2Safresh1            );
6975759b3d2Safresh1            $st_ctx->do_in_context($orig, @args);
6985759b3d2Safresh1        };
6995759b3d2Safresh1    }
7005759b3d2Safresh1
701256a93a4Safresh1    my $start_stamp = time;
702256a93a4Safresh1
7035759b3d2Safresh1    my ($ok, $err, $finished);
7045759b3d2Safresh1    T2_SUBTEST_WRAPPER: {
7055759b3d2Safresh1        # Do not use 'try' cause it localizes __DIE__
7065759b3d2Safresh1        $ok = eval { $code->(@args); 1 };
7075759b3d2Safresh1        $err = $@;
7085759b3d2Safresh1
7095759b3d2Safresh1        # They might have done 'BEGIN { skip_all => "whatever" }'
7105759b3d2Safresh1        if (!$ok && $err =~ m/Label not found for "last T2_SUBTEST_WRAPPER"/ || (blessed($err) && blessed($err) eq 'Test::Builder::Exception')) {
7115759b3d2Safresh1            $ok  = undef;
7125759b3d2Safresh1            $err = undef;
7135759b3d2Safresh1        }
7145759b3d2Safresh1        else {
7155759b3d2Safresh1            $finished = 1;
7165759b3d2Safresh1        }
7175759b3d2Safresh1    }
7185759b3d2Safresh1
719256a93a4Safresh1    my $stop_stamp = time;
720256a93a4Safresh1
7215759b3d2Safresh1    if ($params->{no_fork}) {
7225759b3d2Safresh1        if ($$ != $ctx->trace->pid) {
7235759b3d2Safresh1            warn $ok ? "Forked inside subtest, but subtest never finished!\n" : $err;
7245759b3d2Safresh1            exit 255;
7255759b3d2Safresh1        }
7265759b3d2Safresh1
7275759b3d2Safresh1        if (get_tid() != $ctx->trace->tid) {
7285759b3d2Safresh1            warn $ok ? "Started new thread inside subtest, but thread never finished!\n" : $err;
7295759b3d2Safresh1            exit 255;
7305759b3d2Safresh1        }
7315759b3d2Safresh1    }
7325759b3d2Safresh1    elsif (!$parent->is_local && !$parent->ipc) {
7335759b3d2Safresh1        warn $ok ? "A new process or thread was started inside subtest, but IPC is not enabled!\n" : $err;
7345759b3d2Safresh1        exit 255;
7355759b3d2Safresh1    }
7365759b3d2Safresh1
7375759b3d2Safresh1    $stack->pop($hub);
7385759b3d2Safresh1
7395759b3d2Safresh1    my $trace = $ctx->trace;
7405759b3d2Safresh1
7415759b3d2Safresh1    my $bailed = $hub->bailed_out;
7425759b3d2Safresh1
7435759b3d2Safresh1    if (!$finished) {
7445759b3d2Safresh1        if ($bailed && !$buffered) {
7455759b3d2Safresh1            $ctx->bail($bailed->reason);
7465759b3d2Safresh1        }
7475759b3d2Safresh1        elsif ($bailed && $buffered) {
7485759b3d2Safresh1            $ok = 1;
7495759b3d2Safresh1        }
7505759b3d2Safresh1        else {
7515759b3d2Safresh1            my $code = $hub->exit_code;
7525759b3d2Safresh1            $ok = !$code;
7535759b3d2Safresh1            $err = "Subtest ended with exit code $code" if $code;
7545759b3d2Safresh1        }
7555759b3d2Safresh1    }
7565759b3d2Safresh1
7575759b3d2Safresh1    $hub->finalize($trace->snapshot(huuid => $hub->uuid, hid => $hub->hid, nested => $hub->nested, buffered => $buffered), 1)
7585759b3d2Safresh1        if $ok
7595759b3d2Safresh1        && !$hub->no_ending
7605759b3d2Safresh1        && !$hub->ended;
7615759b3d2Safresh1
7625759b3d2Safresh1    my $pass = $ok && $hub->is_passing;
7635759b3d2Safresh1    my $e = $ctx->build_event(
7645759b3d2Safresh1        'Subtest',
7655759b3d2Safresh1        pass         => $pass,
7665759b3d2Safresh1        name         => $name,
7675759b3d2Safresh1        subtest_id   => $hub->id,
7685759b3d2Safresh1        subtest_uuid => $hub->uuid,
7695759b3d2Safresh1        buffered     => $buffered,
7705759b3d2Safresh1        subevents    => \@events,
771256a93a4Safresh1        start_stamp  => $start_stamp,
772256a93a4Safresh1        stop_stamp   => $stop_stamp,
7735759b3d2Safresh1    );
7745759b3d2Safresh1
7755759b3d2Safresh1    my $plan_ok = $hub->check_plan;
7765759b3d2Safresh1
7775759b3d2Safresh1    $ctx->hub->send($e);
7785759b3d2Safresh1
7795759b3d2Safresh1    $ctx->failure_diag($e) unless $e->pass;
7805759b3d2Safresh1
7815759b3d2Safresh1    $ctx->diag("Caught exception in subtest: $err") unless $ok;
7825759b3d2Safresh1
7835759b3d2Safresh1    $ctx->diag("Bad subtest plan, expected " . $hub->plan . " but ran " . $hub->count)
7845759b3d2Safresh1        if defined($plan_ok) && !$plan_ok;
7855759b3d2Safresh1
7865759b3d2Safresh1    $ctx->bail($bailed->reason) if $bailed && $buffered;
7875759b3d2Safresh1
7885759b3d2Safresh1    $ctx->release;
7895759b3d2Safresh1    return $pass;
7905759b3d2Safresh1}
7915759b3d2Safresh1
7925759b3d2Safresh1# There is a use-cycle between API and API/Context. Context needs to use some
7935759b3d2Safresh1# API functions as the package is compiling. Test2::API::context() needs
7945759b3d2Safresh1# Test2::API::Context to be loaded, but we cannot 'require' the module there as
7955759b3d2Safresh1# it causes a very noticeable performance impact with how often context() is
7965759b3d2Safresh1# called.
7975759b3d2Safresh1require Test2::API::Context;
7985759b3d2Safresh1
7995759b3d2Safresh11;
8005759b3d2Safresh1
8015759b3d2Safresh1__END__
8025759b3d2Safresh1
8035759b3d2Safresh1=pod
8045759b3d2Safresh1
8055759b3d2Safresh1=encoding UTF-8
8065759b3d2Safresh1
8075759b3d2Safresh1=head1 NAME
8085759b3d2Safresh1
8095759b3d2Safresh1Test2::API - Primary interface for writing Test2 based testing tools.
8105759b3d2Safresh1
8115759b3d2Safresh1=head1 ***INTERNALS NOTE***
8125759b3d2Safresh1
8135759b3d2Safresh1B<The internals of this package are subject to change at any time!> The public
8145759b3d2Safresh1methods provided will not change in backwards-incompatible ways (once there is
8155759b3d2Safresh1a stable release), but the underlying implementation details might.
8165759b3d2Safresh1B<Do not break encapsulation here!>
8175759b3d2Safresh1
8185759b3d2Safresh1Currently the implementation is to create a single instance of the
8195759b3d2Safresh1L<Test2::API::Instance> Object. All class methods defer to the single
8205759b3d2Safresh1instance. There is no public access to the singleton, and that is intentional.
8215759b3d2Safresh1The class methods provided by this package provide the only functionality
8225759b3d2Safresh1publicly exposed.
8235759b3d2Safresh1
8245759b3d2Safresh1This is done primarily to avoid the problems Test::Builder had by exposing its
8255759b3d2Safresh1singleton. We do not want anyone to replace this singleton, rebless it, or
8265759b3d2Safresh1directly muck with its internals. If you need to do something and cannot
8275759b3d2Safresh1because of the restrictions placed here, then please report it as an issue. If
8285759b3d2Safresh1possible, we will create a way for you to implement your functionality without
8295759b3d2Safresh1exposing things that should not be exposed.
8305759b3d2Safresh1
8315759b3d2Safresh1=head1 DESCRIPTION
8325759b3d2Safresh1
8335759b3d2Safresh1This package exports all the functions necessary to write and/or verify testing
8345759b3d2Safresh1tools. Using these building blocks you can begin writing test tools very
8355759b3d2Safresh1quickly. You are also provided with tools that help you to test the tools you
8365759b3d2Safresh1write.
8375759b3d2Safresh1
8385759b3d2Safresh1=head1 SYNOPSIS
8395759b3d2Safresh1
8405759b3d2Safresh1=head2 WRITING A TOOL
8415759b3d2Safresh1
8425759b3d2Safresh1The C<context()> method is your primary interface into the Test2 framework.
8435759b3d2Safresh1
8445759b3d2Safresh1    package My::Ok;
8455759b3d2Safresh1    use Test2::API qw/context/;
8465759b3d2Safresh1
8475759b3d2Safresh1    our @EXPORT = qw/my_ok/;
8485759b3d2Safresh1    use base 'Exporter';
8495759b3d2Safresh1
8505759b3d2Safresh1    # Just like ok() from Test::More
8515759b3d2Safresh1    sub my_ok($;$) {
8525759b3d2Safresh1        my ($bool, $name) = @_;
8535759b3d2Safresh1        my $ctx = context(); # Get a context
8545759b3d2Safresh1        $ctx->ok($bool, $name);
8555759b3d2Safresh1        $ctx->release; # Release the context
8565759b3d2Safresh1        return $bool;
8575759b3d2Safresh1    }
8585759b3d2Safresh1
8595759b3d2Safresh1See L<Test2::API::Context> for a list of methods available on the context object.
8605759b3d2Safresh1
8615759b3d2Safresh1=head2 TESTING YOUR TOOLS
8625759b3d2Safresh1
8635759b3d2Safresh1The C<intercept { ... }> tool lets you temporarily intercept all events
8645759b3d2Safresh1generated by the test system:
8655759b3d2Safresh1
8665759b3d2Safresh1    use Test2::API qw/intercept/;
8675759b3d2Safresh1
8685759b3d2Safresh1    use My::Ok qw/my_ok/;
8695759b3d2Safresh1
8705759b3d2Safresh1    my $events = intercept {
8715759b3d2Safresh1        # These events are not displayed
8725759b3d2Safresh1        my_ok(1, "pass");
8735759b3d2Safresh1        my_ok(0, "fail");
8745759b3d2Safresh1    };
8755759b3d2Safresh1
876256a93a4Safresh1As of version 1.302178 this now returns an arrayref that is also an instance of
877256a93a4Safresh1L<Test2::API::InterceptResult>. See the L<Test2::API::InterceptResult>
878256a93a4Safresh1documentation for details on how to best use it.
8795759b3d2Safresh1
8805759b3d2Safresh1=head2 OTHER API FUNCTIONS
8815759b3d2Safresh1
8825759b3d2Safresh1    use Test2::API qw{
8835759b3d2Safresh1        test2_init_done
8845759b3d2Safresh1        test2_stack
8855759b3d2Safresh1        test2_set_is_end
8865759b3d2Safresh1        test2_get_is_end
8875759b3d2Safresh1        test2_ipc
8885759b3d2Safresh1        test2_formatter_set
8895759b3d2Safresh1        test2_formatter
890de8cc8edSafresh1        test2_is_testing_done
8915759b3d2Safresh1    };
8925759b3d2Safresh1
8935759b3d2Safresh1    my $init  = test2_init_done();
8945759b3d2Safresh1    my $stack = test2_stack();
8955759b3d2Safresh1    my $ipc   = test2_ipc();
8965759b3d2Safresh1
8975759b3d2Safresh1    test2_formatter_set($FORMATTER)
8985759b3d2Safresh1    my $formatter = test2_formatter();
8995759b3d2Safresh1
9005759b3d2Safresh1    ... And others ...
9015759b3d2Safresh1
9025759b3d2Safresh1=head1 MAIN API EXPORTS
9035759b3d2Safresh1
9045759b3d2Safresh1All exports are optional. You must specify subs to import.
9055759b3d2Safresh1
9065759b3d2Safresh1    use Test2::API qw/context intercept run_subtest/;
9075759b3d2Safresh1
9085759b3d2Safresh1This is the list of exports that are most commonly needed. If you are simply
9095759b3d2Safresh1writing a tool, then this is probably all you need. If you need something and
9105759b3d2Safresh1you cannot find it here, then you can also look at L</OTHER API EXPORTS>.
9115759b3d2Safresh1
9125759b3d2Safresh1These exports lack the 'test2_' prefix because of how important/common they
9135759b3d2Safresh1are. Exports in the L</OTHER API EXPORTS> section have the 'test2_' prefix to
9145759b3d2Safresh1ensure they stand out.
9155759b3d2Safresh1
9165759b3d2Safresh1=head2 context(...)
9175759b3d2Safresh1
9185759b3d2Safresh1Usage:
9195759b3d2Safresh1
9205759b3d2Safresh1=over 4
9215759b3d2Safresh1
9225759b3d2Safresh1=item $ctx = context()
9235759b3d2Safresh1
9245759b3d2Safresh1=item $ctx = context(%params)
9255759b3d2Safresh1
9265759b3d2Safresh1=back
9275759b3d2Safresh1
9285759b3d2Safresh1The C<context()> function will always return the current context. If
9295759b3d2Safresh1there is already a context active, it will be returned. If there is not an
9305759b3d2Safresh1active context, one will be generated. When a context is generated it will
9315759b3d2Safresh1default to using the file and line number where the currently running sub was
9325759b3d2Safresh1called from.
9335759b3d2Safresh1
9345759b3d2Safresh1Please see L<Test2::API::Context/"CRITICAL DETAILS"> for important rules about
9355759b3d2Safresh1what you can and cannot do with a context once it is obtained.
9365759b3d2Safresh1
9375759b3d2Safresh1B<Note> This function will throw an exception if you ignore the context object
9385759b3d2Safresh1it returns.
9395759b3d2Safresh1
940*5486feefSafresh1B<Note> On perls 5.14+ a depth check is used to ensure there are no context
9415759b3d2Safresh1leaks. This cannot be safely done on older perls due to
9425759b3d2Safresh1L<https://rt.perl.org/Public/Bug/Display.html?id=127774>
9435759b3d2Safresh1You can forcefully enable it either by setting C<$ENV{T2_CHECK_DEPTH} = 1> or
9445759b3d2Safresh1C<$Test2::API::DO_DEPTH_CHECK = 1> B<BEFORE> loading L<Test2::API>.
9455759b3d2Safresh1
9465759b3d2Safresh1=head3 OPTIONAL PARAMETERS
9475759b3d2Safresh1
9485759b3d2Safresh1All parameters to C<context> are optional.
9495759b3d2Safresh1
9505759b3d2Safresh1=over 4
9515759b3d2Safresh1
9525759b3d2Safresh1=item level => $int
9535759b3d2Safresh1
9545759b3d2Safresh1If you must obtain a context in a sub deeper than your entry point you can use
9555759b3d2Safresh1this to tell it how many EXTRA stack frames to look back. If this option is not
9565759b3d2Safresh1provided the default of C<0> is used.
9575759b3d2Safresh1
9585759b3d2Safresh1    sub third_party_tool {
9595759b3d2Safresh1        my $sub = shift;
9605759b3d2Safresh1        ... # Does not obtain a context
9615759b3d2Safresh1        $sub->();
9625759b3d2Safresh1        ...
9635759b3d2Safresh1    }
9645759b3d2Safresh1
9655759b3d2Safresh1    third_party_tool(sub {
9665759b3d2Safresh1        my $ctx = context(level => 1);
9675759b3d2Safresh1        ...
9685759b3d2Safresh1        $ctx->release;
9695759b3d2Safresh1    });
9705759b3d2Safresh1
9715759b3d2Safresh1=item wrapped => $int
9725759b3d2Safresh1
9735759b3d2Safresh1Use this if you need to write your own tool that wraps a call to C<context()>
9745759b3d2Safresh1with the intent that it should return a context object.
9755759b3d2Safresh1
9765759b3d2Safresh1    sub my_context {
9775759b3d2Safresh1        my %params = ( wrapped => 0, @_ );
9785759b3d2Safresh1        $params{wrapped}++;
9795759b3d2Safresh1        my $ctx = context(%params);
9805759b3d2Safresh1        ...
9815759b3d2Safresh1        return $ctx;
9825759b3d2Safresh1    }
9835759b3d2Safresh1
9845759b3d2Safresh1    sub my_tool {
9855759b3d2Safresh1        my $ctx = my_context();
9865759b3d2Safresh1        ...
9875759b3d2Safresh1        $ctx->release;
9885759b3d2Safresh1    }
9895759b3d2Safresh1
9905759b3d2Safresh1If you do not do this, then tools you call that also check for a context will
9915759b3d2Safresh1notice that the context they grabbed was created at the same stack depth, which
9925759b3d2Safresh1will trigger protective measures that warn you and destroy the existing
9935759b3d2Safresh1context.
9945759b3d2Safresh1
9955759b3d2Safresh1=item stack => $stack
9965759b3d2Safresh1
9975759b3d2Safresh1Normally C<context()> looks at the global hub stack. If you are maintaining
9985759b3d2Safresh1your own L<Test2::API::Stack> instance you may pass it in to be used
9995759b3d2Safresh1instead of the global one.
10005759b3d2Safresh1
10015759b3d2Safresh1=item hub => $hub
10025759b3d2Safresh1
10035759b3d2Safresh1Use this parameter if you want to obtain the context for a specific hub instead
10045759b3d2Safresh1of whatever one happens to be at the top of the stack.
10055759b3d2Safresh1
10065759b3d2Safresh1=item on_init => sub { ... }
10075759b3d2Safresh1
10085759b3d2Safresh1This lets you provide a callback sub that will be called B<ONLY> if your call
10095759b3d2Safresh1to C<context()> generated a new context. The callback B<WILL NOT> be called if
10105759b3d2Safresh1C<context()> is returning an existing context. The only argument passed into
10115759b3d2Safresh1the callback will be the context object itself.
10125759b3d2Safresh1
10135759b3d2Safresh1    sub foo {
10145759b3d2Safresh1        my $ctx = context(on_init => sub { 'will run' });
10155759b3d2Safresh1
10165759b3d2Safresh1        my $inner = sub {
10175759b3d2Safresh1            # This callback is not run since we are getting the existing
10185759b3d2Safresh1            # context from our parent sub.
10195759b3d2Safresh1            my $ctx = context(on_init => sub { 'will NOT run' });
10205759b3d2Safresh1            $ctx->release;
10215759b3d2Safresh1        }
10225759b3d2Safresh1        $inner->();
10235759b3d2Safresh1
10245759b3d2Safresh1        $ctx->release;
10255759b3d2Safresh1    }
10265759b3d2Safresh1
10275759b3d2Safresh1=item on_release => sub { ... }
10285759b3d2Safresh1
10295759b3d2Safresh1This lets you provide a callback sub that will be called when the context
10305759b3d2Safresh1instance is released. This callback will be added to the returned context even
10315759b3d2Safresh1if an existing context is returned. If multiple calls to context add callbacks,
10325759b3d2Safresh1then all will be called in reverse order when the context is finally released.
10335759b3d2Safresh1
10345759b3d2Safresh1    sub foo {
10355759b3d2Safresh1        my $ctx = context(on_release => sub { 'will run second' });
10365759b3d2Safresh1
10375759b3d2Safresh1        my $inner = sub {
10385759b3d2Safresh1            my $ctx = context(on_release => sub { 'will run first' });
10395759b3d2Safresh1
10405759b3d2Safresh1            # Neither callback runs on this release
10415759b3d2Safresh1            $ctx->release;
10425759b3d2Safresh1        }
10435759b3d2Safresh1        $inner->();
10445759b3d2Safresh1
10455759b3d2Safresh1        # Both callbacks run here.
10465759b3d2Safresh1        $ctx->release;
10475759b3d2Safresh1    }
10485759b3d2Safresh1
10495759b3d2Safresh1=back
10505759b3d2Safresh1
10515759b3d2Safresh1=head2 release($;$)
10525759b3d2Safresh1
10535759b3d2Safresh1Usage:
10545759b3d2Safresh1
10555759b3d2Safresh1=over 4
10565759b3d2Safresh1
10575759b3d2Safresh1=item release $ctx;
10585759b3d2Safresh1
10595759b3d2Safresh1=item release $ctx, ...;
10605759b3d2Safresh1
10615759b3d2Safresh1=back
10625759b3d2Safresh1
10635759b3d2Safresh1This is intended as a shortcut that lets you release your context and return a
10645759b3d2Safresh1value in one statement. This function will get your context, and an optional
10655759b3d2Safresh1return value. It will release your context, then return your value. Scalar
10665759b3d2Safresh1context is always assumed.
10675759b3d2Safresh1
10685759b3d2Safresh1    sub tool {
10695759b3d2Safresh1        my $ctx = context();
10705759b3d2Safresh1        ...
10715759b3d2Safresh1
10725759b3d2Safresh1        return release $ctx, 1;
10735759b3d2Safresh1    }
10745759b3d2Safresh1
10755759b3d2Safresh1This tool is most useful when you want to return the value you get from calling
10765759b3d2Safresh1a function that needs to see the current context:
10775759b3d2Safresh1
10785759b3d2Safresh1    my $ctx = context();
10795759b3d2Safresh1    my $out = some_tool(...);
10805759b3d2Safresh1    $ctx->release;
10815759b3d2Safresh1    return $out;
10825759b3d2Safresh1
10835759b3d2Safresh1We can combine the last 3 lines of the above like so:
10845759b3d2Safresh1
10855759b3d2Safresh1    my $ctx = context();
10865759b3d2Safresh1    release $ctx, some_tool(...);
10875759b3d2Safresh1
10885759b3d2Safresh1=head2 context_do(&;@)
10895759b3d2Safresh1
10905759b3d2Safresh1Usage:
10915759b3d2Safresh1
10925759b3d2Safresh1    sub my_tool {
10935759b3d2Safresh1        context_do {
10945759b3d2Safresh1            my $ctx = shift;
10955759b3d2Safresh1
10965759b3d2Safresh1            my (@args) = @_;
10975759b3d2Safresh1
10985759b3d2Safresh1            $ctx->ok(1, "pass");
10995759b3d2Safresh1
11005759b3d2Safresh1            ...
11015759b3d2Safresh1
11025759b3d2Safresh1            # No need to call $ctx->release, done for you on scope exit.
11035759b3d2Safresh1        } @_;
11045759b3d2Safresh1    }
11055759b3d2Safresh1
11065759b3d2Safresh1Using this inside your test tool takes care of a lot of boilerplate for you. It
11075759b3d2Safresh1will ensure a context is acquired. It will capture and rethrow any exception. It
1108*5486feefSafresh1will ensure the context is released when you are done. It preserves the
1109*5486feefSafresh1subroutine call context (list, scalar, void).
11105759b3d2Safresh1
11115759b3d2Safresh1This is the safest way to write a test tool. The only two downsides to this are a
11125759b3d2Safresh1slight performance decrease, and some extra indentation in your source. If the
11135759b3d2Safresh1indentation is a problem for you then you can take a peek at the next section.
11145759b3d2Safresh1
11155759b3d2Safresh1=head2 no_context(&;$)
11165759b3d2Safresh1
11175759b3d2Safresh1Usage:
11185759b3d2Safresh1
11195759b3d2Safresh1=over 4
11205759b3d2Safresh1
11215759b3d2Safresh1=item no_context { ... };
11225759b3d2Safresh1
11235759b3d2Safresh1=item no_context { ... } $hid;
11245759b3d2Safresh1
11255759b3d2Safresh1    sub my_tool(&) {
11265759b3d2Safresh1        my $code = shift;
11275759b3d2Safresh1        my $ctx = context();
11285759b3d2Safresh1        ...
11295759b3d2Safresh1
11305759b3d2Safresh1        no_context {
11315759b3d2Safresh1            # Things in here will not see our current context, they get a new
11325759b3d2Safresh1            # one.
11335759b3d2Safresh1
11345759b3d2Safresh1            $code->();
11355759b3d2Safresh1        };
11365759b3d2Safresh1
11375759b3d2Safresh1        ...
11385759b3d2Safresh1        $ctx->release;
11395759b3d2Safresh1    };
11405759b3d2Safresh1
11415759b3d2Safresh1=back
11425759b3d2Safresh1
11435759b3d2Safresh1This tool will hide a context for the provided block of code. This means any
11445759b3d2Safresh1tools run inside the block will get a completely new context if they acquire
11455759b3d2Safresh1one. The new context will be inherited by tools nested below the one that
11465759b3d2Safresh1acquired it.
11475759b3d2Safresh1
11485759b3d2Safresh1This will normally hide the current context for the top hub. If you need to
11495759b3d2Safresh1hide the context for a different hub you can pass in the optional C<$hid>
11505759b3d2Safresh1parameter.
11515759b3d2Safresh1
11525759b3d2Safresh1=head2 intercept(&)
11535759b3d2Safresh1
11545759b3d2Safresh1Usage:
11555759b3d2Safresh1
11565759b3d2Safresh1    my $events = intercept {
11575759b3d2Safresh1        ok(1, "pass");
11585759b3d2Safresh1        ok(0, "fail");
11595759b3d2Safresh1        ...
11605759b3d2Safresh1    };
11615759b3d2Safresh1
11625759b3d2Safresh1This function takes a codeblock as its only argument, and it has a prototype.
11635759b3d2Safresh1It will execute the codeblock, intercepting any generated events in the
11645759b3d2Safresh1process. It will return an array reference with all the generated event
11655759b3d2Safresh1objects. All events should be subclasses of L<Test2::Event>.
11665759b3d2Safresh1
1167256a93a4Safresh1As of version 1.302178 the events array that is returned is blssed as an
1168256a93a4Safresh1L<Test2::API::InterceptResult> instance. L<Test2::API::InterceptResult>
1169256a93a4Safresh1Provides a helpful interface for filtering and/or inspecting the events list
1170256a93a4Safresh1overall, or individual events within the list.
1171256a93a4Safresh1
1172256a93a4Safresh1This is intended to help you test your test code. This is not intended for
1173256a93a4Safresh1people simply writing tests.
11745759b3d2Safresh1
11755759b3d2Safresh1=head2 run_subtest(...)
11765759b3d2Safresh1
11775759b3d2Safresh1Usage:
11785759b3d2Safresh1
11795759b3d2Safresh1    run_subtest($NAME, \&CODE, $BUFFERED, @ARGS)
11805759b3d2Safresh1
11815759b3d2Safresh1    # or
11825759b3d2Safresh1
11835759b3d2Safresh1    run_subtest($NAME, \&CODE, \%PARAMS, @ARGS)
11845759b3d2Safresh1
11855759b3d2Safresh1This will run the provided codeblock with the args in C<@args>. This codeblock
11865759b3d2Safresh1will be run as a subtest. A subtest is an isolated test state that is condensed
11875759b3d2Safresh1into a single L<Test2::Event::Subtest> event, which contains all events
11885759b3d2Safresh1generated inside the subtest.
11895759b3d2Safresh1
11905759b3d2Safresh1=head3 ARGUMENTS:
11915759b3d2Safresh1
11925759b3d2Safresh1=over 4
11935759b3d2Safresh1
11945759b3d2Safresh1=item $NAME
11955759b3d2Safresh1
11965759b3d2Safresh1The name of the subtest.
11975759b3d2Safresh1
11985759b3d2Safresh1=item \&CODE
11995759b3d2Safresh1
12005759b3d2Safresh1The code to run inside the subtest.
12015759b3d2Safresh1
12025759b3d2Safresh1=item $BUFFERED or \%PARAMS
12035759b3d2Safresh1
12045759b3d2Safresh1If this is a simple scalar then it will be treated as a boolean for the
12055759b3d2Safresh1'buffered' setting. If this is a hash reference then it will be used as a
12065759b3d2Safresh1parameters hash. The param hash will be used for hub construction (with the
12075759b3d2Safresh1specified keys removed).
12085759b3d2Safresh1
12095759b3d2Safresh1Keys that are removed and used by run_subtest:
12105759b3d2Safresh1
12115759b3d2Safresh1=over 4
12125759b3d2Safresh1
12135759b3d2Safresh1=item 'buffered' => $bool
12145759b3d2Safresh1
12155759b3d2Safresh1Toggle buffered status.
12165759b3d2Safresh1
12175759b3d2Safresh1=item 'inherit_trace' => $bool
12185759b3d2Safresh1
12195759b3d2Safresh1Normally the subtest hub is pushed and the sub is allowed to generate its own
12205759b3d2Safresh1root context for the hub. When this setting is turned on a root context will be
12215759b3d2Safresh1created for the hub that shares the same trace as the current context.
12225759b3d2Safresh1
12235759b3d2Safresh1Set this to true if your tool is producing subtests without user-specified
12245759b3d2Safresh1subs.
12255759b3d2Safresh1
12265759b3d2Safresh1=item 'no_fork' => $bool
12275759b3d2Safresh1
12285759b3d2Safresh1Defaults to off. Normally forking inside a subtest will actually fork the
12295759b3d2Safresh1subtest, resulting in 2 final subtest events. This parameter will turn off that
12305759b3d2Safresh1behavior, only the original process/thread will return a final subtest event.
12315759b3d2Safresh1
12325759b3d2Safresh1=back
12335759b3d2Safresh1
12345759b3d2Safresh1=item @ARGS
12355759b3d2Safresh1
12365759b3d2Safresh1Any extra arguments you want passed into the subtest code.
12375759b3d2Safresh1
12385759b3d2Safresh1=back
12395759b3d2Safresh1
12405759b3d2Safresh1=head3 BUFFERED VS UNBUFFERED (OR STREAMED)
12415759b3d2Safresh1
12425759b3d2Safresh1Normally all events inside and outside a subtest are sent to the formatter
12435759b3d2Safresh1immediately by the hub. Sometimes it is desirable to hold off sending events
12445759b3d2Safresh1within a subtest until the subtest is complete. This usually depends on the
12455759b3d2Safresh1formatter being used.
12465759b3d2Safresh1
12475759b3d2Safresh1=over 4
12485759b3d2Safresh1
1249*5486feefSafresh1=item Things not affected by this flag
12505759b3d2Safresh1
12515759b3d2Safresh1In both cases events are generated and stored in an array. This array is
12525759b3d2Safresh1eventually used to populate the C<subevents> attribute on the
12535759b3d2Safresh1L<Test2::Event::Subtest> event that is generated at the end of the subtest.
12545759b3d2Safresh1This flag has no effect on this part, it always happens.
12555759b3d2Safresh1
12565759b3d2Safresh1At the end of the subtest, the final L<Test2::Event::Subtest> event is sent to
12575759b3d2Safresh1the formatter.
12585759b3d2Safresh1
1259*5486feefSafresh1=item Things that are affected by this flag
12605759b3d2Safresh1
12615759b3d2Safresh1The C<buffered> attribute of the L<Test2::Event::Subtest> event will be set to
12625759b3d2Safresh1the value of this flag. This means any formatter, listener, etc which looks at
12635759b3d2Safresh1the event will know if it was buffered.
12645759b3d2Safresh1
1265*5486feefSafresh1=item Things that are formatter dependent
12665759b3d2Safresh1
12675759b3d2Safresh1Events within a buffered subtest may or may not be sent to the formatter as
12685759b3d2Safresh1they happen. If a formatter fails to specify then the default is to B<NOT SEND>
12695759b3d2Safresh1the events as they are generated, instead the formatter can pull them from the
12705759b3d2Safresh1C<subevents> attribute.
12715759b3d2Safresh1
12725759b3d2Safresh1A formatter can specify by implementing the C<hide_buffered()> method. If this
12735759b3d2Safresh1method returns true then events generated inside a buffered subtest will not be
12745759b3d2Safresh1sent independently of the final subtest event.
12755759b3d2Safresh1
12765759b3d2Safresh1=back
12775759b3d2Safresh1
12785759b3d2Safresh1An example of how this is used is the L<Test2::Formatter::TAP> formatter. For
12795759b3d2Safresh1unbuffered subtests the events are rendered as they are generated. At the end
12805759b3d2Safresh1of the subtest, the final subtest event is rendered, but the C<subevents>
12815759b3d2Safresh1attribute is ignored. For buffered subtests the opposite occurs, the events are
12825759b3d2Safresh1NOT rendered as they are generated, instead the C<subevents> attribute is used
12835759b3d2Safresh1to render them all at once. This is useful when running subtests tests in
12845759b3d2Safresh1parallel, since without it the output from subtests would be interleaved
12855759b3d2Safresh1together.
12865759b3d2Safresh1
12875759b3d2Safresh1=head1 OTHER API EXPORTS
12885759b3d2Safresh1
12895759b3d2Safresh1Exports in this section are not commonly needed. These all have the 'test2_'
12905759b3d2Safresh1prefix to help ensure they stand out. You should look at the L</MAIN API
12915759b3d2Safresh1EXPORTS> section before looking here. This section is one where "Great power
12925759b3d2Safresh1comes with great responsibility". It is possible to break things badly if you
12935759b3d2Safresh1are not careful with these.
12945759b3d2Safresh1
12955759b3d2Safresh1All exports are optional. You need to list which ones you want at import time:
12965759b3d2Safresh1
12975759b3d2Safresh1    use Test2::API qw/test2_init_done .../;
12985759b3d2Safresh1
12995759b3d2Safresh1=head2 STATUS AND INITIALIZATION STATE
13005759b3d2Safresh1
13015759b3d2Safresh1These provide access to internal state and object instances.
13025759b3d2Safresh1
13035759b3d2Safresh1=over 4
13045759b3d2Safresh1
13055759b3d2Safresh1=item $bool = test2_init_done()
13065759b3d2Safresh1
13075759b3d2Safresh1This will return true if the stack and IPC instances have already been
13085759b3d2Safresh1initialized. It will return false if they have not. Init happens as late as
13095759b3d2Safresh1possible. It happens as soon as a tool requests the IPC instance, the
13105759b3d2Safresh1formatter, or the stack.
13115759b3d2Safresh1
13125759b3d2Safresh1=item $bool = test2_load_done()
13135759b3d2Safresh1
13145759b3d2Safresh1This will simply return the boolean value of the loaded flag. If Test2 has
13155759b3d2Safresh1finished loading this will be true, otherwise false. Loading is considered
13165759b3d2Safresh1complete the first time a tool requests a context.
13175759b3d2Safresh1
13185759b3d2Safresh1=item test2_set_is_end()
13195759b3d2Safresh1
13205759b3d2Safresh1=item test2_set_is_end($bool)
13215759b3d2Safresh1
13225759b3d2Safresh1This is used to toggle Test2's belief that the END phase has already started.
13235759b3d2Safresh1With no arguments this will set it to true. With arguments it will set it to
13245759b3d2Safresh1the first argument's value.
13255759b3d2Safresh1
13265759b3d2Safresh1This is used to prevent the use of C<caller()> in END blocks which can cause
13275759b3d2Safresh1segfaults. This is only necessary in some persistent environments that may have
13285759b3d2Safresh1multiple END phases.
13295759b3d2Safresh1
13305759b3d2Safresh1=item $bool = test2_get_is_end()
13315759b3d2Safresh1
13325759b3d2Safresh1Check if Test2 believes it is the END phase.
13335759b3d2Safresh1
13345759b3d2Safresh1=item $stack = test2_stack()
13355759b3d2Safresh1
13365759b3d2Safresh1This will return the global L<Test2::API::Stack> instance. If this has not
13375759b3d2Safresh1yet been initialized it will be initialized now.
13385759b3d2Safresh1
1339de8cc8edSafresh1=item $bool = test2_is_testing_done()
1340de8cc8edSafresh1
1341de8cc8edSafresh1This will return true if testing is complete and no other events should be
1342de8cc8edSafresh1sent. This is useful in things like warning handlers where you might want to
1343de8cc8edSafresh1turn warnings into events, but need them to start acting like normal warnings
1344de8cc8edSafresh1when testing is done.
1345de8cc8edSafresh1
1346de8cc8edSafresh1    $SIG{__WARN__} = sub {
1347de8cc8edSafresh1        my ($warning) = @_;
1348de8cc8edSafresh1
1349de8cc8edSafresh1        if (test2_is_testing_done()) {
1350de8cc8edSafresh1            warn @_;
1351de8cc8edSafresh1        }
1352de8cc8edSafresh1        else {
1353de8cc8edSafresh1            my $ctx = context();
1354de8cc8edSafresh1            ...
1355de8cc8edSafresh1            $ctx->release
1356de8cc8edSafresh1        }
1357de8cc8edSafresh1    }
1358de8cc8edSafresh1
13595759b3d2Safresh1=item test2_ipc_disable
13605759b3d2Safresh1
13615759b3d2Safresh1Disable IPC.
13625759b3d2Safresh1
1363*5486feefSafresh1=item $bool = test2_ipc_disabled
13645759b3d2Safresh1
13655759b3d2Safresh1Check if IPC is disabled.
13665759b3d2Safresh1
13675759b3d2Safresh1=item test2_ipc_wait_enable()
13685759b3d2Safresh1
13695759b3d2Safresh1=item test2_ipc_wait_disable()
13705759b3d2Safresh1
13715759b3d2Safresh1=item $bool = test2_ipc_wait_enabled()
13725759b3d2Safresh1
13735759b3d2Safresh1These can be used to turn IPC waiting on and off, or check the current value of
13745759b3d2Safresh1the flag.
13755759b3d2Safresh1
13765759b3d2Safresh1Waiting is turned on by default. Waiting will cause the parent process/thread
13775759b3d2Safresh1to wait until all child processes and threads are finished before exiting. You
13785759b3d2Safresh1will almost never want to turn this off.
13795759b3d2Safresh1
13805759b3d2Safresh1=item $bool = test2_no_wait()
13815759b3d2Safresh1
13825759b3d2Safresh1=item test2_no_wait($bool)
13835759b3d2Safresh1
13845759b3d2Safresh1B<DISCOURAGED>: This is a confusing interface, it is better to use
13855759b3d2Safresh1C<test2_ipc_wait_enable()>, C<test2_ipc_wait_disable()> and
13865759b3d2Safresh1C<test2_ipc_wait_enabled()>.
13875759b3d2Safresh1
13885759b3d2Safresh1This can be used to get/set the no_wait status. Waiting is turned on by
13895759b3d2Safresh1default. Waiting will cause the parent process/thread to wait until all child
13905759b3d2Safresh1processes and threads are finished before exiting. You will almost never want
13915759b3d2Safresh1to turn this off.
13925759b3d2Safresh1
13935759b3d2Safresh1=item $fh = test2_stdout()
13945759b3d2Safresh1
13955759b3d2Safresh1=item $fh = test2_stderr()
13965759b3d2Safresh1
13975759b3d2Safresh1These functions return the filehandles that test output should be written to.
13985759b3d2Safresh1They are primarily useful when writing a custom formatter and code that turns
1399f3efcd01Safresh1events into actual output (TAP, etc.).  They will return a dupe of the original
14005759b3d2Safresh1filehandles that formatted output can be sent to regardless of whatever state
14015759b3d2Safresh1the currently running test may have left STDOUT and STDERR in.
14025759b3d2Safresh1
14035759b3d2Safresh1=item test2_reset_io()
14045759b3d2Safresh1
14055759b3d2Safresh1Re-dupe the internal filehandles returned by C<test2_stdout()> and
14065759b3d2Safresh1C<test2_stderr()> from the current STDOUT and STDERR.  You shouldn't need to do
14075759b3d2Safresh1this except in very peculiar situations (for example, you're testing a new
14085759b3d2Safresh1formatter and you need control over where the formatter is sending its output.)
14095759b3d2Safresh1
14105759b3d2Safresh1=back
14115759b3d2Safresh1
14125759b3d2Safresh1=head2 BEHAVIOR HOOKS
14135759b3d2Safresh1
14145759b3d2Safresh1These are hooks that allow you to add custom behavior to actions taken by Test2
14155759b3d2Safresh1and tools built on top of it.
14165759b3d2Safresh1
14175759b3d2Safresh1=over 4
14185759b3d2Safresh1
14195759b3d2Safresh1=item test2_add_callback_exit(sub { ... })
14205759b3d2Safresh1
14215759b3d2Safresh1This can be used to add a callback that is called after all testing is done. This
14225759b3d2Safresh1is too late to add additional results, the main use of this callback is to set the
14235759b3d2Safresh1exit code.
14245759b3d2Safresh1
14255759b3d2Safresh1    test2_add_callback_exit(
14265759b3d2Safresh1        sub {
14275759b3d2Safresh1            my ($context, $exit, \$new_exit) = @_;
14285759b3d2Safresh1            ...
14295759b3d2Safresh1        }
14305759b3d2Safresh1    );
14315759b3d2Safresh1
14325759b3d2Safresh1The C<$context> passed in will be an instance of L<Test2::API::Context>. The
14335759b3d2Safresh1C<$exit> argument will be the original exit code before anything modified it.
14345759b3d2Safresh1C<$$new_exit> is a reference to the new exit code. You may modify this to
14355759b3d2Safresh1change the exit code. Please note that C<$$new_exit> may already be different
14365759b3d2Safresh1from C<$exit>
14375759b3d2Safresh1
14385759b3d2Safresh1=item test2_add_callback_post_load(sub { ... })
14395759b3d2Safresh1
14405759b3d2Safresh1Add a callback that will be called when Test2 is finished loading. This
14415759b3d2Safresh1means the callback will be run once, the first time a context is obtained.
14425759b3d2Safresh1If Test2 has already finished loading then the callback will be run immediately.
14435759b3d2Safresh1
1444f3efcd01Safresh1=item test2_add_callback_testing_done(sub { ... })
1445f3efcd01Safresh1
1446f3efcd01Safresh1This adds your coderef as a follow-up to the root hub after Test2 is finished loading.
1447f3efcd01Safresh1
1448f3efcd01Safresh1This is essentially a helper to do the following:
1449f3efcd01Safresh1
1450f3efcd01Safresh1    test2_add_callback_post_load(sub {
1451f3efcd01Safresh1        my $stack = test2_stack();
1452*5486feefSafresh1        $stack->top; # Ensure we have a hub
1453f3efcd01Safresh1        my ($hub) = Test2::API::test2_stack->all;
1454f3efcd01Safresh1
1455f3efcd01Safresh1        $hub->set_active(1);
1456f3efcd01Safresh1
1457f3efcd01Safresh1        $hub->follow_up(sub { ... }); # <-- Your coderef here
1458f3efcd01Safresh1    });
1459f3efcd01Safresh1
14605759b3d2Safresh1=item test2_add_callback_context_acquire(sub { ... })
14615759b3d2Safresh1
14625759b3d2Safresh1Add a callback that will be called every time someone tries to acquire a
14635759b3d2Safresh1context. This will be called on EVERY call to C<context()>. It gets a single
14645759b3d2Safresh1argument, a reference to the hash of parameters being used the construct the
14655759b3d2Safresh1context. This is your chance to change the parameters by directly altering the
14665759b3d2Safresh1hash.
14675759b3d2Safresh1
14685759b3d2Safresh1    test2_add_callback_context_acquire(sub {
14695759b3d2Safresh1        my $params = shift;
14705759b3d2Safresh1        $params->{level}++;
14715759b3d2Safresh1    });
14725759b3d2Safresh1
14735759b3d2Safresh1This is a very scary API function. Please do not use this unless you need to.
14745759b3d2Safresh1This is here for L<Test::Builder> and backwards compatibility. This has you
14755759b3d2Safresh1directly manipulate the hash instead of returning a new one for performance
14765759b3d2Safresh1reasons.
14775759b3d2Safresh1
14785759b3d2Safresh1=item test2_add_callback_context_init(sub { ... })
14795759b3d2Safresh1
14805759b3d2Safresh1Add a callback that will be called every time a new context is created. The
14815759b3d2Safresh1callback will receive the newly created context as its only argument.
14825759b3d2Safresh1
14835759b3d2Safresh1=item test2_add_callback_context_release(sub { ... })
14845759b3d2Safresh1
14855759b3d2Safresh1Add a callback that will be called every time a context is released. The
14865759b3d2Safresh1callback will receive the released context as its only argument.
14875759b3d2Safresh1
14885759b3d2Safresh1=item test2_add_callback_pre_subtest(sub { ... })
14895759b3d2Safresh1
14905759b3d2Safresh1Add a callback that will be called every time a subtest is going to be
14915759b3d2Safresh1run. The callback will receive the subtest name, coderef, and any
14925759b3d2Safresh1arguments.
14935759b3d2Safresh1
14945759b3d2Safresh1=item @list = test2_list_context_acquire_callbacks()
14955759b3d2Safresh1
14965759b3d2Safresh1Return all the context acquire callback references.
14975759b3d2Safresh1
14985759b3d2Safresh1=item @list = test2_list_context_init_callbacks()
14995759b3d2Safresh1
15005759b3d2Safresh1Returns all the context init callback references.
15015759b3d2Safresh1
15025759b3d2Safresh1=item @list = test2_list_context_release_callbacks()
15035759b3d2Safresh1
15045759b3d2Safresh1Returns all the context release callback references.
15055759b3d2Safresh1
15065759b3d2Safresh1=item @list = test2_list_exit_callbacks()
15075759b3d2Safresh1
15085759b3d2Safresh1Returns all the exit callback references.
15095759b3d2Safresh1
15105759b3d2Safresh1=item @list = test2_list_post_load_callbacks()
15115759b3d2Safresh1
15125759b3d2Safresh1Returns all the post load callback references.
15135759b3d2Safresh1
15145759b3d2Safresh1=item @list = test2_list_pre_subtest_callbacks()
15155759b3d2Safresh1
15165759b3d2Safresh1Returns all the pre-subtest callback references.
15175759b3d2Safresh1
15185759b3d2Safresh1=item test2_add_uuid_via(sub { ... })
15195759b3d2Safresh1
15205759b3d2Safresh1=item $sub = test2_add_uuid_via()
15215759b3d2Safresh1
15225759b3d2Safresh1This allows you to provide a UUID generator. If provided UUIDs will be attached
15235759b3d2Safresh1to all events, hubs, and contexts. This is useful for storing, tracking, and
15245759b3d2Safresh1linking these objects.
15255759b3d2Safresh1
15265759b3d2Safresh1The sub you provide should always return a unique identifier. Most things will
15275759b3d2Safresh1expect a proper UUID string, however nothing in Test2::API enforces this.
15285759b3d2Safresh1
15295759b3d2Safresh1The sub will receive exactly 1 argument, the type of thing being tagged
15305759b3d2Safresh1'context', 'hub', or 'event'. In the future additional things may be tagged, in
15315759b3d2Safresh1which case new strings will be passed in. These are purely informative, you can
15325759b3d2Safresh1(and usually should) ignore them.
15335759b3d2Safresh1
15345759b3d2Safresh1=back
15355759b3d2Safresh1
15365759b3d2Safresh1=head2 IPC AND CONCURRENCY
15375759b3d2Safresh1
15385759b3d2Safresh1These let you access, or specify, the IPC system internals.
15395759b3d2Safresh1
15405759b3d2Safresh1=over 4
15415759b3d2Safresh1
15425759b3d2Safresh1=item $bool = test2_has_ipc()
15435759b3d2Safresh1
15445759b3d2Safresh1Check if IPC is enabled.
15455759b3d2Safresh1
15465759b3d2Safresh1=item $ipc = test2_ipc()
15475759b3d2Safresh1
15485759b3d2Safresh1This will return the global L<Test2::IPC::Driver> instance. If this has not yet
15495759b3d2Safresh1been initialized it will be initialized now.
15505759b3d2Safresh1
15515759b3d2Safresh1=item test2_ipc_add_driver($DRIVER)
15525759b3d2Safresh1
15535759b3d2Safresh1Add an IPC driver to the list. This will add the driver to the start of the
15545759b3d2Safresh1list.
15555759b3d2Safresh1
15565759b3d2Safresh1=item @drivers = test2_ipc_drivers()
15575759b3d2Safresh1
15585759b3d2Safresh1Get the list of IPC drivers.
15595759b3d2Safresh1
15605759b3d2Safresh1=item $bool = test2_ipc_polling()
15615759b3d2Safresh1
15625759b3d2Safresh1Check if polling is enabled.
15635759b3d2Safresh1
15645759b3d2Safresh1=item test2_ipc_enable_polling()
15655759b3d2Safresh1
15665759b3d2Safresh1Turn on polling. This will cull events from other processes and threads every
15675759b3d2Safresh1time a context is created.
15685759b3d2Safresh1
15695759b3d2Safresh1=item test2_ipc_disable_polling()
15705759b3d2Safresh1
15715759b3d2Safresh1Turn off IPC polling.
15725759b3d2Safresh1
15735759b3d2Safresh1=item test2_ipc_enable_shm()
15745759b3d2Safresh1
1575f3efcd01Safresh1Legacy, this is currently a no-op that returns 0;
15765759b3d2Safresh1
15775759b3d2Safresh1=item test2_ipc_set_pending($uniq_val)
15785759b3d2Safresh1
15795759b3d2Safresh1Tell other processes and events that an event is pending. C<$uniq_val> should
15805759b3d2Safresh1be a unique value no other thread/process will generate.
15815759b3d2Safresh1
15825759b3d2Safresh1B<Note:> After calling this C<test2_ipc_get_pending()> will return 1. This is
15835759b3d2Safresh1intentional, and not avoidable.
15845759b3d2Safresh1
15855759b3d2Safresh1=item $pending = test2_ipc_get_pending()
15865759b3d2Safresh1
15875759b3d2Safresh1This returns -1 if there is no way to check (assume yes)
15885759b3d2Safresh1
15895759b3d2Safresh1This returns 0 if there are (most likely) no pending events.
15905759b3d2Safresh1
15915759b3d2Safresh1This returns 1 if there are (likely) pending events. Upon return it will reset,
15925759b3d2Safresh1nothing else will be able to see that there were pending events.
15935759b3d2Safresh1
15945759b3d2Safresh1=item $timeout = test2_ipc_get_timeout()
15955759b3d2Safresh1
15965759b3d2Safresh1=item test2_ipc_set_timeout($timeout)
15975759b3d2Safresh1
15985759b3d2Safresh1Get/Set the timeout value for the IPC system. This timeout is how long the IPC
15995759b3d2Safresh1system will wait for child processes and threads to finish before aborting.
16005759b3d2Safresh1
16015759b3d2Safresh1The default value is C<30> seconds.
16025759b3d2Safresh1
16035759b3d2Safresh1=back
16045759b3d2Safresh1
16055759b3d2Safresh1=head2 MANAGING FORMATTERS
16065759b3d2Safresh1
16075759b3d2Safresh1These let you access, or specify, the formatters that can/should be used.
16085759b3d2Safresh1
16095759b3d2Safresh1=over 4
16105759b3d2Safresh1
16115759b3d2Safresh1=item $formatter = test2_formatter
16125759b3d2Safresh1
16135759b3d2Safresh1This will return the global formatter class. This is not an instance. By
16145759b3d2Safresh1default the formatter is set to L<Test2::Formatter::TAP>.
16155759b3d2Safresh1
16165759b3d2Safresh1You can override this default using the C<T2_FORMATTER> environment variable.
16175759b3d2Safresh1
16185759b3d2Safresh1Normally 'Test2::Formatter::' is prefixed to the value in the
16195759b3d2Safresh1environment variable:
16205759b3d2Safresh1
16215759b3d2Safresh1    $ T2_FORMATTER='TAP' perl test.t     # Use the Test2::Formatter::TAP formatter
16225759b3d2Safresh1    $ T2_FORMATTER='Foo' perl test.t     # Use the Test2::Formatter::Foo formatter
16235759b3d2Safresh1
16245759b3d2Safresh1If you want to specify a full module name you use the '+' prefix:
16255759b3d2Safresh1
16265759b3d2Safresh1    $ T2_FORMATTER='+Foo::Bar' perl test.t     # Use the Foo::Bar formatter
16275759b3d2Safresh1
16285759b3d2Safresh1=item test2_formatter_set($class_or_instance)
16295759b3d2Safresh1
16305759b3d2Safresh1Set the global formatter class. This can only be set once. B<Note:> This will
16315759b3d2Safresh1override anything specified in the 'T2_FORMATTER' environment variable.
16325759b3d2Safresh1
16335759b3d2Safresh1=item @formatters = test2_formatters()
16345759b3d2Safresh1
16355759b3d2Safresh1Get a list of all loaded formatters.
16365759b3d2Safresh1
16375759b3d2Safresh1=item test2_formatter_add($class_or_instance)
16385759b3d2Safresh1
16395759b3d2Safresh1Add a formatter to the list. Last formatter added is used at initialization. If
16405759b3d2Safresh1this is called after initialization a warning will be issued.
16415759b3d2Safresh1
16425759b3d2Safresh1=back
16435759b3d2Safresh1
1644*5486feefSafresh1=head2 TIME STAMPS
1645*5486feefSafresh1
1646*5486feefSafresh1You can enable or disable timestamps in trace facets. They are disabled by
1647*5486feefSafresh1default for compatibility and performance reasons.
1648*5486feefSafresh1
1649*5486feefSafresh1=over 4
1650*5486feefSafresh1
1651*5486feefSafresh1=item test2_enable_trace_stamps()
1652*5486feefSafresh1
1653*5486feefSafresh1Enable stamps in traces.
1654*5486feefSafresh1
1655*5486feefSafresh1=item test2_disable_trace_stamps()
1656*5486feefSafresh1
1657*5486feefSafresh1Disable stamps in traces.
1658*5486feefSafresh1
1659*5486feefSafresh1=item $bool = test2_trace_stamps_enabled()
1660*5486feefSafresh1
1661*5486feefSafresh1Check status of trace stamps.
1662*5486feefSafresh1
1663*5486feefSafresh1=back
1664*5486feefSafresh1
16655759b3d2Safresh1=head1 OTHER EXAMPLES
16665759b3d2Safresh1
16675759b3d2Safresh1See the C</Examples/> directory included in this distribution.
16685759b3d2Safresh1
16695759b3d2Safresh1=head1 SEE ALSO
16705759b3d2Safresh1
16715759b3d2Safresh1L<Test2::API::Context> - Detailed documentation of the context object.
16725759b3d2Safresh1
16735759b3d2Safresh1L<Test2::IPC> - The IPC system used for threading/fork support.
16745759b3d2Safresh1
16755759b3d2Safresh1L<Test2::Formatter> - Formatters such as TAP live here.
16765759b3d2Safresh1
16775759b3d2Safresh1L<Test2::Event> - Events live in this namespace.
16785759b3d2Safresh1
16795759b3d2Safresh1L<Test2::Hub> - All events eventually funnel through a hub. Custom hubs are how
16805759b3d2Safresh1C<intercept()> and C<run_subtest()> are implemented.
16815759b3d2Safresh1
16825759b3d2Safresh1=head1 MAGIC
16835759b3d2Safresh1
16845759b3d2Safresh1This package has an END block. This END block is responsible for setting the
16855759b3d2Safresh1exit code based on the test results. This end block also calls the callbacks that
16865759b3d2Safresh1can be added to this package.
16875759b3d2Safresh1
16885759b3d2Safresh1=head1 SOURCE
16895759b3d2Safresh1
16905759b3d2Safresh1The source code repository for Test2 can be found at
1691*5486feefSafresh1L<https://github.com/Test-More/test-more/>.
16925759b3d2Safresh1
16935759b3d2Safresh1=head1 MAINTAINERS
16945759b3d2Safresh1
16955759b3d2Safresh1=over 4
16965759b3d2Safresh1
16975759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt>
16985759b3d2Safresh1
16995759b3d2Safresh1=back
17005759b3d2Safresh1
17015759b3d2Safresh1=head1 AUTHORS
17025759b3d2Safresh1
17035759b3d2Safresh1=over 4
17045759b3d2Safresh1
17055759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt>
17065759b3d2Safresh1
17075759b3d2Safresh1=back
17085759b3d2Safresh1
17095759b3d2Safresh1=head1 COPYRIGHT
17105759b3d2Safresh1
1711256a93a4Safresh1Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>.
17125759b3d2Safresh1
17135759b3d2Safresh1This program is free software; you can redistribute it and/or
17145759b3d2Safresh1modify it under the same terms as Perl itself.
17155759b3d2Safresh1
1716*5486feefSafresh1See L<https://dev.perl.org/licenses/>
17175759b3d2Safresh1
17185759b3d2Safresh1=cut
1719