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