1package Test2::API::Instance;
2use strict;
3use warnings;
4
5our $VERSION = '1.302194';
6
7our @CARP_NOT = qw/Test2::API Test2::API::Instance Test2::IPC::Driver Test2::Formatter/;
8use Carp qw/confess carp/;
9use Scalar::Util qw/reftype/;
10
11use Test2::Util qw/get_tid USE_THREADS CAN_FORK pkg_to_file try CAN_SIGSYS/;
12
13use Test2::EventFacet::Trace();
14use Test2::API::Stack();
15
16use Test2::Util::HashBase qw{
17    _pid _tid
18    no_wait
19    finalized loaded
20    ipc stack formatter
21    contexts
22
23    add_uuid_via
24
25    -preload
26
27    ipc_disabled
28    ipc_polling
29    ipc_drivers
30    ipc_timeout
31    formatters
32
33    exit_callbacks
34    post_load_callbacks
35    context_acquire_callbacks
36    context_init_callbacks
37    context_release_callbacks
38    pre_subtest_callbacks
39};
40
41sub DEFAULT_IPC_TIMEOUT() { 30 }
42
43sub pid { $_[0]->{+_PID} }
44sub tid { $_[0]->{+_TID} }
45
46# Wrap around the getters that should call _finalize.
47BEGIN {
48    for my $finalizer (IPC, FORMATTER) {
49        my $orig = __PACKAGE__->can($finalizer);
50        my $new  = sub {
51            my $self = shift;
52            $self->_finalize unless $self->{+FINALIZED};
53            $self->$orig;
54        };
55
56        no strict 'refs';
57        no warnings 'redefine';
58        *{$finalizer} = $new;
59    }
60}
61
62sub has_ipc { !!$_[0]->{+IPC} }
63
64sub import {
65    my $class = shift;
66    return unless @_;
67    my ($ref) = @_;
68    $$ref = $class->new;
69}
70
71sub init { $_[0]->reset }
72
73sub start_preload {
74    my $self = shift;
75
76    confess "preload cannot be started, Test2::API has already been initialized"
77        if $self->{+FINALIZED} || $self->{+LOADED};
78
79    return $self->{+PRELOAD} = 1;
80}
81
82sub stop_preload {
83    my $self = shift;
84
85    return 0 unless $self->{+PRELOAD};
86    $self->{+PRELOAD} = 0;
87
88    $self->post_preload_reset();
89
90    return 1;
91}
92
93sub post_preload_reset {
94    my $self = shift;
95
96    delete $self->{+_PID};
97    delete $self->{+_TID};
98
99    $self->{+ADD_UUID_VIA} = undef unless exists $self->{+ADD_UUID_VIA};
100
101    $self->{+CONTEXTS} = {};
102
103    $self->{+FORMATTERS} = [];
104
105    $self->{+FINALIZED} = undef;
106    $self->{+IPC}       = undef;
107    $self->{+IPC_DISABLED} = $ENV{T2_NO_IPC} ? 1 : 0;
108
109    $self->{+IPC_TIMEOUT} = DEFAULT_IPC_TIMEOUT() unless defined $self->{+IPC_TIMEOUT};
110
111    $self->{+LOADED} = 0;
112
113    $self->{+STACK} ||= Test2::API::Stack->new;
114}
115
116sub reset {
117    my $self = shift;
118
119    delete $self->{+_PID};
120    delete $self->{+_TID};
121
122    $self->{+ADD_UUID_VIA} = undef;
123
124    $self->{+CONTEXTS} = {};
125
126    $self->{+IPC_DRIVERS} = [];
127    $self->{+IPC_POLLING} = undef;
128
129    $self->{+FORMATTERS} = [];
130    $self->{+FORMATTER}  = undef;
131
132    $self->{+FINALIZED}    = undef;
133    $self->{+IPC}          = undef;
134    $self->{+IPC_DISABLED} = $ENV{T2_NO_IPC} ? 1 : 0;
135
136    $self->{+IPC_TIMEOUT} = DEFAULT_IPC_TIMEOUT() unless defined $self->{+IPC_TIMEOUT};
137
138    $self->{+NO_WAIT} = 0;
139    $self->{+LOADED}  = 0;
140
141    $self->{+EXIT_CALLBACKS}            = [];
142    $self->{+POST_LOAD_CALLBACKS}       = [];
143    $self->{+CONTEXT_ACQUIRE_CALLBACKS} = [];
144    $self->{+CONTEXT_INIT_CALLBACKS}    = [];
145    $self->{+CONTEXT_RELEASE_CALLBACKS} = [];
146    $self->{+PRE_SUBTEST_CALLBACKS}     = [];
147
148    $self->{+STACK} = Test2::API::Stack->new;
149}
150
151sub _finalize {
152    my $self = shift;
153    my ($caller) = @_;
154    $caller ||= [caller(1)];
155
156    confess "Attempt to initialize Test2::API during preload"
157        if $self->{+PRELOAD};
158
159    $self->{+FINALIZED} = $caller;
160
161    $self->{+_PID} = $$        unless defined $self->{+_PID};
162    $self->{+_TID} = get_tid() unless defined $self->{+_TID};
163
164    unless ($self->{+FORMATTER}) {
165        my ($formatter, $source);
166        if ($ENV{T2_FORMATTER}) {
167            $source = "set by the 'T2_FORMATTER' environment variable";
168
169            if ($ENV{T2_FORMATTER} =~ m/^(\+)?(.*)$/) {
170                $formatter = $1 ? $2 : "Test2::Formatter::$2"
171            }
172            else {
173                $formatter = '';
174            }
175        }
176        elsif (@{$self->{+FORMATTERS}}) {
177            ($formatter) = @{$self->{+FORMATTERS}};
178            $source = "Most recently added";
179        }
180        else {
181            $formatter = 'Test2::Formatter::TAP';
182            $source    = 'default formatter';
183        }
184
185        unless (ref($formatter) || $formatter->can('write')) {
186            my $file = pkg_to_file($formatter);
187            my ($ok, $err) = try { require $file };
188            unless ($ok) {
189                my $line   = "* COULD NOT LOAD FORMATTER '$formatter' ($source) *";
190                my $border = '*' x length($line);
191                die "\n\n  $border\n  $line\n  $border\n\n$err";
192            }
193        }
194
195        $self->{+FORMATTER} = $formatter;
196    }
197
198    # Turn on IPC if threads are on, drivers are registered, or the Test2::IPC
199    # module is loaded.
200    return if $self->{+IPC_DISABLED};
201    return unless USE_THREADS || $INC{'Test2/IPC.pm'} || @{$self->{+IPC_DRIVERS}};
202
203    # Turn on polling by default, people expect it.
204    $self->enable_ipc_polling;
205
206    unless (@{$self->{+IPC_DRIVERS}}) {
207        my ($ok, $error) = try { require Test2::IPC::Driver::Files };
208        die $error unless $ok;
209        push @{$self->{+IPC_DRIVERS}} => 'Test2::IPC::Driver::Files';
210    }
211
212    for my $driver (@{$self->{+IPC_DRIVERS}}) {
213        next unless $driver->can('is_viable') && $driver->is_viable;
214        $self->{+IPC} = $driver->new or next;
215        return;
216    }
217
218    die "IPC has been requested, but no viable drivers were found. Aborting...\n";
219}
220
221sub formatter_set { $_[0]->{+FORMATTER} ? 1 : 0 }
222
223sub add_formatter {
224    my $self = shift;
225    my ($formatter) = @_;
226    unshift @{$self->{+FORMATTERS}} => $formatter;
227
228    return unless $self->{+FINALIZED};
229
230    # Why is the @CARP_NOT entry not enough?
231    local %Carp::Internal = %Carp::Internal;
232    $Carp::Internal{'Test2::Formatter'} = 1;
233
234    carp "Formatter $formatter loaded too late to be used as the global formatter";
235}
236
237sub add_context_acquire_callback {
238    my $self =  shift;
239    my ($code) = @_;
240
241    my $rtype = reftype($code) || "";
242
243    confess "Context-acquire callbacks must be coderefs"
244        unless $code && $rtype eq 'CODE';
245
246    push @{$self->{+CONTEXT_ACQUIRE_CALLBACKS}} => $code;
247}
248
249sub add_context_init_callback {
250    my $self =  shift;
251    my ($code) = @_;
252
253    my $rtype = reftype($code) || "";
254
255    confess "Context-init callbacks must be coderefs"
256        unless $code && $rtype eq 'CODE';
257
258    push @{$self->{+CONTEXT_INIT_CALLBACKS}} => $code;
259}
260
261sub add_context_release_callback {
262    my $self =  shift;
263    my ($code) = @_;
264
265    my $rtype = reftype($code) || "";
266
267    confess "Context-release callbacks must be coderefs"
268        unless $code && $rtype eq 'CODE';
269
270    push @{$self->{+CONTEXT_RELEASE_CALLBACKS}} => $code;
271}
272
273sub add_post_load_callback {
274    my $self = shift;
275    my ($code) = @_;
276
277    my $rtype = reftype($code) || "";
278
279    confess "Post-load callbacks must be coderefs"
280        unless $code && $rtype eq 'CODE';
281
282    push @{$self->{+POST_LOAD_CALLBACKS}} => $code;
283    $code->() if $self->{+LOADED};
284}
285
286sub add_pre_subtest_callback {
287    my $self =  shift;
288    my ($code) = @_;
289
290    my $rtype = reftype($code) || "";
291
292    confess "Pre-subtest callbacks must be coderefs"
293        unless $code && $rtype eq 'CODE';
294
295    push @{$self->{+PRE_SUBTEST_CALLBACKS}} => $code;
296}
297
298sub load {
299    my $self = shift;
300    unless ($self->{+LOADED}) {
301        confess "Attempt to initialize Test2::API during preload"
302            if $self->{+PRELOAD};
303
304        $self->{+_PID} = $$        unless defined $self->{+_PID};
305        $self->{+_TID} = get_tid() unless defined $self->{+_TID};
306
307        # This is for https://github.com/Test-More/test-more/issues/16
308        # and https://rt.perl.org/Public/Bug/Display.html?id=127774
309        # END blocks run in reverse order. This insures the END block is loaded
310        # as late as possible. It will not solve all cases, but it helps.
311        eval "END { Test2::API::test2_set_is_end() }; 1" or die $@;
312
313        $self->{+LOADED} = 1;
314        $_->() for @{$self->{+POST_LOAD_CALLBACKS}};
315    }
316    return $self->{+LOADED};
317}
318
319sub add_exit_callback {
320    my $self = shift;
321    my ($code) = @_;
322    my $rtype = reftype($code) || "";
323
324    confess "End callbacks must be coderefs"
325        unless $code && $rtype eq 'CODE';
326
327    push @{$self->{+EXIT_CALLBACKS}} => $code;
328}
329
330sub ipc_disable {
331    my $self = shift;
332
333    confess "Attempt to disable IPC after it has been initialized"
334        if $self->{+IPC};
335
336    $self->{+IPC_DISABLED} = 1;
337}
338
339sub add_ipc_driver {
340    my $self = shift;
341    my ($driver) = @_;
342    unshift @{$self->{+IPC_DRIVERS}} => $driver;
343
344    return unless $self->{+FINALIZED};
345
346    # Why is the @CARP_NOT entry not enough?
347    local %Carp::Internal = %Carp::Internal;
348    $Carp::Internal{'Test2::IPC::Driver'} = 1;
349
350    carp "IPC driver $driver loaded too late to be used as the global ipc driver";
351}
352
353sub enable_ipc_polling {
354    my $self = shift;
355
356    $self->{+_PID} = $$        unless defined $self->{+_PID};
357    $self->{+_TID} = get_tid() unless defined $self->{+_TID};
358
359    $self->add_context_init_callback(
360        # This is called every time a context is created, it needs to be fast.
361        # $_[0] is a context object
362        sub {
363            return unless $self->{+IPC_POLLING};
364            return unless $self->{+IPC};
365            return unless $self->{+IPC}->pending();
366            return $_[0]->{hub}->cull;
367        }
368    ) unless defined $self->ipc_polling;
369
370    $self->set_ipc_polling(1);
371}
372
373sub get_ipc_pending {
374    my $self = shift;
375    return -1 unless $self->{+IPC};
376    $self->{+IPC}->pending();
377}
378
379sub _check_pid {
380    my $self = shift;
381    my ($pid) = @_;
382    return kill(0, $pid);
383}
384
385sub set_ipc_pending {
386    my $self = shift;
387    return unless $self->{+IPC};
388    my ($val) = @_;
389
390    confess "value is required for set_ipc_pending"
391        unless $val;
392
393    $self->{+IPC}->set_pending($val);
394}
395
396sub disable_ipc_polling {
397    my $self = shift;
398    return unless defined $self->{+IPC_POLLING};
399    $self->{+IPC_POLLING} = 0;
400}
401
402sub _ipc_wait {
403    my ($timeout) = @_;
404    my $fail = 0;
405
406    $timeout = DEFAULT_IPC_TIMEOUT() unless defined $timeout;
407
408    my $ok = eval {
409        if (CAN_FORK) {
410            local $SIG{ALRM} = sub { die "Timeout waiting on child processes" };
411            alarm $timeout;
412
413            while (1) {
414                my $pid = CORE::wait();
415                my $err = $?;
416                last if $pid == -1;
417                next unless $err;
418                $fail++;
419
420                my $sig = $err & 127;
421                my $exit = $err >> 8;
422                warn "Process $pid did not exit cleanly (wstat: $err, exit: $exit, sig: $sig)\n";
423            }
424
425            alarm 0;
426        }
427
428        if (USE_THREADS) {
429            my $start = time;
430
431            while (1) {
432                last unless threads->list();
433                die "Timeout waiting on child thread" if time - $start >= $timeout;
434                sleep 1;
435                for my $t (threads->list) {
436                    # threads older than 1.34 do not have this :-(
437                    next if $t->can('is_joinable') && !$t->is_joinable;
438                    $t->join;
439                    # In older threads we cannot check if a thread had an error unless
440                    # we control it and its return.
441                    my $err = $t->can('error') ? $t->error : undef;
442                    next unless $err;
443                    my $tid = $t->tid();
444                    $fail++;
445                    chomp($err);
446                    warn "Thread $tid did not end cleanly: $err\n";
447                }
448            }
449        }
450
451        1;
452    };
453    my $error = $@;
454
455    return 0 if $ok && !$fail;
456    warn $error unless $ok;
457    return 255;
458}
459
460sub set_exit {
461    my $self = shift;
462
463    return if $self->{+PRELOAD};
464
465    my $exit     = $?;
466    my $new_exit = $exit;
467
468    if ($INC{'Test/Builder.pm'} && $Test::Builder::VERSION ne $Test2::API::VERSION) {
469        print STDERR <<"        EOT";
470
471********************************************************************************
472*                                                                              *
473*            Test::Builder -- Test2::API version mismatch detected             *
474*                                                                              *
475********************************************************************************
476   Test2::API Version: $Test2::API::VERSION
477Test::Builder Version: $Test::Builder::VERSION
478
479This is not a supported configuration, you will have problems.
480
481        EOT
482    }
483
484    for my $ctx (values %{$self->{+CONTEXTS}}) {
485        next unless $ctx;
486
487        next if $ctx->_aborted && ${$ctx->_aborted};
488
489        # Only worry about contexts in this PID
490        my $trace = $ctx->trace || next;
491        next unless $trace->pid && $trace->pid == $$;
492
493        # Do not worry about contexts that have no hub
494        my $hub = $ctx->hub  || next;
495
496        # Do not worry if the state came to a sudden end.
497        next if $hub->bailed_out;
498        next if defined $hub->skip_reason;
499
500        # now we worry
501        $trace->alert("context object was never released! This means a testing tool is behaving very badly");
502
503        $exit     = 255;
504        $new_exit = 255;
505    }
506
507    if (!defined($self->{+_PID}) or !defined($self->{+_TID}) or $self->{+_PID} != $$ or $self->{+_TID} != get_tid()) {
508        $? = $exit;
509        return;
510    }
511
512    my @hubs = $self->{+STACK} ? $self->{+STACK}->all : ();
513
514    if (@hubs and $self->{+IPC} and !$self->{+NO_WAIT}) {
515        local $?;
516        my %seen;
517        for my $hub (reverse @hubs) {
518            my $ipc = $hub->ipc or next;
519            next if $seen{$ipc}++;
520            $ipc->waiting();
521        }
522
523        my $ipc_exit = _ipc_wait($self->{+IPC_TIMEOUT});
524        $new_exit ||= $ipc_exit;
525    }
526
527    # None of this is necessary if we never got a root hub
528    if(my $root = shift @hubs) {
529        my $trace = Test2::EventFacet::Trace->new(
530            frame  => [__PACKAGE__, __FILE__, 0, __PACKAGE__ . '::END'],
531            detail => __PACKAGE__ . ' END Block finalization',
532        );
533        my $ctx = Test2::API::Context->new(
534            trace => $trace,
535            hub   => $root,
536        );
537
538        if (@hubs) {
539            $ctx->diag("Test ended with extra hubs on the stack!");
540            $new_exit  = 255;
541        }
542
543        unless ($root->no_ending) {
544            local $?;
545            $root->finalize($trace) unless $root->ended;
546            $_->($ctx, $exit, \$new_exit) for @{$self->{+EXIT_CALLBACKS}};
547            $new_exit ||= $root->failed;
548            $new_exit ||= 255 unless $root->is_passing;
549        }
550    }
551
552    $new_exit = 255 if $new_exit > 255;
553
554    if ($new_exit && eval { require Test2::API::Breakage; 1 }) {
555        my @warn = Test2::API::Breakage->report();
556
557        if (@warn) {
558            print STDERR "\nYou have loaded versions of test modules known to have problems with Test2.\nThis could explain some test failures.\n";
559            print STDERR "$_\n" for @warn;
560            print STDERR "\n";
561        }
562    }
563
564    $? = $new_exit;
565}
566
5671;
568
569__END__
570
571=pod
572
573=encoding UTF-8
574
575=head1 NAME
576
577Test2::API::Instance - Object used by Test2::API under the hood
578
579=head1 DESCRIPTION
580
581This object encapsulates the global shared state tracked by
582L<Test2>. A single global instance of this package is stored (and
583obscured) by the L<Test2::API> package.
584
585There is no reason to directly use this package. This package is documented for
586completeness. This package can change, or go away completely at any time.
587Directly using, or monkeypatching this package is not supported in any way
588shape or form.
589
590=head1 SYNOPSIS
591
592    use Test2::API::Instance;
593
594    my $obj = Test2::API::Instance->new;
595
596=over 4
597
598=item $pid = $obj->pid
599
600PID of this instance.
601
602=item $obj->tid
603
604Thread ID of this instance.
605
606=item $obj->reset()
607
608Reset the object to defaults.
609
610=item $obj->load()
611
612Set the internal state to loaded, and run and stored post-load callbacks.
613
614=item $bool = $obj->loaded
615
616Check if the state is set to loaded.
617
618=item $arrayref = $obj->post_load_callbacks
619
620Get the post-load callbacks.
621
622=item $obj->add_post_load_callback(sub { ... })
623
624Add a post-load callback. If C<load()> has already been called then the callback will
625be immediately executed. If C<load()> has not been called then the callback will be
626stored and executed later when C<load()> is called.
627
628=item $hashref = $obj->contexts()
629
630Get a hashref of all active contexts keyed by hub id.
631
632=item $arrayref = $obj->context_acquire_callbacks
633
634Get all context acquire callbacks.
635
636=item $arrayref = $obj->context_init_callbacks
637
638Get all context init callbacks.
639
640=item $arrayref = $obj->context_release_callbacks
641
642Get all context release callbacks.
643
644=item $arrayref = $obj->pre_subtest_callbacks
645
646Get all pre-subtest callbacks.
647
648=item $obj->add_context_init_callback(sub { ... })
649
650Add a context init callback. Subs are called every time a context is created. Subs
651get the newly created context as their only argument.
652
653=item $obj->add_context_release_callback(sub { ... })
654
655Add a context release callback. Subs are called every time a context is released. Subs
656get the released context as their only argument. These callbacks should not
657call release on the context.
658
659=item $obj->add_pre_subtest_callback(sub { ... })
660
661Add a pre-subtest callback. Subs are called every time a subtest is
662going to be run. Subs get the subtest name, coderef, and any
663arguments.
664
665=item $obj->set_exit()
666
667This is intended to be called in an C<END { ... }> block. This will look at
668test state and set $?. This will also call any end callbacks, and wait on child
669processes/threads.
670
671=item $obj->set_ipc_pending($val)
672
673Tell other processes and threads there is a pending event. C<$val> should be a
674unique value no other thread/process will generate.
675
676B<Note:> This will also make the current process see a pending event.
677
678=item $pending = $obj->get_ipc_pending()
679
680This returns -1 if it is not possible to know.
681
682This returns 0 if there are no pending events.
683
684This returns 1 if there are pending events.
685
686=item $timeout = $obj->ipc_timeout;
687
688=item $obj->set_ipc_timeout($timeout);
689
690How long to wait for child processes and threads before aborting.
691
692=item $drivers = $obj->ipc_drivers
693
694Get the list of IPC drivers.
695
696=item $obj->add_ipc_driver($DRIVER_CLASS)
697
698Add an IPC driver to the list. The most recently added IPC driver will become
699the global one during initialization. If a driver is added after initialization
700has occurred a warning will be generated:
701
702    "IPC driver $driver loaded too late to be used as the global ipc driver"
703
704=item $bool = $obj->ipc_polling
705
706Check if polling is enabled.
707
708=item $obj->enable_ipc_polling
709
710Turn on polling. This will cull events from other processes and threads every
711time a context is created.
712
713=item $obj->disable_ipc_polling
714
715Turn off IPC polling.
716
717=item $bool = $obj->no_wait
718
719=item $bool = $obj->set_no_wait($bool)
720
721Get/Set no_wait. This option is used to turn off process/thread waiting at exit.
722
723=item $arrayref = $obj->exit_callbacks
724
725Get the exit callbacks.
726
727=item $obj->add_exit_callback(sub { ... })
728
729Add an exit callback. This callback will be called by C<set_exit()>.
730
731=item $bool = $obj->finalized
732
733Check if the object is finalized. Finalization happens when either C<ipc()>,
734C<stack()>, or C<format()> are called on the object. Once finalization happens
735these fields are considered unchangeable (not enforced here, enforced by
736L<Test2>).
737
738=item $ipc = $obj->ipc
739
740Get the one true IPC instance.
741
742=item $obj->ipc_disable
743
744Turn IPC off
745
746=item $bool = $obj->ipc_disabled
747
748Check if IPC is disabled
749
750=item $stack = $obj->stack
751
752Get the one true hub stack.
753
754=item $formatter = $obj->formatter
755
756Get the global formatter. By default this is the C<'Test2::Formatter::TAP'>
757package. This could be any package that implements the C<write()> method. This
758can also be an instantiated object.
759
760=item $bool = $obj->formatter_set()
761
762Check if a formatter has been set.
763
764=item $obj->add_formatter($class)
765
766=item $obj->add_formatter($obj)
767
768Add a formatter. The most recently added formatter will become the global one
769during initialization. If a formatter is added after initialization has occurred
770a warning will be generated:
771
772    "Formatter $formatter loaded too late to be used as the global formatter"
773
774=item $obj->set_add_uuid_via(sub { ... })
775
776=item $sub = $obj->add_uuid_via()
777
778This allows you to provide a UUID generator. If provided UUIDs will be attached
779to all events, hubs, and contexts. This is useful for storing, tracking, and
780linking these objects.
781
782The sub you provide should always return a unique identifier. Most things will
783expect a proper UUID string, however nothing in Test2::API enforces this.
784
785The sub will receive exactly 1 argument, the type of thing being tagged
786'context', 'hub', or 'event'. In the future additional things may be tagged, in
787which case new strings will be passed in. These are purely informative, you can
788(and usually should) ignore them.
789
790=back
791
792=head1 SOURCE
793
794The source code repository for Test2 can be found at
795F<http://github.com/Test-More/test-more/>.
796
797=head1 MAINTAINERS
798
799=over 4
800
801=item Chad Granum E<lt>exodist@cpan.orgE<gt>
802
803=back
804
805=head1 AUTHORS
806
807=over 4
808
809=item Chad Granum E<lt>exodist@cpan.orgE<gt>
810
811=back
812
813=head1 COPYRIGHT
814
815Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>.
816
817This program is free software; you can redistribute it and/or
818modify it under the same terms as Perl itself.
819
820See F<http://dev.perl.org/licenses/>
821
822=cut
823