15759b3d2Safresh1package Test2::API::Instance; 25759b3d2Safresh1use strict; 35759b3d2Safresh1use warnings; 45759b3d2Safresh1 5*5486feefSafresh1our $VERSION = '1.302199'; 65759b3d2Safresh1 75759b3d2Safresh1our @CARP_NOT = qw/Test2::API Test2::API::Instance Test2::IPC::Driver Test2::Formatter/; 85759b3d2Safresh1use Carp qw/confess carp/; 95759b3d2Safresh1use Scalar::Util qw/reftype/; 105759b3d2Safresh1 115759b3d2Safresh1use Test2::Util qw/get_tid USE_THREADS CAN_FORK pkg_to_file try CAN_SIGSYS/; 125759b3d2Safresh1 135759b3d2Safresh1use Test2::EventFacet::Trace(); 145759b3d2Safresh1use Test2::API::Stack(); 155759b3d2Safresh1 165759b3d2Safresh1use Test2::Util::HashBase qw{ 175759b3d2Safresh1 _pid _tid 185759b3d2Safresh1 no_wait 195759b3d2Safresh1 finalized loaded 205759b3d2Safresh1 ipc stack formatter 215759b3d2Safresh1 contexts 225759b3d2Safresh1 235759b3d2Safresh1 add_uuid_via 245759b3d2Safresh1 255759b3d2Safresh1 -preload 265759b3d2Safresh1 275759b3d2Safresh1 ipc_disabled 285759b3d2Safresh1 ipc_polling 295759b3d2Safresh1 ipc_drivers 305759b3d2Safresh1 ipc_timeout 315759b3d2Safresh1 formatters 325759b3d2Safresh1 335759b3d2Safresh1 exit_callbacks 345759b3d2Safresh1 post_load_callbacks 355759b3d2Safresh1 context_acquire_callbacks 365759b3d2Safresh1 context_init_callbacks 375759b3d2Safresh1 context_release_callbacks 385759b3d2Safresh1 pre_subtest_callbacks 39*5486feefSafresh1 40*5486feefSafresh1 trace_stamps 415759b3d2Safresh1}; 425759b3d2Safresh1 435759b3d2Safresh1sub DEFAULT_IPC_TIMEOUT() { 30 } 445759b3d2Safresh1 45*5486feefSafresh1sub test2_enable_trace_stamps { $_[0]->{+TRACE_STAMPS} = 1 } 46*5486feefSafresh1sub test2_disable_trace_stamps { $_[0]->{+TRACE_STAMPS} = 0 } 47*5486feefSafresh1sub test2_trace_stamps_enabled { $_[0]->{+TRACE_STAMPS} } 48*5486feefSafresh1 495759b3d2Safresh1sub pid { $_[0]->{+_PID} } 505759b3d2Safresh1sub tid { $_[0]->{+_TID} } 515759b3d2Safresh1 525759b3d2Safresh1# Wrap around the getters that should call _finalize. 535759b3d2Safresh1BEGIN { 545759b3d2Safresh1 for my $finalizer (IPC, FORMATTER) { 555759b3d2Safresh1 my $orig = __PACKAGE__->can($finalizer); 565759b3d2Safresh1 my $new = sub { 575759b3d2Safresh1 my $self = shift; 585759b3d2Safresh1 $self->_finalize unless $self->{+FINALIZED}; 595759b3d2Safresh1 $self->$orig; 605759b3d2Safresh1 }; 615759b3d2Safresh1 625759b3d2Safresh1 no strict 'refs'; 635759b3d2Safresh1 no warnings 'redefine'; 645759b3d2Safresh1 *{$finalizer} = $new; 655759b3d2Safresh1 } 665759b3d2Safresh1} 675759b3d2Safresh1 685759b3d2Safresh1sub has_ipc { !!$_[0]->{+IPC} } 695759b3d2Safresh1 705759b3d2Safresh1sub import { 715759b3d2Safresh1 my $class = shift; 725759b3d2Safresh1 return unless @_; 735759b3d2Safresh1 my ($ref) = @_; 745759b3d2Safresh1 $$ref = $class->new; 755759b3d2Safresh1} 765759b3d2Safresh1 775759b3d2Safresh1sub init { $_[0]->reset } 785759b3d2Safresh1 795759b3d2Safresh1sub start_preload { 805759b3d2Safresh1 my $self = shift; 815759b3d2Safresh1 825759b3d2Safresh1 confess "preload cannot be started, Test2::API has already been initialized" 835759b3d2Safresh1 if $self->{+FINALIZED} || $self->{+LOADED}; 845759b3d2Safresh1 855759b3d2Safresh1 return $self->{+PRELOAD} = 1; 865759b3d2Safresh1} 875759b3d2Safresh1 885759b3d2Safresh1sub stop_preload { 895759b3d2Safresh1 my $self = shift; 905759b3d2Safresh1 915759b3d2Safresh1 return 0 unless $self->{+PRELOAD}; 925759b3d2Safresh1 $self->{+PRELOAD} = 0; 935759b3d2Safresh1 945759b3d2Safresh1 $self->post_preload_reset(); 955759b3d2Safresh1 965759b3d2Safresh1 return 1; 975759b3d2Safresh1} 985759b3d2Safresh1 995759b3d2Safresh1sub post_preload_reset { 1005759b3d2Safresh1 my $self = shift; 1015759b3d2Safresh1 1025759b3d2Safresh1 delete $self->{+_PID}; 1035759b3d2Safresh1 delete $self->{+_TID}; 1045759b3d2Safresh1 1055759b3d2Safresh1 $self->{+ADD_UUID_VIA} = undef unless exists $self->{+ADD_UUID_VIA}; 1065759b3d2Safresh1 1075759b3d2Safresh1 $self->{+CONTEXTS} = {}; 1085759b3d2Safresh1 1095759b3d2Safresh1 $self->{+FORMATTERS} = []; 1105759b3d2Safresh1 1115759b3d2Safresh1 $self->{+FINALIZED} = undef; 1125759b3d2Safresh1 $self->{+IPC} = undef; 1135759b3d2Safresh1 $self->{+IPC_DISABLED} = $ENV{T2_NO_IPC} ? 1 : 0; 1145759b3d2Safresh1 1155759b3d2Safresh1 $self->{+IPC_TIMEOUT} = DEFAULT_IPC_TIMEOUT() unless defined $self->{+IPC_TIMEOUT}; 1165759b3d2Safresh1 1175759b3d2Safresh1 $self->{+LOADED} = 0; 1185759b3d2Safresh1 1195759b3d2Safresh1 $self->{+STACK} ||= Test2::API::Stack->new; 1205759b3d2Safresh1} 1215759b3d2Safresh1 1225759b3d2Safresh1sub reset { 1235759b3d2Safresh1 my $self = shift; 1245759b3d2Safresh1 1255759b3d2Safresh1 delete $self->{+_PID}; 1265759b3d2Safresh1 delete $self->{+_TID}; 1275759b3d2Safresh1 128*5486feefSafresh1 $self->{+TRACE_STAMPS} = $ENV{T2_TRACE_STAMPS} || 0; 129*5486feefSafresh1 1305759b3d2Safresh1 $self->{+ADD_UUID_VIA} = undef; 1315759b3d2Safresh1 1325759b3d2Safresh1 $self->{+CONTEXTS} = {}; 1335759b3d2Safresh1 1345759b3d2Safresh1 $self->{+IPC_DRIVERS} = []; 1355759b3d2Safresh1 $self->{+IPC_POLLING} = undef; 1365759b3d2Safresh1 1375759b3d2Safresh1 $self->{+FORMATTERS} = []; 1385759b3d2Safresh1 $self->{+FORMATTER} = undef; 1395759b3d2Safresh1 1405759b3d2Safresh1 $self->{+FINALIZED} = undef; 1415759b3d2Safresh1 $self->{+IPC} = undef; 1425759b3d2Safresh1 $self->{+IPC_DISABLED} = $ENV{T2_NO_IPC} ? 1 : 0; 1435759b3d2Safresh1 1445759b3d2Safresh1 $self->{+IPC_TIMEOUT} = DEFAULT_IPC_TIMEOUT() unless defined $self->{+IPC_TIMEOUT}; 1455759b3d2Safresh1 1465759b3d2Safresh1 $self->{+NO_WAIT} = 0; 1475759b3d2Safresh1 $self->{+LOADED} = 0; 1485759b3d2Safresh1 1495759b3d2Safresh1 $self->{+EXIT_CALLBACKS} = []; 1505759b3d2Safresh1 $self->{+POST_LOAD_CALLBACKS} = []; 1515759b3d2Safresh1 $self->{+CONTEXT_ACQUIRE_CALLBACKS} = []; 1525759b3d2Safresh1 $self->{+CONTEXT_INIT_CALLBACKS} = []; 1535759b3d2Safresh1 $self->{+CONTEXT_RELEASE_CALLBACKS} = []; 1545759b3d2Safresh1 $self->{+PRE_SUBTEST_CALLBACKS} = []; 1555759b3d2Safresh1 1565759b3d2Safresh1 $self->{+STACK} = Test2::API::Stack->new; 1575759b3d2Safresh1} 1585759b3d2Safresh1 1595759b3d2Safresh1sub _finalize { 1605759b3d2Safresh1 my $self = shift; 1615759b3d2Safresh1 my ($caller) = @_; 1625759b3d2Safresh1 $caller ||= [caller(1)]; 1635759b3d2Safresh1 1645759b3d2Safresh1 confess "Attempt to initialize Test2::API during preload" 1655759b3d2Safresh1 if $self->{+PRELOAD}; 1665759b3d2Safresh1 1675759b3d2Safresh1 $self->{+FINALIZED} = $caller; 1685759b3d2Safresh1 1695759b3d2Safresh1 $self->{+_PID} = $$ unless defined $self->{+_PID}; 1705759b3d2Safresh1 $self->{+_TID} = get_tid() unless defined $self->{+_TID}; 1715759b3d2Safresh1 1725759b3d2Safresh1 unless ($self->{+FORMATTER}) { 1735759b3d2Safresh1 my ($formatter, $source); 1745759b3d2Safresh1 if ($ENV{T2_FORMATTER}) { 1755759b3d2Safresh1 $source = "set by the 'T2_FORMATTER' environment variable"; 1765759b3d2Safresh1 1775759b3d2Safresh1 if ($ENV{T2_FORMATTER} =~ m/^(\+)?(.*)$/) { 1785759b3d2Safresh1 $formatter = $1 ? $2 : "Test2::Formatter::$2" 1795759b3d2Safresh1 } 1805759b3d2Safresh1 else { 1815759b3d2Safresh1 $formatter = ''; 1825759b3d2Safresh1 } 1835759b3d2Safresh1 } 1845759b3d2Safresh1 elsif (@{$self->{+FORMATTERS}}) { 1855759b3d2Safresh1 ($formatter) = @{$self->{+FORMATTERS}}; 1865759b3d2Safresh1 $source = "Most recently added"; 1875759b3d2Safresh1 } 1885759b3d2Safresh1 else { 1895759b3d2Safresh1 $formatter = 'Test2::Formatter::TAP'; 1905759b3d2Safresh1 $source = 'default formatter'; 1915759b3d2Safresh1 } 1925759b3d2Safresh1 1935759b3d2Safresh1 unless (ref($formatter) || $formatter->can('write')) { 1945759b3d2Safresh1 my $file = pkg_to_file($formatter); 1955759b3d2Safresh1 my ($ok, $err) = try { require $file }; 1965759b3d2Safresh1 unless ($ok) { 1975759b3d2Safresh1 my $line = "* COULD NOT LOAD FORMATTER '$formatter' ($source) *"; 1985759b3d2Safresh1 my $border = '*' x length($line); 1995759b3d2Safresh1 die "\n\n $border\n $line\n $border\n\n$err"; 2005759b3d2Safresh1 } 2015759b3d2Safresh1 } 2025759b3d2Safresh1 2035759b3d2Safresh1 $self->{+FORMATTER} = $formatter; 2045759b3d2Safresh1 } 2055759b3d2Safresh1 2065759b3d2Safresh1 # Turn on IPC if threads are on, drivers are registered, or the Test2::IPC 2075759b3d2Safresh1 # module is loaded. 2085759b3d2Safresh1 return if $self->{+IPC_DISABLED}; 2095759b3d2Safresh1 return unless USE_THREADS || $INC{'Test2/IPC.pm'} || @{$self->{+IPC_DRIVERS}}; 2105759b3d2Safresh1 2115759b3d2Safresh1 # Turn on polling by default, people expect it. 2125759b3d2Safresh1 $self->enable_ipc_polling; 2135759b3d2Safresh1 2145759b3d2Safresh1 unless (@{$self->{+IPC_DRIVERS}}) { 2155759b3d2Safresh1 my ($ok, $error) = try { require Test2::IPC::Driver::Files }; 2165759b3d2Safresh1 die $error unless $ok; 2175759b3d2Safresh1 push @{$self->{+IPC_DRIVERS}} => 'Test2::IPC::Driver::Files'; 2185759b3d2Safresh1 } 2195759b3d2Safresh1 2205759b3d2Safresh1 for my $driver (@{$self->{+IPC_DRIVERS}}) { 2215759b3d2Safresh1 next unless $driver->can('is_viable') && $driver->is_viable; 2225759b3d2Safresh1 $self->{+IPC} = $driver->new or next; 2235759b3d2Safresh1 return; 2245759b3d2Safresh1 } 2255759b3d2Safresh1 2265759b3d2Safresh1 die "IPC has been requested, but no viable drivers were found. Aborting...\n"; 2275759b3d2Safresh1} 2285759b3d2Safresh1 2295759b3d2Safresh1sub formatter_set { $_[0]->{+FORMATTER} ? 1 : 0 } 2305759b3d2Safresh1 2315759b3d2Safresh1sub add_formatter { 2325759b3d2Safresh1 my $self = shift; 2335759b3d2Safresh1 my ($formatter) = @_; 2345759b3d2Safresh1 unshift @{$self->{+FORMATTERS}} => $formatter; 2355759b3d2Safresh1 2365759b3d2Safresh1 return unless $self->{+FINALIZED}; 2375759b3d2Safresh1 2385759b3d2Safresh1 # Why is the @CARP_NOT entry not enough? 2395759b3d2Safresh1 local %Carp::Internal = %Carp::Internal; 2405759b3d2Safresh1 $Carp::Internal{'Test2::Formatter'} = 1; 2415759b3d2Safresh1 2425759b3d2Safresh1 carp "Formatter $formatter loaded too late to be used as the global formatter"; 2435759b3d2Safresh1} 2445759b3d2Safresh1 2455759b3d2Safresh1sub add_context_acquire_callback { 2465759b3d2Safresh1 my $self = shift; 2475759b3d2Safresh1 my ($code) = @_; 2485759b3d2Safresh1 2495759b3d2Safresh1 my $rtype = reftype($code) || ""; 2505759b3d2Safresh1 2515759b3d2Safresh1 confess "Context-acquire callbacks must be coderefs" 2525759b3d2Safresh1 unless $code && $rtype eq 'CODE'; 2535759b3d2Safresh1 2545759b3d2Safresh1 push @{$self->{+CONTEXT_ACQUIRE_CALLBACKS}} => $code; 2555759b3d2Safresh1} 2565759b3d2Safresh1 2575759b3d2Safresh1sub add_context_init_callback { 2585759b3d2Safresh1 my $self = shift; 2595759b3d2Safresh1 my ($code) = @_; 2605759b3d2Safresh1 2615759b3d2Safresh1 my $rtype = reftype($code) || ""; 2625759b3d2Safresh1 2635759b3d2Safresh1 confess "Context-init callbacks must be coderefs" 2645759b3d2Safresh1 unless $code && $rtype eq 'CODE'; 2655759b3d2Safresh1 2665759b3d2Safresh1 push @{$self->{+CONTEXT_INIT_CALLBACKS}} => $code; 2675759b3d2Safresh1} 2685759b3d2Safresh1 2695759b3d2Safresh1sub add_context_release_callback { 2705759b3d2Safresh1 my $self = shift; 2715759b3d2Safresh1 my ($code) = @_; 2725759b3d2Safresh1 2735759b3d2Safresh1 my $rtype = reftype($code) || ""; 2745759b3d2Safresh1 2755759b3d2Safresh1 confess "Context-release callbacks must be coderefs" 2765759b3d2Safresh1 unless $code && $rtype eq 'CODE'; 2775759b3d2Safresh1 2785759b3d2Safresh1 push @{$self->{+CONTEXT_RELEASE_CALLBACKS}} => $code; 2795759b3d2Safresh1} 2805759b3d2Safresh1 2815759b3d2Safresh1sub add_post_load_callback { 2825759b3d2Safresh1 my $self = shift; 2835759b3d2Safresh1 my ($code) = @_; 2845759b3d2Safresh1 2855759b3d2Safresh1 my $rtype = reftype($code) || ""; 2865759b3d2Safresh1 2875759b3d2Safresh1 confess "Post-load callbacks must be coderefs" 2885759b3d2Safresh1 unless $code && $rtype eq 'CODE'; 2895759b3d2Safresh1 2905759b3d2Safresh1 push @{$self->{+POST_LOAD_CALLBACKS}} => $code; 2915759b3d2Safresh1 $code->() if $self->{+LOADED}; 2925759b3d2Safresh1} 2935759b3d2Safresh1 2945759b3d2Safresh1sub add_pre_subtest_callback { 2955759b3d2Safresh1 my $self = shift; 2965759b3d2Safresh1 my ($code) = @_; 2975759b3d2Safresh1 2985759b3d2Safresh1 my $rtype = reftype($code) || ""; 2995759b3d2Safresh1 3005759b3d2Safresh1 confess "Pre-subtest callbacks must be coderefs" 3015759b3d2Safresh1 unless $code && $rtype eq 'CODE'; 3025759b3d2Safresh1 3035759b3d2Safresh1 push @{$self->{+PRE_SUBTEST_CALLBACKS}} => $code; 3045759b3d2Safresh1} 3055759b3d2Safresh1 3065759b3d2Safresh1sub load { 3075759b3d2Safresh1 my $self = shift; 3085759b3d2Safresh1 unless ($self->{+LOADED}) { 3095759b3d2Safresh1 confess "Attempt to initialize Test2::API during preload" 3105759b3d2Safresh1 if $self->{+PRELOAD}; 3115759b3d2Safresh1 3125759b3d2Safresh1 $self->{+_PID} = $$ unless defined $self->{+_PID}; 3135759b3d2Safresh1 $self->{+_TID} = get_tid() unless defined $self->{+_TID}; 3145759b3d2Safresh1 3155759b3d2Safresh1 # This is for https://github.com/Test-More/test-more/issues/16 3165759b3d2Safresh1 # and https://rt.perl.org/Public/Bug/Display.html?id=127774 3175759b3d2Safresh1 # END blocks run in reverse order. This insures the END block is loaded 3185759b3d2Safresh1 # as late as possible. It will not solve all cases, but it helps. 3195759b3d2Safresh1 eval "END { Test2::API::test2_set_is_end() }; 1" or die $@; 3205759b3d2Safresh1 3215759b3d2Safresh1 $self->{+LOADED} = 1; 3225759b3d2Safresh1 $_->() for @{$self->{+POST_LOAD_CALLBACKS}}; 3235759b3d2Safresh1 } 3245759b3d2Safresh1 return $self->{+LOADED}; 3255759b3d2Safresh1} 3265759b3d2Safresh1 3275759b3d2Safresh1sub add_exit_callback { 3285759b3d2Safresh1 my $self = shift; 3295759b3d2Safresh1 my ($code) = @_; 3305759b3d2Safresh1 my $rtype = reftype($code) || ""; 3315759b3d2Safresh1 3325759b3d2Safresh1 confess "End callbacks must be coderefs" 3335759b3d2Safresh1 unless $code && $rtype eq 'CODE'; 3345759b3d2Safresh1 3355759b3d2Safresh1 push @{$self->{+EXIT_CALLBACKS}} => $code; 3365759b3d2Safresh1} 3375759b3d2Safresh1 3385759b3d2Safresh1sub ipc_disable { 3395759b3d2Safresh1 my $self = shift; 3405759b3d2Safresh1 3415759b3d2Safresh1 confess "Attempt to disable IPC after it has been initialized" 3425759b3d2Safresh1 if $self->{+IPC}; 3435759b3d2Safresh1 3445759b3d2Safresh1 $self->{+IPC_DISABLED} = 1; 3455759b3d2Safresh1} 3465759b3d2Safresh1 3475759b3d2Safresh1sub add_ipc_driver { 3485759b3d2Safresh1 my $self = shift; 3495759b3d2Safresh1 my ($driver) = @_; 3505759b3d2Safresh1 unshift @{$self->{+IPC_DRIVERS}} => $driver; 3515759b3d2Safresh1 3525759b3d2Safresh1 return unless $self->{+FINALIZED}; 3535759b3d2Safresh1 3545759b3d2Safresh1 # Why is the @CARP_NOT entry not enough? 3555759b3d2Safresh1 local %Carp::Internal = %Carp::Internal; 3565759b3d2Safresh1 $Carp::Internal{'Test2::IPC::Driver'} = 1; 3575759b3d2Safresh1 3585759b3d2Safresh1 carp "IPC driver $driver loaded too late to be used as the global ipc driver"; 3595759b3d2Safresh1} 3605759b3d2Safresh1 3615759b3d2Safresh1sub enable_ipc_polling { 3625759b3d2Safresh1 my $self = shift; 3635759b3d2Safresh1 3645759b3d2Safresh1 $self->{+_PID} = $$ unless defined $self->{+_PID}; 3655759b3d2Safresh1 $self->{+_TID} = get_tid() unless defined $self->{+_TID}; 3665759b3d2Safresh1 3675759b3d2Safresh1 $self->add_context_init_callback( 3685759b3d2Safresh1 # This is called every time a context is created, it needs to be fast. 3695759b3d2Safresh1 # $_[0] is a context object 3705759b3d2Safresh1 sub { 3715759b3d2Safresh1 return unless $self->{+IPC_POLLING}; 372f3efcd01Safresh1 return unless $self->{+IPC}; 373f3efcd01Safresh1 return unless $self->{+IPC}->pending(); 374f3efcd01Safresh1 return $_[0]->{hub}->cull; 3755759b3d2Safresh1 } 3765759b3d2Safresh1 ) unless defined $self->ipc_polling; 3775759b3d2Safresh1 3785759b3d2Safresh1 $self->set_ipc_polling(1); 3795759b3d2Safresh1} 3805759b3d2Safresh1 3815759b3d2Safresh1sub get_ipc_pending { 3825759b3d2Safresh1 my $self = shift; 383f3efcd01Safresh1 return -1 unless $self->{+IPC}; 384f3efcd01Safresh1 $self->{+IPC}->pending(); 385f3efcd01Safresh1} 386f3efcd01Safresh1 387f3efcd01Safresh1sub _check_pid { 388f3efcd01Safresh1 my $self = shift; 389f3efcd01Safresh1 my ($pid) = @_; 390f3efcd01Safresh1 return kill(0, $pid); 3915759b3d2Safresh1} 3925759b3d2Safresh1 3935759b3d2Safresh1sub set_ipc_pending { 3945759b3d2Safresh1 my $self = shift; 395f3efcd01Safresh1 return unless $self->{+IPC}; 3965759b3d2Safresh1 my ($val) = @_; 3975759b3d2Safresh1 3985759b3d2Safresh1 confess "value is required for set_ipc_pending" 3995759b3d2Safresh1 unless $val; 4005759b3d2Safresh1 401f3efcd01Safresh1 $self->{+IPC}->set_pending($val); 4025759b3d2Safresh1} 4035759b3d2Safresh1 4045759b3d2Safresh1sub disable_ipc_polling { 4055759b3d2Safresh1 my $self = shift; 4065759b3d2Safresh1 return unless defined $self->{+IPC_POLLING}; 4075759b3d2Safresh1 $self->{+IPC_POLLING} = 0; 4085759b3d2Safresh1} 4095759b3d2Safresh1 4105759b3d2Safresh1sub _ipc_wait { 4115759b3d2Safresh1 my ($timeout) = @_; 4125759b3d2Safresh1 my $fail = 0; 4135759b3d2Safresh1 4145759b3d2Safresh1 $timeout = DEFAULT_IPC_TIMEOUT() unless defined $timeout; 4155759b3d2Safresh1 4165759b3d2Safresh1 my $ok = eval { 4175759b3d2Safresh1 if (CAN_FORK) { 4185759b3d2Safresh1 local $SIG{ALRM} = sub { die "Timeout waiting on child processes" }; 4195759b3d2Safresh1 alarm $timeout; 4205759b3d2Safresh1 4215759b3d2Safresh1 while (1) { 4225759b3d2Safresh1 my $pid = CORE::wait(); 4235759b3d2Safresh1 my $err = $?; 4245759b3d2Safresh1 last if $pid == -1; 4255759b3d2Safresh1 next unless $err; 4265759b3d2Safresh1 $fail++; 4275759b3d2Safresh1 4285759b3d2Safresh1 my $sig = $err & 127; 4295759b3d2Safresh1 my $exit = $err >> 8; 4305759b3d2Safresh1 warn "Process $pid did not exit cleanly (wstat: $err, exit: $exit, sig: $sig)\n"; 4315759b3d2Safresh1 } 4325759b3d2Safresh1 4335759b3d2Safresh1 alarm 0; 4345759b3d2Safresh1 } 4355759b3d2Safresh1 4365759b3d2Safresh1 if (USE_THREADS) { 4375759b3d2Safresh1 my $start = time; 4385759b3d2Safresh1 4395759b3d2Safresh1 while (1) { 4405759b3d2Safresh1 last unless threads->list(); 4415759b3d2Safresh1 die "Timeout waiting on child thread" if time - $start >= $timeout; 4425759b3d2Safresh1 sleep 1; 4435759b3d2Safresh1 for my $t (threads->list) { 4445759b3d2Safresh1 # threads older than 1.34 do not have this :-( 4455759b3d2Safresh1 next if $t->can('is_joinable') && !$t->is_joinable; 4465759b3d2Safresh1 $t->join; 4475759b3d2Safresh1 # In older threads we cannot check if a thread had an error unless 4485759b3d2Safresh1 # we control it and its return. 4495759b3d2Safresh1 my $err = $t->can('error') ? $t->error : undef; 4505759b3d2Safresh1 next unless $err; 4515759b3d2Safresh1 my $tid = $t->tid(); 4525759b3d2Safresh1 $fail++; 4535759b3d2Safresh1 chomp($err); 4545759b3d2Safresh1 warn "Thread $tid did not end cleanly: $err\n"; 4555759b3d2Safresh1 } 4565759b3d2Safresh1 } 4575759b3d2Safresh1 } 4585759b3d2Safresh1 4595759b3d2Safresh1 1; 4605759b3d2Safresh1 }; 4615759b3d2Safresh1 my $error = $@; 4625759b3d2Safresh1 4635759b3d2Safresh1 return 0 if $ok && !$fail; 4645759b3d2Safresh1 warn $error unless $ok; 4655759b3d2Safresh1 return 255; 4665759b3d2Safresh1} 4675759b3d2Safresh1 4685759b3d2Safresh1sub set_exit { 4695759b3d2Safresh1 my $self = shift; 4705759b3d2Safresh1 4715759b3d2Safresh1 return if $self->{+PRELOAD}; 4725759b3d2Safresh1 4735759b3d2Safresh1 my $exit = $?; 4745759b3d2Safresh1 my $new_exit = $exit; 4755759b3d2Safresh1 4765759b3d2Safresh1 if ($INC{'Test/Builder.pm'} && $Test::Builder::VERSION ne $Test2::API::VERSION) { 4775759b3d2Safresh1 print STDERR <<" EOT"; 4785759b3d2Safresh1 4795759b3d2Safresh1******************************************************************************** 4805759b3d2Safresh1* * 4815759b3d2Safresh1* Test::Builder -- Test2::API version mismatch detected * 4825759b3d2Safresh1* * 4835759b3d2Safresh1******************************************************************************** 4845759b3d2Safresh1 Test2::API Version: $Test2::API::VERSION 4855759b3d2Safresh1Test::Builder Version: $Test::Builder::VERSION 4865759b3d2Safresh1 4875759b3d2Safresh1This is not a supported configuration, you will have problems. 4885759b3d2Safresh1 4895759b3d2Safresh1 EOT 4905759b3d2Safresh1 } 4915759b3d2Safresh1 4925759b3d2Safresh1 for my $ctx (values %{$self->{+CONTEXTS}}) { 4935759b3d2Safresh1 next unless $ctx; 4945759b3d2Safresh1 4955759b3d2Safresh1 next if $ctx->_aborted && ${$ctx->_aborted}; 4965759b3d2Safresh1 4975759b3d2Safresh1 # Only worry about contexts in this PID 4985759b3d2Safresh1 my $trace = $ctx->trace || next; 4995759b3d2Safresh1 next unless $trace->pid && $trace->pid == $$; 5005759b3d2Safresh1 5015759b3d2Safresh1 # Do not worry about contexts that have no hub 5025759b3d2Safresh1 my $hub = $ctx->hub || next; 5035759b3d2Safresh1 5045759b3d2Safresh1 # Do not worry if the state came to a sudden end. 5055759b3d2Safresh1 next if $hub->bailed_out; 5065759b3d2Safresh1 next if defined $hub->skip_reason; 5075759b3d2Safresh1 5085759b3d2Safresh1 # now we worry 5095759b3d2Safresh1 $trace->alert("context object was never released! This means a testing tool is behaving very badly"); 5105759b3d2Safresh1 5115759b3d2Safresh1 $exit = 255; 5125759b3d2Safresh1 $new_exit = 255; 5135759b3d2Safresh1 } 5145759b3d2Safresh1 5155759b3d2Safresh1 if (!defined($self->{+_PID}) or !defined($self->{+_TID}) or $self->{+_PID} != $$ or $self->{+_TID} != get_tid()) { 5165759b3d2Safresh1 $? = $exit; 5175759b3d2Safresh1 return; 5185759b3d2Safresh1 } 5195759b3d2Safresh1 5205759b3d2Safresh1 my @hubs = $self->{+STACK} ? $self->{+STACK}->all : (); 5215759b3d2Safresh1 5225759b3d2Safresh1 if (@hubs and $self->{+IPC} and !$self->{+NO_WAIT}) { 5235759b3d2Safresh1 local $?; 5245759b3d2Safresh1 my %seen; 5255759b3d2Safresh1 for my $hub (reverse @hubs) { 5265759b3d2Safresh1 my $ipc = $hub->ipc or next; 5275759b3d2Safresh1 next if $seen{$ipc}++; 5285759b3d2Safresh1 $ipc->waiting(); 5295759b3d2Safresh1 } 5305759b3d2Safresh1 5315759b3d2Safresh1 my $ipc_exit = _ipc_wait($self->{+IPC_TIMEOUT}); 5325759b3d2Safresh1 $new_exit ||= $ipc_exit; 5335759b3d2Safresh1 } 5345759b3d2Safresh1 5355759b3d2Safresh1 # None of this is necessary if we never got a root hub 5365759b3d2Safresh1 if(my $root = shift @hubs) { 5375759b3d2Safresh1 my $trace = Test2::EventFacet::Trace->new( 5385759b3d2Safresh1 frame => [__PACKAGE__, __FILE__, 0, __PACKAGE__ . '::END'], 5395759b3d2Safresh1 detail => __PACKAGE__ . ' END Block finalization', 5405759b3d2Safresh1 ); 5415759b3d2Safresh1 my $ctx = Test2::API::Context->new( 5425759b3d2Safresh1 trace => $trace, 5435759b3d2Safresh1 hub => $root, 5445759b3d2Safresh1 ); 5455759b3d2Safresh1 5465759b3d2Safresh1 if (@hubs) { 5475759b3d2Safresh1 $ctx->diag("Test ended with extra hubs on the stack!"); 5485759b3d2Safresh1 $new_exit = 255; 5495759b3d2Safresh1 } 5505759b3d2Safresh1 5515759b3d2Safresh1 unless ($root->no_ending) { 5525759b3d2Safresh1 local $?; 5535759b3d2Safresh1 $root->finalize($trace) unless $root->ended; 5545759b3d2Safresh1 $_->($ctx, $exit, \$new_exit) for @{$self->{+EXIT_CALLBACKS}}; 5555759b3d2Safresh1 $new_exit ||= $root->failed; 5565759b3d2Safresh1 $new_exit ||= 255 unless $root->is_passing; 5575759b3d2Safresh1 } 5585759b3d2Safresh1 } 5595759b3d2Safresh1 5605759b3d2Safresh1 $new_exit = 255 if $new_exit > 255; 5615759b3d2Safresh1 5625759b3d2Safresh1 if ($new_exit && eval { require Test2::API::Breakage; 1 }) { 5635759b3d2Safresh1 my @warn = Test2::API::Breakage->report(); 5645759b3d2Safresh1 5655759b3d2Safresh1 if (@warn) { 5665759b3d2Safresh1 print STDERR "\nYou have loaded versions of test modules known to have problems with Test2.\nThis could explain some test failures.\n"; 5675759b3d2Safresh1 print STDERR "$_\n" for @warn; 5685759b3d2Safresh1 print STDERR "\n"; 5695759b3d2Safresh1 } 5705759b3d2Safresh1 } 5715759b3d2Safresh1 5725759b3d2Safresh1 $? = $new_exit; 5735759b3d2Safresh1} 5745759b3d2Safresh1 5755759b3d2Safresh11; 5765759b3d2Safresh1 5775759b3d2Safresh1__END__ 5785759b3d2Safresh1 5795759b3d2Safresh1=pod 5805759b3d2Safresh1 5815759b3d2Safresh1=encoding UTF-8 5825759b3d2Safresh1 5835759b3d2Safresh1=head1 NAME 5845759b3d2Safresh1 5855759b3d2Safresh1Test2::API::Instance - Object used by Test2::API under the hood 5865759b3d2Safresh1 5875759b3d2Safresh1=head1 DESCRIPTION 5885759b3d2Safresh1 5895759b3d2Safresh1This object encapsulates the global shared state tracked by 5905759b3d2Safresh1L<Test2>. A single global instance of this package is stored (and 5915759b3d2Safresh1obscured) by the L<Test2::API> package. 5925759b3d2Safresh1 5935759b3d2Safresh1There is no reason to directly use this package. This package is documented for 5945759b3d2Safresh1completeness. This package can change, or go away completely at any time. 5955759b3d2Safresh1Directly using, or monkeypatching this package is not supported in any way 5965759b3d2Safresh1shape or form. 5975759b3d2Safresh1 5985759b3d2Safresh1=head1 SYNOPSIS 5995759b3d2Safresh1 6005759b3d2Safresh1 use Test2::API::Instance; 6015759b3d2Safresh1 6025759b3d2Safresh1 my $obj = Test2::API::Instance->new; 6035759b3d2Safresh1 6045759b3d2Safresh1=over 4 6055759b3d2Safresh1 6065759b3d2Safresh1=item $pid = $obj->pid 6075759b3d2Safresh1 6085759b3d2Safresh1PID of this instance. 6095759b3d2Safresh1 6105759b3d2Safresh1=item $obj->tid 6115759b3d2Safresh1 6125759b3d2Safresh1Thread ID of this instance. 6135759b3d2Safresh1 6145759b3d2Safresh1=item $obj->reset() 6155759b3d2Safresh1 6165759b3d2Safresh1Reset the object to defaults. 6175759b3d2Safresh1 6185759b3d2Safresh1=item $obj->load() 6195759b3d2Safresh1 6205759b3d2Safresh1Set the internal state to loaded, and run and stored post-load callbacks. 6215759b3d2Safresh1 6225759b3d2Safresh1=item $bool = $obj->loaded 6235759b3d2Safresh1 6245759b3d2Safresh1Check if the state is set to loaded. 6255759b3d2Safresh1 6265759b3d2Safresh1=item $arrayref = $obj->post_load_callbacks 6275759b3d2Safresh1 6285759b3d2Safresh1Get the post-load callbacks. 6295759b3d2Safresh1 6305759b3d2Safresh1=item $obj->add_post_load_callback(sub { ... }) 6315759b3d2Safresh1 6325759b3d2Safresh1Add a post-load callback. If C<load()> has already been called then the callback will 6335759b3d2Safresh1be immediately executed. If C<load()> has not been called then the callback will be 6345759b3d2Safresh1stored and executed later when C<load()> is called. 6355759b3d2Safresh1 6365759b3d2Safresh1=item $hashref = $obj->contexts() 6375759b3d2Safresh1 6385759b3d2Safresh1Get a hashref of all active contexts keyed by hub id. 6395759b3d2Safresh1 6405759b3d2Safresh1=item $arrayref = $obj->context_acquire_callbacks 6415759b3d2Safresh1 6425759b3d2Safresh1Get all context acquire callbacks. 6435759b3d2Safresh1 6445759b3d2Safresh1=item $arrayref = $obj->context_init_callbacks 6455759b3d2Safresh1 6465759b3d2Safresh1Get all context init callbacks. 6475759b3d2Safresh1 6485759b3d2Safresh1=item $arrayref = $obj->context_release_callbacks 6495759b3d2Safresh1 6505759b3d2Safresh1Get all context release callbacks. 6515759b3d2Safresh1 6525759b3d2Safresh1=item $arrayref = $obj->pre_subtest_callbacks 6535759b3d2Safresh1 6545759b3d2Safresh1Get all pre-subtest callbacks. 6555759b3d2Safresh1 6565759b3d2Safresh1=item $obj->add_context_init_callback(sub { ... }) 6575759b3d2Safresh1 6585759b3d2Safresh1Add a context init callback. Subs are called every time a context is created. Subs 6595759b3d2Safresh1get the newly created context as their only argument. 6605759b3d2Safresh1 6615759b3d2Safresh1=item $obj->add_context_release_callback(sub { ... }) 6625759b3d2Safresh1 6635759b3d2Safresh1Add a context release callback. Subs are called every time a context is released. Subs 6645759b3d2Safresh1get the released context as their only argument. These callbacks should not 6655759b3d2Safresh1call release on the context. 6665759b3d2Safresh1 6675759b3d2Safresh1=item $obj->add_pre_subtest_callback(sub { ... }) 6685759b3d2Safresh1 6695759b3d2Safresh1Add a pre-subtest callback. Subs are called every time a subtest is 6705759b3d2Safresh1going to be run. Subs get the subtest name, coderef, and any 6715759b3d2Safresh1arguments. 6725759b3d2Safresh1 6735759b3d2Safresh1=item $obj->set_exit() 6745759b3d2Safresh1 6755759b3d2Safresh1This is intended to be called in an C<END { ... }> block. This will look at 6765759b3d2Safresh1test state and set $?. This will also call any end callbacks, and wait on child 6775759b3d2Safresh1processes/threads. 6785759b3d2Safresh1 6795759b3d2Safresh1=item $obj->set_ipc_pending($val) 6805759b3d2Safresh1 681f3efcd01Safresh1Tell other processes and threads there is a pending event. C<$val> should be a 682f3efcd01Safresh1unique value no other thread/process will generate. 6835759b3d2Safresh1 684f3efcd01Safresh1B<Note:> This will also make the current process see a pending event. 6855759b3d2Safresh1 6865759b3d2Safresh1=item $pending = $obj->get_ipc_pending() 6875759b3d2Safresh1 688f3efcd01Safresh1This returns -1 if it is not possible to know. 6895759b3d2Safresh1 690f3efcd01Safresh1This returns 0 if there are no pending events. 6915759b3d2Safresh1 692f3efcd01Safresh1This returns 1 if there are pending events. 6935759b3d2Safresh1 6945759b3d2Safresh1=item $timeout = $obj->ipc_timeout; 6955759b3d2Safresh1 6965759b3d2Safresh1=item $obj->set_ipc_timeout($timeout); 6975759b3d2Safresh1 6985759b3d2Safresh1How long to wait for child processes and threads before aborting. 6995759b3d2Safresh1 7005759b3d2Safresh1=item $drivers = $obj->ipc_drivers 7015759b3d2Safresh1 7025759b3d2Safresh1Get the list of IPC drivers. 7035759b3d2Safresh1 7045759b3d2Safresh1=item $obj->add_ipc_driver($DRIVER_CLASS) 7055759b3d2Safresh1 7065759b3d2Safresh1Add an IPC driver to the list. The most recently added IPC driver will become 7075759b3d2Safresh1the global one during initialization. If a driver is added after initialization 7085759b3d2Safresh1has occurred a warning will be generated: 7095759b3d2Safresh1 7105759b3d2Safresh1 "IPC driver $driver loaded too late to be used as the global ipc driver" 7115759b3d2Safresh1 7125759b3d2Safresh1=item $bool = $obj->ipc_polling 7135759b3d2Safresh1 7145759b3d2Safresh1Check if polling is enabled. 7155759b3d2Safresh1 7165759b3d2Safresh1=item $obj->enable_ipc_polling 7175759b3d2Safresh1 7185759b3d2Safresh1Turn on polling. This will cull events from other processes and threads every 7195759b3d2Safresh1time a context is created. 7205759b3d2Safresh1 7215759b3d2Safresh1=item $obj->disable_ipc_polling 7225759b3d2Safresh1 7235759b3d2Safresh1Turn off IPC polling. 7245759b3d2Safresh1 7255759b3d2Safresh1=item $bool = $obj->no_wait 7265759b3d2Safresh1 7275759b3d2Safresh1=item $bool = $obj->set_no_wait($bool) 7285759b3d2Safresh1 7295759b3d2Safresh1Get/Set no_wait. This option is used to turn off process/thread waiting at exit. 7305759b3d2Safresh1 7315759b3d2Safresh1=item $arrayref = $obj->exit_callbacks 7325759b3d2Safresh1 7335759b3d2Safresh1Get the exit callbacks. 7345759b3d2Safresh1 7355759b3d2Safresh1=item $obj->add_exit_callback(sub { ... }) 7365759b3d2Safresh1 7375759b3d2Safresh1Add an exit callback. This callback will be called by C<set_exit()>. 7385759b3d2Safresh1 7395759b3d2Safresh1=item $bool = $obj->finalized 7405759b3d2Safresh1 7415759b3d2Safresh1Check if the object is finalized. Finalization happens when either C<ipc()>, 7425759b3d2Safresh1C<stack()>, or C<format()> are called on the object. Once finalization happens 7435759b3d2Safresh1these fields are considered unchangeable (not enforced here, enforced by 7445759b3d2Safresh1L<Test2>). 7455759b3d2Safresh1 7465759b3d2Safresh1=item $ipc = $obj->ipc 7475759b3d2Safresh1 7485759b3d2Safresh1Get the one true IPC instance. 7495759b3d2Safresh1 7505759b3d2Safresh1=item $obj->ipc_disable 7515759b3d2Safresh1 7525759b3d2Safresh1Turn IPC off 7535759b3d2Safresh1 7545759b3d2Safresh1=item $bool = $obj->ipc_disabled 7555759b3d2Safresh1 7565759b3d2Safresh1Check if IPC is disabled 7575759b3d2Safresh1 7585759b3d2Safresh1=item $stack = $obj->stack 7595759b3d2Safresh1 7605759b3d2Safresh1Get the one true hub stack. 7615759b3d2Safresh1 7625759b3d2Safresh1=item $formatter = $obj->formatter 7635759b3d2Safresh1 7645759b3d2Safresh1Get the global formatter. By default this is the C<'Test2::Formatter::TAP'> 7655759b3d2Safresh1package. This could be any package that implements the C<write()> method. This 7665759b3d2Safresh1can also be an instantiated object. 7675759b3d2Safresh1 7685759b3d2Safresh1=item $bool = $obj->formatter_set() 7695759b3d2Safresh1 7705759b3d2Safresh1Check if a formatter has been set. 7715759b3d2Safresh1 7725759b3d2Safresh1=item $obj->add_formatter($class) 7735759b3d2Safresh1 7745759b3d2Safresh1=item $obj->add_formatter($obj) 7755759b3d2Safresh1 7765759b3d2Safresh1Add a formatter. The most recently added formatter will become the global one 7775759b3d2Safresh1during initialization. If a formatter is added after initialization has occurred 7785759b3d2Safresh1a warning will be generated: 7795759b3d2Safresh1 7805759b3d2Safresh1 "Formatter $formatter loaded too late to be used as the global formatter" 7815759b3d2Safresh1 7825759b3d2Safresh1=item $obj->set_add_uuid_via(sub { ... }) 7835759b3d2Safresh1 7845759b3d2Safresh1=item $sub = $obj->add_uuid_via() 7855759b3d2Safresh1 7865759b3d2Safresh1This allows you to provide a UUID generator. If provided UUIDs will be attached 7875759b3d2Safresh1to all events, hubs, and contexts. This is useful for storing, tracking, and 7885759b3d2Safresh1linking these objects. 7895759b3d2Safresh1 7905759b3d2Safresh1The sub you provide should always return a unique identifier. Most things will 7915759b3d2Safresh1expect a proper UUID string, however nothing in Test2::API enforces this. 7925759b3d2Safresh1 7935759b3d2Safresh1The sub will receive exactly 1 argument, the type of thing being tagged 7945759b3d2Safresh1'context', 'hub', or 'event'. In the future additional things may be tagged, in 7955759b3d2Safresh1which case new strings will be passed in. These are purely informative, you can 7965759b3d2Safresh1(and usually should) ignore them. 7975759b3d2Safresh1 7985759b3d2Safresh1=back 7995759b3d2Safresh1 8005759b3d2Safresh1=head1 SOURCE 8015759b3d2Safresh1 8025759b3d2Safresh1The source code repository for Test2 can be found at 803*5486feefSafresh1L<https://github.com/Test-More/test-more/>. 8045759b3d2Safresh1 8055759b3d2Safresh1=head1 MAINTAINERS 8065759b3d2Safresh1 8075759b3d2Safresh1=over 4 8085759b3d2Safresh1 8095759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt> 8105759b3d2Safresh1 8115759b3d2Safresh1=back 8125759b3d2Safresh1 8135759b3d2Safresh1=head1 AUTHORS 8145759b3d2Safresh1 8155759b3d2Safresh1=over 4 8165759b3d2Safresh1 8175759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt> 8185759b3d2Safresh1 8195759b3d2Safresh1=back 8205759b3d2Safresh1 8215759b3d2Safresh1=head1 COPYRIGHT 8225759b3d2Safresh1 823256a93a4Safresh1Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>. 8245759b3d2Safresh1 8255759b3d2Safresh1This program is free software; you can redistribute it and/or 8265759b3d2Safresh1modify it under the same terms as Perl itself. 8275759b3d2Safresh1 828*5486feefSafresh1See L<https://dev.perl.org/licenses/> 8295759b3d2Safresh1 8305759b3d2Safresh1=cut 831