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