Acme-Albed
view release on metacpan or search on metacpan
inc/Test/Builder.pm view on Meta::CPAN
sub new {
my($class) = shift;
$Test ||= $class->create;
return $Test;
}
#line 139
sub create {
my $class = shift;
my $self = bless {}, $class;
$self->reset;
return $self;
}
#line 168
sub child {
my( $self, $name ) = @_;
if( $self->{Child_Name} ) {
$self->croak("You already have a child named ($self->{Child_Name}) running");
}
my $child = bless {}, ref $self;
$child->reset;
# Add to our indentation
$child->_indent( $self->_indent . ' ' );
$child->{$_} = $self->{$_} foreach qw{Out_FH Todo_FH Fail_FH};
# This will be reset in finalize. We do this here lest one child failure
# cause all children to fail.
$child->{Child_Error} = $?;
$? = 0;
$child->{Parent} = $self;
$child->{Name} = $name || "Child of " . $self->name;
$self->{Child_Name} = $child->name;
return $child;
}
#line 201
sub subtest {
my $self = shift;
my($name, $subtests) = @_;
if ('CODE' ne ref $subtests) {
$self->croak("subtest()'s second argument must be a code ref");
}
# Turn the child into the parent so anyone who has stored a copy of
# the Test::Builder singleton will get the child.
my $child = $self->child($name);
my %parent = %$self;
%$self = %$child;
my $error;
if( !eval { $subtests->(); 1 } ) {
$error = $@;
}
# Restore the parent and the copied child.
%$child = %$self;
%$self = %parent;
# Die *after* we restore the parent.
die $error if $error and !eval { $error->isa('Test::Builder::Exception') };
return $child->finalize;
}
#line 250
sub finalize {
my $self = shift;
return unless $self->parent;
if( $self->{Child_Name} ) {
$self->croak("Can't call finalize() with child ($self->{Child_Name}) active");
}
$self->_ending;
# XXX This will only be necessary for TAP envelopes (we think)
#$self->_print( $self->is_passing ? "PASS\n" : "FAIL\n" );
my $ok = 1;
$self->parent->{Child_Name} = undef;
if ( $self->{Skip_All} ) {
$self->parent->skip($self->{Skip_All});
}
elsif ( not @{ $self->{Test_Results} } ) {
$self->parent->ok( 0, sprintf q[No tests run for subtest "%s"], $self->name );
}
else {
$self->parent->ok( $self->is_passing, $self->name );
}
$? = $self->{Child_Error};
delete $self->{Parent};
return $self->is_passing;
}
sub _indent {
my $self = shift;
if( @_ ) {
$self->{Indent} = shift;
}
return $self->{Indent};
}
#line 300
sub parent { shift->{Parent} }
#line 312
sub name { shift->{Name} }
sub DESTROY {
my $self = shift;
if ( $self->parent ) {
my $name = $self->name;
$self->diag(<<"FAIL");
Child ($name) exited without calling finalize()
inc/Test/Builder.pm view on Meta::CPAN
}
#line 973
sub isnt_eq {
my( $self, $got, $dont_expect, $name ) = @_;
local $Level = $Level + 1;
if( !defined $got || !defined $dont_expect ) {
# undef only matches undef and nothing else
my $test = defined $got || defined $dont_expect;
$self->ok( $test, $name );
$self->_isnt_diag( $got, 'ne' ) unless $test;
return $test;
}
return $self->cmp_ok( $got, 'ne', $dont_expect, $name );
}
sub isnt_num {
my( $self, $got, $dont_expect, $name ) = @_;
local $Level = $Level + 1;
if( !defined $got || !defined $dont_expect ) {
# undef only matches undef and nothing else
my $test = defined $got || defined $dont_expect;
$self->ok( $test, $name );
$self->_isnt_diag( $got, '!=' ) unless $test;
return $test;
}
return $self->cmp_ok( $got, '!=', $dont_expect, $name );
}
#line 1022
sub like {
my( $self, $this, $regex, $name ) = @_;
local $Level = $Level + 1;
return $self->_regex_ok( $this, $regex, '=~', $name );
}
sub unlike {
my( $self, $this, $regex, $name ) = @_;
local $Level = $Level + 1;
return $self->_regex_ok( $this, $regex, '!~', $name );
}
#line 1046
my %numeric_cmps = map { ( $_, 1 ) } ( "<", "<=", ">", ">=", "==", "!=", "<=>" );
sub cmp_ok {
my( $self, $got, $type, $expect, $name ) = @_;
my $test;
my $error;
{
## no critic (BuiltinFunctions::ProhibitStringyEval)
local( $@, $!, $SIG{__DIE__} ); # isolate eval
my($pack, $file, $line) = $self->caller();
$test = eval qq[
#line 1 "cmp_ok [from $file line $line]"
\$got $type \$expect;
];
$error = $@;
}
local $Level = $Level + 1;
my $ok = $self->ok( $test, $name );
# Treat overloaded objects as numbers if we're asked to do a
# numeric comparison.
my $unoverload
= $numeric_cmps{$type}
? '_unoverload_num'
: '_unoverload_str';
$self->diag(<<"END") if $error;
An error occurred while using $type:
------------------------------------
$error
------------------------------------
END
unless($ok) {
$self->$unoverload( \$got, \$expect );
if( $type =~ /^(eq|==)$/ ) {
$self->_is_diag( $got, $type, $expect );
}
elsif( $type =~ /^(ne|!=)$/ ) {
$self->_isnt_diag( $got, $type );
}
else {
$self->_cmp_diag( $got, $type, $expect );
}
}
return $ok;
}
sub _cmp_diag {
my( $self, $got, $type, $expect ) = @_;
$got = defined $got ? "'$got'" : 'undef';
$expect = defined $expect ? "'$expect'" : 'undef';
local $Level = $Level + 1;
return $self->diag(<<"DIAGNOSTIC");
$got
$type
$expect
DIAGNOSTIC
}
sub _caller_context {
my $self = shift;
my( $pack, $file, $line ) = $self->caller(1);
my $code = '';
$code .= "#line $line $file\n" if defined $file and defined $line;
return $code;
}
#line 1145
sub BAIL_OUT {
my( $self, $reason ) = @_;
$self->{Bailed_Out} = 1;
$self->_print("Bail out! $reason");
exit 255;
}
#line 1158
{
no warnings 'once';
*BAILOUT = \&BAIL_OUT;
}
inc/Test/Builder.pm view on Meta::CPAN
sub _is_qr {
my $regex = shift;
# is_regexp() checks for regexes in a robust manner, say if they're
# blessed.
return re::is_regexp($regex) if defined &re::is_regexp;
return ref $regex eq 'Regexp';
}
sub _regex_ok {
my( $self, $this, $regex, $cmp, $name ) = @_;
my $ok = 0;
my $usable_regex = $self->maybe_regex($regex);
unless( defined $usable_regex ) {
local $Level = $Level + 1;
$ok = $self->ok( 0, $name );
$self->diag(" '$regex' doesn't look much like a regex to me.");
return $ok;
}
{
## no critic (BuiltinFunctions::ProhibitStringyEval)
my $test;
my $context = $self->_caller_context;
local( $@, $!, $SIG{__DIE__} ); # isolate eval
$test = eval $context . q{$test = $this =~ /$usable_regex/ ? 1 : 0};
$test = !$test if $cmp eq '!~';
local $Level = $Level + 1;
$ok = $self->ok( $test, $name );
}
unless($ok) {
$this = defined $this ? "'$this'" : 'undef';
my $match = $cmp eq '=~' ? "doesn't match" : "matches";
local $Level = $Level + 1;
$self->diag( sprintf <<'DIAGNOSTIC', $this, $match, $regex );
%s
%13s '%s'
DIAGNOSTIC
}
return $ok;
}
# I'm not ready to publish this. It doesn't deal with array return
# values from the code or context.
#line 1389
sub _try {
my( $self, $code, %opts ) = @_;
my $error;
my $return;
{
local $!; # eval can mess up $!
local $@; # don't set $@ in the test
local $SIG{__DIE__}; # don't trip an outside DIE handler.
$return = eval { $code->() };
$error = $@;
}
die $error if $error and $opts{die_on_fail};
return wantarray ? ( $return, $error ) : $return;
}
#line 1418
sub is_fh {
my $self = shift;
my $maybe_fh = shift;
return 0 unless defined $maybe_fh;
return 1 if ref $maybe_fh eq 'GLOB'; # its a glob ref
return 1 if ref \$maybe_fh eq 'GLOB'; # its a glob
return eval { $maybe_fh->isa("IO::Handle") } ||
eval { tied($maybe_fh)->can('TIEHANDLE') };
}
#line 1461
sub level {
my( $self, $level ) = @_;
if( defined $level ) {
$Level = $level;
}
return $Level;
}
#line 1493
sub use_numbers {
my( $self, $use_nums ) = @_;
if( defined $use_nums ) {
$self->{Use_Nums} = $use_nums;
}
return $self->{Use_Nums};
}
#line 1526
foreach my $attribute (qw(No_Header No_Ending No_Diag)) {
my $method = lc $attribute;
my $code = sub {
my( $self, $no ) = @_;
if( defined $no ) {
$self->{$attribute} = $no;
}
return $self->{$attribute};
};
no strict 'refs'; ## no critic
*{ __PACKAGE__ . '::' . $method } = $code;
}
#line 1579
sub diag {
my $self = shift;
inc/Test/Builder.pm view on Meta::CPAN
}
return $self->{Out_FH};
}
sub failure_output {
my( $self, $fh ) = @_;
if( defined $fh ) {
$self->{Fail_FH} = $self->_new_fh($fh);
}
return $self->{Fail_FH};
}
sub todo_output {
my( $self, $fh ) = @_;
if( defined $fh ) {
$self->{Todo_FH} = $self->_new_fh($fh);
}
return $self->{Todo_FH};
}
sub _new_fh {
my $self = shift;
my($file_or_fh) = shift;
my $fh;
if( $self->is_fh($file_or_fh) ) {
$fh = $file_or_fh;
}
elsif( ref $file_or_fh eq 'SCALAR' ) {
# Scalar refs as filehandles was added in 5.8.
if( $] >= 5.008 ) {
open $fh, ">>", $file_or_fh
or $self->croak("Can't open scalar ref $file_or_fh: $!");
}
# Emulate scalar ref filehandles with a tie.
else {
$fh = Test::Builder::IO::Scalar->new($file_or_fh)
or $self->croak("Can't tie scalar ref $file_or_fh");
}
}
else {
open $fh, ">", $file_or_fh
or $self->croak("Can't open test output log $file_or_fh: $!");
_autoflush($fh);
}
return $fh;
}
sub _autoflush {
my($fh) = shift;
my $old_fh = select $fh;
$| = 1;
select $old_fh;
return;
}
my( $Testout, $Testerr );
sub _dup_stdhandles {
my $self = shift;
$self->_open_testhandles;
# Set everything to unbuffered else plain prints to STDOUT will
# come out in the wrong order from our own prints.
_autoflush($Testout);
_autoflush( \*STDOUT );
_autoflush($Testerr);
_autoflush( \*STDERR );
$self->reset_outputs;
return;
}
sub _open_testhandles {
my $self = shift;
return if $self->{Opened_Testhandles};
# We dup STDOUT and STDERR so people can change them in their
# test suites while still getting normal test output.
open( $Testout, ">&STDOUT" ) or die "Can't dup STDOUT: $!";
open( $Testerr, ">&STDERR" ) or die "Can't dup STDERR: $!";
# $self->_copy_io_layers( \*STDOUT, $Testout );
# $self->_copy_io_layers( \*STDERR, $Testerr );
$self->{Opened_Testhandles} = 1;
return;
}
sub _copy_io_layers {
my( $self, $src, $dst ) = @_;
$self->_try(
sub {
require PerlIO;
my @src_layers = PerlIO::get_layers($src);
binmode $dst, join " ", map ":$_", @src_layers if @src_layers;
}
);
return;
}
#line 1857
sub reset_outputs {
my $self = shift;
$self->output ($Testout);
$self->failure_output($Testerr);
$self->todo_output ($Testout);
return;
}
#line 1883
sub _message_at_caller {
my $self = shift;
local $Level = $Level + 1;
my( $pack, $file, $line ) = $self->caller;
return join( "", @_ ) . " at $file line $line.\n";
}
sub carp {
my $self = shift;
return warn $self->_message_at_caller(@_);
}
sub croak {
my $self = shift;
return die $self->_message_at_caller(@_);
}
#line 1923
sub current_test {
my( $self, $num ) = @_;
lock( $self->{Curr_Test} );
if( defined $num ) {
$self->{Curr_Test} = $num;
# If the test counter is being pushed forward fill in the details.
my $test_results = $self->{Test_Results};
if( $num > @$test_results ) {
my $start = @$test_results ? @$test_results : 0;
for( $start .. $num - 1 ) {
$test_results->[$_] = &share(
{
'ok' => 1,
actual_ok => undef,
reason => 'incrementing test number',
type => 'unknown',
name => undef
}
);
}
}
# If backward, wipe history. Its their funeral.
elsif( $num < @$test_results ) {
$#{$test_results} = $num - 1;
}
}
return $self->{Curr_Test};
}
#line 1971
( run in 2.617 seconds using v1.01-cache-2.11-cpan-0bb4e1dffa6 )