This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update Test-Simple to alpha 076
[perl5.git] / cpan / Test-Simple / lib / Test / Stream.pm
CommitLineData
518760d9
CG
1package Test::Stream;
2use strict;
3use warnings;
4
136323e4 5our $VERSION = '1.301001_076';
518760d9
CG
6$VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval)
7
4e88444f 8use Test::Stream::Context qw/context/;
518760d9
CG
9use Test::Stream::Threads;
10use Test::Stream::IOSets;
11use Test::Stream::Util qw/try/;
12use Test::Stream::Carp qw/croak confess carp/;
13use Test::Stream::Meta qw/MODERN ENCODING init_tester/;
14
15use Test::Stream::ArrayBase(
16 accessors => [qw{
17 no_ending no_diag no_header
18 pid tid
19 state
20 subtests subtest_todo subtest_exception
21 subtest_tap_instant
22 subtest_tap_delayed
23 mungers
24 listeners
25 follow_ups
26 bailed_out
27 exit_on_disruption
28 use_tap use_legacy _use_fork
29 use_numbers
30 io_sets
31 event_id
32 in_subthread
33 }],
34);
35
36sub STATE_COUNT() { 0 }
37sub STATE_FAILED() { 1 }
38sub STATE_PLAN() { 2 }
39sub STATE_PASSING() { 3 }
40sub STATE_LEGACY() { 4 }
41sub STATE_ENDED() { 5 }
42
43sub OUT_STD() { 0 }
44sub OUT_ERR() { 1 }
45sub OUT_TODO() { 2 }
46
47use Test::Stream::Exporter;
48exports qw/
49 OUT_STD OUT_ERR OUT_TODO
50 STATE_COUNT STATE_FAILED STATE_PLAN STATE_PASSING STATE_LEGACY STATE_ENDED
51/;
4e88444f 52default_exports qw/ cull tap_encoding context /;
518760d9
CG
53Test::Stream::Exporter->cleanup;
54
55sub tap_encoding {
56 my ($encoding) = @_;
57
58 require Encode;
59
60 croak "encoding '$encoding' is not valid, or not available"
61 unless $encoding eq 'legacy' || Encode::find_encoding($encoding);
62
63 require Test::Stream::Context;
64 my $ctx = Test::Stream::Context::context();
65 $ctx->stream->io_sets->init_encoding($encoding);
66
67 my $meta = init_tester($ctx->package);
68 $meta->[ENCODING] = $encoding;
69}
70
71sub cull {
518760d9
CG
72 my $ctx = Test::Stream::Context::context();
73 $ctx->stream->fork_cull();
74}
75
76sub before_import {
77 my $class = shift;
78 my ($importer, $list) = @_;
79
80 if (@$list && $list->[0] eq '-internal') {
81 shift @$list;
82 return;
83 }
84
85 my $meta = init_tester($importer);
86 $meta->[MODERN] = 1;
87
88 my $other = [];
89 my $idx = 0;
90 my $stream = $class->shared;
91
92 while ($idx <= $#{$list}) {
93 my $item = $list->[$idx++];
94 next unless $item;
95
96 if ($item eq 'subtest_tap') {
97 my $val = $list->[$idx++];
98 if (!$val || $val eq 'none') {
99 $stream->set_subtest_tap_instant(0);
100 $stream->set_subtest_tap_delayed(0);
101 }
102 elsif ($val eq 'instant') {
103 $stream->set_subtest_tap_instant(1);
104 $stream->set_subtest_tap_delayed(0);
105 }
106 elsif ($val eq 'delayed') {
107 $stream->set_subtest_tap_instant(0);
108 $stream->set_subtest_tap_delayed(1);
109 }
110 elsif ($val eq 'both') {
111 $stream->set_subtest_tap_instant(1);
112 $stream->set_subtest_tap_delayed(1);
113 }
114 else {
115 croak "'$val' is not a valid option for '$item'";
116 }
117 }
118 elsif ($item eq 'utf8') {
119 $stream->io_sets->init_encoding('utf8');
120 $meta->[ENCODING] = 'utf8';
121 }
122 elsif ($item eq 'encoding') {
123 my $encoding = $list->[$idx++];
124
125 croak "encoding '$encoding' is not valid, or not available"
126 unless Encode::find_encoding($encoding);
127
128 $stream->io_sets->init_encoding($encoding);
129 $meta->[ENCODING] = $encoding;
130 }
131 elsif ($item eq 'enable_fork') {
132 $stream->use_fork;
133 }
134 else {
135 push @$other => $item;
136 }
137 }
138
139 @$list = @$other;
140
141 return;
142}
143
144sub plan { $_[0]->[STATE]->[-1]->[STATE_PLAN] }
145sub count { $_[0]->[STATE]->[-1]->[STATE_COUNT] }
146sub failed { $_[0]->[STATE]->[-1]->[STATE_FAILED] }
147sub ended { $_[0]->[STATE]->[-1]->[STATE_ENDED] }
148sub legacy { $_[0]->[STATE]->[-1]->[STATE_LEGACY] }
149
150sub is_passing {
151 my $self = shift;
152
153 if (@_) {
154 ($self->[STATE]->[-1]->[STATE_PASSING]) = @_;
155 }
156
157 my $current = $self->[STATE]->[-1]->[STATE_PASSING];
158
159 my $plan = $self->[STATE]->[-1]->[STATE_PLAN];
160 return $current if $self->[STATE]->[-1]->[STATE_ENDED];
161 return $current unless $plan;
162 return $current unless $plan->max;
163 return $current if $plan->directive && $plan->directive eq 'NO PLAN';
164 return $current unless $self->[STATE]->[-1]->[STATE_COUNT] > $plan->max;
165
166 return $self->[STATE]->[-1]->[STATE_PASSING] = 0;
167}
168
169sub init {
170 my $self = shift;
171
172 $self->[PID] = $$;
173 $self->[TID] = get_tid();
174 $self->[STATE] = [[0, 0, undef, 1]];
175 $self->[USE_TAP] = 1;
176 $self->[USE_NUMBERS] = 1;
177 $self->[IO_SETS] = Test::Stream::IOSets->new;
178 $self->[EVENT_ID] = 1;
179 $self->[NO_ENDING] = 1;
180 $self->[SUBTESTS] = [];
181
182 $self->[SUBTEST_TAP_INSTANT] = 1;
183 $self->[SUBTEST_TAP_DELAYED] = 0;
184
185 $self->use_fork if USE_THREADS;
186
187 $self->[EXIT_ON_DISRUPTION] = 1;
188}
189
190{
191 my ($root, @stack, $magic);
192
193 END {
194 $root->fork_cull if $root && $root->_use_fork && $$ == $root->[PID];
195 $magic->do_magic($root) if $magic && $root && !$root->[NO_ENDING]
196 }
197
198 sub _stack { @stack }
199
200 sub shared {
201 my ($class) = @_;
202 return $stack[-1] if @stack;
203
204 @stack = ($root = $class->new(0));
205 $root->[NO_ENDING] = 0;
206
207 require Test::Stream::Context;
208 require Test::Stream::Event::Finish;
209 require Test::Stream::ExitMagic;
210 require Test::Stream::ExitMagic::Context;
211
212 $magic = Test::Stream::ExitMagic->new;
213
214 return $root;
215 }
216
217 sub clear {
218 $root->[NO_ENDING] = 1;
219 $root = undef;
220 $magic = undef;
221 @stack = ();
222 }
223
224 sub intercept_start {
225 my $class = shift;
226 my ($new) = @_;
227
228 my $old = $stack[-1];
229
230 unless($new) {
231 $new = $class->new();
232
233 $new->set_exit_on_disruption(0);
234 $new->set_use_tap(0);
235 $new->set_use_legacy(0);
236 }
237
238 push @stack => $new;
239
240 return ($new, $old);
241 }
242
243 sub intercept_stop {
244 my $class = shift;
245 my ($current) = @_;
246 croak "Stream stack inconsistency" unless $current == $stack[-1];
247 pop @stack;
248 }
249}
250
251sub intercept {
252 my $class = shift;
253 my ($code) = @_;
254
255 croak "The first argument to intercept must be a coderef"
256 unless $code && ref $code && ref $code eq 'CODE';
257
258 my ($new, $old) = $class->intercept_start();
259 my ($ok, $error) = try { $code->($new, $old) };
260 $class->intercept_stop($new);
261
262 die $error unless $ok;
263 return $ok;
264}
265
266sub listen {
267 my $self = shift;
268 for my $sub (@_) {
269 next unless $sub;
270
271 croak "listen only takes coderefs for arguments, got '$sub'"
272 unless ref $sub && ref $sub eq 'CODE';
273
274 push @{$self->[LISTENERS]} => $sub;
275 }
276}
277
278sub munge {
279 my $self = shift;
280 for my $sub (@_) {
281 next unless $sub;
282
283 croak "munge only takes coderefs for arguments, got '$sub'"
284 unless ref $sub && ref $sub eq 'CODE';
285
286 push @{$self->[MUNGERS]} => $sub;
287 }
288}
289
290sub follow_up {
291 my $self = shift;
292 for my $sub (@_) {
293 next unless $sub;
294
295 croak "follow_up only takes coderefs for arguments, got '$sub'"
296 unless ref $sub && ref $sub eq 'CODE';
297
298 push @{$self->[FOLLOW_UPS]} => $sub;
299 }
300}
301
302sub use_fork {
303 require File::Temp;
304 require Storable;
305
306 $_[0]->[_USE_FORK] ||= File::Temp::tempdir(CLEANUP => 0);
307 confess "Could not get a temp dir" unless $_[0]->[_USE_FORK];
308 if ($^O eq 'VMS') {
309 require VMS::Filespec;
310 $_[0]->[_USE_FORK] = VMS::Filespec::unixify($_[0]->[_USE_FORK]);
311 }
312 return 1;
313}
314
315sub fork_out {
316 my $self = shift;
317
318 my $tempdir = $self->[_USE_FORK];
319 confess "Fork support has not been turned on!" unless $tempdir;
320
321 my $tid = get_tid();
322
323 for my $event (@_) {
324 next unless $event;
325 next if $event->isa('Test::Stream::Event::Finish');
326
327 # First write the file, then rename it so that it is not read before it is ready.
328 my $name = $tempdir . "/$$-$tid-" . ($self->[EVENT_ID]++);
329 my ($ret, $err) = try { Storable::store($event, $name) };
330 # Temporary to debug an error on one cpan-testers box
331 unless ($ret) {
332 require Data::Dumper;
333 confess(Data::Dumper::Dumper({ error => $err, event => $event}));
334 }
335 rename($name, "$name.ready") || confess "Could not rename file '$name' -> '$name.ready'";
336 }
337}
338
339sub fork_cull {
340 my $self = shift;
341
342 confess "fork_cull() can only be called from the parent process!"
343 if $$ != $self->[PID];
344
345 confess "fork_cull() can only be called from the parent thread!"
346 if get_tid() != $self->[TID];
347
348 my $tempdir = $self->[_USE_FORK];
349 confess "Fork support has not been turned on!" unless $tempdir;
350
351 opendir(my $dh, $tempdir) || croak "could not open temp dir ($tempdir)!";
352
353 my @files = sort readdir($dh);
354 for my $file (@files) {
355 next if $file =~ m/^\.+$/;
356 next unless $file =~ m/\.ready$/;
357
358 # Untaint the path.
359 my $full = "$tempdir/$file";
360 ($full) = ($full =~ m/^(.*)$/gs);
361
362 my $obj = Storable::retrieve($full);
363 confess "Empty event object found '$full'" unless $obj;
364
365 if ($ENV{TEST_KEEP_TMP_DIR}) {
366 rename($full, "$full.complete")
367 || confess "Could not rename file '$full', '$full.complete'";
368 }
369 else {
370 unlink($full) || die "Could not unlink file: $file";
371 }
372
373 my $cache = $self->_update_state($self->[STATE]->[0], $obj);
374 $self->_process_event($obj, $cache);
375 $self->_finalize_event($obj, $cache);
376 }
377
378 closedir($dh);
379}
380
381sub done_testing {
382 my $self = shift;
383 my ($ctx, $num) = @_;
384 my $state = $self->[STATE]->[-1];
385
386 if (my $old = $state->[STATE_ENDED]) {
387 my ($p1, $f1, $l1) = $old->call;
388 $ctx->ok(0, "done_testing() was already called at $f1 line $l1");
389 return;
390 }
391
392 if ($self->[FOLLOW_UPS]) {
393 $_->($ctx) for @{$self->[FOLLOW_UPS]};
394 }
395
396 $state->[STATE_ENDED] = $ctx->snapshot;
397
398 my $ran = $state->[STATE_COUNT];
399 my $plan = $state->[STATE_PLAN] ? $state->[STATE_PLAN]->max : 0;
400
401 if (defined($num) && $plan && $num != $plan) {
402 $ctx->ok(0, "planned to run $plan but done_testing() expects $num");
403 return;
404 }
405
406 $ctx->plan($num || $plan || $ran) unless $state->[STATE_PLAN];
407
408 if ($plan && $plan != $ran) {
409 $state->[STATE_PASSING] = 0;
410 return;
411 }
412
413 if ($num && $num != $ran) {
414 $state->[STATE_PASSING] = 0;
415 return;
416 }
417
418 unless ($ran) {
419 $state->[STATE_PASSING] = 0;
420 return;
421 }
422}
423
424sub send {
425 my ($self, $e) = @_;
426
427 # Subtest state management
428 if ($e->isa('Test::Stream::Event::Child')) {
429 if ($e->action eq 'push') {
430 $e->context->note("Subtest: " . $e->name) if $self->[SUBTEST_TAP_INSTANT] && !$e->no_note;
431
432 push @{$self->[STATE]} => [0, 0, undef, 1];
433 push @{$self->[SUBTESTS]} => [];
434 push @{$self->[SUBTEST_TODO]} => $e->context->in_todo;
435 push @{$self->[SUBTEST_EXCEPTION]} => undef;
436
437 return $e;
438 }
439 else {
440 pop @{$self->[SUBTEST_TODO]};
441 my $events = pop @{$self->[SUBTESTS]} || confess "Unbalanced subtest stack (events)!";
442 my $state = pop @{$self->[STATE]} || confess "Unbalanced subtest stack (state)!";
443 confess "Child pop left the stream without a state!" unless @{$self->[STATE]};
444
445 $e = Test::Stream::Event::Subtest->new_from_pairs(
446 context => $e->context,
447 created => $e->created,
448 events => $events,
449 state => $state,
450 name => $e->name,
451 exception => pop @{$self->[SUBTEST_EXCEPTION]},
452 );
453 }
454 }
455
456 my $cache = $self->_update_state($self->[STATE]->[-1], $e);
457
458 # Subtests get dibbs on events
459 if (@{$self->[SUBTESTS]}) {
460 $e->context->set_diag_todo(1) if $self->[SUBTEST_TODO]->[-1];
461 $e->set_in_subtest(scalar @{$self->[SUBTESTS]});
462 push @{$self->[SUBTESTS]->[-1]} => $e;
463
464 $self->_render_tap($cache) if $self->[SUBTEST_TAP_INSTANT] && !$cache->{no_out};
465 }
466 elsif($self->[_USE_FORK] && ($$ != $self->[PID] || get_tid() != $self->[TID])) {
467 $self->fork_out($e);
468 }
469 else {
470 $self->_process_event($e, $cache);
471 }
472
473 $self->_finalize_event($e, $cache);
474
475 return $e;
476}
477
478sub _update_state {
479 my ($self, $state, $e) = @_;
480 my $cache = {tap_event => $e, state => $state};
481
482 if ($e->isa('Test::Stream::Event::Ok')) {
483 $cache->{do_tap} = 1;
484 $state->[STATE_COUNT]++;
485 if (!$e->bool) {
486 $state->[STATE_FAILED]++;
487 $state->[STATE_PASSING] = 0;
488 }
489 }
490 elsif (!$self->[NO_HEADER] && $e->isa('Test::Stream::Event::Finish')) {
491 if ($self->[FOLLOW_UPS]) {
492 $_->($e->context) for @{$self->[FOLLOW_UPS]};
493 }
494
495 $state->[STATE_ENDED] = $e->context->snapshot;
496
497 my $plan = $state->[STATE_PLAN];
498 if ($plan && $e->tests_run && $plan->directive eq 'NO PLAN') {
499 $plan->set_max($state->[STATE_COUNT]);
500 $plan->set_directive(undef);
501 $cache->{tap_event} = $plan;
502 $cache->{do_tap} = 1;
503 }
504 else {
505 $cache->{do_tap} = 0;
506 $cache->{no_out} = 1;
507 }
508 }
509 elsif ($self->[NO_DIAG] && $e->isa('Test::Stream::Event::Diag')) {
510 $cache->{no_out} = 1;
511 }
512 elsif ($e->isa('Test::Stream::Event::Plan')) {
513 $cache->{is_plan} = 1;
514
515 if($self->[NO_HEADER]) {
516 $cache->{no_out} = 1;
517 }
518 elsif(my $existing = $state->[STATE_PLAN]) {
519 my $directive = $existing ? $existing->directive : '';
520
521 if ($existing && (!$directive || $directive eq 'NO PLAN')) {
522 my ($p1, $f1, $l1) = $existing->context->call;
523 my ($p2, $f2, $l2) = $e->context->call;
524 die "Tried to plan twice!\n $f1 line $l1\n $f2 line $l2\n";
525 }
526 }
527
528 my $directive = $e->directive;
529 $cache->{no_out} = 1 if $directive && $directive eq 'NO PLAN';
530 }
531
532 push @{$state->[STATE_LEGACY]} => $e if $self->[USE_LEGACY];
533
534 $cache->{number} = $state->[STATE_COUNT];
535
536 return $cache;
537}
538
539sub _process_event {
540 my ($self, $e, $cache) = @_;
541
542 if ($self->[MUNGERS]) {
543 $_->($self, $e) for @{$self->[MUNGERS]};
544 }
545
546 $self->_render_tap($cache) unless $cache->{no_out};
547
548 if ($self->[LISTENERS]) {
549 $_->($self, $e) for @{$self->[LISTENERS]};
550 }
551}
552
553sub _render_tap {
554 my ($self, $cache) = @_;
555
556 return if $^C;
557 return unless $self->[USE_TAP];
558 my $e = $cache->{tap_event};
559 return unless $cache->{do_tap} || $e->can('to_tap');
560
561 my $num = $self->use_numbers ? $cache->{number} : undef;
562 confess "XXX" unless $e->can('to_tap');
563 my @sets = $e->to_tap($num, $self->[SUBTEST_TAP_DELAYED]);
564
565 my $in_subtest = $e->in_subtest || 0;
566 my $indent = ' ' x $in_subtest;
567
568 for my $set (@sets) {
569 my ($hid, $msg) = @$set;
570 next unless $msg;
571 my $enc = $e->encoding || confess "Could not find encoding!";
572 my $io = $self->[IO_SETS]->{$enc}->[$hid] || confess "Could not find IO $hid for $enc";
573
574 local($\, $", $,) = (undef, ' ', '');
575 $msg =~ s/^/$indent/mg if $in_subtest;
576 print $io $msg;
577 }
578}
579
580sub _finalize_event {
581 my ($self, $e, $cache) = @_;
582
583 if ($cache->{is_plan}) {
584 $cache->{state}->[STATE_PLAN] = $e;
585 return unless $e->directive;
586 return unless $e->directive eq 'SKIP';
587
588 $self->[SUBTEST_EXCEPTION]->[-1] = $e if $e->in_subtest;
589
590 die $e if $e->in_subtest || !$self->[EXIT_ON_DISRUPTION];
591 exit 0;
592 }
593 elsif (!$cache->{do_tap} && $e->isa('Test::Stream::Event::Bail')) {
594 $self->[BAILED_OUT] = $e;
595 $self->[NO_ENDING] = 1;
596
597 $self->[SUBTEST_EXCEPTION]->[-1] = $e if $e->in_subtest;
598
599 die $e if $e->in_subtest || !$self->[EXIT_ON_DISRUPTION];
600 exit 255;
601 }
602}
603
604sub _reset {
605 my $self = shift;
606
607 return unless $self->pid != $$ || $self->tid != get_tid();
608
609 $self->[PID] = $$;
610 $self->[TID] = get_tid();
611 if (USE_THREADS || $self->[_USE_FORK]) {
612 $self->[_USE_FORK] = undef;
613 $self->use_fork;
614 }
615 $self->[STATE] = [[0, 0, undef, 1]];
616}
617
618sub CLONE {
619 for my $stream (_stack()) {
620 next unless defined $stream->pid;
621 next unless defined $stream->tid;
622
623 next if $$ == $stream->pid && get_tid() == $stream->tid;
624
625 $stream->[IN_SUBTHREAD] = 1;
626 }
627}
628
629sub DESTROY {
630 my $self = shift;
631
632 return if $self->in_subthread;
633
634 my $dir = $self->[_USE_FORK] || return;
635
636 return unless defined $self->pid;
637 return unless defined $self->tid;
638
639 return unless $$ == $self->pid;
640 return unless get_tid() == $self->tid;
641
642 if ($ENV{TEST_KEEP_TMP_DIR}) {
643 print STDERR "# Not removing temp dir: $dir\n";
644 return;
645 }
646
647 opendir(my $dh, $dir) || confess "Could not open temp dir! ($dir)";
648 while(my $file = readdir($dh)) {
649 next if $file =~ m/^\.+$/;
650 die "Unculled event! You ran tests in a child process, but never pulled them in!\n"
651 if $file !~ m/\.complete$/;
652 unlink("$dir/$file") || confess "Could not unlink file: '$dir/$file'";
653 }
654 closedir($dh);
655 rmdir($dir) || warn "Could not remove temp dir ($dir)";
656}
657
658sub STORABLE_freeze {
659 my ($self, $cloning) = @_;
660 return if $cloning;
661 return ($self);
662}
663
664sub STORABLE_thaw {
665 my ($self, $cloning, @vals) = @_;
666 return if $cloning;
667 return Test::Stream->shared;
668}
669
670
6711;
672
673__END__
674
675=head1 NAME
676
677Test::Stream - A modern infrastructure for testing.
678
679=head1 SYNOPSYS
680
681 # Enables modern enhancements such as forking support and TAP encoding.
682 # Also turns off expensive legacy support.
683 use Test::Stream;
684 use Test::More;
685
686 # ... Tests ...
687
688 done_testing;
689
690=head1 FEATURES
691
692When you load Test::Stream inside your test file you prevent Test::More from
693turning on some expensive legacy support. You will also get warnings if your
694code, or any other code you load uses deprecated or discouraged practices.
695
696=head1 IMPORT ARGUMENTS
697
698Any import argument not recognised will be treated as an export, if it is not a
699valid export an exception will be thrown.
700
701=over 4
702
703=item '-internal'
704
705This argument, I<when given first>, will prevent the import process from
706turning on enhanced features. This is mainly for internal use (thus the name)
707in order to access/load Test::Stream.
708
709=item subtest_tap => 'none'
710
711Do not show events within subtests, just the subtest result itself.
712
713=item subtest_tap => 'instant'
714
715Show events as they happen (this is how legacy Test::More worked). This is the
716default.
717
718=item subtest_tap => 'delayed'
719
720Show events within subtest AFTER the subtest event itself is complete.
721
722=item subtest_tap => 'both'
723
724Show events as they happen, then also display them after.
725
726=item 'enable_fork'
727
728Turns on support for code that forks. This is not activated by default because
729it adds ~30ms to the Test::More compile-time, which can really add up in large
730test suites. Turn it on only when needed.
731
732=item 'utf8'
733
734Set the TAP encoding to utf8
735
736=item encoding => '...'
737
738Set the TAP encoding.
739
740=back
741
742=head1 EXPORTS
743
744=head2 DEFAULT EXPORTS
745
746=over 4
747
748=item tap_encoding( $ENCODING )
749
750Set the tap encoding from this point on.
751
752=item cull
753
754Bring in results from child processes/threads. This is automatically done
755whenever a context is obtained, but you may wish to do it on demand.
756
757=back
758
759=head2 CONSTANTS
760
761none of these are exported by default you must request them
762
763=over
764
765=item OUT_STD
766
767=item OUT_ERR
768
769=item OUT_TODO
770
771These are indexes of specific IO handles inside an IO set (each encoding has an
772IO set).
773
774=item STATE_COUNT
775
776=item STATE_FAILED
777
778=item STATE_PLAN
779
780=item STATE_PASSING
781
782=item STATE_LEGACY
783
784=item STATE_ENDED
785
786These are indexes into the STATE array present in the stream.
787
788=back
789
790=head1 THE STREAM STACK AND METHODS
791
792At any point there can be any number of streams. Most streams will be present
793in the stream stack. The stack is managed via a collection of class methods.
794You can always access the "current" or "central" stream using
795Test::Stream->shared. If you want your events to go where they are supposed to
796then you should always send them to the shared stream.
797
798It is important to note that any toogle, control, listener, munger, etc.
799applied to a stream will effect only that stream. Independant streams, streams
800down the stack, and streams added later will not get any settings from other
801stacks. Keep this in mind if you take it upon yourself to modify the stream
802stack.
803
804=head2 TOGGLES AND CONTROLS
805
806=over 4
807
808=item $stream->use_fork
809
810Turn on forking support (it cannot be turned off).
811
812=item $stream->set_subtest_tap_instant($bool)
813
814=item $bool = $stream->subtest_tap_instant
815
816Render subtest events as they happen.
817
818=item $stream->set_subtest_tap_delayed($bool)
819
820=item $bool = $stream->subtest_tap_delayed
821
822Render subtest events when printing the result of the subtest
823
824=item $stream->set_exit_on_disruption($bool)
825
826=item $bool = $stream->exit_on_disruption
827
828When true, skip_all and bailout will call exit. When false the bailout and
829skip_all events will be thrown as exceptions.
830
831=item $stream->set_use_tap($bool)
832
833=item $bool = $stream->use_tap
834
835Turn TAP rendering on or off.
836
837=item $stream->set_use_legacy($bool)
838
839=item $bool = $stream->use_legacy
840
841Turn legacy result storing on and off.
842
843=item $stream->set_use_numbers($bool)
844
845=item $bool = $stream->use_numbers
846
847Turn test numbers on and off.
848
849=back
850
851=head2 SENDING EVENTS
852
853 Test::Stream->shared->send($event)
854
855The C<send()> method is used to issue an event to the stream. This method will
856handle thread/fork sych, mungers, listeners, TAP output, etc.
857
858=head2 ALTERING EVENTS
859
860 Test::Stream->shared->munge(sub {
861 my ($stream, $event) = @_;
862
863 ... Modify the event object ...
864
865 # return is ignored.
866 });
867
868Mungers can never be removed once added. The return from a munger is ignored.
869Any changes you wish to make to the object must be done directly by altering
870it in place. The munger is called before the event is rendered as TAP, and
871AFTER the event has made any necessary state changes.
872
873=head2 LISTENING FOR EVENTS
874
875 Test::Stream->shared->listen(sub {
876 my ($stream, $event) = @_;
877
878 ... do whatever you want with the event ...
879
880 # return is ignored
881 });
882
883Listeners can never be removed once added. The return from a listener is
884ignored. Changing an event in a listener is not something you should ever do,
885though no protections are in place to prevent it (this may change!). The
886listeners are called AFTER the event has been rendered as TAP.
887
888=head2 POST-TEST BEHAVIORS
889
890 Test::Stream->shared->follow_up(sub {
891 my ($context) = @_;
892
893 ... do whatever you need to ...
894
895 # Return is ignored
896 });
897
898follow_up subs are called only once, when the stream recieves a finish event. There are 2 ways a finish event can occur:
899
900=over 4
901
902=item done_testing
903
904A finish event is generated when you call done_testing. The finish event occurs
905before the plan is output.
906
907=item EXIT MAGIC
908
909A finish event is generated when the Test::Stream END block is called, just
910before cleanup. This event will not happen if it was already geenerated by a
911call to done_testing.
912
913=back
914
915=head2 OTHER METHODS
916
917=over
918
919=item $stream->state
920
921Get the current state of the stream. The state is an array where specific
922indexes have specific meanings. These indexes are managed via constants.
923
924=item $stream->plan
925
926Get the plan event, if a plan has been issued.
927
928=item $stream->count
929
930Get the test count so far.
931
932=item $stream->failed
933
934Get the number of failed tests so far.
935
936=item $stream->ended
937
938Get the context in which the tests ended, if they have ended.
939
940=item $stream->legacy
941
942Used internally to store events for legacy support.
943
944=item $stream->is_passing
945
946Check if the test is passing its plan.
947
948=item $stream->done_testing($context, $max)
949
950Tell the stream we are done testing.
951
952=item $stream->fork_cull
953
954Gather events from other threads/processes.
955
956=back
957
958=head2 STACK METHODS AND INTERCEPTING EVENTS
959
960=over 4
961
962=item $stream = Test::Stream->shared
963
964Get the current shared stream. The shared stream is the stream at the top of
965the stack.
966
967=item Test::Stream->clear
968
969Completely remove the stream stack. It is very unlikely you will ever want to
970do this.
971
972=item ($new, $old) = Test::Stream->intercept_start($new)
973
974=item ($new, $old) = Test::Stream->intercept_start
975
976Push a new stream to the top of the stack. If you do not provide a stack a new
977one will be created for you. If you have one created for you it will have the
978following differences from a default stack:
979
980 $new->set_exit_on_disruption(0);
981 $new->set_use_tap(0);
982 $new->set_use_legacy(0);
983
984=item Test::Stream->intercept_stop($top)
985
986Pop the stack, you must pass in the instance you expect to be popped, there
987will be an exception if they do not match.
988
989=item Test::Stream->intercept(sub { ... })
990
991 Test::Stream->intercept(sub {
992 my ($new, $old) = @_;
993
994 ...
995 });
996
997Temporarily push a new stream to the top of the stack. The codeblock you pass
998in will be run. Once your codelbock returns the stack will be popped and
999restored to the previous state.
1000
1001=back
1002
1003=encoding utf8
1004
1005=head1 SOURCE
1006
1007The source code repository for Test::More can be found at
1008F<http://github.com/Test-More/test-more/>.
1009
1010=head1 MAINTAINER
1011
1012=over 4
1013
1014=item Chad Granum E<lt>exodist@cpan.orgE<gt>
1015
1016=back
1017
1018=head1 AUTHORS
1019
1020The following people have all contributed to the Test-More dist (sorted using
1021VIM's sort function).
1022
1023=over 4
1024
1025=item Chad Granum E<lt>exodist@cpan.orgE<gt>
1026
1027=item Fergal Daly E<lt>fergal@esatclear.ie>E<gt>
1028
1029=item Mark Fowler E<lt>mark@twoshortplanks.comE<gt>
1030
1031=item Michael G Schwern E<lt>schwern@pobox.comE<gt>
1032
1033=item 唐鳳
1034
1035=back
1036
1037=head1 COPYRIGHT
1038
1039There has been a lot of code migration between modules,
1040here are all the original copyrights together:
1041
1042=over 4
1043
1044=item Test::Stream
1045
1046=item Test::Stream::Tester
1047
1048Copyright 2014 Chad Granum E<lt>exodist7@gmail.comE<gt>.
1049
1050This program is free software; you can redistribute it and/or
1051modify it under the same terms as Perl itself.
1052
1053See F<http://www.perl.com/perl/misc/Artistic.html>
1054
1055=item Test::Simple
1056
1057=item Test::More
1058
1059=item Test::Builder
1060
1061Originally authored by Michael G Schwern E<lt>schwern@pobox.comE<gt> with much
1062inspiration from Joshua Pritikin's Test module and lots of help from Barrie
1063Slaymaker, Tony Bowden, blackstar.co.uk, chromatic, Fergal Daly and the perl-qa
1064gang.
1065
1066Idea by Tony Bowden and Paul Johnson, code by Michael G Schwern
1067E<lt>schwern@pobox.comE<gt>, wardrobe by Calvin Klein.
1068
1069Copyright 2001-2008 by Michael G Schwern E<lt>schwern@pobox.comE<gt>.
1070
1071This program is free software; you can redistribute it and/or
1072modify it under the same terms as Perl itself.
1073
1074See F<http://www.perl.com/perl/misc/Artistic.html>
1075
1076=item Test::use::ok
1077
1078To the extent possible under law, 唐鳳 has waived all copyright and related
1079or neighboring rights to L<Test-use-ok>.
1080
1081This work is published from Taiwan.
1082
1083L<http://creativecommons.org/publicdomain/zero/1.0>
1084
1085=item Test::Tester
1086
1087This module is copyright 2005 Fergal Daly <fergal@esatclear.ie>, some parts
1088are based on other people's work.
1089
1090Under the same license as Perl itself
1091
1092See http://www.perl.com/perl/misc/Artistic.html
1093
1094=item Test::Builder::Tester
1095
1096Copyright Mark Fowler E<lt>mark@twoshortplanks.comE<gt> 2002, 2004.
1097
1098This program is free software; you can redistribute it
1099and/or modify it under the same terms as Perl itself.
1100
1101=back