summaryrefslogtreecommitdiff
path: root/cpan/Test-Simple/lib/Test/Builder/ExitMagic.pm
diff options
context:
space:
mode:
Diffstat (limited to 'cpan/Test-Simple/lib/Test/Builder/ExitMagic.pm')
-rw-r--r--cpan/Test-Simple/lib/Test/Builder/ExitMagic.pm194
1 files changed, 194 insertions, 0 deletions
diff --git a/cpan/Test-Simple/lib/Test/Builder/ExitMagic.pm b/cpan/Test-Simple/lib/Test/Builder/ExitMagic.pm
new file mode 100644
index 0000000000..021cad9649
--- /dev/null
+++ b/cpan/Test-Simple/lib/Test/Builder/ExitMagic.pm
@@ -0,0 +1,194 @@
+package Test::Builder::ExitMagic;
+use strict;
+use warnings;
+
+use Test::Builder::Util qw/new accessors/;
+require Test::Builder::Result::Finish;
+
+accessors qw/stream tb ended pid/;
+
+sub init {
+ my $self = shift;
+ $self->pid($$);
+}
+
+sub do_magic {
+ my $self = shift;
+
+ return if $self->ended; $self->ended(1);
+
+ # Don't bother with an ending if this is a forked copy. Only the parent
+ # should do the ending.
+ return unless $self->pid == $$;
+
+ my $stream = $self->stream || (Test::Builder::Stream->root ? Test::Builder::Stream->shared : undef);
+ return unless $stream; # No stream? no point!
+ my $tb = $self->tb;
+
+ return if $stream->no_ending;
+
+ my $real_exit_code = $?;
+
+ my $plan = $stream->plan;
+ my $total = $stream->tests_run;
+ my $fails = $stream->tests_failed;
+
+ $stream->send(
+ Test::Builder::Result::Finish->new(
+ tests_run => $total,
+ tests_failed => $fails,
+ depth => $tb->depth,
+ source => $tb->name,
+ )
+ );
+
+ # Ran tests but never declared a plan or hit done_testing
+ return $self->no_plan_magic($stream, $tb, $total, $fails, $real_exit_code)
+ if $total && !$plan;
+
+ # Exit if plan() was never called. This is so "require Test::Simple"
+ # doesn't puke.
+ return unless $plan;
+
+ # Don't do an ending if we bailed out.
+ if( $stream->bailed_out ) {
+ $stream->is_passing(0);
+ return;
+ }
+
+ # Figure out if we passed or failed and print helpful messages.
+ return $self->be_helpful_magic($stream, $tb, $total, $fails, $plan, $real_exit_code)
+ if $total && $plan;
+
+ if ($plan->directive && $plan->directive eq 'SKIP') {
+ $? = 0;
+ return;
+ }
+
+ if($real_exit_code) {
+ $tb->diag("Looks like your test exited with $real_exit_code before it could output anything.\n");
+ $stream->is_passing(0);
+ $? = $real_exit_code;
+ return;
+ }
+
+ unless ($total) {
+ $tb->diag("No tests run!\n");
+ $tb->is_passing(0);
+ $? = 255;
+ return;
+ }
+
+ $tb->is_passing(0);
+ $tb->_whoa( 1, "We fell off the end of _ending()" );
+
+ 1;
+}
+
+sub no_plan_magic {
+ my $self = shift;
+ my ($stream, $tb, $total, $fails, $real_exit_code) = @_;
+
+ $stream->is_passing(0);
+ $tb->diag("Tests were run but no plan was declared and done_testing() was not seen.");
+
+ if($real_exit_code) {
+ $tb->diag("Looks like your test exited with $real_exit_code just after $total.\n");
+ $? = $real_exit_code;
+ return;
+ }
+
+ # But if the tests ran, handle exit code.
+ if ($total && $fails) {
+ my $exit_code = $fails <= 254 ? $fails : 254;
+ $? = $exit_code;
+ return;
+ }
+
+ $? = 254;
+ return;
+}
+
+sub be_helpful_magic {
+ my $self = shift;
+ my ($stream, $tb, $total, $fails, $plan, $real_exit_code) = @_;
+
+ my $planned = $plan->max;
+ my $num_extra = $plan->directive && $plan->directive eq 'NO_PLAN' ? 0 : $total - $planned;
+
+ if ($num_extra != 0) {
+ my $s = $planned == 1 ? '' : 's';
+ $tb->diag("Looks like you planned $planned test$s but ran $total.\n");
+ $tb->is_passing(0);
+ }
+
+ if($fails) {
+ my $s = $fails == 1 ? '' : 's';
+ my $qualifier = $num_extra == 0 ? '' : ' run';
+ $tb->diag("Looks like you failed $fails test$s of ${total}${qualifier}.\n");
+ $tb->is_passing(0);
+ }
+
+ if($real_exit_code) {
+ $tb->diag("Looks like your test exited with $real_exit_code just after $total.\n");
+ $tb->is_passing(0);
+ $? = $real_exit_code;
+ return;
+ }
+
+ my $exit_code;
+ if($fails) {
+ $exit_code = $fails <= 254 ? $fails : 254;
+ }
+ elsif($num_extra != 0) {
+ $exit_code = 255;
+ }
+ else {
+ $exit_code = 0;
+ }
+
+ $? = $exit_code;
+ return;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Test::Builder::ExitMagic - Encapsulate the magic exit logic used by
+Test::Builder.
+
+=head1 DESCRIPTION
+
+It's magic! well kinda..
+
+=head1 SYNOPSYS
+
+Don't use this yourself, let L<Test::Builder> handle it.
+
+=head1 AUTHORS
+
+=over 4
+
+=item Chad Granum E<lt>exodist@cpan.orgE<gt>
+
+=back
+
+=head1 SOURCE
+
+The source code repository for Test::More can be found at
+F<http://github.com/Test-More/test-more/>.
+
+=head1 COPYRIGHT
+
+Copyright 2014 Chad Granum E<lt>exodist7@gmail.comE<gt>.
+
+Most of this code was pulled out ot L<Test::Builder>, written by Schwern and
+others.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+See F<http://www.perl.com/perl/misc/Artistic.html>