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