1 package Test2::API::Instance;
5 our $VERSION = '1.302022';
8 our @CARP_NOT = qw/Test2::API Test2::API::Instance Test2::IPC::Driver Test2::Formatter/;
9 use Carp qw/confess carp/;
10 use Scalar::Util qw/reftype/;
12 use Test2::Util qw/get_tid USE_THREADS CAN_FORK pkg_to_file try/;
14 use Test2::Util::Trace();
15 use Test2::API::Stack();
17 use Test2::Util::HashBase qw{
33 context_acquire_callbacks
34 context_init_callbacks
35 context_release_callbacks
38 sub pid { $_[0]->{+_PID} ||= $$ }
39 sub tid { $_[0]->{+_TID} ||= get_tid() }
41 # Wrap around the getters that should call _finalize.
43 for my $finalizer (IPC, FORMATTER) {
44 my $orig = __PACKAGE__->can($finalizer);
47 $self->_finalize unless $self->{+FINALIZED};
52 no warnings 'redefine';
64 sub init { $_[0]->reset }
69 delete $self->{+_PID};
70 delete $self->{+_TID};
72 $self->{+CONTEXTS} = {};
74 $self->{+IPC_DRIVERS} = [];
75 $self->{+IPC_POLLING} = undef;
77 $self->{+FORMATTERS} = [];
78 $self->{+FORMATTER} = undef;
80 $self->{+FINALIZED} = undef;
81 $self->{+IPC} = undef;
83 $self->{+NO_WAIT} = 0;
86 $self->{+EXIT_CALLBACKS} = [];
87 $self->{+POST_LOAD_CALLBACKS} = [];
88 $self->{+CONTEXT_ACQUIRE_CALLBACKS} = [];
89 $self->{+CONTEXT_INIT_CALLBACKS} = [];
90 $self->{+CONTEXT_RELEASE_CALLBACKS} = [];
92 $self->{+STACK} = Test2::API::Stack->new;
98 $caller ||= [caller(1)];
100 $self->{+FINALIZED} = $caller;
102 $self->{+_PID} = $$ unless defined $self->{+_PID};
103 $self->{+_TID} = get_tid() unless defined $self->{+_TID};
105 unless ($self->{+FORMATTER}) {
106 my ($formatter, $source);
107 if ($ENV{T2_FORMATTER}) {
108 $source = "set by the 'T2_FORMATTER' environment variable";
110 if ($ENV{T2_FORMATTER} =~ m/^(\+)?(.*)$/) {
111 $formatter = $1 ? $2 : "Test2::Formatter::$2"
117 elsif (@{$self->{+FORMATTERS}}) {
118 ($formatter) = @{$self->{+FORMATTERS}};
119 $source = "Most recently added";
122 $formatter = 'Test2::Formatter::TAP';
123 $source = 'default formatter';
126 unless (ref($formatter) || $formatter->can('write')) {
127 my $file = pkg_to_file($formatter);
128 my ($ok, $err) = try { require $file };
130 my $line = "* COULD NOT LOAD FORMATTER '$formatter' ($source) *";
131 my $border = '*' x length($line);
132 die "\n\n $border\n $line\n $border\n\n$err";
136 $self->{+FORMATTER} = $formatter;
139 # Turn on IPC if threads are on, drivers are registered, or the Test2::IPC
141 return unless USE_THREADS || $INC{'Test2/IPC.pm'} || @{$self->{+IPC_DRIVERS}};
143 # Turn on polling by default, people expect it.
144 $self->enable_ipc_polling;
146 unless (@{$self->{+IPC_DRIVERS}}) {
147 my ($ok, $error) = try { require Test2::IPC::Driver::Files };
148 die $error unless $ok;
149 push @{$self->{+IPC_DRIVERS}} => 'Test2::IPC::Driver::Files';
152 for my $driver (@{$self->{+IPC_DRIVERS}}) {
153 next unless $driver->can('is_viable') && $driver->is_viable;
154 $self->{+IPC} = $driver->new or next;
155 $self->ipc_enable_shm if $self->{+IPC}->use_shm;
159 die "IPC has been requested, but no viable drivers were found. Aborting...\n";
162 sub formatter_set { $_[0]->{+FORMATTER} ? 1 : 0 }
166 my ($formatter) = @_;
167 unshift @{$self->{+FORMATTERS}} => $formatter;
169 return unless $self->{+FINALIZED};
171 # Why is the @CARP_NOT entry not enough?
172 local %Carp::Internal = %Carp::Internal;
173 $Carp::Internal{'Test2::Formatter'} = 1;
175 carp "Formatter $formatter loaded too late to be used as the global formatter";
178 sub add_context_acquire_callback {
182 my $rtype = reftype($code) || "";
184 confess "Context-acquire callbacks must be coderefs"
185 unless $code && $rtype eq 'CODE';
187 push @{$self->{+CONTEXT_ACQUIRE_CALLBACKS}} => $code;
190 sub add_context_init_callback {
194 my $rtype = reftype($code) || "";
196 confess "Context-init callbacks must be coderefs"
197 unless $code && $rtype eq 'CODE';
199 push @{$self->{+CONTEXT_INIT_CALLBACKS}} => $code;
202 sub add_context_release_callback {
206 my $rtype = reftype($code) || "";
208 confess "Context-release callbacks must be coderefs"
209 unless $code && $rtype eq 'CODE';
211 push @{$self->{+CONTEXT_RELEASE_CALLBACKS}} => $code;
214 sub add_post_load_callback {
218 my $rtype = reftype($code) || "";
220 confess "Post-load callbacks must be coderefs"
221 unless $code && $rtype eq 'CODE';
223 push @{$self->{+POST_LOAD_CALLBACKS}} => $code;
224 $code->() if $self->{+LOADED};
229 unless ($self->{+LOADED}) {
230 $self->{+_PID} = $$ unless defined $self->{+_PID};
231 $self->{+_TID} = get_tid() unless defined $self->{+_TID};
233 # This is for https://github.com/Test-More/test-more/issues/16
234 # and https://rt.perl.org/Public/Bug/Display.html?id=127774
235 # END blocks run in reverse order. This insures the END block is loaded
236 # as late as possible. It will not solve all cases, but it helps.
237 eval "END { Test2::API::test2_set_is_end() }; 1" or die $@;
239 $self->{+LOADED} = 1;
240 $_->() for @{$self->{+POST_LOAD_CALLBACKS}};
242 return $self->{+LOADED};
245 sub add_exit_callback {
248 my $rtype = reftype($code) || "";
250 confess "End callbacks must be coderefs"
251 unless $code && $rtype eq 'CODE';
253 push @{$self->{+EXIT_CALLBACKS}} => $code;
259 unshift @{$self->{+IPC_DRIVERS}} => $driver;
261 return unless $self->{+FINALIZED};
263 # Why is the @CARP_NOT entry not enough?
264 local %Carp::Internal = %Carp::Internal;
265 $Carp::Internal{'Test2::IPC::Driver'} = 1;
267 carp "IPC driver $driver loaded too late to be used as the global ipc driver";
270 sub enable_ipc_polling {
273 $self->add_context_init_callback(
274 # This is called every time a context is created, it needs to be fast.
275 # $_[0] is a context object
277 return unless $self->{+IPC_POLLING};
278 return $_[0]->{hub}->cull unless $self->{+IPC_SHM_ID};
282 shmread($self->{+IPC_SHM_ID}, $val, 0, $self->{+IPC_SHM_SIZE}) or return;
284 return if $val eq $self->{+IPC_SHM_LAST};
285 $self->{+IPC_SHM_LAST} = $val;
290 ) unless defined $self->ipc_polling;
292 $self->set_ipc_polling(1);
298 return 1 if defined $self->{+IPC_SHM_ID};
300 my ($ok, $err) = try {
303 my $ipc_key = IPC::SysV::IPC_PRIVATE();
304 my $shm_size = $self->{+IPC}->can('shm_size') ? $self->{+IPC}->shm_size : 64;
305 my $shm_id = shmget($ipc_key, $shm_size, 0666) or die;
307 my $initial = 'a' x $shm_size;
308 shmwrite($shm_id, $initial, 0, $shm_size) or die;
310 $self->{+IPC_SHM_SIZE} = $shm_size;
311 $self->{+IPC_SHM_ID} = $shm_id;
312 $self->{+IPC_SHM_LAST} = $initial;
321 my $id = delete $self->{+IPC_SHM_ID};
322 return unless defined $id;
324 shmctl($id, IPC::SysV::IPC_RMID(), 0);
327 sub get_ipc_pending {
329 return -1 unless defined $self->{+IPC_SHM_ID};
331 shmread($self->{+IPC_SHM_ID}, $val, 0, $self->{+IPC_SHM_SIZE}) or return -1;
332 return 0 if $val eq $self->{+IPC_SHM_LAST};
333 $self->{+IPC_SHM_LAST} = $val;
337 sub set_ipc_pending {
340 return undef unless defined $self->{+IPC_SHM_ID};
344 confess "value is required for set_ipc_pending"
347 shmwrite($self->{+IPC_SHM_ID}, $val, 0, $self->{+IPC_SHM_SIZE});
350 sub disable_ipc_polling {
352 return unless defined $self->{+IPC_POLLING};
353 $self->{+IPC_POLLING} = 0;
361 my $pid = CORE::wait();
367 warn "Process $pid did not exit cleanly (status: $err)\n";
372 for my $t (threads->list()) {
374 # In older threads we cannot check if a thread had an error unless
375 # we control it and its return.
376 my $err = $t->can('error') ? $t->error : undef;
381 warn "Thread $tid did not end cleanly: $err\n";
385 return 0 unless $fail;
392 return unless defined($self->{+_PID}) && $self->{+_PID} == $$;
393 return unless defined($self->{+_TID}) && $self->{+_TID} == get_tid();
395 shmctl($self->{+IPC_SHM_ID}, IPC::SysV::IPC_RMID(), 0)
396 if defined $self->{+IPC_SHM_ID};
403 my $new_exit = $exit;
405 if ($INC{'Test/Builder.pm'} && $Test::Builder::VERSION ne $Test2::API::VERSION) {
406 print STDERR <<" EOT";
408 ********************************************************************************
410 * Test::Builder -- Test2::API version mismatch detected *
412 ********************************************************************************
413 Test2::API Version: $Test2::API::VERSION
414 Test::Builder Version: $Test::Builder::VERSION
416 This is not a supported configuration, you will have problems.
421 for my $ctx (values %{$self->{+CONTEXTS}}) {
424 next if $ctx->_aborted && ${$ctx->_aborted};
426 # Only worry about contexts in this PID
427 my $trace = $ctx->trace || next;
428 next unless $trace->pid && $trace->pid == $$;
430 # Do not worry about contexts that have no hub
431 my $hub = $ctx->hub || next;
433 # Do not worry if the state came to a sudden end.
434 next if $hub->bailed_out;
435 next if defined $hub->skip_reason;
438 $trace->alert("context object was never released! This means a testing tool is behaving very badly");
444 if (!defined($self->{+_PID}) or !defined($self->{+_TID}) or $self->{+_PID} != $$ or $self->{+_TID} != get_tid()) {
449 my @hubs = $self->{+STACK} ? $self->{+STACK}->all : ();
451 if (@hubs and $self->{+IPC} and !$self->{+NO_WAIT}) {
454 for my $hub (reverse @hubs) {
455 my $ipc = $hub->ipc or next;
456 next if $seen{$ipc}++;
460 my $ipc_exit = _ipc_wait();
461 $new_exit ||= $ipc_exit;
464 # None of this is necessary if we never got a root hub
465 if(my $root = shift @hubs) {
466 my $trace = Test2::Util::Trace->new(
467 frame => [__PACKAGE__, __FILE__, 0, __PACKAGE__ . '::END'],
468 detail => __PACKAGE__ . ' END Block finalization',
470 my $ctx = Test2::API::Context->new(
476 $ctx->diag("Test ended with extra hubs on the stack!");
480 unless ($root->no_ending) {
482 $root->finalize($trace) unless $root->ended;
483 $_->($ctx, $exit, \$new_exit) for @{$self->{+EXIT_CALLBACKS}};
484 $new_exit ||= $root->failed;
488 $new_exit = 255 if $new_exit > 255;
491 require Test2::API::Breakage;
492 my @warn = Test2::API::Breakage->report();
495 print STDERR "\nYou have loaded versions of test modules known to have problems with Test2.\nThis could explain some test failures.\n";
496 print STDERR "$_\n" for @warn;
514 Test2::API::Instance - Object used by Test2::API under the hood
518 This object encapsulates the global shared state tracked by
519 L<Test2>. A single global instance of this package is stored (and
520 obscured) by the L<Test2::API> package.
522 There is no reason to directly use this package. This package is documented for
523 completeness. This package can change, or go away completely at any time.
524 Directly using, or monkeypatching this package is not supported in any way
529 use Test2::API::Instance;
531 my $obj = Test2::API::Instance->new;
535 =item $pid = $obj->pid
537 PID of this instance.
541 Thread ID of this instance.
545 Reset the object to defaults.
549 Set the internal state to loaded, and run and stored post-load callbacks.
551 =item $bool = $obj->loaded
553 Check if the state is set to loaded.
555 =item $arrayref = $obj->post_load_callbacks
557 Get the post-load callbacks.
559 =item $obj->add_post_load_callback(sub { ... })
561 Add a post-load callback. If C<load()> has already been called then the callback will
562 be immediately executed. If C<load()> has not been called then the callback will be
563 stored and executed later when C<load()> is called.
565 =item $hashref = $obj->contexts()
567 Get a hashref of all active contexts keyed by hub id.
569 =item $arrayref = $obj->context_acquire_callbacks
571 Get all context acquire callbacks.
573 =item $arrayref = $obj->context_init_callbacks
575 Get all context init callbacks.
577 =item $arrayref = $obj->context_release_callbacks
579 Get all context release callbacks.
581 =item $obj->add_context_init_callback(sub { ... })
583 Add a context init callback. Subs are called every time a context is created. Subs
584 get the newly created context as their only argument.
586 =item $obj->add_context_release_callback(sub { ... })
588 Add a context release callback. Subs are called every time a context is released. Subs
589 get the released context as their only argument. These callbacks should not
590 call release on the context.
592 =item $obj->set_exit()
594 This is intended to be called in an C<END { ... }> block. This will look at
595 test state and set $?. This will also call any end callbacks, and wait on child
598 =item $obj->ipc_enable_shm()
600 Turn on SHM for IPC (if possible)
602 =item $shm_id = $obj->ipc_shm_id()
604 If SHM is enabled for IPC this will be the shm_id for it.
606 =item $shm_size = $obj->ipc_shm_size()
608 If SHM is enabled for IPC this will be the size of it.
610 =item $shm_last_val = $obj->ipc_shm_last()
612 If SHM is enabled for IPC this will return the last SHM value seen.
614 =item $obj->set_ipc_pending($val)
616 use the IPC SHM to tell other processes and threads there is a pending event.
617 C<$val> should be a unique value no other thread/process will generate.
619 B<Note:> This will also make the current process see a pending event. It does
620 not set C<ipc_shm_last()>, this is important because doing so could hide a
623 =item $pending = $obj->get_ipc_pending()
625 This returns -1 if SHM is not enabled for IPC.
627 This returns 0 if the SHM value matches the last known value, which means there
628 are no pending events.
630 This returns 1 if the SHM value has changed, which means there are probably
633 When 1 is returned this will set C<< $obj->ipc_shm_last() >>.
635 =item $drivers = $obj->ipc_drivers
637 Get the list of IPC drivers.
639 =item $obj->add_ipc_driver($DRIVER_CLASS)
641 Add an IPC driver to the list. The most recently added IPC driver will become
642 the global one during initialization. If a driver is added after initialization
643 has occurred a warning will be generated:
645 "IPC driver $driver loaded too late to be used as the global ipc driver"
647 =item $bool = $obj->ipc_polling
649 Check if polling is enabled.
651 =item $obj->enable_ipc_polling
653 Turn on polling. This will cull events from other processes and threads every
654 time a context is created.
656 =item $obj->disable_ipc_polling
658 Turn off IPC polling.
660 =item $bool = $obj->no_wait
662 =item $bool = $obj->set_no_wait($bool)
664 Get/Set no_wait. This option is used to turn off process/thread waiting at exit.
666 =item $arrayref = $obj->exit_callbacks
668 Get the exit callbacks.
670 =item $obj->add_exit_callback(sub { ... })
672 Add an exit callback. This callback will be called by C<set_exit()>.
674 =item $bool = $obj->finalized
676 Check if the object is finalized. Finalization happens when either C<ipc()>,
677 C<stack()>, or C<format()> are called on the object. Once finalization happens
678 these fields are considered unchangeable (not enforced here, enforced by
681 =item $ipc = $obj->ipc
683 Get the one true IPC instance.
685 =item $stack = $obj->stack
687 Get the one true hub stack.
689 =item $formatter = $obj->formatter
691 Get the global formatter. By default this is the C<'Test2::Formatter::TAP'>
692 package. This could be any package that implements the C<write()> method. This
693 can also be an instantiated object.
695 =item $bool = $obj->formatter_set()
697 Check if a formatter has been set.
699 =item $obj->add_formatter($class)
701 =item $obj->add_formatter($obj)
703 Add a formatter. The most recently added formatter will become the global one
704 during initialization. If a formatter is added after initialization has occurred
705 a warning will be generated:
707 "Formatter $formatter loaded too late to be used as the global formatter"
713 The source code repository for Test2 can be found at
714 F<http://github.com/Test-More/test-more/>.
720 =item Chad Granum E<lt>exodist@cpan.orgE<gt>
728 =item Chad Granum E<lt>exodist@cpan.orgE<gt>
734 Copyright 2016 Chad Granum E<lt>exodist@cpan.orgE<gt>.
736 This program is free software; you can redistribute it and/or
737 modify it under the same terms as Perl itself.
739 See F<http://dev.perl.org/licenses/>